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 modelslexVariantParameterWiper
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 tosim codegen switching
. The step signal is connected to thesim
input of the Variant Source block and the driver-provided setting is connected to thecodegen
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 parametersGearRatio
,SweepAngle
, andWiperLength
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 aSimulink.VariantControl
object namedWiper
to specify the variant conditions for the choices. TheWiper
value can be set to the valuesWiperPosition.FRONT_DRIVER
,WiperPosition.FRONT_PASSENGER
, orWiperPosition.REAR
defined in theWiperPosition.m
file. TheActivationTime
property ofWiper
is set tostartup
and is specified as a model argument.
In the top-level model, for each instance of the
slexVariantParameterWiper
model, the model argumentWiper
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 ofWiper
set from the top-level model. This image shows the instance value specified forWiper
in the block parameters dialog box of the Model blockFront 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
Simulink.VariantVariable
| Simulink.VariantControl