Generate Code for Variant Parameter Banks in Model Reference Hierarchy
This example shows how to generate code for a model reference hierarchy that uses the same variant parameter bank to group variant parameters used by models across the hierarchy.
A variant parameter bank (Simulink.VariantBank
object) enables you to group variant parameter values with the same variant conditions into a structure array in the generated code. Variant parameters are implemented as Simulink.VariantVariable
objects. For an example that shows the use of variant parameter banks, see Group Variant Parameter Values and Conditionally Switch Active Value Sets in Generated Code.
When you generate code for a model using variant parameter banks, the code generator identifies all variant parameters in a variant parameter bank within the base workspace or data dictionaries visible to the model hierarchy and includes them in the parameter bank definition. The header file that contains the type definition of the variant parameter bank is generated in a shared utilities folder slprj/ target /_sharedutils
, where | _target_ | is the name of the system target file for code generation. This mechanism enables sharing the variant parameter bank across multiple models in the hierarchy.
Explore Example Model
1. Open the top-level model slexVariantParameterBankMdlRef
and the referenced model slexVariantParameterBankWithSLDD
.
open_system("slexVariantParameterBankMdlRef");
open_system("slexVariantParameterBankWithSLDD");
In these models:
The top-level model
slexVariantParameterBankMdlRef
contains a Gain block namedScale Value
that uses a variant parameterSCALE_FACTOR
to set the Gain parameter value.SCALE_FACTOR
is defined as aSimulink.VariantVariable
object in the data dictionarytopBankedVariantParameterData.sldd
.
The model
slexVariantParameterBankWithSLDD
contains multiple blocks that use variant parameters defined in the data dictionarybankedVariantParameterData.sldd
. The values of the Constant parameters of the two Constant blocks in the model are set to the variant parameter objectsSHIFT_VALUE
andTABLE_DIM_0
. The Table data and Breakpoint sets of the n-D Lookup Table blocks are specified using the variant parameter objectsT1Break
,T1Data
,T2Break
, andT2Data
.
The Architectural Data section of
bankedVariantParameterData.sldd
hastopBankedVariantParameterData.sldd
specified as a referenced dictionary.
The top model data dictionary topBankedVariantParameterData.sldd
also defines these Simulink.VariantControl
, Simulink.VariantBank
, and Simulink.VariantBankCoderInfo
objects that are used by variant parameter objects in the model hierarchy:
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 in the model hierarchy. 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
,T2Data
, andSCALE_FACTOR
. TheBank
property of these variant parameter objects is set toLUTBank
.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, 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.
Generate Code
To generate code that uses variant parameter bank switching, use Embedded Coder®. For more information, see Generate Code Using Embedded Coder.
slbuild("slexVariantParameterBankMdlRef")
### Searching for referenced models in model 'slexVariantParameterBankMdlRef'. ### Total of 2 models to build. ### Starting serial code generation build. ### Starting build procedure for: slexVariantParameterBankWithSLDD ### Successful completion of build procedure for: slexVariantParameterBankWithSLDD ### Starting build procedure for: slexVariantParameterBankMdlRef ### Successful completion of build procedure for: slexVariantParameterBankMdlRef Build Summary Model reference code generation targets: Model Build Reason Status Build Duration ========================================================================================================================================== slexVariantParameterBankWithSLDD Target (slexVariantParameterBankWithSLDD.c) did not exist. Code generated and compiled. 0h 0m 7.8958s Top model targets: Model Build Reason Status Build Duration ================================================================================================================================= slexVariantParameterBankMdlRef Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 9.6188s 2 of 2 models built (0 models already up to date) Build duration: 0h 0m 18.592s
Review Generated Code
1. In the C Code tab, select Open Report.
2. In the code generation report, open the header files variantBank_lut_array_p.h
and variantBank_lut_ptr_p.h
from the shared utilities folder slprj/ert/_sharedutils
. These files contain the type definition and declaration for the variant parameter bank structure array and pointer variable. The parameter bank definition contains variant parameters used by the top-level model and the referenced model.
file = fullfile("slprj/ert/_sharedutils", ... "variantBank_lut_array_p.h"); coder.example.extractLines(file,"typedef struct {","#pragma end",1,1)
typedef struct { real_T T1Break[11]; real_T T1Data[11]; real_T T2Break[3]; real_T T2Data[9]; real_T SCALE_FACTOR; } LUTBpAndData; /* Exported data declaration */ /* Variant parameter bank: LUTBank */ /* Variant parameter bank section */ #pragma data_seg(.arrdata) extern const LUTBpAndData LUTBpAndData_ptr_impl[2];
file = fullfile("slprj/ert/_sharedutils/", ... "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
3. In the code generation report, open the slexVariantParameterBankMdlRef.c
and slexVariantParameterBankWithSLDD.c
files. The code for the top-level model and referenced model accesses the active value set fom the shared variant parameter bank using the pointer variable.
file = fullfile("slexVariantParameterBankMdlRef_ert_rtw",... "slexVariantParameterBankMdlRef.c"); coder.example.extractLines(file,"/* Model step function */","/* Model terminate function */",1,0)
/* Model step function */ void slexVariantParameterBankMdlRef_step(void) { real_T rtb_Output; /* ModelReference: '<Root>/Value' */ slexVariantParameterBankWithSLDD(&rtb_Output, &(slexVariantParameterBankMdlRef_DW.Value_InstanceData.rtdw)); /* Outport: '<Root>/Out1' incorporates: * Gain: '<Root>/Scale Value' */ slexVariantParameterBankMdlRef_Y.Out1 = LUTBpAndData_ptr->SCALE_FACTOR * rtb_Output; } /* Model initialize function */ void slexVariantParameterBankMdlRef_initialize(void) { /* Model Initialize function for ModelReference Block: '<Root>/Value' */ slexVariantParameterBankWithSLDD_initialize(rtmGetErrorStatusPointer (slexVariantParameterBankMdlRef_M), &(slexVariantParameterBankMdlRef_DW.Value_InstanceData.rtm)); /* Variant Parameters startup activation time */ 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) { rtP_SHIFT_VALUE = -18.0; rtP_TABLE_DIM_0 = 10.0; } else if (VCtrl == 2) { rtP_SHIFT_VALUE = -16.0; rtP_TABLE_DIM_0 = 20.0; } slexVariantParameterBankMdlRef_startupVariantChecker(); }
file = fullfile("slprj/ert/slexVariantParameterBankWithSLDD",... "slexVariantParameterBankWithSLDD.c"); coder.example.extractLines(file,"/* Output and update for referenced model: 'slexVariantParameterBankWithSLDD' */","/* Model initialize function */",1,0)
/* Output and update for referenced model: 'slexVariantParameterBankWithSLDD' */ void slexVariantParameterBankWithSLDD(real_T *rty_Out1, DW_slexVariantParameterBankWithSLDD_f_T *localDW) { /* Gain: '<Root>/Gain' incorporates: * Constant: '<Root>/Constant' * Constant: '<Root>/Constant1' * Lookup_n-D: '<Root>/1D Lookup' * Lookup_n-D: '<Root>/2D Lookup' * Sin: '<Root>/Sine Wave' * Sum: '<Root>/Sum' */ *rty_Out1 = (look2_binlx(rtP_TABLE_DIM_0, look1_binlx(sin((real_T) localDW->counter * 2.0 * 3.1415926535897931 / 100.0) * 5.0, LUTBpAndData_ptr->T1Break, LUTBpAndData_ptr->T1Data, 10U), LUTBpAndData_ptr->T2Break, LUTBpAndData_ptr->T2Break, LUTBpAndData_ptr->T2Data, rtCP_uDLookup_maxIndex, 3U) + rtP_SHIFT_VALUE) * -2.0; /* Update for Sin: '<Root>/Sine Wave' */ localDW->counter++; if (localDW->counter == 100) { localDW->counter = 0; } /* End of Update for Sin: '<Root>/Sine Wave' */ }
See Also
Simulink.VariantBank
| Simulink.VariantBankCoderInfo
| Simulink.VariantVariable