Configure Symbolic Dimensions for S-Function Blocks - MATLAB & Simulink (original) (raw)

Main Content

To configure symbolic dimensions for S-function blocks, you can use the following C/C++ functions. You can configure S-functions to support forward propagation, backward propagation, or forward and backward propagation of symbolic dimensions during simulation.

Many of these functions return the variable SymbDimsId. ASymbDimsId is a unique integer value. This value corresponds to each symbolic dimension specification that you create or is the result of a mathematical operation that you perform with symbolic dimensions.

Generate Code from an S-Function Block with Dimension Variants

The model ex_msymbdims_sfcn_one contains an S-function that subtracts the symbolic dimension B from a symbolic input dimension, A + B. The model supports forward propagation because the symbolic dimensions of the output ports are set. The model does not support backward propagation of symbolic dimensions because the compiled symbolic dimensions of the input ports are not set.

model='ex_msymbdims_sfcn_one'; open_system(model);

The sfun_symbdims_sfcn_one.c file contains this code.

type sfun_symbdims_sfcn_one.c

/* Copyright 2024 The MathWorks, Inc. */ #define S_FUNCTION_NAME sfun_symbdims_sfcn_one #define S_FUNCTION_LEVEL 2

#include "simstruc.h"

#include <assert.h>

/* Function: mdlInitializeSizes ===============================================

ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);

if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortDirectFeedThrough(S, 0, 1);
ssSetInputPortDimensionInfo(S, 0, DYNAMIC_DIMENSION);
ssSetInputPortRequiredContiguous(S, 0, 1);

if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortDimensionInfo(S, 0, DYNAMIC_DIMENSION);   
ssSetNumSampleTimes(S, 1);

ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);

ssSetNumModes(S, 0);
ssSetNumNonsampledZCs( S, 0);

ssAllowSignalsWithMoreThan2D(S);

ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);

ssSetSymbolicDimsSupport(S, true);

}

/If underspecified for propagation, say i/o are scalars./ #if defined(MATLAB_MEX_FILE) #define MDL_SET_DEFAULT_PORT_DIMENSION_INFO static void mdlSetDefaultPortDimensionInfo(SimStruct *S) { if( (ssGetOutputPortWidth(S, 0) == DYNAMICALLY_SIZED) && (ssGetInputPortWidth(S, 0) == DYNAMICALLY_SIZED) ) { ssSetOutputPortMatrixDimensions(S, 0, 1, 1 ); } } #endif

#if defined(MATLAB_MEX_FILE) #define MDL_SET_INPUT_PORT_SYMBOLIC_DIMENSIONS static void mdlSetInputPortSymbolicDimensions(SimStruct* S, int_T portIndex, SymbDimsId symbDimsId) { assert(0 == portIndex); // Set the compiled input symbolic dimension. ssSetCompInputPortSymbolicDimsId(S, portIndex, symbDimsId); const SymbDimsId symbolId = ssRegisterSymbolicDimsString(S, "B"); const SymbDimsId outputDimsId = ssRegisterSymbolicDimsMinus(S, symbDimsId, symbolId); ssSetCompOutputPortSymbolicDimsId(S, portIndex, outputDimsId); } #endif

#if defined(MATLAB_MEX_FILE) #define MDL_SET_OUTPUT_PORT_SYMBOLIC_DIMENSIONS static void mdlSetOutputPortSymbolicDimensions(SimStruct *S, int_T portIndex, SymbDimsId symbDimsId) { assert(0 == portIndex); // The input dimensions are not set, so this S-function only // supports forward propagation. ssSetCompOutputPortSymbolicDimsId(S, portIndex, symbDimsId); } #endif

/* Function: mdlInitializeSampleTimes =========================================

*/ static void mdlInitializeSampleTimes(SimStruct S) { ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME); ssSetOffsetTime(S, 0, 0.0); ssSetModelReferenceSampleTimeDefaultInheritance(S);
} /
Function: mdlOutputs =======================================================

*/ static void mdlOutputs(SimStruct *S, int_T tid) { }

/* Function: mdlTerminate =====================================================

*/ static void mdlTerminate(SimStruct S) { UNUSED_ARG(S); / unused input argument */ }

#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? / #include "simulink.c" / MEX-file interface mechanism / #else #include "cg_sfun.h" / Code generation registration function */ #endif

The Simulink.Parameter objects A and B contain these definitions.

A = Simulink.Parameter; A.DataType = 'int32'; A.Value = 6; A.Min=5; A.Max=7; A.CoderInfo.StorageClass = 'Custom'; A.CoderInfo.CustomStorageClass = 'ImportedDefine'; A.CoderInfo.CustomAttributes.HeaderFile = 'ImportedDefinitions.h';

B = Simulink.Parameter; B.DataType = 'int32'; B.Value = 10; B.Min=9; B.Max=11; B.CoderInfo.StorageClass = 'Custom'; B.CoderInfo.CustomStorageClass = 'ImportedDefine'; B.CoderInfo.CustomAttributes.HeaderFile = 'ImportedDefinitions.h';

The ImportedDefinitions header file contains this code.

type ImportedDefinitions.h

/* Copyright 2024 The MathWorks, Inc. */ #ifndef IMPORTEDDEFINITIONS_H #define IMPORTEDDEFINITIONS_H #define A 6 #define B 10 #endif

In the Configuration Parameters dialog box, the Custom Code pane contains the #include "ImportedDefinitions.h" statement.

The sfun_symbdims_sfcn_one S-function is inlined, so a TLC file with this code must be present on the path with the model and other supporting files.

type sfun_symbdims_sfcn_one.tlc

%implements "sfun_symbdims_sfcn_one" "C"

%% Enabling Enhanced TLC Block Interface =================================== %function BlockInstanceSetup(block, system) void %<LibEnableBlockFcnOptimizations(block)> %endfunction

%% Function: BlockOutputSignal ================================================= %function BlockOutputSignal(block,system,portIdx,ucv,lcv,idx,retType) void %endfunction

%% Function: Outputs =========================================================== %% %function Outputs(block, system) Output

%assign rollVars = ["U", "Y"] %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars %% %assign u = LibBlockInputSignal( 0, "", lcv, idx) %assign y = LibBlockOutputSignal(0, "", lcv, idx)

%<y> = %<u>;
                                                  

%endroll

%endfunction %% Outputs

To generate a MEX function, at the command-line, enter this command:

mex sfun_symbdims_sfcn_one.c

Building with 'gcc'. MEX completed successfully.

Generate code for the model.

currentDir=pwd; slbuild(model);

Searching for referenced models in model 'ex_msymbdims_sfcn_one'.

Total of 1 models to build.

Starting build procedure for: ex_msymbdims_sfcn_one

Successful completion of build procedure for: ex_msymbdims_sfcn_one

Build Summary

Top model targets:

Model Build Reason Status Build Duration

ex_msymbdims_sfcn_one Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 6.3329s

1 of 1 models built (0 models already up to date) Build duration: 0h 0m 6.5743s

View the generated code for the model. The ex_msymbdims_sfcn_one_step function contains this code. The S-function code is set inline and the symbolic dimensions A and B are in the generated code.

cfile=fullfile(currentDir, 'ex_msymbdims_sfcn_one_ert_rtw','ex_msymbdims_sfcn_one.c'); coder.example.extractLines(cfile,'/* Model step', '/* Model initialize', 1, 0);

/* Model step function */ void ex_msymbdims_sfcn_one_step(void) { int32_T i;

/* Gain: '/Gain' incorporates:

/* End of Gain: '/Gain' */

/* Gain: '/Gain2' incorporates:

/* End of Gain: '/Gain2' */

/* S-Function (sfun_symbdims_sfcn_one): '/Minus' incorporates:

Close the model

S-Function That Supports Forward and Backward Propagation of Symbolic Dimensions

This S-function transposes two symbolic dimensions. It supports forward and backward propagation of symbolic dimensions because the compiled symbolic dimension of both the input and output ports are set.

static void mdlInitializeSizes(SimStruct *S) { // Enable symbolic dimensions for the s-function. ssSetSymbolicDimsSupport(S, true); }

#if defined(MATLAB_MEX_FILE) #define MDL_SET_INPUT_PORT_SYMBOLIC_DIMENSIONS static void mdlSetInputPortSymbolicDimensions(SimStruct* S, int_T portIndex, SymbDimsId symbDimsId) { assert(0 == portIndex);

ssSetCompInputPortSymbolicDimsId(S,  portIndex, symbDimsId);

assert(2U == ssGetNumSymbolicDims(S, symbDimsId));

if (SL_INHERIT == 
    ssGetCompOutputPortSymbolicDimsId(S, portIndex)) {

    const SymbDimsId idVec[] = {
        ssGetSymbolicDim(S, symbDimsId, 1),
        ssGetSymbolicDim(S, symbDimsId, 0)};
    // Register the transposed dimensions.
   // Set the output symbolic dimension to the resulting id.

const SymbDimsId outputDimsId = ssRegisterSymbolicDims(S, idVec, 2U);

    ssSetCompOutputPortSymbolicDimsId(S, portIndex, 
       outputDimsId);
}

} #endif

#if defined(MATLAB_MEX_FILE) #define MDL_SET_OUTPUT_PORT_SYMBOLIC_DIMENSIONS static void mdlSetOutputPortSymbolicDimensions(SimStruct *S, int_T portIndex, SymbDimsId symbDimsId) { assert(0 == portIndex); ssSetCompOutputPortSymbolicDimsId(S, portIndex, symbDimsId);

assert(2U == ssGetNumSymbolicDims(S, symbDimsId));

if (SL_INHERIT == 
    ssGetCompInputPortSymbolicDimsId(S, portIndex)) {

    const SymbDimsId idVec[] = {
        ssGetSymbolicDim(S, symbDimsId, 1),
        ssGetSymbolicDim(S, symbDimsId, 0)};
    const SymbDimsId inputDimsId = 
        ssRegisterSymbolicDims(S, idVec, 2U);
    // Register the transposed dimensions.
   // Set the input symbolic dimension to the resulting id.
    ssSetCompInputPortSymbolicDimsId(S, portIndex, inputDimsId);
}

} #endif

See Also

Topics