Writing S-Functions    

Work Vectors

If your S-function needs persistent memory storage, use S-function work vectors instead of static or global variables. If you use static or global variables, they are used by multiple instances of your S-function. This occurs when you have multiple S-Function blocks in a Simulink model and the same S-function C MEX-file has been specified. The ability to keep track of multiple instances of an S-function is called reentrancy.

You can create an S-function that is reentrant by using work vectors. These are persistent storage locations that Simulink manages for an S-function. Integer, floating-point (real), pointer, and general data types are supported. The number of elements in each vector can be specified dynamically as a function of the number of inputs to the S-function.

Work vectors have several advantages:

For example, suppose you'd like to track the previous value of each input signal element entering input port 1 of your S-function. Either the discrete-state vector or the real-work vector could be used for this, depending upon whether the previous value is considered a discrete state (that is, compare the unit delay and the memory block). If you do not want the previous value to be logged when states are saved, use the real-work vector, rwork. To do this, in mdlInitializeSizes specify the length of this vector by using ssSetNumRWork. Then in either mdlStart or mdlInitializeConditions, initialize the rwork vector ssGetRWork. In mdlOutputs, you can retrieve the previous inputs by using ssGetRWork. In mdlUpdate, update the previous value of the rwork vector by using ssGetInputPortRealSignalPtrs.

Use the macros in this table to specify the length of the work vectors for each instance of your S-function in mdlInitializeSizes.

Table 7-1: Macros Used in Specifying Vector Widths  
Macro
Description
ssSetNumContStates
Width of the continuous-state vector
ssSetNumDiscStates
Width of the discrete-state vector
ssSetNumDWork
Width of the data type work vector
ssSetNumRWork
Width of the real-work vector
ssSetNumIWork
Width of the integer-work vector
ssSetNumPWork
Width of the pointer-work vector
ssSetNumModes
Width of the mode-work vector
ssSetNumNonsampledZCs
Width of the nonsampled zero-crossing vector

Specify vector widths in mdlInitializeSizes. There are three choices:

If the default behavior of dynamically sized vectors does not meet your needs, use mdlSetWorkWidths and the macros listed in Table 7-1, Macros Used in Specifying Vector Widths, to set the sizes of the work vectors explicitly. mdlSetWorkWidths also allows you to set your work vector lengths as functions of the block sample time and/or port widths.

The continuous states are used when you have a state that needs to be integrated by one of Simulink's solvers. When you specify continuous states, you must return the states' derivatives in mdlDerivatives. The discrete state vector is used to maintain state information that changes at fixed intervals. Typically the discrete state vector is updated in place in mdlUpdate.

The integer, real, and pointer work vectors are storage locations that are not logged by Simulink during simulations. They maintain persistent data between calls to your S-function.


  Synchronizing Multirate S-Function Blocks Work Vectors and Zero Crossings