S-Functions That Specify Port Scope and Reusability - MATLAB & Simulink (original) (raw)

You can use the following SimStruct macros in themdlInitializeSizes method to specify the scope and reusability of the memory used for your S-function's input and output ports:

You declare an input or output as local or global, and indicate its reusability, by passing one of the following four options to thessSetInputPortOptimOpts andssSetOutputPortOptimOpts macros:

Note

Marking an input or output port as a local variable does not imply that the code generator uses a local variable in the generated code. If your S-function accesses the inputs and outputs only in its mdlOutputs routine, the code generator declares the inputs and outputs as local variables. However, if the inputs and outputs are used elsewhere in the S-function, the code generator includes them in the global block input and output structure.

The reusability setting indicates if the memory associated with an input or output port can be overwritten. To reuse input and output port memory:

  1. Indicate the ports are reusable using either theSS_REUSABLE_AND_LOCAL orSS_REUSABLE_AND_GLOBAL option in thessSetInputPortOptimOpts andssSetOutputPortOptimOpts macros.
  2. Indicate the input port memory is overwritable usingssSetInputPortOverWritable.
  3. If your S-function has multiple input and output ports, usessSetOutputPortOverwritesInputPort to indicate which output and input ports share memory.

The following example shows how different scope and reusability settings affect the generated code. The following model contains an S-function block pointing to the C MEX S-function_`matlabroot`_/toolbox/simulink/simdemos/simfeatures/src/[sfun_directlook.c](https://mdsite.deno.dev/matlab:sfunddg%5Fcb%5Fedit%28'sfun%5Fdirectlook'%29;), which models a direct 1-D lookup table.

The S-function's mdlInitializeSizes method declares the input port as reusable, local, and overwritable and the output port as reusable and local, as follows:

static void mdlInitializeSizes(SimStruct S) { / snip */ ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL); ssSetInputPortOverWritable(S, 0, TRUE);

/* snip */ ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL);

/* snip */ }

The generated code for this model stores the input and output signals in a single local variable rtb_SFunction, as shown in the following output function:

static void sl_directlook_output(int_T tid) { /* local block i/o variables */ real_T rtb_SFunction[2];

/* Sin: '/Sine Wave' */ rtb_SFunction[0] = sin(((real_T)sl_directlook_DWork.counter[0] + sl_directlook_P.SineWave_Offset) * 2.0 * 3.1415926535897931E+000 / sl_directlook_P.SineWave_NumSamp) * sl_directlook_P.SineWave_Amp[0] + sl_directlook_P.SineWave_Bias; rtb_SFunction[1] = sin(((real_T)sl_directlook_DWork.counter[1] + sl_directlook_P.SineWave_Offset) * 2.0 * 3.1415926535897931E+000 / sl_directlook_P.SineWave_NumSamp) * sl_directlook_P.SineWave_Amp[1] + sl_directlook_P.SineWave_Bias;

/* S-Function Block: /S-Function */ { const real_T *xData = &sl_directlook_P.SFunction_XData[0]; const real_T *yData = &sl_directlook_P.SFunction_YData [0]; real_T spacing = xData[1] - xData[0]; if (rtb_SFunction[0] <= xData[0] ) { rtb_SFunction[0] = yData[0]; } else if (rtb_SFunction[0] >= yData[20] ) { rtb_SFunction[0] = yData[20]; } else { int_T idx = (int_T)( ( rtb_SFunction[0] - xData[0] ) / spacing ); rtb_SFunction[0] = yData[idx]; }

if (rtb_SFunction[1] <= xData[0] ) {
  rtb_SFunction[1] = yData[0];
} else if (rtb_SFunction[1] >= yData[20] ) {
  rtb_SFunction[1] = yData[20];
} else {
  int_T idx = (int_T)( ( rtb_SFunction[1] - xData[0] ) / spacing );
  rtb_SFunction[1] = yData[idx];
}

}

/* Outport: '/Out1' */ sl_directlook_Y.Out1[0] = rtb_SFunction[0]; sl_directlook_Y.Out1[1] = rtb_SFunction[1]; UNUSED_PARAMETER(tid); }

This table shows variations of the code generated for this model when using the generic real-time target (GRT). Each row explains a different setting for the scope and reusability of the S-function's input and output ports.

Scope and reusability S-function mdlInitializeSizes code Generated code
Inputs: Local, reusable, overwritableOutputs: Local, reusable ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL); ssSetInputPortOverWritable(S, 0, TRUE); ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL); The model.c file declares a local variable in the output function./* local block i/o variables */ real_T rtb_SFunction[2];
Inputs: Global, reusable, overwritableOutputs: Global, reusable ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_GLOBAL); ssSetInputPortOverWritable(S, 0, TRUE); ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_GLOBAL); The model.h file defines a block signals structure with a single element to store the S-function's input and output./* Block signals (auto storage) */ typedef struct { real_T SFunction[2]; } BlockIO_sl_directlook;The_model_.c file uses this element of the structure in calculations of the S-function's input and output signals. /* Sin: '/Sine Wave' */ sl_directlook_B.SFunction[0] = sin ... /* snip */ /*S-Function Block:/S-Function*/ { const real_T *xData = &sl_directlook_P.SFunction_XData[0]
Inputs: Local, not reusableOutputs: Local, not reusable ssSetInputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_LOCAL); ssSetInputPortOverWritable(S, 0, FALSE); ssSetOutputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_LOCAL); The model.c file declares local variables for the S-function's input and output in the output function/* local block i/o variables */ real_T rtb_SineWave[2]; real_T rtb_SFunction[2];
Inputs: Global, not reusableOutputs: Global, not reusable ssSetInputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_GLOBAL); ssSetInputPortOverWritable(S, 0, FALSE); ssSetOutputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_GLOBAL); The model.h file defines a block signal structure with individual elements to store the S-function's input and output./* Block signals (auto storage) */ typedef struct { real_T SineWave[2]; real_T SFunction[2]; } BlockIO_sl_directlook;The_model_.c file uses the different elements in this structure when calculating the S-function's input and output. /* Sin: '/Sine Wave' */ sl_directlook_B.SineWave[0] = sin ... /* snip */ /*S-Function Block:/S-Function*/ { const real_T *xData = &sl_directlook_P.SFunction_XData[0]

To check if the S-function input or output buffer reuse takes place, you can useLibBlockInputSignalBufferDstPort function.

See Also

Topics