Group Variant Parameter Values and Conditionally Switch Active Value Sets in Generated Code - MATLAB & Simulink (original) (raw)
This example shows how to group variant parameters with the same variant conditions into a structure in the generated code. You will learn to:
- Use variant parameter banks to group variant parameters with
startup
activation time in code generated by Embedded Coder®. - Specify code generation properties for variant parameter banks.
Overview of Variant Parameters
Variant parameters enable you to conditionally vary the values of block parameters in a Simulink® model. Use the Simulink.VariantVariable class to create a variant parameter object. A variant parameter object defines a set of values, referred to as choices, and variant condition expressions associated with each choice. During simulation, the choice associated with the variant condition that evaluates to true
becomes the active value of the variant parameter.
To specify the variant conditions for a variant parameter, use a variant control variable of type Simulink.VariantControl. The Simulink.VariantControl
object allows you to specify a variant activation time for the variant parameter. For example, in this MATLAB® code, VCtrl
is a variant control with startup
activation time. The variant parameter TABLE_DIM_0
has two choices, 10
and 20
. For each choice, a variant condition is specified using VCtrl
.
VCtrl = Simulink.VariantControl('Value',int32(1),'ActivationTime','startup'); TABLE_DIM_0 = Simulink.VariantVariable('Choices',{'VCtrl == 1',10,'VCtrl == 2',20});
The representation of variant parameters in the generated code depends on the [ActivationTime](../../simulink/slref/simulink.variantcontrol-class.html#mw%5F0b2d1f0b-dda5-47f1-a6a5-18ffa2721f27)
of Simulink.VariantControl
and the [Specification](../../simulink/slref/simulink.variantvariable-class.html#mw%5Fa8c688d5-0f56-445c-9286-f115a7c323d3)
property of the Simulink.VariantVariable
object. Based on the variant activation time, Simulink determines whether to include only the active choice or both the active and inactive choices of the variant parameter in the code. The Specification
property allows you to specify properties such as data type, dimensions, and storage class applicable to all the choices.
For more information on variant activation times, see Activate Variant During Different Stages of Simulation and Code Generation Workflow. For information on variant parameter code generation, see Options to Represent Variant Parameters in Generated Code.
Overview of Variant Parameter Banks
When you generate code for variant parameters with startup
activation time, the values of variant parameters are enclosed in if
and else if
statements in the model_initialize
function. This involves reading and copying all parameter values into the program memory. Also, when you define a custom storage class to define the variant parameter values in a separate definition file, only the active values of the parameters are present in the definition file. To improve the efficiency and readability of the generated code for variant parameters with startup
activation time, you can use variant parameter banks.
Parameter banks help you to:
- Group variant parameter values with the same variant conditions into a structure array.
- Use a pointer switching mechanism to switch the set of active parameter values in the code based on variant conditions.
- Customize code placement and specify the memory section to place the parameter values and the pointer variable in the compiled code.
A variant parameter bank is an object of type Simulink.VariantBank. To add a variant parameter to a variant parameter bank, set the Bank
property of the Simulink.VariantVariable
object to the name of the Simulink.VariantBank
object. When you generate code, Simulink.VariantVariable
objects that share the same Bank
property become part of the same structure in the code.
You must specify a list of variant conditions for a parameter bank. These conditions must match the variant conditions of the variant parameters in this parameter bank, except any default variant choice specified for the variant parameters using the (default)
keyword. For example, this MATLAB code creates a variant parameter bank.
LUTBank = Simulink.VariantBank(Name='LUTBpAndData',... Description='Lookup table breakpoint and data',... VariantConditions={'VCtrl == 1','VCtrl == 2'});
Alternatively, you can create variant parameter banks from Variant Manager. See Manage Variant Parameters Using Variant Manager.
Note: When using both Specification
and Bank
properties for a Simulink.VariantVariable
object, the specification object must have storage class set to Auto
and it must not use symbolic dimensions. For a variant parameter bank, use a Simulink.VariantBankCoderInfo object to specify code generation attributes.
Explore Example Model
1. Open the model slexVariantParameterBank
.
model = "slexVariantParameterBank"; open_system(model);
The slexVariantParameterBank
model contains blocks that use variant parameters. The variant parameters are defined as Simulink.VariantVariable
objects in the slexVariantParameterBankData.m
file.
The values of the Constant parameters of the two Constant blocks in the model are set to the variant parameter objects
SHIFT_VALUE
andTABLE_DIM_0
.The Table data and Breakpoint sets of the n-D Lookup Table blocks are specified using the variant parameter objects
T1Break
,T1Data
,T2Break
, andT2Data
.
2. Open the file slexVariantParameterBankData.m
. Observe these settings in the file:
VCtrl
is defined as aSimulink.VariantControl
object. The value ofVCtrl
is set to1
, and its activation time is set tostartup
. This object is used as a variant control variable to define the variant conditions for all the variant parameter objects. During simulation, the choices associated with the conditionVCtrl==1
become active, and the choices associated withVCtrl==2
become inactive.LUTBank
is defined as aSimulink.VariantBank
object. This variant parameter bank is used to group the variant parameter objectsT1Break
,T1Data
,T2Break
, andT2Data
. Hence,LUTBank
has the same set of variant conditions as these variant parameter objects. TheAllChoicesCoderInfo
property of this variant parameter bank object is set toLUTAllChoicesCoderInfo
and theActiveChoiceCoderInfo
property is set toLUTActiveChoiceCoderInfo
.LUTAllChoicesCoderInfo
andLUTActiveChoiceCoderInfo
areSimulink.VariantBankCoderInfo
objects. TheLUTAllChoicesCoderInfo
object specifies code generation properties such as the header file, definition file, type qualifier, and#pragma
directives for the structure array that representsLUTBank
in the generated code. Similarly,LUTActiveChoiceCoderInfo
allows you to specify these attributes separately for the pointer variable.The
Bank
property of the variant parameter objectsT1Break
,T1Data
,T2Break
, andT2Data
is set toLUTBank
.
Generate Code
To generate code that uses variant parameter bank switching, use Embedded Coder. Before you generate code from the model, check whether you have write permission in your current folder. For more information, see Generate Code Using Embedded Coder.
Searching for referenced models in model 'slexVariantParameterBank'.
Total of 1 models to build.
Starting build procedure for: slexVariantParameterBank
Successful completion of build procedure for: slexVariantParameterBank
Build Summary
Top model targets:
Model Build Reason Status Build Duration
slexVariantParameterBank Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 24.866s
1 of 1 models built (0 models already up to date) Build duration: 0h 0m 27.181s
Review Generated Code
1. In the C Code tab, select Open Report. In the Code > Data Files section of the report, the header and definition files are named according to the properties of the objects LUTAllChoicesCoderInfo
and LUTActiveChoiceCoderInfo
.
2. Select the header file variantBank_lut_array_p.h
. The file contains the type definition and data declarations of the variant parameter bank structure array.
The variant parameters that are part of the parameter bank LUTBank
are grouped in the same structure. This structure is named LUTBpAndData
, according to the Name
property of the object LUTBank
.
file = fullfile("slexVariantParameterBank_ert_rtw", ... "variantBank_lut_array_p.h"); coder.example.extractLines(file,"typedef struct {","} LUTBpAndData;",1,1)
typedef struct { real_T T1Break[11]; /* Variable: T1Break * Referenced by: '/1D Lookup' / real_T T1Data[11]; / Variable: T1Data * Referenced by: '/1D Lookup' / real_T T2Break[3]; / Variable: T2Break * Referenced by: '/2D Lookup' / real_T T2Data[9]; / Variable: T2Data * Referenced by: '/2D Lookup' */ } LUTBpAndData;
A structure array named LUTBpAndData_ptr_impl
of type LUTBpAndData
is declared. The number of elements in the array depends on the number of variant conditions in the VariantConditions
property of the parameter bank object LUTBank
. These statements are guarded with the code specified in the PreStatement
and PostStatement
properties of the LUTActiveChoiceCoderInfo
object. The type qualifier specified in the Qualifier
property is applied to the declaration and definition of the array.
file = fullfile("slexVariantParameterBank_ert_rtw", ... "variantBank_lut_array_p.h"); coder.example.extractLines(file,"#pragma data_seg(.arrdata)","#endif",1,0)
#pragma data_seg(.arrdata)
extern const LUTBpAndData LUTBpAndData_ptr_impl[2];
#pragma end
3. Select the definition file variantBank_lut_array_p.c
. The file contains the definition of the structure array.
The LUTBpAndData_ptr_impl
array contains the choices of the variant parameters, grouped by the variant conditions specified for the parameter bank.
file = fullfile("slexVariantParameterBank_ert_rtw", ... "variantBank_lut_array_p.c"); coder.example.extractLines(file,"#pragma data_seg(.arrdata)"," * File trailer for generated code.",1,0)
#pragma data_seg(.arrdata)
const LUTBpAndData LUTBpAndData_ptr_impl[2] = { { /* Variable: T1Break * Referenced by: '/1D Lookup' */ { -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 },
/* Variable: T1Data
* Referenced by: '<Root>/1D Lookup'
*/
{ -0.99990920426259511, -0.999329299739067, -0.99505475368673046,
-0.9640275800758169, -0.76159415595576485, 0.0, 0.76159415595576485,
0.9640275800758169, 0.99505475368673046, 0.999329299739067,
0.99990920426259511 },
/* Variable: T2Break
* Referenced by: '<Root>/2D Lookup'
*/
{ -10.0, 0.0, 10.0 },
/* Variable: T2Data
* Referenced by: '<Root>/2D Lookup'
*/
{ 4.0, 16.0, 10.0, 5.0, 19.0, 18.0, 6.0, 20.0, 23.0 }
}, { /* Variable: T1Break * Referenced by: '/1D Lookup' */ { -10.0, -8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0 },
/* Variable: T1Data
* Referenced by: '<Root>/1D Lookup'
*/
{ -74.203210577788752, -27.28991719712775, -10.017874927409903,
-3.626860407847019, -1.1752011936438014, 0.0, 1.1752011936438014,
3.626860407847019, 10.017874927409903, 27.28991719712775,
74.203210577788752 },
/* Variable: T2Break
* Referenced by: '<Root>/2D Lookup'
*/
{ -20.0, 0.0, 20.0 },
/* Variable: T2Data
* Referenced by: '<Root>/2D Lookup'
*/
{ 6.0, 16.0, 12.0, 7.0, 19.0, 16.0, 8.0, 20.0, 20.0 }
} };
#pragma end
/*
4. Similarly, inspect the variantBank_lut_ptr_p.h
and variantBank_lut_ptr_p.c
files that contain the declaration and definition of the pointer variable, as specified in the object LUTActiveChoiceCoderInfo
.
file = fullfile("slexVariantParameterBank_ert_rtw", ... "variantBank_lut_ptr_p.h"); coder.example.extractLines(file,"#pragma data_seg(.ptrdata)","#endif",1,0)
#pragma data_seg(.ptrdata)
extern const volatile LUTBpAndData *LUTBpAndData_ptr;
#pragma end
file = fullfile("slexVariantParameterBank_ert_rtw", ... "variantBank_lut_ptr_p.c"); coder.example.extractLines(file,"#pragma data_seg(.ptrdata)"," * File trailer for generated code.",1,0)
#pragma data_seg(.ptrdata)
const volatile LUTBpAndData *LUTBpAndData_ptr = &LUTBpAndData_ptr_impl[0];
#pragma end
/*
5. Select the slexVariantParameterBank.c
file. The model_initialize
function contains the code to switch the active variant choice based on variant conditions. For variant parameters that are part of a parameter bank, the pointer variable is used to access the active value set from the structure array based on variant conditions.
file = fullfile("slexVariantParameterBank_ert_rtw", ... "slexVariantParameterBank.c"); coder.example.extractLines(file,"/* Variant Parameters startup activation time */","slexVaria_startupVariantChecker();",0,0)
if (VCtrl == 1) { LUTBpAndData_ptr = &LUTBpAndData_ptr_impl[0U]; } else if (VCtrl == 2) { LUTBpAndData_ptr = &LUTBpAndData_ptr_impl[1U]; }
/* Variant Parameters startup activation time */ if (VCtrl == 1) { slexVariantParameterBank_P.SHIFT_VALUE = -18.0; slexVariantParameterBank_P.TABLE_DIM_0 = 10.0; } else if (VCtrl == 2) { slexVariantParameterBank_P.SHIFT_VALUE = -16.0; slexVariantParameterBank_P.TABLE_DIM_0 = 20.0; }
See Also
Simulink.VariantVariable | Simulink.VariantBank | Simulink.VariantBankCoderInfo