Input and Output Ports
Creating Input Ports for C S-Functions
To create and configure input ports, the mdlInitializeSizes
method should
first specify the number of S-function input ports, using
ssSetNumInputPorts
. Then, for each input port, the method
should specify
The dimensions of the input port (see Initializing Input Port Dimensions)
If you want your S-function to inherit its dimensionality from the port to which it is connected, you should specify that the port is dynamically sized in
mdlInitializeSizes
(see Sizing an Input Port Dynamically).Whether the input port allows scalar expansion of inputs (see Scalar Expansion of Inputs)
Whether the input port has direct feedthrough, using
ssSetInputPortDirectFeedThrough
A port has direct feedthrough if the input is used in either the
mdlOutputs
ormdlGetTimeOfNextVarHit
functions. The direct feedthrough flag for each input port can be set to either1=yes
or0=no
. It should be set to 1 if the input,u
, is used in themdlOutputs
ormdlGetTimeOfNextVarHit
routine. Setting the direct feedthrough flag to 0 tells the Simulink® engine thatu
is not used in either of these S-function routines. Violating this leads to unpredictable results.The data type of the input port, if not the default
double
Use
to set the input port's data type. If you want the data type of the port to depend on the data type of the port to which it is connected, specify the data type asssSetInputPortDataType
DYNAMICALLY_TYPED
. In this case, you must provide implementations of the
andmdlSetInputPortDataType
methods to enable the data type to be set correctly during signal propagation.mdlSetDefaultPortDataTypes
The numeric type of the input port, if the port accepts complex-valued signals
Use
to set the input port's numeric type. If you want the numeric type of the port to depend on the numeric type of the port to which it is connected, specify the numeric type asssSetInputPortComplexSignal
COMPLEX_INHERITED
. In this case, you must provide implementations of the
andmdlSetInputPortComplexSignal
methods to enable the numeric type to be set correctly during signal propagation.mdlSetDefaultPortComplexSignals
You can configure additional input port properties using other S-function macros. See Input and Output Ports in the “SimStruct Macros and Functions Listed by Usage” section for more information.
Note
The mdlInitializeSizes
method must specify the number of
ports before setting any properties. If it attempts to set a property of a port
that doesn't exist, it is accessing invalid memory and a segmentation violation
occurs.
Initializing Input Port Dimensions
You can set input port dimensions using one of the following macros:
If the input signal must be one-dimensional and the input port width is
w
, usessSetInputPortWidth
(S, inputPortIdx, w)If the input signal must be a matrix of dimension
m
-by-n
, usessSetInputPortMatrixDimensions
(S, inputPortIdx, m, n)Otherwise, if the input signal can have either one or two dimensions, use
ssSetInputPortDimensionInfo
(S, inputPortIdx, dimsInfo)You can use this function to fully or partially initialize the port dimensions (see next section).
Sizing an Input Port Dynamically
If your S-function does not require that its input signals have specific dimensions, you can set the dimensionality of the input ports to match the dimensionality of the signals connected to them.
To dynamically dimension an input port:
Specify some or all of the dimensions of the input port as dynamically sized in
mdlInitializeSizes
.If the input port can accept a signal of any dimensionality, use
ssSetInputPortDimensionInfo(S, inputPortIdx, DYNAMIC_DIMENSION)
to set the dimensionality of the input port.
If the input port can accept only vector (1-D) signals but the signals can be of any size, use
ssSetInputPortWidth(S, inputPortIdx, DYNAMICALLY_SIZED)
to specify the dimensionality of the input port.
If the input port can accept only matrix signals but can accept any row or column size, use
ssSetInputPortMatrixDimensions(S, inputPortIdx, DYNAMICALLY_SIZED, DYNAMICALLY_SIZED)
Provide an
method that sets the dimensions of the input port to the size of the signal connected to it.mdlSetInputPortDimensionInfo
The Simulink engine invokes this method during signal propagation when it has determined the dimensionality of the signal connected to the input port.
Provide an
mdlSetDefaultPortDimensionInfo
method that sets the dimensions of the block's ports to a default value. Seesfun_dynsize.c
for an example that implements this macro.The engine invokes this method during signal propagation when it cannot determine the dimensionality of the signal connected to some or all of the block's input ports. This can happen, for example, if an input port is unconnected. If the S-function does not provide this method, the signal propagation routine sets the dimension of the block's ports to 1-D scalar.
Example: Defining Multiple S-Function Input Ports
The following code in mdlInitializeSizes
configures an
S-function with two input ports. See Input and Output Ports in the “SimStruct Macros and Functions
Listed by Usage” section for more information on the macros used in this
example.
if (!ssSetNumInputPorts(S, 2)) return; for (i = 0; i < 2; i++) { /* Input has direct feedthrough */ ssSetInputPortDirectFeedThrough(S, i, 1); /* Input is a real signal */ ssSetInputPortComplexSignal(S, i, COMPLEX_NO); /* Input is a dynamically sized 2-D matrix */ ssSetInputPortMatrixDimensions(S ,i, DYNAMICALLY_SIZED, DYNAMICALLY_SIZED); /* Input inherits its sample time */ ssSetInputPortSampleTime(S, i,INHERITED_SAMPLE_TIME); /* Input signal must be contiguous */ ssSetInputPortRequiredContiguous(S, i, 1); /* The input port cannot share memory */ ssSetInputPortOverWritable(S, i, 0); }
During signal propagation, the Simulink engine calls this S-function's
mdlSetInputPortDimensionInfo
macro to initialize the
input port dimensions. In this example,
mdlSetInputPortDimensionInfo
sets the input dimensions to
the candidate dimensions passed to the macro by the engine.
#if defined(MATLAB_MEX_FILE) #define MDL_SET_INPUT_PORT_DIMENSION_INFO static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) { if(!ssSetInputPortDimensionInfo(S, port, dimsInfo)) return; } #endif
For an example that configures an S-function with multiple input and output
ports, open the Simulink model sfcndemo_sfun_multiport
and inspect the S-function
sfun_multiport.c
.
Creating Output Ports for C S-Functions
To create and configure output ports, the mdlInitializeSizes
method should
first specify the number of S-function output ports, using
ssSetNumOutputPorts
. Then, for each output port, the method
should specify
Dimensions of the output port
You can set output port dimensions using one of the following macros:
If you want the port's dimensions to depend on block connectivity, set the dimensions to
DYNAMIC_DIMENSIONS
when usingssSetOutputPortDimensionInfo
or toDYNAMICALLY_SIZED
for all other macros. The S-function must then provide
andmdlSetOutputPortDimensionInfo
methods to ensure that output port dimensions are set to the correct values in code generation.mdlSetDefaultPortDimensionInfo
Data type of the output port
Use
to set the output port's data type. If you want the data type of the port to depend on block connectivity, specify the data type asssSetOutputPortDataType
DYNAMICALLY_TYPED
. In this case, you must provide implementations of the
andmdlSetOutputPortDataType
methods to enable the data type to be set correctly during signal propagation.mdlSetDefaultPortDataTypes
The numeric type of the output port, if the port outputs complex-valued signals
Use
to set the output port's numeric type. If you want the numeric type of the port to depend on the numeric type of the port to which it is connected, specify the numeric type asssSetOutputPortComplexSignal
COMPLEX_INHERITED
. In this case, you must provide implementations of the
andmdlSetOutputPortComplexSignal
methods to enable the numeric type to be set correctly during signal propagation.mdlSetDefaultPortComplexSignals
See Creating Input Ports for C S-Functions for an example showing how to initialize an S-function input port. You use the same procedure to initialize the S-function output ports, but with the corresponding output port macro.
Scalar Expansion of Inputs
Scalar expansion of inputs refers conceptually to the process of expanding scalar input signals to the same dimensions as wide input signals connected to other S-function input ports. This is done by setting each element of the expanded signal to the value of the scalar input.
A Level-2 MATLAB® S-function uses the default scalar expansion rules if the input and output ports are specified as dynamically sized (see Scalar Expansion of Inputs and Parameters in Using Simulink).
With scalar expansion on, the S-function mdlInitializeSizes
method should specify that the input and output ports are dynamically sized. The
Simulink engine uses a default method to set the dimensions of the input and
output ports. If the block has more than two inputs, the input signals can be scalar
or wide signals, where the wide signals all have the same number of elements. In
this case, the engine sets the dimensions of the output ports to the width of the
wide input signals and expands any scalar inputs to this width. If the wide inputs
are driven by 1-D and 2-D vectors, the output is a 2-D vector signal, and the scalar
inputs are expanded to a 2-D vector signal.
If scalar expansion is not on, the engine assumes that all ports (input and output ports) must have the same dimensions, and it sets all port dimensions to the same dimensions specified by one of the driving blocks.
Note
The engine ignores the scalar expansion option if the S-function specifies or
controls the dimensions of its input and output ports either by initializing the
dimensions in mdlInitializeSizes
, using mdlSetInputPortWidth
and
mdlSetOutputPortWidth
, or
using mdlSetInputPortDimensionInfo
,
mdlSetOutputPortDimensionInfo
,
and mdlSetDefaultPortDimensionInfo
.
The best way to understand how to use scalar expansion is to consider the example
sfcndemo_sfun_multiport
. This model contains three
S-function blocks, each with multiple input ports. The S-function sfun_multiport.c
used in these blocks sets the
SS_OPTION_ALLOW_INPUT_SCALAR_EXPANSION
option in its
mdlInitializeSizes
method, allowing scalar expansion of the
inputs. The S-function specifies that its inputs and outputs are dynamically sized.
Therefore, during signal propagation, the engine sets the width of the input ports
to the width of the signal connected to the port, and the width of the output ports
to the width of any wide input signal. The mdlOutputs
method
performs an element-by-element sum on the input signals, expanding any scalar
inputs, as needed.
/* Calculate an element-by-element sum of the input signals. yWidth is the width of the output signal. */ for (el = 0; el < yWidth; el++) { int_T port; real_T sum = 0.0; for (port = 0; port < nInputPorts; port++) { /* Get the input signal value */ InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,port); if (el < ssGetInputPortWidth(S,port)) { /* Input is a wide signal. Use specific element */ sum = sum + ((real_T)signs[port] * (*uPtrs[el])); } else { /* Use the scalar value to expand the signal */ sum = sum + ((real_T)signs[port] * (*uPtrs[0])); } } }
Masked Multiport S-Functions
If you are developing masked multiport S-function blocks whose number of ports varies based on some parameter, and want to place them in a Simulink library, you must specify that the mask modifies the appearance of the block. To do this, execute the command
set_param(blockname,'MaskSelfModifiable','on')
at the MATLAB command prompt before saving the library, where blockname
is the full path to the block. Failure to specify that the mask modifies the appearance of the block means that an instance of the block in a model reverts to the number of ports in the library whenever you load the model or update the library link.