Use symbolic dimensions to simulate various sets of dimension choices without regenerating code for every set. Set up your model with dimensions that you specify as symbols in blocks and data objects. These symbols propagate throughout the model during simulation, and then go into the generated code. Modeling constraints for symbols during simulation (for example, C=A+B
) are output as preprocessor conditionals in either the model.h
or the model
_
types.h
file.
You can directly specify dimension information as a symbol or a numeric constant for these blocks and data objects:
Inport
Outport
Signal Specification
Data Store Memory
Interpreted MATLAB Function
Simulink.Signal
Simulink.Parameter
Simulink.BusElement
AUTOSAR.Parameter
The Data Store Memory and Interpreted MATLAB Function blocks also support variable dimension signals. For these blocks, the symbolic dimensions control the maximum allowed size.
You must provide the initialization code for Simulink.Parameter
objects that contain symbolic dimensions. To prevent the generated code from initializing these parameters, you must either:
Configure the parameters to use a storage class with the Data scope property set to Imported
, such as the ImportedExtern
or ImportedExternPointer
built-in storage classes.
Configure the parameters to use a storage class with the Data initialization property set to None
.
You use Simulink.Parameter
objects to specify dimension information as symbols. For more information on signal dimensions, see Determine Signal Dimensions.
You must fix symbolic dimension values at compile-time. You can not resolve a symbolic dimension to another variable and then vary it during run-time because you define the behavior during simulation.
Note: The dimension variants feature is on by default. You can turn off this feature by clearing the Allow symbolic dimension specification parameter in the Configuration Parameters dialog box.
Define Symbolic Dimensions
This example uses the model rtwdemo_dimension_variants
to show how to implement symbolic dimensions. This model has four modeling patterns involving vectors and matrices.
To show block names, on the Debug tab, on the Information Overlays menu, clear the Hide Automatic Block Names parameter.
Open the Embedded Coder app. In the C Code tab, select Code Interface > Individual Element Code Mappings.
In the Code Mappings editor, on the Parameters tab, click the refresh button. Seven Simulink.Parameter
objects appear. Four of these objects are for specifying symbolic dimensions. These Simulink.Parameter
objects have the names A
, B
, C
, and D
. Notice that these parameters have a storage class of CompilerFlag
.
To use a Simulink.Parameter
object for dimension specification, it must be defined in the base workspace and have one of these storage classes:
Define
or ImportedDefine
with header file specified
CompilerFlag
User-defined custom storage class that defines data as a macro in a specified header file
For Simulink.Parameter
objects with an ImportedDefine
custom storage class, provide a header file on the MATLAB path. Insert the name of the header file in the HeaderFile field in the Simulink.Parameter dialog box.
You can use MATLAB expressions to specify symbolic dimensions. For a list of supported MATLAB expressions, see the section Operators and Operands in Variant Condition Expressions in Introduction to Variant Controls.
Specify Symbolic Dimensions for Blocks and Data Objects
Click Inport Block In2
. On the Property Inspector, on the Parameters tab, the Port Dimensions field contains the Simulink.Parameter
object A
. For Inport blocks, you specify symbolic dimensions in the Port Dimensions field.
Click Inport block In3
. The Port Dimensions field contains the Simulink.Parameter
object B
.
Click the Constant block. The Constant value parameter has a value of Data
. In the Code Mappings editor, on the Parameters tab, click the Simulink.Parameter
object Data
. On the Property Inspector, the Dimension field has the character vector '[1,C]'
, which is equivalent to '[1,5]'
because C
has a value of 5
. The Value field contains an array with 5
values, which is consistent with its dimensions. The dimensions of the data object must be consistent with the value of the Simulink.Parameter
object that is in the Dimensions field. Notice that Data
has a Storage class of ImportedExtern
.
Open the 1-D Lookup Table1
block parameters dialog box. The Table data field contains the Simulink.Parameter
, PT
. The Breakpoints 1 field contains the Simulink.Parameter
, PB
.
In the Code Mappings editor, click PB
and PT
and view their properties. These parameters contain the character vector '[1,D]'
in their Dimensions field and are arrays consisting of 15 values. The value of D
is consistent with the dimension of the PB
and PT
parameters because D
has a value of 15
.
Simulate the model. Simulink propagates the dimensions symbolically in the diagram. During propagation, Simulink establishes modeling constraints among symbols. Simulink then checks for consistency with these constraints based on current numerical assignments. One modeling constraint for rtwdemo_dimension_variants
is that C=A+B
. The Diagnostic Viewer produces a warning for any violations of constraints.
Change the dimension specification to a different configuration and simulate the model again.
Though not shown in this example, you can specify an n-D dimension expression with one or more of the dimensions being a symbol (for example, '[A,B,C]'
or '[1,A,3]'
).
Generate Code for a Model with Dimension Variants
Once you have verified dimension specifications through model simulation, generate code for rtwdemo_dimension_variants
.
Create a temporary folder for the build and inspection process.
currentDir = pwd; [~,cgDir] = rtwdemodir();
Build the model.
model='rtwdemo_dimension_variants';
rtwbuild(model)
### Starting build procedure for: rtwdemo_dimension_variants ### Successful completion of build procedure for: rtwdemo_dimension_variants Build Summary Top model targets built: Model Action Rebuild Reason =========================================================================================================== rtwdemo_dimension_variants Code generated and compiled Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 14.241s
View the generated code. In the rtwdemo_dimension_variants.h
file, symbolic dimensions are in data declarations.
hfile = fullfile(cgDir,'rtwdemo_dimension_variants_ert_rtw',... 'rtwdemo_dimension_variants.h'); rtwdemodbtype(hfile,'/* External inputs', '/* Real-time', 1, 0);
/* External inputs (root inport signals with default storage) */ typedef struct { real_T In2[A]; /* '<Root>/In2' */ real_T In3[B]; /* '<Root>/In3' */ } ExtU; /* External outputs (root outports fed by signals with default storage) */ typedef struct { real_T Out1[(A + B)]; /* '<Root>/Out1' */ real_T Out2[(A + B)]; /* '<Root>/Out2' */ } ExtY;
The rtwdemo_dimension_variants.h
file contains data definitions and preprocessor conditionals that define constraints established among the symbols during simulation. One of these constraints is that the value of a symbolic dimension must be greater than 1
. This file also includes the user-provided header file for any Simulink.Parameter
objects with an ImportedDefine
custom storage class.
hfile = fullfile(cgDir,'rtwdemo_dimension_variants_ert_rtw',... 'rtwdemo_dimension_variants.h'); rtwdemodbtype(hfile,'#ifndef A', '/* Macros for accessing', 1, 0);
#ifndef A #error The variable for the parameter "A" is not defined #endif #ifndef B #error The variable for the parameter "B" is not defined #endif #ifndef C #error The variable for the parameter "C" is not defined #endif #ifndef D #error The variable for the parameter "D" is not defined #endif /* * Constraints for division operations in dimension variants */ #if (1 == 0) || (((A+B) % 1) != 0) # error "The preprocessor definition '1' must not be equal to zero and the division of '(A+B)' by '1' must not have a remainder." #endif /* * Registered constraints for dimension variants */ /* Constraint 'C == (A+B)' registered by: * '<Root>/1-D Lookup Table1' */ #if C != (A+B) # error "The preprocessor definition 'C' must be equal to '(A+B)'" #endif #if A <= 1 # error "The preprocessor definition 'A' must be greater than '1'" #endif #if B <= 1 # error "The preprocessor definition 'B' must be greater than '1'" #endif /* Constraint 'D > 1' registered by: * '<Root>/1-D Lookup Table1' */ #if D <= 1 # error "The preprocessor definition 'D' must be greater than '1'" #endif /* Constraint 'C > 1' registered by: * '<S2>/Assignment' */ #if C <= 1 # error "The preprocessor definition 'C' must be greater than '1'" #endif #if A >= 11 # error "The preprocessor definition 'A' must be less than '11'" #endif #if B >= 11 # error "The preprocessor definition 'B' must be less than '11'" #endif /* Constraint 'D < 21' registered by: * '<Root>/1-D Lookup Table1' */ #if D >= 21 # error "The preprocessor definition 'D' must be less than '21'" #endif /* Constraint 'C < 11' registered by: * '<S2>/Assignment' */ #if C >= 11 # error "The preprocessor definition 'C' must be less than '11'" #endif
In the rtwdemo_dimension_variants.c
file, symbolic dimensions participate in loop bound calculations, array size and index offset calculations, and a parameterized utility function (for example, Lookup Table block) calculation.
cfile = fullfile(cgDir,'rtwdemo_dimension_variants_ert_rtw',... 'rtwdemo_dimension_variants.c'); rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */ void rtwdemo_dimension_variants_step(void) { real_T rtb_VectorConcatenate[A + B]; real_T rtb_VectorConcatenate_m; int32_T ForEach_itr; int32_T i; int32_T s2_iter; /* Gain: '<Root>/Gain' incorporates: * Inport: '<Root>/In2' */ for (ForEach_itr = 0; ForEach_itr <= (int32_T)(A - 1); ForEach_itr++) { rtb_VectorConcatenate[ForEach_itr] = 2.0 * rtU.In2[ForEach_itr]; } /* End of Gain: '<Root>/Gain' */ /* Gain: '<Root>/Gain1' incorporates: * Inport: '<Root>/In3' */ for (ForEach_itr = 0; ForEach_itr <= (int32_T)(B - 1); ForEach_itr++) { rtb_VectorConcatenate[(int32_T)(A + ForEach_itr)] = 3.0 * rtU.In3[ForEach_itr]; } /* End of Gain: '<Root>/Gain1' */ /* Outputs for Iterator SubSystem: '<Root>/For Each Subsystem' incorporates: * ForEach: '<S1>/For Each' */ for (ForEach_itr = 0; ForEach_itr <= (int32_T)((int32_T)(A + B) - 1); ForEach_itr++) { /* Sum: '<Root>/Add' incorporates: * Constant: '<Root>/Constant' * Lookup_n-D: '<Root>/1-D Lookup Table1' */ rtb_VectorConcatenate_m = rtb_VectorConcatenate[ForEach_itr] + look1_binlx (Data[ForEach_itr], PB, PT, (uint32_T)((uint32_T)D - 1U)); /* ForEachSliceAssignment generated from: '<S1>/Out1' incorporates: * MATLAB Function: '<S1>/MATLAB Function' */ /* MATLAB Function 'For Each Subsystem/MATLAB Function': '<S3>:1' */ /* '<S3>:1:4' y = 2*u; */ rtY.Out1[ForEach_itr] = 2.0 * rtb_VectorConcatenate_m; /* Sum: '<Root>/Add' */ rtb_VectorConcatenate[ForEach_itr] = rtb_VectorConcatenate_m; } /* End of Outputs for SubSystem: '<Root>/For Each Subsystem' */ /* Outputs for Iterator SubSystem: '<Root>/For Iterator Subsystem' incorporates: * ForIterator: '<S2>/For Iterator' */ /* Constant: '<Root>/Constant1' */ ForEach_itr = ((int32_T)A); if (((int32_T)A) < 0) { ForEach_itr = 0; } /* End of Constant: '<Root>/Constant1' */ for (s2_iter = 0; s2_iter < ForEach_itr; s2_iter++) { /* Assignment: '<S2>/Assignment' incorporates: * Constant: '<S2>/Constant' * Outport: '<Root>/Out2' * Product: '<S2>/Product' * Selector: '<S2>/Selector' */ if (s2_iter == 0) { for (i = 0; i <= (int32_T)((int32_T)(A + B) - 1); i++) { rtY.Out2[i] = rtb_VectorConcatenate[i]; } } rtY.Out2[s2_iter] = rtb_VectorConcatenate[s2_iter] * 2.0; /* End of Assignment: '<S2>/Assignment' */ } /* End of Outputs for SubSystem: '<Root>/For Iterator Subsystem' */ }
Close the model and code generation report.
bdclose(model) rtwdemoclean; cd(currentDir)
When you specify the dimensions of a parameter in a model by using a symbol, you must make sure that the parameter value is consistent with the dimension value. To simulate different choices for the dimension value, you must manually correct the parameter value.
For example, in the rtwdemo_dimension_variants
model , the
Simulink.Parameter
object Data
stores a vector value,
[1 2 3 4 5]
, and uses a symbolic dimension C
with
initial value 5
. If you change the value of C
, to
simulate the model, you must make sure the number of elements in the vector value matches
the new value of C
.
To reduce the effort of maintenance when you change the value of C
,
you can set the value of Data
to an expression involving
C
.
Open the model.
rtwdemo_dimension_variants
At the command prompt, inspect the initial values of Data
and
C
. The value of Data
is a vector of integers
from 1
to C
.
Data.Value
ans = 1 2 3 4 5
C.Value
ans = 5
In MATLAB® code syntax, the value of Data
is
1:C
. To preserve this relationship between the parameter objects,
set the value of Data
by using the slexpr
function.
Data.Value = slexpr('1:C');
To prevent data type propagation errors, set the data type of
Data
explicitly to double
, which is the data
type that the parameter acquired before you set the parameter value to an
expression.
Data.DataType = 'double';
Set the value of C
to a different number, such as
6
. Due to dimension constraints in the model, you must set the
value of another dimension symbol, A
, to
3
.
C.Value = 6; A.Value = 3;
Simulate the model. The block diagram shows that the value of
Data
now has six elements.
For more complicated applications, you can write your own MATLAB function that returns parameter values based on dimension symbols. Set the value of the parameter data to an expression that calls your function.
For general information about using an expression to set the value of a
Simulink.Parameter
object, see Set Variable Value by Using a Mathematical Expression.
When you create a model with symbolic dimensions, be aware of the following optimization considerations:
The code generator reuses buffers only if dimension propagation establishes equivalence among buffers.
Two loops with symbolic loop bound calculations are fused together only if they share equivalent symbolic expression.
Optimizations do not eliminate a symbolic expression or condition check based on the current value of a symbolic dimension.
If an existing model uses Simulink.Parameter
objects to specify dimensions,
it can be incompatible with dimension variants. Here are two common scenarios:
Only a subset of blocks accepts symbolic dimension specifications. If a block is not compatible with symbolic dimensions, it causes an update diagram error.
Simulink.Parameter
objects that you use to define symbolic dimensions or have
symbolic dimensions must have one of the storage classes described in this example. If
these specifications are not met, the build procedure for the model fails during code
generation.
You can address these backward compatibility issues by doing the following:
Turn off dimension variants feature by clearing the Allow symbolic dimension specification parameter in the Configuration Parameters dialog box.
Update Simulink.Parameter
objects that define symbolic dimensions or have
symbolic dimension specifications.
Update the model so that only supported blocks have symbolic dimensions or propagate symbolic dimensions.
For a list of supported blocks, see the Block Support Table.
To access the information in this table, enter showblockdatatypetable
at
the MATLAB command prompt. Unsupported blocks (for example, MATLAB
Function) can still work in a model containing symbolic dimensions
as long as these blocks do not directly interact with symbolic dimensions.
In the following cases, supported blocks do not propagate symbolic dimensions.
For Assignment and Selector blocks, you set the Block Parameters > Index Option parameter to Index vector (dialog)
. For
Selector and Assignment blocks, if you specify a
symbolic dimension for the Index parameter, the code generator does not honor the
symbolic dimension in the generated code.
For the Product block, you specify a value of 1
for the Block Parameters > Number of inputs parameter, and you set the Multiply over parameter to
Specified dimensions
.
For the ForEach block, you specify a symbolic dimension for the Partition Width parameter.
Note that the following modeling patterns are among those modeling patterns that can cause Simulink to error out:
For Switch blocks, an input signal or the Threshold parameter has symbolic dimensions, and you select Allow different data input sizes (Results in variable-size output signal).
A Data Store Read block selects elements
of a Simulink.Bus
signal that has symbolic dimensions.
For Lookup Table blocks, on the Block Parameters > Algorithm tab, you select the parameter Use one input port for all input data.
The following products and software capabilities support dimension variants in that they act on the numeric value of a symbolic dimension. These features do not support the propagation of symbolic dimensions during model simulation and the preservation of symbolic dimensions in the generated code.
Code Replacement for Lookup Tables
Software-in-the-Loop (SIL) and Processor-in-the-Loop (PIL) simulations
Accelerator and rapid accelerator simulation modes
Scope and simulation observation (for example, logging, SDI, and so on)
Model coverage
Simulink Design Verifier
Fixed-Point Designer
Data Dictionary
Simulink PLC Coder
HDL Coder
The following do not support dimension variants:
System Object
Stateflow charts that use MATLAB as the action language
Physical modeling
Discrete-event simulation
Frame data
MATLAB functions
The following limitations also apply to models that utilize symbolic dimensions.
For simulation, the size of a symbolic dimension can
equal 1. For code generation, the size of a symbolic dimension must
be greater than 1
.
If a symbolic dimension is a MATLAB expression that
contains an arithmetic expression and either a relational or logical
expression, you must add +0
after the relational
or logical part of the MATLAB expression. If you do not add +0
,
the model errors out during simulation because you cannot mix a boolean
data
type with integer or double
data types. Adding +0
converts
the data type of the relational or logical part of the expression
from a boolean
to a double
.
For example, suppose in the Inport block parameters dialog box,
the Port dimensions parameter has the expression [(C==8)*D+E,3]
.
The Data type parameter is set to double
.
Since C==8
is a relational expression, you must
change the expression to [((C==8)+0)*D+E,3]
to
prevent the model from producing an error during simulation.
Simulink propagates symbolic dimensions for an entire structure or matrix, but not for a part
of a structure or matrix. For example, the Simulink.Parameter
P
is a 2x3
matrix with symbolic dimensions
[Dim,Dim1]
.
p=Simulink.Parameter(struct('A',[1 2 3;4 5 6])) p.DataType='Bus:bo' bo=Simulink.Bus bo.Elements(1).Name='A' bo.Elements(1).Dimensions='[Dim,Dim1]' Dim=Simulink.Parameter(2) Dim1=Simulink.Parameter(3) p.CoderInfo.StorageClass='Custom' p.CoderInfo.CustomStorageClass='Define' Dim.CoderInfo.StorageClass='Custom' Dim.CoderInfo.CustomStorageClass='Define' Dim1.CoderInfo.StorageClass='Custom' Dim1.CoderInfo.CustomStorageClass='Define'
If you specify p.A
for a dimensions parameter,
Simulink propagates the symbolic dimensions [Dim,Dim1]
.
If you specify p.A(1,:)
, Simulink propagates the
numeric dimension 3
but not the symbolic dimension, Dim1
.
The MATLAB expression A(:)
does
not maintain symbolic dimension information. Use A
instead.
The MATLAB expression P(2:A)
does
not maintain symbolic dimension information. Use the Selector block
instead.
The MATLAB expression P(2,:)
is
not a tunable expression, so it does not maintain symbolic dimension
information.
Suppose that you set the value of a mask parameter, myMaskParam
, by using a
field of a structure or by using a subset of the structures in an array of structures.
You store the structure or array of structures in a Simulink.Parameter
object so that you can use a Simulink.Bus
object to
apply symbolic dimensions to the structure fields. Under the mask, you configure a block
parameter to use one of the fields that have symbolic dimensions. The table shows some
example cases.
Description | Value
of mask parameter (myMaskParam ) | Value of block parameter |
---|---|---|
myStruct is a structure with field gains ,
which uses symbolic dimensions. | myStruct.gains | myMaskParam |
myStruct is a structure with field hierarchy myStruct.subStruct.gains .
The field gains uses symbolic dimensions. | myStruct.subStruct | myMaskParam.gains |
myStructs is an array of structures. Each
structure has a field gains , which uses symbolic
dimensions. | myStructs(2) | myMaskParam.gains |
In these cases, you cannot generate code from the model. As a workaround, choose one of these techniques:
Use the entire structure (myStruct
)
or array of structures (myStructs
) as the value
of the mask parameter. Under the mask, configure the block parameter
to dereference the target field from the mask parameter by using an
expression such as myMaskParam.subStruct.gains
.
Use literal dimensions instead of symbolic dimensions
for the target field (gains
).
This limitation also applies when you use a field of a structure or a subset of the structures in an array of structures as the value of a model argument in a Model block.