Main Content

Generate Code for Instance-Specific Variation of Variant Parameter Values in Model Reference Hierarchy

Variant parameters enable you to conditionally vary the values of block parameters in a Simulink® model. For more information, see Simulink.VariantVariable. For an example, see Create a Simple Variant Parameter Model.

You can generate code from models that define variant parameters (Simulink.VariantVariable objects) in the model workspace. To generate code from such models, set the ActivationTime property of the Simulink.VariantControl object used as the variant control variable for the variant parameter to update diagram, update diagram analyze all choices, or startup. The objects associated with the variant parameter object such as the Simulink.VariantControl object, the Simulink.Parameter object used to set the Specification property, and any Simulink.Parameter objects used as values of the variant parameter, must be defined in the model workspace along with the parameter.

By using variant parameters defined in the model workspace, you can configure instance-specific values for variant parameters in a referenced model. That is, when you reference the same model multiple times by using multiple Model blocks in a parent model, you can configure a variant parameter in the referenced model to use a different value for each instance of the model. To achieve this, configure the associated Simulink.VariantControl object defined in the model workspace of the referenced model as a model argument. To learn more about the simulation workflow for variant parameters in model workspace, see Configure Variant Parameter Values for Instances of Referenced Models.

When you generate code from a model hierarchy that uses model arguments, the arguments appear in the code as formal parameters of the referenced model entry-point functions, such as the step and initialize functions. The generated code then passes the instance-specific parameter values, which you specify in each Model block, to the corresponding function calls.

Note

You can use the Code Mappings editor to configure the code generation attributes for ERT-based and GRT-based targets for Simulink.VariantVariable and Simulink.VariantControl objects defined in the model workspace of a model. For an example, see Configure Code Generation for Variant Parameters in Model Workspace Using Code Mappings Editor.

Specify Instance-Specific Variant Parameters Values in Referenced Model

Open the model slexVariantParameterMultiInstance and the referenced model slexVariantParameterWiper.

open_system("slexVariantParameterMultiInstance");
open_system("slexVariantParameterWiper");

Explore the Model

  • The top-level model slexVariantParameterMultiInstance uses the referenced model slexVariantParameterWiper to implement a system that takes the speed of a car wiper motor as the input and computes the sweep time and sweep area parameters of the wiper. The model is configured to automatically switch between two input sources for simulation and code generation workflows: a Step block for simulation and a driver-provided wiper setting from the car for code generation. To achieve this, the model uses two Variant Source blocks with the Variant control mode parameter set to sim codegen switching. The step signal is connected to the sim input of the Variant Source block and the driver-provided setting is connected to the codegen input.

  • The top-level model computes the parameters for the front driver, front passenger, and rear wipers of the car by providing the corresponding wiper motor speed as input to three instances of the slexVariantParameterWiper model.

  • The slexVariantParameterWiper model takes the motor speed as input and uses three variant parameters GearRatio, SweepAngle, and WiperLength defined in the model workspace to calculate the value of the required output parameters. These variant parameters take a different value for each of the driver, passenger, and rear wiper positions. The variant parameters use a Simulink.VariantControl object named Wiper to specify the variant conditions for the choices. The Wiper value can be set to the values WiperPosition.FRONT_DRIVER, WiperPosition.FRONT_PASSENGER, or WiperPosition.REAR defined in the WiperPosition.m file. The ActivationTime property of Wiper is set to startup and is specified as a model argument.

  • In the top-level model, for each instance of the slexVariantParameterWiper model, the model argument Wiper is set to an instance-specific value corresponding to the wiper position. During simulation, the active choice of variant parameters in the referenced model vary for each instance based on the value of Wiper set from the top-level model. This image shows the instance value specified for Wiper in the block parameters dialog box of the Model block Front Driver Wiper.

Generate Code

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

  slbuild("slexVariantParameterMultiInstance")
### Searching for referenced models in model 'slexVariantParameterMultiInstance'.
### Total of 2 models to build.
### Starting serial code generation build.
### Starting build procedure for: slexVariantParameterWiper
### Successful completion of build procedure for: slexVariantParameterWiper
### Starting build procedure for: slexVariantParameterMultiInstance
### Successful completion of build procedure for: slexVariantParameterMultiInstance

Build Summary

Model reference code generation targets:

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

Top model targets:

Model                              Build Reason                                         Status                        Build Duration
====================================================================================================================================
slexVariantParameterMultiInstance  Information cache folder or artifacts were missing.  Code generated and compiled.  0h 0m 8.2705s 

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

Review Generated Code

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

2. Select the header file slexVariantParameterWiper.h. The code for the referenced model contains a type definition for the instance parameters and a pointer to an instance of that data structure.

file = fullfile("slprj/ert/slexVariantParameterWiper",...
    "slexVariantParameterWiper.h");
coder.example.extractLines(file,"typedef struct {","} InstP_slexVariantParameterWiper_T;",1,1)
typedef struct {
  real_T GearRatio;                    /* Variable: GearRatio
                                        * Referenced by:
                                        */
  real_T SweepAngle;                   /* Variable: SweepAngle
                                        * Referenced by:
                                        */
  real_T WiperLength;                  /* Variable: WiperLength
                                        * Referenced by:
                                        */
} InstP_slexVariantParameterWiper_T;
file = fullfile("slprj/ert/slexVariantParameterWiper",...
    "slexVariantParameterWiper.h");
coder.example.extractLines(file,"/* Real-time Model Data Structure */", "/* Model reference registration function */",1,1)
/* Real-time Model Data Structure */
struct tag_RTM_slexVariantParameterWiper_T {
  const char_T **errorStatus;
  InstP_slexVariantParameterWiper_T *slexVariantParameterWiper_InstP_ref;
};

typedef struct {
  RT_MODEL_slexVariantParameterWiper_T rtm;
} MdlrefDW_slexVariantParameterWiper_T;

extern P_slexVariantParameterWiper_T slexVariantParameterWiper_P;

3. Select the definition file slexVariantParameterWiper.c. The model initialization function of the referenced model selects the active value for the variant parameter based on the value of the variant control Wiper for the given instance.

file = fullfile("slprj/ert/slexVariantParameterWiper",...
    "slexVariantParameterWiper.c");
coder.example.extractLines(file,"/* Model initialize function */", "slexVariantParameterWiper_M->slexVariantParameterWiper_InstP_ref);",1,1)
/* Model initialize function */
void slexVariantParameterWiper_initialize(const char_T **rt_errorStatus,
  WiperPosition rtp_Wiper, RT_MODEL_slexVariantParameterWiper_T *const
  slexVariantParameterWiper_M)
{
  InstP_slexVariantParameterWiper_T *slexVariantParameterWiper_InstP_arg =
    ((InstP_slexVariantParameterWiper_T *)
     slexVariantParameterWiper_M->slexVariantParameterWiper_InstP_ref);
file = fullfile("slprj/ert/slexVariantParameterWiper",...
    "slexVariantParameterWiper.c");
coder.example.extractLines(file,"/* Variant Parameters startup activation time */", "slexVariantParameterWiper_startupVariantChecker(rtp_Wiper);",1,0)
  /* Variant Parameters startup activation time */
  if (rtp_Wiper == WiperPosition_FRONT_DRIVER) {
    slexVariantParameterWiper_InstP_arg->GearRatio = 0.5;
    slexVariantParameterWiper_InstP_arg->SweepAngle = 120.0;
    slexVariantParameterWiper_InstP_arg->WiperLength = 56.0;
  } else if (rtp_Wiper == WiperPosition_FRONT_PASSENGER) {
    slexVariantParameterWiper_InstP_arg->GearRatio = 0.375;
    slexVariantParameterWiper_InstP_arg->SweepAngle = 90.0;
    slexVariantParameterWiper_InstP_arg->WiperLength = 50.0;
  } else if (rtp_Wiper == WiperPosition_REAR) {
    slexVariantParameterWiper_InstP_arg->GearRatio = 0.3;
    slexVariantParameterWiper_InstP_arg->SweepAngle = 150.0;
    slexVariantParameterWiper_InstP_arg->WiperLength = 40.0;
  }

4. Select the slexVariantParameterMultiInstance_data.c file. The code for the top model defines the instance-specific parameters by using the values provided by the top model.

file = fullfile("slexVariantParameterMultiInstance_ert_rtw",...
    "slexVariantParameterMultiInstance_data.c");
coder.example.extractLines(file,"/* instance parameters */", "* File trailer for generated code.",1,0)
/* instance parameters */
InstP_slexVariantParameterMultiInstance_T
  slexVariantParameterMultiInstance_InstP = {
  {
    /*
     * slexVariantParameterMultiInstance/Front Driver Wiper
     *   slexVariantParameterWiper:GearRatio
     */
    0.5,

    /*
     * slexVariantParameterMultiInstance/Front Driver Wiper
     *   slexVariantParameterWiper:SweepAngle
     */
    120.0,

    /*
     * slexVariantParameterMultiInstance/Front Driver Wiper
     *   slexVariantParameterWiper:WiperLength
     */
    56.0
  },

  {
    /*
     * slexVariantParameterMultiInstance/Front Passenger Wiper
     *   slexVariantParameterWiper:GearRatio
     */
    0.375,

    /*
     * slexVariantParameterMultiInstance/Front Passenger Wiper
     *   slexVariantParameterWiper:SweepAngle
     */
    90.0,

    /*
     * slexVariantParameterMultiInstance/Front Passenger Wiper
     *   slexVariantParameterWiper:WiperLength
     */
    50.0
  },

  {
    /*
     * slexVariantParameterMultiInstance/Rear Wiper
     *   slexVariantParameterWiper:GearRatio
     */
    0.3,

    /*
     * slexVariantParameterMultiInstance/Rear Wiper
     *   slexVariantParameterWiper:SweepAngle
     */
    150.0,

    /*
     * slexVariantParameterMultiInstance/Rear Wiper
     *   slexVariantParameterWiper:WiperLength
     */
    40.0
  }
};

/*

5. Select the slexVariantParameterMultiInstance.c file. The model initialization function of the top model calls the referenced model's initialize method for each instance. The top model code also initializes the pointer in the self structure for the referenced model. The referenced model has access to its parameter values through this pointer.

file = fullfile("slexVariantParameterMultiInstance_ert_rtw",...
    "slexVariantParameterMultiInstance.c");
coder.example.extractLines(file,"/* Model initialize function */", "/* Model terminate function */",1,0)
/* Model initialize function */
void slexVariantParameterMultiInstance_initialize(void)
{
  /* Assign pointer for instance parameters, Block: '<Root>/Front Driver Wiper' */
  slexVariantParameterMultiInstance_DW.FrontDriverWiper_InstanceData.rtm.slexVariantParameterWiper_InstP_ref
    =
    &slexVariantParameterMultiInstance_InstP.slexVariantParameterMultiInstance_FrontDriverWiper;

  /* Assign pointer for instance parameters, Block: '<Root>/Front Passenger Wiper' */
  slexVariantParameterMultiInstance_DW.FrontPassengerWiper_InstanceData.rtm.slexVariantParameterWiper_InstP_ref
    =
    &slexVariantParameterMultiInstance_InstP.slexVariantParameterMultiInstance_FrontPassengerWiper;

  /* Assign pointer for instance parameters, Block: '<Root>/Rear Wiper' */
  slexVariantParameterMultiInstance_DW.RearWiper_InstanceData.rtm.slexVariantParameterWiper_InstP_ref
    =
    &slexVariantParameterMultiInstance_InstP.slexVariantParameterMultiInstance_RearWiper;

  /* Model Initialize function for ModelReference Block: '<Root>/Front Driver Wiper' */
  slexVariantParameterWiper_initialize(rtmGetErrorStatusPointer
    (slexVariantParameterMultiInstance_M),
    slexVariantParameterMultiInstance_P.FrontDriverWiper_Wiper,
    &(slexVariantParameterMultiInstance_DW.FrontDriverWiper_InstanceData.rtm));

  /* Model Initialize function for ModelReference Block: '<Root>/Front Passenger Wiper' */
  slexVariantParameterWiper_initialize(rtmGetErrorStatusPointer
    (slexVariantParameterMultiInstance_M),
    slexVariantParameterMultiInstance_P.FrontPassengerWiper_Wiper,
    &(slexVariantParameterMultiInstance_DW.FrontPassengerWiper_InstanceData.rtm));

  /* Model Initialize function for ModelReference Block: '<Root>/Rear Wiper' */
  slexVariantParameterWiper_initialize(rtmGetErrorStatusPointer
    (slexVariantParameterMultiInstance_M),
    slexVariantParameterMultiInstance_P.RearWiper_Wiper,
    &(slexVariantParameterMultiInstance_DW.RearWiper_InstanceData.rtm));
}

See Also

|

Topics