Create and Update S-Function Run-Time Parameters
About Run-Time Parameters
You can create internal representations of external S-function dialog box parameters called run-time parameters. Every run-time parameter corresponds to one or more dialog box parameters and can have the same value and data type as its corresponding external parameters or a different value or data type. If a run-time parameter differs in value or data type from its external counterpart, the dialog parameter is said to have been transformed to create the run-time parameter. The value of a run-time parameter that corresponds to multiple dialog parameters is typically a function of the values of the dialog parameters. The Simulink® engine allocates and frees storage for run-time parameters and provides functions for updating and accessing them, thus eliminating the need for S-functions to perform these tasks. Run-time parameters facilitate the following kinds of S-function operations:
Computed parameters
Often the output of a block is a function of the values of several dialog parameters. For example, suppose a block has two parameters, the volume and density of some object, and the output of the block is a function of the input signal and the mass of the object. In this case, the mass can be viewed as a third internal parameter computed from the two external parameters, volume and density. An S-function can create a run-time parameter corresponding to the computed weight, thereby eliminating the need to provide special case handling for weight in the output computation. See Creating Run-Time Parameters from Multiple S-Function Parameters for more information.
Data type conversions
Often a block needs to change the data type of a dialog parameter to facilitate internal processing. For example, suppose that the output of the block is a function of the input and a dialog parameter and the input and dialog parameter are of different data types. In this case, the S-function can create a run-time parameter that has the same value as the dialog parameter but has the data type of the input signal, and use the run-time parameter in the computation of the output.
Code generation
During code generation, the Simulink Coder™ product writes all run-time parameters automatically to the
model.rtwfile, eliminating the need for the S-function to perform this task via anmdlRTWmethod.
The sfcndemo_runtime
Simulink model contains four example S-functions that create run-time
parameters.
Creating Run-Time Parameters
In a C S-function, you can create run-time parameters in a number of ways. The following sections describe different methods for creating run-time parameters in a C S-function.
Creating Run-Time Parameters All at Once
Use the SimStruct function in
ssRegAllTunableParamsAsRunTimeParams
to create run-time parameters corresponding to all tunable parameters. This
function requires that you pass it an array of names, one for each run-time
parameter. The Simulink
Coder product uses these names as the names of the parameters during
code generation. The S-function mdlSetWorkWidthssfun_runtime1.c shows how to create run-time
parameters all at once.
This approach to creating run-time parameters assumes that there is a one-to-one correspondence between an S-function run-time parameters and its tunable dialog parameters. This might not be the case. For example, an S-function might want to use a computed parameter whose value is a function of several dialog parameters. In such cases, the S-function might need to create the run-time parameters individually.
Creating Run-Time Parameters Individually
To create run-time parameters individually, the S-function
method shouldmdlSetWorkWidths
Specify the number of run-time parameters it intends to use, using
ssSetNumRunTimeParams.Use
ssRegDlgParamAsRunTimeParamto register a run-time parameter that corresponds to a single dialog parameter, even if there is a data type transformation, orssSetRunTimeParamInfoto set the attributes of a run-time parameter that corresponds to more than one dialog parameter.
The following example uses ssRegDlgParamAsRunTimeParam and
is taken from the S-function sfun_runtime3.c. This example creates a run-time
parameter directly from the dialog parameter and with the same data type as the
first input port's signal.
static void mdlSetWorkWidths(SimStruct *S)
{
/* Get data type of input to use for run-time parameter */
DTypeId dtId = ssGetInputPortDataType(S, 0);
/* Define name of run-time parameter */
const char_T *rtParamName = "Gain";
ssSetNumRunTimeParams(S, 1); /* One run-time parameter */
if (ssGetErrorStatus(S) != NULL) return;
ssRegDlgParamAsRunTimeParam(S, GAIN_IDX, 0, rtParamName, dtId);
}
#endif /* MDL_SET_WORK_WIDTHS */The next example uses ssSetRunTimeParamInfo and is taken
from the S-function sfun_runtime2.c.
static void mdlSetWorkWidths(SimStruct *S)
{
ssParamRec p; /* Initialize an ssParamRec structure */
int dlgP = GAIN_IDX; /* Index of S-function parameter */
/* Configure run-time parameter information */
p.name = "Gain";
p.nDimensions = 2;
p.dimensions = (int_T *) mxGetDimensions(GAIN_PARAM(S));
p.dataTypeId = SS_DOUBLE;
p.complexSignal = COMPLEX_NO;
p.data = (void *)mxGetPr(GAIN_PARAM(S));
p.dataAttributes = NULL;
p.nDlgParamIndices = 1;
p.dlgParamIndices = &dlgP;
p.transformed = false;
p.outputAsMatrix = false;
/* Set number of run-time parameters */
if (!ssSetNumRunTimeParams(S, 1)) return;
/* Set run-time parameter information */
if (!ssSetRunTimeParamInfo(S, 0, &p)) return;
}The S-function sfun_runtime2.c defines the parameters
GAIN_IDX and GAIN_PARAM as follows,
prior to using these parameters in mdlSetWorkWidths.
#define GAIN_IDX 1 #define GAIN_PARAM(S) ssGetSFcnParam(S,GAIN_IDX)
Creating Run-Time Parameters from Multiple S-Function Parameters
Use the ssSetRunTimeParamInfo
function in mdlSetWorkWidths to create run-time parameters as
a function of multiple S-function parameters. For example, consider an
S-function with two S-function parameters, density and volume. The S-function
inputs a force (F) and outputs an acceleration
(a). The mdlOutputs method calculates
the force using the equation F=m*a, where the mass
(m) is the product of the density and volume.
The S-function sfun_runtime4.c implements this example using a single
run-time parameter to store the mass. The S-function begins by defining the
run-time parameter data type, as well as variables associated with volume and
density.
#define RUN_TIME_DATA_TYPE SS_DOUBLE #if RUN_TIME_DATA_TYPE == SS_DOUBLE typedef real_T RunTimeDataType; #endif #define VOL_IDX 0 #define VOL_PARAM(S) ssGetSFcnParam(S,VOL_IDX) #define DEN_IDX 1 #define DEN_PARAM(S) ssGetSFcnParam(S,DEN_IDX)
The mdlSetWorkWidths method then initializes the run-time
parameter, as follows.
static void mdlSetWorkWidths(SimStruct *S)
{
ssParamRec p; /* Initialize an ssParamRec structure */
int dlg[2]; /* Stores dialog indices */
real_T vol = *mxGetPr(VOL_PARAM(S));
real_T den = *mxGetPr(DEN_PARAM(S));
RunTimeDataType *mass;
/* Initialize dimensions for the run-time parameter as a
* local variable. The Simulink engine makes a copy of this
* information to store in the run-time parameter. */
int_T massDims[2] = {1,1};
/* Allocate memory for the run-time parameter data. The S-function
* owns this memory location. The Simulink engine does not copy the data.*/
if ((mass=(RunTimeDataType*)malloc(1)) == NULL) {
ssSetErrorStatus(S,"Memory allocation error");
return;
}
/* Store the pointer to the memory location in the S-function
* userdata. Since the S-function owns this data, it needs to
* free the memory during mdlTerminate */
ssSetUserData(S, (void*)mass);
/* Call a local function to initialize the run-time
* parameter data. The Simulink engine checks that the data is not
* empty so an initial value must be stored. */
calcMass(mass, vol, den);
/* Specify mass as a function of two S-function dialog parameters */
dlg[0] = VOL_IDX;
dlg[1] = DEN_IDX;
/* Configure run-time parameter information. */
p.name = "Mass";
p.nDimensions = 2;
p.dimensions = massDims;
p.dataTypeId = RUN_TIME_DATA_TYPE;
p.complexSignal = COMPLEX_NO;
p.data = mass;
p.dataAttributes = NULL;
p.nDlgParamIndices = 2;
p.dlgParamIndices = &dlg
p.transformed = RTPARAM_TRANSFORMED;
p.outputAsMatrix = false;
/* Set number of run-time parameters */
if (!ssSetNumRunTimeParams(S, 1)) return;
/* Set run-time parameter information */
if (!ssSetRunTimeParamInfo(S,0,&p)) return;
}
The local function calcMass updates the run-time parameter
value in mdlSetWorkWidths and in
mdlProcessParameters, when the values of density or
volume are tuned.
/* Function: calcMass ==============================================
* Abstract:
* Local function to calculate the mass as a function of volume
* and density.
*/
static void calcMass(RunTimeDataType *mass, real_T vol, real_T den)
{
*mass = vol * den;
}
The mdlOutputs method uses the stored mass to calculate the
force.
/* Function: mdlOutputs ==========================================
* Abstract:
*
* Output acceleration calculated as input force divided by mass.
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
real_T *y1 = ssGetOutputPortRealSignal(S,0);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
RunTimeDataType *mass =
(RunTimeDataType *)((ssGetRunTimeParamInfo(S,0))->data);
/*
* Output acceleration = force / mass
*/
y1[0] = (*uPtrs[0]) / *mass;
}Lastly, the mdlTerminate method frees the memory allocated
for the run-time parameter in mdlSetWorkWidths.
/* Function: mdlTerminate ==========================================
* Abstract:
* Free the user data.
*/
static void mdlTerminate(SimStruct *S)
{
/* Free memory used to store the run-time parameter data*/
RunTimeDataType *mass = ssGetUserData(S);
if (mass != NULL) {
free(mass);
}
}To run the example, open the Simulink model:
Updating Run-Time Parameters
Whenever you change the values of S-function dialog parameters during simulation,
the Simulink engine invokes the S-function
method to validate the changes. If the changes are valid, the engine invokes the
S-function mdlCheckParameters
method at the beginning of the next time step. This method should update the
S-function run-time parameters to reflect the changes in the dialog
parameters.mdlProcessParameters
In a C S-function, update the run-time parameters using the method appropriate for how the run-time parameters were created, as described in the following sections.
Updating All Parameters at Once
In a C MEX S-function, if there is a one-to-one correspondence between the
S-function tunable dialog parameters and the run-time parameters, i.e., the
run-time parameters were registered using
ssRegAllTunableParamsAsRunTimeParams, the S-function can
use the SimStruct function to
accomplish this task. This function updates each run-time parameter to have the
same value as the corresponding dialog parameter. See ssUpdateAllTunableParamsAsRunTimeParamssfun_runtime1.c for an example.
Updating Parameters Individually
If there is not a one-to-one correspondence between the S-function dialog and
run-time parameters or the run-time parameters are transformed versions of the
dialog parameters, the mdlProcessParameters method must
update each parameter individually. Choose the method used to update the
run-time parameter based on how it was registered.
If you register a run-time parameter using
ssSetRunTimeParamInfo, the
mdlProcessParameters method uses ssUpdateRunTimeParamData to
update the run-time parameter, as shown in sfun_runtime2.c. This function updates the data field
in the parameter's attributes record, ssParamRec, with a new
value. You cannot directly modify the ssParamRec, even though
you can obtain a pointer to the ssParamRec using
ssGetRunTimeParamInfo.
If you register a run-time parameter using
ssRegDlgParamAsRunTimeParam, the
mdlProcessParameters method uses ssUpdateDlgParamAsRunTimeParam to update the run-time parameter,
as is shown in sfun_runtime3.c.
Updating Parameters as Functions of Multiple S-Function Parameters
If you register a run-time parameter as a function of multiple S-function
parameters, the mdlProcessParameters method uses ssUpdateRunTimeParamData to
update the run-time parameter.
The S-function sfun_runtime4.c provides an example. In this example,
the mdlProcessParameters method calculates a new value for
the run-time parameter and passes the value to the pointer of the run-time
parameter's memory location, which was allocated during the call to
mdlSetWorkWidths. The
mdlProcessParameters method then passes the updated
run-time parameter's pointer to
ssUpdateRunTimeParamData.
Tuning Run-Time Parameters
Tuning a dialog parameter tunes the corresponding run-time parameter during simulation and in code generated only if the dialog parameter meets the following conditions:
The S-function marks the dialog parameter as tunable, using
ssSetSFcnParamTunable.The dialog parameter is a MATLAB® array of values with a data type supported by the Simulink product.
Note that you cannot tune a run-time parameter whose value is a cell array or structure.
Accessing Run-Time Parameters
You can easily access run-time parameters from the S-function code. In order to access run-time parameter data, choose one of the following methods based on the data type.
If the data is of type
double:real_T *dataPtr = (real_T *) ssGetRunTimeParamInfo(S, #)->data;
If the parameter is complex, the real and imaginary parts of the data are interleaved. For example, if a user enters the following:
K = [1+2i, 3+4i; 5+6i, 7+8i]
the matrix that is generated is
K = 1+2i 3+4i 5+6i 7+8iThe memory for this matrix is laid out as
[1, 2, 5, 6, 3, 4, 7, 8]
To access a complex run-time parameter from the S-function code:
for (i = 0; i<width; i++) { real_T realData = dataPtr[(2*i)]; real_T imagData = dataPtr[(2*i)+1]; }
Note
Matrix elements are written out in column-major format. Real and imaginary values are interleaved.