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
.rtw
file, eliminating the need for the S-function to perform this task via anmdlRTW
method.
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 mdlSetWorkWidths
sfun_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
ssRegDlgParamAsRunTimeParam
to register a run-time parameter that corresponds to a single dialog parameter, even if there is a data type transformation, orssSetRunTimeParamInfo
to 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 ssUpdateAllTunableParamsAsRunTimeParams
sfun_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+8i
The 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.