主要内容

Generate Code for Instance-Specific Variant Blocks Using Model Arguments in Model Reference Hierarchy

R2026b

Variant blocks enable you to conditionally vary the structure of a Simulink® model by selecting among variant choices. For more information, see Visualize and Interpret Variant Elements in Simulink Models.

You can generate code from models that contain variant blocks by defining variant control variables in the model workspace. For supported variant control variable types, workspaces, and variant activation times, see Verify Variable Type Compatibility with Workspace and Variant Activation Time.

By using variant control variables defined in the model workspace, you can configure instance-specific values for variant blocks in a referenced model. When the variant control variable is specified as a model argument, each instance of the referenced model can activate a different variant choice during code generation without duplicating the model.

Prerequisite

Before you proceed with this example, complete Use Model Arguments with Fast Restart to Switch Variant Choices Per Instance Without Recompiling for Variant Blocks.

Explore the Model

Open the model slexVariantsWithModelArguments.

open_system("slexVariantsWithModelArguments");

The top-level model slexVariantsWithModelArguments contains two Model blocks, Model and Model1, both referencing the FogLightController model. The top-level model provides the corresponding input signals to each instance of the FogLightController model.

Open the referenced model FogLightController.

open_system("FogLightController");

The FogLightController model accepts the driver switch and sensor signals as inputs and uses a Variant Subsystem block to select between two variant choices Sensors Connected and Driver Switch.

In the model workspace of FogLightController, a Simulink.Parameter object named CTRL_MODE is defined with the data type Enum: InputType. The InputType enumeration class defines the values InputType.Sensor and InputType.Driver in the InputType.m file. The CTRL_MODE variable has the Argument option selected, which allows the parent model to set a different value for each instance.

In the Block Parameters dialog box of the Variant Subsystem block, the variant control expressions are CTRL_MODE == InputType.Sensor and CTRL_MODE == InputType.Driver. Variant activation time is set to startup.

In the top-level model, for each Model block instance, the model argument CTRL_MODE is set to an instance-specific value in the Block Parameters dialog box on the Instance parameters tab. The Model block has CTRL_MODE set to InputType.Sensor and the Model1 block has CTRL_MODE set to InputType.Driver. During simulation, the active variant choice of the variant block in the referenced model varies for each instance based on the value of CTRL_MODE set from the top-level model.

Generate Code

Generate code from the top-level model using Simulink Coder® or Embedded Coder®.

slbuild("slexVariantsWithModelArguments")
### Searching for referenced models in model 'slexVariantsWithModelArguments'.
### Total of 2 models to build.
### Starting serial code generation build.
### Starting model reference code generation target build for: FogLightController
### Successful completion of build procedure for: FogLightController
### Starting top model code generation target build for: slexVariantsWithModelArguments
### Successful completion of build procedure for: slexVariantsWithModelArguments

Build Summary

Model reference code generation targets:

Model               Build Reason                                  Status                        Build Duration
==============================================================================================================
FogLightController  Target (FogLightController.c) did not exist.  Code generated and compiled.  0h 0m 26.648s

Top model targets:

Model                           Build Reason                                              Status                        Build Duration
======================================================================================================================================
slexVariantsWithModelArguments  Target (slexVariantsWithModelArguments.c) did not exist.  Code generated and compiled.  0h 0m 14.984s

2 of 2 models built (0 models already up to date)
Build duration: 0h 0m 47.61s

Review Generated Code

In the C Code tab, select Open Report. The Code > Model Files section shows the header and definition files.

Select the header file FogLightController_types.h. The code for the referenced model contains a type definition for the InputType enumeration used as the variant control.

file = fullfile("slprj/ert/FogLightController", ...
    "FogLightController_types.h");
coder.example.extractLines(file, ...
    "#ifndef DEFINED_TYPEDEF_FOR_InputType_", ...
    "#endif",1,1)
#ifndef DEFINED_TYPEDEF_FOR_InputType_
#define DEFINED_TYPEDEF_FOR_InputType_

typedef enum {
  InputType_Sensor = 1,                /* Default value */
  InputType_Driver
} InputType;

#endif

Select the definition file FogLightController.c. The step function of the referenced model selects the active variant choice based on the value of the variant control CTRL_MODE for the given instance.

file = fullfile("slprj/ert/FogLightController", ...
    "FogLightController.c");
coder.example.extractLines(file, ...
    "/* Output and update for referenced model", ...
    "/* Model initialize function */",1,0)
/* Output and update for referenced model: 'FogLightController' */
void FogLightController(const real_T *rtu_DriverSwitch, const real_T *rtu_Sensor,
  real_T *rty_LightCommand, boolean_T *rty_SensorFault, real_T *rty_SensorOutput,
  InputType rtp_CTRL_MODE, DW_FogLightController_f_T *localDW)
{
  /* Outputs for Atomic SubSystem: '<Root>/Variant Subsystem' */
  if (rtp_CTRL_MODE == InputType_Driver) {
    /* Outputs for Atomic SubSystem: '<S1>/Driver Switch' */
    /* Delay: '<S2>/Delay' */
    *rty_LightCommand = localDW->Delay_DSTATE_c;

    /* Update for Delay: '<S2>/Delay' */
    localDW->Delay_DSTATE_c = *rtu_DriverSwitch;

    /* End of Outputs for SubSystem: '<S1>/Driver Switch' */
  } else {
    /* Outputs for Atomic SubSystem: '<S1>/Sensors Connected' */
    /* Logic: '<S3>/Logical Operator' incorporates:
     *  Constant: '<S3>/Constant'
     *  Constant: '<S3>/Constant1'
     *  RelationalOperator: '<S3>/OverVolt'
     *  RelationalOperator: '<S3>/UnderVolt'
     */
    *rty_SensorFault = ((*rtu_Sensor > 5.0) || (*rtu_Sensor < 0.5));

    /* Saturate: '<S3>/Saturation' */
    if (*rtu_Sensor > 5.0) {
      *rty_SensorOutput = 5.0;
    } else if (*rtu_Sensor < 0.0) {
      *rty_SensorOutput = 0.0;
    } else {
      *rty_SensorOutput = *rtu_Sensor;
    }

    /* End of Saturate: '<S3>/Saturation' */

    /* Switch: '<S3>/Switch' incorporates:
     *  Delay: '<S3>/Delay'
     */
    if (*rty_SensorFault) {
      *rty_LightCommand = localDW->Delay_DSTATE;
    } else {
      *rty_LightCommand = *rty_SensorOutput;
    }

    /* End of Switch: '<S3>/Switch' */

    /* Update for Delay: '<S3>/Delay' */
    localDW->Delay_DSTATE = *rtu_DriverSwitch;

    /* End of Outputs for SubSystem: '<S1>/Sensors Connected' */
  }

  /* End of Outputs for SubSystem: '<Root>/Variant Subsystem' */
}

Select the slexVariantsWithModelArguments.c file. The step function of the top-level model calls the step function of the referenced model for each instance. The top-level model code passes the instance-specific value of CTRL_MODE to each call. The referenced model uses this value to determine which variant choice to execute.

file = fullfile("slexVariantsWithModelArguments_ert_rtw", ...
    "slexVariantsWithModelArguments.c");
coder.example.extractLines(file, ...
    "/* ModelReference: '<Root>/Model' incorporates:", ...
    "/* Scope: '<Root>/Scope1' incorporates:", 1, 0)
    /* ModelReference: '<Root>/Model' incorporates:
     *  Constant: '<S1>/Constant'
     *  Outport: '<Root>/LightCommandInst1'
     */
    FogLightController(&slexVariantsWithModelArguments_B.Driver,
                       &rtCP_Constant_Value,
                       &slexVariantsWithModelArguments_Y.LightCommandInst1,
                       &slexVariantsWithModelArguments_B.SensorFault,
                       &slexVariantsWithModelArguments_B.SensorOutput,
                       InputType_Sensor,
                       &(slexVariantsWithModelArguments_DW.Model_InstanceData.rtdw));

    /* ModelReference: '<Root>/Model1' incorporates:
     *  Constant: '<S1>/Constant'
     *  Outport: '<Root>/LightCommandInst2'
     */
    FogLightController(&slexVariantsWithModelArguments_B.Driver,
                       &rtCP_Constant_Value,
                       &slexVariantsWithModelArguments_Y.LightCommandInst2,
                       &slexVariantsWithModelArguments_B.SensorFault_a,
                       &slexVariantsWithModelArguments_B.SensorOutput_l,
                       InputType_Driver,
                       &(slexVariantsWithModelArguments_DW.Model1_InstanceData.rtdw));

See Also