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
ssSetInputPortDirectFeedThroughA port has direct feedthrough if the input is used in either the
mdlOutputsormdlGetTimeOfNextVarHitfunctions. The direct feedthrough flag for each input port can be set to either1=yesor0=no. It should be set to 1 if the input,u, is used in themdlOutputsormdlGetTimeOfNextVarHitroutine. Setting the direct feedthrough flag to 0 tells the Simulink® engine thatuis 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
doubleUse
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 asssSetInputPortDataTypeDYNAMICALLY_TYPED. In this case, you must provide implementations of theandmdlSetInputPortDataTypemethods to enable the data type to be set correctly during signal propagation.mdlSetDefaultPortDataTypesThe 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 asssSetInputPortComplexSignalCOMPLEX_INHERITED. In this case, you must provide implementations of theandmdlSetInputPortComplexSignalmethods 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.mdlSetInputPortDimensionInfoThe Simulink engine invokes this method during signal propagation when it has determined the dimensionality of the signal connected to the input port.
Provide an
mdlSetDefaultPortDimensionInfomethod that sets the dimensions of the block's ports to a default value. Seesfun_dynsize.cfor 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_DIMENSIONSwhen usingssSetOutputPortDimensionInfoor toDYNAMICALLY_SIZEDfor all other macros. The S-function must then provideandmdlSetOutputPortDimensionInfomethods to ensure that output port dimensions are set to the correct values in code generation.mdlSetDefaultPortDimensionInfoData 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 asssSetOutputPortDataTypeDYNAMICALLY_TYPED. In this case, you must provide implementations of theandmdlSetOutputPortDataTypemethods to enable the data type to be set correctly during signal propagation.mdlSetDefaultPortDataTypesThe 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 asssSetOutputPortComplexSignalCOMPLEX_INHERITED. In this case, you must provide implementations of theandmdlSetOutputPortComplexSignalmethods 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.