Main Content

Options to Represent Variant Parameters in Generated Code

You can generate the code only for active values or for both active and inactive values of variant parameters in Simulink®. You can also represent the values of variant parameters as inline variables or as tunable variables in the generated code.

Note

For variant parameters associated with the startup activation time, you can generate code for both active and inactive choices by installing Simulink Coder™ or Embedded Coder®.

For variant parameters associated with the code compile activation time:

  • You must install Simulink Coder to generate code for only active values of variant parameters. Generating code using Simulink Coder is supported only if values of a variant parameter have same dimension.

  • You must install Embedded Coder to generate code for both active and inactive values of variant parameters. Generating code using Embedded Coder is supported for variant parameters values having same and different dimensions.

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 a variant parameter associated with the condition that evaluates to true is the active value of the variant parameter. The value associated with the condition that evaluates to false is the inactive value of the variant parameter. When you generate code, you can choose to include only the active value or both the active and inactive values in the generated code. You can also choose to represent the values as inline or as tunable variables in the generated code. For more information on variant parameters, see Use Variant Parameters to Reuse Block Parameters with Different Values.

Choice of Values in Generated Code

Simulink supports generating code only for active values or for both active and inactive values of variant parameters. Values included in the code are based on the variant activation time you specify for the variant parameters. For more information, see Activate Variant During Different Stages of Simulation and Code Generation Workflow.

When you specify the variant activation time as:

  • 'update diagram' –– Simulink does not analyze the values of variant parameters for incompatibilities in signal attributes. It generates code only for the active values of variant parameters.

  • 'update diagram analyze all choices' –– Simulink analyzes both active and inactive values of variant parameters for incompatibilities in signal attributes, however it generates code only for the active values of variant parameters.

  • 'code compile' –– Simulink analyzes both active and inactive values of variant parameters for incompatibilities in signal attributes and it also generates code for both active and inactive values of the variant parameters. The values are enclosed in C preprocessor conditional statements #if and #endif that are conditionally compiled when you compile the generated code. If the variant parameter has a default value specified using the (default) variant condition, the value is assigned in the #else condition in the code.

  • 'startup' ––Simulink analyzes both active and inactive values of variant parameters for incompatibilities in signal attributes and it also generates code for both active and inactive values of the variant parameters. The values are enclosed in regular if conditions inside the model_initialize function of the generated code that are conditionally evaluated when you run the executable that is built from the code. If the variant parameter has a default value specified using the (default) variant condition, the value is assigned in the else condition in the code.

Types of Variables in Generated Code

Simulink supports representing the values of variant parameters as inline variables or as tunable variables in the generated code. The representation of values in the code are based on the storage class you specify for the variant parameters.

  • Inline variable: If you specify the storage class of a variant parameter as Auto, which is a default storage class, and the activation time as update diagram or update diagram analyze all choices, then the variant parameter is inlined to the literal numeric value of the parameter in the generated code. If you specify the storage class of a variant parameter as Auto and the activation time as code compile, then the variant parameter is inlined as macros in the generated code. Inlined variables reduce global RAM usage and increase efficiency of the generated code. The code does not allocate memory to represent numeric block parameters, such as the Gain parameter of a Gain block. Instead, the code is inlined to the literal numeric value of the parameter.

  • Tunable: If you specify the storage class of a variant parameter as anything other than Auto, then the variant parameter is represented using symbolic names in the generated code. For a list of built-in storage classes supported for different activation times, see Storage Classes for Different Variant Activation Times.

Storage Classes for Different Variant Activation Times

When you specify a condition expression to determine the active choice, each variant control variable of the expression has a storage class associated with it. Use storage classes to control the appearance and placement of the variant control variables in the generated code. Storage classes also prevent the optimizations such as elimination of the storage for variant control variables in the generated code. For more information, see Choose Storage Class for Controlling Data Representation in Generated Code.

The variables used in the variant condition expressions must satisfy these criteria to generate code with Simulink Coder or Embedded Coder.

  • The variant control variables in variant condition expressions must have these storage classes.

  • If the activation time of a variant control variable is set to startup, then specifying its storage class to any of these is not supported:

    • Storage classes such as Define that generates macros in the code.

    • Storage classes such as Const that generates constant qualified variables in the code.

  • If a variant parameter is part of a variant parameter bank (a Simulink.VariantBank object) and if the activation time of the corresponding variant control variable is set to startup, specifying storage class using the Specification property of the Simulink.VariantVariable object is not supported. Use the Simulink.VariantBankCoderInfo class instead.

  • If the activation time of a variant control variable is set to code compile and if the values have different dimensions, then specifying its storage class such as Define that generates macros in the code is not supported.

Symbolic Dimensions in Generated Code

If a variant parameter has values with multiple dimensions, Simulink generates symbols to represent dimensions in the generated code. Representing dimensions as symbols enable the code to flexibly switch between dimension values for the given active choice without regenerating code every time you change the value of the variant control variable. For more information on symbolic dimensions in variant parameters, see Compile Code Conditionally for All Values of Variant Parameters with Same and Different Dimensions.

Group Variant Parameter Values in Generated Code

With Embedded Coder, you can use variant parameter banks to group variant parameters that have the same set of variant conditions into a structure in the generated code. The code generator supports variant parameter banks only for variant parameters with variant activation time set to startup.

The generated code contains an array of the variant parameter bank structure type. The code generator groups all choice values of the variant parameters based on variant conditions and each set of choice values becomes an element of the array. The code uses a pointer variable to access the active set of values from the array. Parameter bank switching using a pointer variable avoids copying the choice values into the main program memory and improves the efficiency and readability of the generated code. See Simulink.VariantBank.

Generate C Code for Variant Parameters

This example shows how to generate C code for variant parameters.

Explore the Model

Consider the slexVariantParameters model. To open the model, use the following command.

openExample('simulink_variants/CreateASimpleVariantParameterModelExample');

Variant parameter in a Gain block

The Gain parameters of the Gain1 and the Gain2 blocks are variant parameters with their values set to K1 and K2, respectively. The variable K1 has two values: 3.5 and 8.5. The variable K2 has two values: 4.5 and 9.5.

Simulink chooses active values of K1 and K2 based on the value of the variant control variable V. If V==1 evaluates to true, then the value of K1 is set to 3.5, and the value of K2 is set to 8.5. If V==2 evaluates to true, then the value of K1 is set to 4.5, and the value of K2 is set to 9.5.

In this example, the variant activation time is set to update diagram, and the storage class is set as Auto. When you generate a code from this model, the code is generated only for the active values of K1 and K2. In the generated code, the values are inlined to the literal value of the parameters.

Generate Inline and Tunable Code for Variant Parameters using Embedded Coder

Before you generate code from the model, you must have write permission in your current folder.

  1. Prepare the model for code generation by specifying code generation settings in the Configuration Parameters dialog box. Choose the solver and code generation target, and check the model configuration for execution efficiency. For more details on each of these steps, see Generate Code Using Embedded Coder (Embedded Coder).

  2. In the Apps gallery of the model toolstrip, click Simulink Coder.

  3. On the C Code tab, click Build.

    The code generator creates the folder slexVariantParameters_ert_rtw in your current working folder and places source code files in that folder. The generated code is in two primary files: slexVariantParameters.c and slexParameters.h. The file slexVariantParameters.h contains the value of the variant control variable, and the file slexVariantParameters.c contains the values of the variant parameters.

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

  5. Select the slexVariantParameters.c file from the Generated Code pane of the report. The code is generated only for the active values of the K1 and K2. In the generated code, the values are inlined to the literal value of the parameters.

    slexVariantParameters_Y.Out1 = 3.5 * slexVariantParameters_U.In1;
    slexVariantParameters_Y.Out2 = 4.5 * slexVariantParameters_U.In2;
  6. In the model, change the activation time to code compile and the storage class to ExportedGlobal, then generate the code again. Observe the change in the style of the generated code.

    The code is generated only for all the active and inactive values of K1 and K2. In the generated code, the values are represented using symbolic names.

    This table shows the difference in the style of the generated code for storage classes Auto and ExportedGlobal with different activation times.

    Activation timeStorage class
    Auto (default)ExportedGlobal
    update diagram

    The code is generated only for the active values of the variant parameters. In the generated code, the values are inlined to the literal value of the parameters.

    Consider this snippet of the generated code. 4.5 and 3.5 are inline active values of the variant parameters Gain1 and Gain2.

    void slexVariantParameters_step(void)
    {
    slexVariantParameters_Y.Out1 = 3.5 * slexVariantParameters_U.In1;
    slexVariantParameters_Y.Out2 = 4.5 * slexVariantParameters_U.In2;
    }

    The code is generated only for the active values of variant parameters. In the generated code, the values are represented using symbolic names.

    Consider this snippet of the generated code. Here, K1 and K2 are symbolic names for active values of variant parameters Gain1 and Gain2.

    real_T K1 = 3.5;
    real_T K2 = 4.5;
    …
    … 
    
    void slexVariantParameters_step(void)
    {
    slexVariantParameters_Y.Out1 = K1 * slexVariantParameters_U.In1;
    slexVariantParameters_Y.Out2 = K2 * slexVariantParameters_U.In2;
    }

    update diagram analyze all choices

    The generated code is same as that of update diagram. The only difference is that the active and the inactive values of variant parameters are analyzed for consistency of signal attributes such as dimension and data type across the model.

    The generated code is same as that of update diagram. The only difference is that the active and the inactive values of variant parameters are analyzed for consistency of signal attributes such as dimension and data type across the model.

    code compile

    The code is generated for all the active and inactive values of the variant parameters. All of the values are analyzed for consistency of signal attributes such as dimension and data type across the model. In the generated code, the values are inlined as macros and are enclosed in preprocessor conditionals #if and #elif.

    Consider this snippet of the generated code. The active and inactive values are enclosed in C preprocessor conditional statements #if and #elif. rtCP_Gain1_K1 and rtCP_Gain_K2 are the macros for variant parameters Gain1 and Gain2.

    #if V == 1 
    #define rtCP_Gain1_K1     (3.5)
    #elif V == 2
    #define rtCP_Gain1_K1     (8.5) 
    #endif
    
    #if V == 1 
    #define rtCP_Gain_K2      (4.5)
    #elif V == 2
    #define rtCP_Gain_K2      (9.5)
    #endif
    
    void slexVariantParameters_step(void)
    {
    slexVariantParameters_Y.Out1 = rtCP_Gain_K1 * slexVariantParameters_U.In1;
    slexVariantParameters_Y.Out2 = rtCP_Gain1_K2 * slexVariantParameters_U.In2;
    }

    The code is generated for all the active and inactive values of variant parameters. All of the values are analyzed for consistency of signal attributes such as dimension and data type across the model. In the generated code, the values are represented using symbolic names and are enclosed in preprocessor conditionals #if and #elif.

    Consider this snippet of the generated code. The active and inactive values are enclosed in C preprocessor conditional statements #if and #elif. Here, K1 and K2 are symbolic names for variant parameters Gain1 and Gain2.

    #if V == 1 
    real_T K1 = 3.5;
    real_T K2 = 4.5;
    
    #elif V == 2
    real_T K1 = 8.5;
    real_T K2 = 9.5; 
    #endif
    
    void slexVariantParameters_step(void)
    {
    slexVariantParameters_Y.Out1 = K1 * slexVariantParameters_U.In1;
    slexVariantParameters_Y.Out2 = K2 * slexVariantParameters_U.In2;
    )

    startup

    The code is generated for all the active and inactive values of the variant parameters. All of the values are analyzed for consistency of signal attributes such as dimension and data type across the model. In the generated code, the values are inlined as macros and are enclosed in regular if conditions.

    Consider this snippet of the generated code. The active and inactive values are enclosed in regular if condition statements inside the model_initialize function. The model_initialize function also contains an assertion statement to check that at least one variant value is active while running the executable. slexVariantParameters_P.K1 and slexVariantParameters_P.K2 are the members of a structure for variant parameters Gain1 and Gain2.

    static void slexVaria_startupVariantChecker(void)
    {
      /* startup variant condition checks */
      utAssert((V == 1) + (V == 2) == 1);
    }
    
    void slexVariantParameters_step(void)
    {
    slexVariantParameters_Y.Out1 = slexVariantParameters_P.K1 * ...
    slexVariantParameters_U.In1;
    slexVariantParameters_Y.Out2 = slexVariantParameters_P.K2 * ...
    slexVariantParameters_U.In2;
    }
    
    void slexVariantParameters_initialize(void)
    {
    if (V == 1) {
        slexVariantParameters_P.K1 = 3.5;
        slexVariantParameters_P.K2 = 4.5;
      } else if (V == 2) {
        slexVariantParameters_P.K1 = 8.5;
        slexVariantParameters_P.K2 = 9.5;
      }
      slexVaria_startupVariantChecker();
    }

    The code is generated for all the active and inactive values of variant parameters. All of the values are analyzed for consistency of signal attributes such as dimension and data type across the model. In the generated code, the values are represented using symbolic names and are enclosed in regular if conditions.

    Consider this snippet of the generated code. The active and inactive values are enclosed in regular if condition statements inside the model_initialize function. The model_initialize function contains an assertion statement to check that at least one variant value is active. Here, K1 and K2 are symbolic names for variant parameters Gain1 and Gain2.

    static void slexVaria_startupVariantChecker(void)
    {
      /* startup variant condition checks */
      utAssert((V == 1) + (V == 2) == 1);
    }
    
    void slexVariantParameters_step(void)
    {
    slexVariantParameters_Y.Out1 = K1 * slexVariantParameters_U.In1;
    slexVariantParameters_Y.Out2 = K2 * slexVariantParameters_U.In2;
    }
    
    void slexVariantParameters_initialize(void)
    {
    if (V == 1) {
        K1 = 3.5;
        K2 = 4.5;
      } else if (V == 2) {
        K1 = 8.5;
        K2 = 9.5;
      }
     slexVaria_startupVariantChecker();
    }

See Also

|

Related Topics