Main Content

Compile Code Conditionally for all Values of Variant Parameters

This example shows how to generate a C code that contains all the active and inactive values of variant parameters. The values are enclosed in preprocessor conditionals #if and #elif that enables you to compile the code conditionally based on the condition that evaluates to true. You can choose to represent the variables as inline or tunable variables in the generated code.

Overview of Variant Parameters

Variant parameters can have multiple values. Each value of the variant parameter is associated with a variant condition expression. During simulation, the value of the variant parameter associated with the condition that evaluates to true is the active value of that parameter. The value associated with the condition that evaluates to false is the inactive value of that variant parameter. For more information, see Use Variant Parameters to Reuse Block Parameters with Different Values.

In the generated code, the active and inactive values of the variant parameters are enclosed in C preprocessor conditionals #if and #elif. The preprocessor conditionals enable you to conditionally compile the code for a given active value. You generate the code only once. You can then choose the active choice of variant parameters by changing the value of the variant control variable before running the code. You do not need to regenerate the code for different variant parameter choices.

Note: To generate code that contains active and inactive values of variant parameters in C preprocessor conditionals, you must install Embedded Coder™.

The values are represented as inline or tunable variables in the generated code. The representation is determined by the storage class that you specify for the variant parameters in the model. The variant parameters with default storage class Auto are represented as inline variables. The variant parameters with storage class other than Auto are represented as tunable variables in the generated code. For more information on how different storage classes are represented in the generated code, see Choose Storage Class for Controlling Data Representation in Generated Code (Simulink Coder).

Prerequisite

Before you start this example, we recommend you complete Options to Represent Variant Parameters in Generated Code (Embedded Coder).

Explore the model

1. Open the model.

open_system([matlabroot '/examples/simulink_variants/main/slexVariantParametersCC'])

The model contains blocks that have variant parameters that are specified as Simulink.VariantVariable objects. The objects are defined in the slexVariantParameterCCData.m file.

  • Constant: The Constant parameters of the Constant blocks are variant parameters. The parameters are specified as variant variable objects MAX_LIFT and SLIDER_POS.

  • Table data and Breakpoint sets: The Table data and Breakpoint sets of the n-D Lookup Table blocks are variant parameters. The parameters are specified as variant variable objects T1Break1, T1Data, T2Break, and T2Data.

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

  • In this file, VCtrl is the Simulink.VariantControl object that determines the active value of the variant parameter objects MAX_LIFT, SLIDER_POS, T1Break1, T1Data, T2Break, and T2Data. The value of VCtrl is set to 1, and its activation time is specified as code compile. During simulation, the condition VCtrl==1 evaluates to true. All the values associated with VCtrl==1 become active, and the values associated with VCtrl==2 become inactive. When you generate a code from this model, all the active and inactive values are enclosed in preprocessor conditionals #if and #elif.

  • The variant parameter objects MAX_LIFT and SLIDER_POS have scalar numeric values with a default storage class Auto. The variant parameter objects T1Break1, T1Data, T2Break, and T2Data are of Simulink.Parameter type with storage class specified as ExportedGlobal. When you generate the code, the values of the Constant parameters are inlined as macros. The values of the Table data and Breakpoint sets parameters are represented by symbolic names as tunable variables in the generated code.

Set Active Choice of Variant Parameters

1. On the Simulink® toolstrip, click Run. During simulation, VCtrl==1 evaluates to true. All the values associated with VCtrl==1 are assigned to the corresponding variant variable objects and, subsequently, to the variant parameters that use these objects. For example, when VCtrl==1 evaluates to true, the value of MAX_LIFT is set to 10. As the Constant parameter of the Constant1 block is set to MAX_LIFT, the value of the Constant parameter is also set to 10.

2. To change the active values, change the value of VCtrl to 2, then simulate the model again.

VCtrl.Value = 2;

During simulation, all the values associated with VCtrl==2 are assigned to the variant variable objects, and those values are then assigned to the variant parameters using those objects.

Generate Inline and Tunable Code Using Embedded Coder

Before you generate code from the model, make sure that you have write permission in your current folder. To generate code, in the Apps gallery of the model toolstrip, click Embedded Coder. On the C Code tab, click Build. For more information, see Generate Code Using Embedded Coder® (Embedded Coder).

Review Generated Code

1. In the C Code tab, select Open Report.

2. Select the slexVariantParameters_types.h file from the Generated Code pane of the report. This file defines the value of the variant control variable VCtrl as 1. The variant control variable determines the active value of variant parameters.

#ifndef VCtrl
#define VCtrl                          1
#endif

3. Select the slexVariantParameters_private.h file. This file includes macros (#define) corresponding to all the values of the variant parameters with default storage class Auto. The active values of variant parameters MAX_LIFT and SLIDER_POS are enclosed in the C preprocessor conditional statement (#if) on the macros rtCP_Constant_MAX_LIFT and rtCP_Constant1_SLIDER_POS.

#if VCtrl == 1 || VCtrl == 2
/* Variable: MAX_LIFT
 * Referenced by: '<Root>/Constant'
 */
#if VCtrl == 1
#define rtCP_Constant_MAX_LIFT         (10.0)
#elif VCtrl == 2
#define rtCP_Constant_MAX_LIFT         (20.0)
#endif
#endif
#if VCtrl == 1 || VCtrl == 2
/* Variable: SLIDER_POS
 * Referenced by: '<Root>/Constant1'
 */
#if VCtrl == 1
#define rtCP_Constant1_SLIDER_POS      (0.0)
#elif VCtrl == 2
#define rtCP_Constant1_SLIDER_POS      (0.5)
#endif
#endif

4. Select the slexVariantParameters.c file. This file includes symbolic names for all the values of the variant parameters with storage class set to ExportGlobal. All the values of variant parameters are enclosed in C preprocessor conditional statements #if and #elif. When you compile this code, Simulink evaluates the preprocessor conditionals and compiles the code only for the active values of variant parameters.

/* Exported block parameters */
#if VCtrl == 1 || VCtrl == 2
#if VCtrl == 1
real_T T1Break[11] = { -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0,
5.0 } ;                              /* Variable: T1Break
                                       * Referenced by: '<Root>/1D Lookup'*/
real_T T1Data[11] = { -1.0, -0.99, -0.98, -0.96, -0.76, 0.0, 0.76, 0.96, 0.98,
0.99, 1.0 } ;                        /* Variable: T1Data
                                       * Referenced by: '<Root>/1D Lookup'*/
real_T T2Break[3] = { -10.0, 0.0, 10.0 } ;/* Variable: T2Break
                                    * Referenced by: '<Root>/2D Lookup'*/
real_T T2Data[9] = { 4.0, 16.0, 10.0, 5.0, 19.0, 18.0, 6.0, 20.0, 23.0 } ;/* Variable: T2Data
                                   * Referenced by: '<Root>/2D Lookup'*/
#elif VCtrl == 2
real_T T1Break[11] = { -10.0, -8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0,
10.0 } ;                          /* Variable: T1Break
                                   * Referenced by: '<Root>/1D Lookup'*/
real_T T1Data[11] = { -2.0, -1.98, -1.96, -1.92, -1.52, 0.0, 1.52, 1.92, 1.96,
1.98, 2.0 } ;                     /* Variable: T1Data
                                   * Referenced by: '<Root>/1D Lookup'*/
real_T T2Break[3] = { -20.0, 0.0, 20.0 } ;/* Variable: T2Break
                                   * Referenced by: '<Root>/2D Lookup'*/
real_T T2Data[9] = { 8.0, 32.0, 20.0, 10.0, 38.0, 36.0, 12.0, 40.0, 46.0 } ;/* Variable: T2Data
                                   * Referenced by: '<Root>/2D Lookup'*/
#endif
#endif

In this file, calls to the step function of each variant are conditionally compiled. In the step function, the macros and symbol names of variant parameters are used to form the equation.

/* Model step function */
void slexVariantParameters_step(void)
{
  slexVariantParameters_Y.Out1 = 2.0 * slexVariantParameters_U.In1 + -2.0 *
    look2_binlx(rtCP_Constant_MAX_LIFT, look1_binlx(rtCP_Constant1_SLIDER_POS,
    T1Break, T1Data, 10U), T2Break, T2Break, T2Data,
                slexVariantParameters_ConstP.uDLookup_maxIndex, 3U);
}

See Also