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
slexVariantParameterBankMdlRefcontains a Gain block namedScale Valuethat uses a variant parameterSCALE_FACTORto set the Gain parameter value.SCALE_FACTORis defined as aSimulink.VariantVariableobject in the data dictionarytopBankedVariantParameterData.sldd.
The model
slexVariantParameterBankWithSLDDcontains 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_VALUEandTABLE_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.slddhastopBankedVariantParameterData.slddspecified 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:
VCtrlis defined as aSimulink.VariantControlobject. The value ofVCtrlis 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==1become active, and the choices associated withVCtrl==2become inactive.
LUTBankis defined as aSimulink.VariantBankobject. This variant parameter bank is used to group the variant parameter objectsT1Break,T1Data,T2Break,T2Data, andSCALE_FACTOR. TheBankproperty of these variant parameter objects is set toLUTBank.LUTBankhas the same set of variant conditions as these variant parameter objects. TheAllChoicesCoderInfoproperty of this variant parameter bank object is set toLUTAllChoicesCoderInfoand theActiveChoiceCoderInfoproperty is set toLUTActiveChoiceCoderInfo.
LUTAllChoicesCoderInfoandLUTActiveChoiceCoderInfoareSimulink.VariantBankCoderInfoobjects. TheLUTAllChoicesCoderInfoobject specifies code generation properties such as the header file, definition file, and#pragmadirectives for the structure array that representsLUTBankin the generated code. Similarly,LUTActiveChoiceCoderInfoallows 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 codeInterfacePackaging: Nonreusable function codeInterfacePackaging: NonReusable ### 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 8.0278s Top model targets: Model Build Reason Status Build Duration ================================================================================================================================= slexVariantParameterBankMdlRef Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 11.16s 2 of 2 models built (0 models already up to date) Build duration: 0h 0m 20.423s
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