Main Content

Represent Subsystem and Variant Models in Generated Code

Required products: Simulink®, Embedded Coder®, Simulink Coder™

Using Simulink, you can create models that are based on a modular design platform that comprises a fixed common structure with a finite set of variable components. The variability helps you develop a single, fixed master design with variable components. For more information, see What Are Variants and When to Use Them. When you implement variants in the generated code, you can:

  • Reuse generated code from a set of application models that share functionality with minor variations.

  • Share generated code with a third party that activates one of the variants in the code.

  • Validate the supported variants for a model and then choose to activate one variant for a particular application, without regenerating and re-validating the code.

  • Generate code for the default variant that is selected when an active variant does not exist.

Using Embedded Coder, you can generate code from Simulink models containing one or more variant choices. The generated code contains preprocessor conditionals that control the activation of each variant choice.

This example shows how to represent variant choices in a Simulink model and then prepare the model so that those variant choices are represented in generated code.

Step 1: Represent Variant Choices in Simulink

Variant choices are two or more configurations of a component in your model. This example uses the model rtwdemo_preprocessor_subsys to illustrate how to represent variant choices inside Variant Subsystem blocks. For other ways to represent variant choices, see Options for Representing Variants in Simulink.

  1. Open the model rtwdemo_preprocessor_subsys.


    The model contains two Variant Subsystem blocks: LeftController and RightController.


    You can only add Inport, Outport, Subsystem, and Model blocks inside a Variant Subsystem block.

  2. Open the LeftController block.

    The LeftController block serves as the container for the variant choices. It contains two variant choices represented using Subsystem blocks Nonlinear and Linear. The nonlinear controller subsystems implement hysteresis, whereas the linear controller subsystems act as simple low-pass filters.

    The Subsystem blocks have the same number of inports and outports as the containing Variant Subsystem block.

    Variant choices can have different numbers of inports and outports. See Mapping Inports and Outports of Variant Choices.

  3. Open the Nonlinear block.

    The Nonlinear block represents one variant choice that Simulink activates when a condition is satisfied. The Linear block represents another variant choice.


    When you are prototyping variant choices, you can create empty Subsystem blocks with no inputs or outputs inside a Variant Subsystem block. The empty subsystem recreates the situation in which that subsystem is inactive without the need for completely modeling the variant choice.

Step 2: Specify Conditions That Control Variant Choice Selection

You can switch between variant choices by constructing conditional expressions called variant controls for each variant choice represented in a Variant Subsystem block. Variant controls determine which variant choice is active, and changing the value of a variant control causes the active variant choice to switch.

A variant control is a Boolean expression that activates a specific variant choice when it evaluates to true.

For more information, see Introduction to Variant Controls.

  1. Right-click the LeftController block and select Block Parameters (Subsystem).

    The Condition column displays the Boolean expression that when true activates each variant choice. In this example, these conditions are specified using Simulink.Variant objects LINEAR and NONLINEAR.

  2. Use these commands to specify a variant control using a Simulink.Variant object.

    LINEAR = Simulink.Variant;
    LINEAR.Condition = 'VSSMODE==0';
    NONLINEAR = Simulink.Variant;
    NONLINEAR.Condition = 'VSSMODE==1';

    Here, VSSMODE is called a variant control variable that can be specified in one of the ways listed in Approaches for Specifying Variant Controls.

  3. Define the variant control variable VSSMODE.

    You can define VSSMODE as a scalar variable or as a Simulink.Parameter object. In addition to enabling the specification of parameter value, Simulink.Parameter objects allow you to specify other attributes such as data type that are required for generating code.

    VSSMODE = Simulink.Parameter;
    VSSMODE.Value = 1;
    VSSMODE.DataType = 'int32';
    VSSMODE.CoderInfo.StorageClass = 'Custom';
    VSSMODE.CoderInfo.CustomStorageClass = 'ImportedDefine';
    VSSMODE.CoderInfo.CustomAttributes.HeaderFile = 'rtwdemo_importedmacros.h';

    Variant control variables defined as Simulink.Parameter objects can have one of these storage classes.

    • Define or ImportedDefine with header file specified

    • CompilerFlag

    • SystemConstant (AUTOSAR)

    • Your own custom storage class that defines data as a macro

    You can also convert a scalar variant control variable into a Simulink.Parameter object. See Convert Variant Control Variables into Simulink.Parameter Objects.

Step 3: Configure Model for Generating Preprocessor Conditionals

Code generated for each variant choice is enclosed within C preprocessor conditionals #if, #else, #elif, and #endif. Therefore, the active variant is selected at compile time and the preprocessor conditionals determine which sections of the code to execute.

  1. In the Modeling tab of the Simulink toolstrip, click Model Settings.

  2. Select the Code Generation pane, and set System target file to ert.tlc.

  3. In the Report pane, select Create code generation report.

  4. In the Configuration Parameters dialog box, clear Ignore custom storage classes and click Apply.

  5. In your model, right-click the LeftController block and select Block Parameters (Subsystem).

  6. Set the Variant activation time parameter to code compile.

    When you select this option, Simulink analyzes all variant choices during an update diagram or simulation. This analysis provides early validation of the code generation readiness of all variant choices.

  7. Build the model.

Step 4: Review Generated Code

The code generation report contains a section dedicated to the subsystems that have variants controlled by preprocessor conditionals.

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

  2. Select the Code Variant Report from the left.

    In this example, the generated code includes references to the Simulink.Variant objects LINEAR and NONLINEAR. The code also includes the definitions of macros corresponding to those variants. The definitions depend on the value of VSSMODE, which is supplied in an external header file rtwdemo_importedmacros.h. The active variant is determined by using preprocessor conditionals (#if) on the macros (#define) LINEAR and NONLINEAR.

  3. Select the rtwdemo_preprocessor_subsys_types.h file from the left.

    This file contains the definitions of macros LINEAR and NONLINEAR.

    #ifndef LINEAR
    	#define LINEAR      (VSSMODE == 0)
    #ifndef NONLINEAR
    	#define NONLINEAR   (VSSMODE == 1)

  4. Select the rtwdemo_preprocessor_subsys.c file from the left.

    In this file, calls to the step and initialization functions of each variant are conditionally compiled.

    	/* Outputs for Atomic SubSystem: '<Root>/LeftController' */
    #if LINEAR
    	/* Output and update for atomic system: '<S1>/Linear' */
    #elif NONLINEAR
    	/* Output and update for atomic system: '<S1>/Nonlinear' */


  • When you are generating code for Variant Subsystem blocks, the blocks cannot have:

    • Mass matrices

    • Function call ports

    • Outports with constant sample time

    • Simscape™ blocks

  • The port numbers and names for each active child subsystem must belong to a subset of the port numbers and names of the parent Variant Subsystem block.

Related Examples

More About