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:

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:

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.

2. Open the file slexVariantParameterBankData.m. Observe these settings in the file:

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

Topics