Represent Variant Source and Sink Blocks in Generated Code
You can use Variant Source and Variant Sink blocks to perceive multiple implementations of a model in a single, unified block diagram. Each implementation depends on conditions that you set for Variant Source and Variant Sink blocks. Simulink® propagates these conditions to upstream and downstream blocks including root input and root output ports.
You can generate:
Code from a Simulink model containing Variant Sink and Variant Source blocks.
Code that contains preprocessor conditionals that control the activation of each variant choice.
Preprocessor conditionals that allow for no active variant choice.
Represent Variant Source and Variant Sink Blocks in Simulink
This example shows how Variant Source blocks make model elements conditional.
From the Simulink Block Library, add 1 Sine Wave Function block, two Add blocks, three Gain blocks, two Outports, and two Variant Source blocks into a new model.
Open the Sine Wave Function block. For the Sine type parameter, select
Sample based
. For the Time (t) parameter, selectUse simulation time
. For the Sample time parameter, insert a value of0.2
.Make four copies of the Sine Wave Function block.
Connect and name the blocks as shown.
Insert values of
2
,3
, and4
in theGain2
,Gain3
, andGain4
blocks, respectively.Give the model the name
inline_variants_example
.Open the Block Parameters dialog box for
Variant Source
.In the Variant control column, for Port 1, replace
Choice_1
withV==1
. For Port 2, replaceChoice_2
withV==2
.Open the Block Parameters dialog box for
Variant Source1
.In the Variant control column, replace
Choice_1
withW==1
. For Port 2, replaceChoice_2
withW==2
.In the MATLAB Command Window, use these commands to define
V
andW
asSimulink.Parameter
objects.V = Simulink.Parameter; V.Value = 1; V.DataType='int32'; V.CoderInfo.StorageClass = 'custom'; V.CoderInfo.CustomStorageClass = 'Define'; V.CoderInfo.CustomAttributes.HeaderFile='inline_importedmacro.h' W = Simulink.Parameter; W.Value = 2; W.DataType='int32'; W.CoderInfo.StorageClass = 'custom'; W.CoderInfo.CustomStorageClass = 'Define'; W.CoderInfo.CustomAttributes.HeaderFile='inline_importedmacro.h'
In this example, the variant control variables are
Simulink.Parameter
objects. For code generation, if you useSimulink.Variant
objects to specify variant controls, useSimulink.Parameter
objects or MATLAB variables to specify their conditions. .Variant control variables defined as
Simulink.Parameter
objects can have one of these storage classes:Define
with header file specifiedImportedDefine
with header file specifiedCompilerFlag
SystemConstant (AUTOSAR)
User-defined custom storage class that defines data as a macro in a specified header file
If you use scalar variant control variables to simulate the model, you can convert those variables into
Simulink.Parameter
objects. See Convert Variant Control Variables into Simulink.Parameter Objects.Simulate the model.
Input port 1 is the active choice for
Variant Source
because the value of variant control variableV
is1
. Input port 2 is the active choice forVariant Source1
because the value of variant control variableW
is 2. The inactive choices are removed from execution, and their paths are grayed-out in the diagram.
Specify Conditions That Control Variant Choice Selection
You can generate code in which each variant choice is enclosed
within C preprocessor conditionals #if
and #endif
.
The compiler chooses the active variant at compile time and the preprocessor
conditionals determine which sections of the code to execute.
In the Modeling tab of the Simulink toolstrip, click Model Settings.
On the Code Generation pane, and set System target file to
ert.tlc
.On the Solver pane, set the Type parameter to
Fixed-step
.In your model, open the block parameters dialog box for
Variant Source
.Set the Variant activation time parameter to
code compile
. During an update diagram or simulation, when you set this parameter value, Simulink analyzes all variant choices. This analysis provides early validation of the code generation readiness of variant choices. During code generation, when you set this parameter value, the code generator generates preprocessor conditionals that control the activation of each variant choice.Clear the Allow zero active variant controls parameter.
Open the Block Parameters dialog box for
Variant Source 1
. Repeat steps 5 through 7.Build the model. When code generation is complete, the generated code is displayed in the Code view.
Review the Generated Code
In the Code view, select the
inline_variants_example.c
file.In the
inline_variants_example.c
file, the call to theinline_variants_example_step
function is conditionally compiled as shown:/* Model step function */ void inline_variants_example_step(void) { real_T rtb_VariantMerge_For_Variant_So; real_T rtb_VariantMerge_For_Variant__e; /* Sin: '<Root>/Sine2' incorporates: * Sin: '<Root>/Sine3' * Sum: '<Root>/Add' */ #if V == 2 rtb_VariantMerge_For_Variant_So = sin((real_T) inline_variants_example_DW.counter * 2.0 * 3.1415926535897931 / 10.0) + sin ((real_T)inline_variants_example_DW.counter_g * 2.0 * 3.1415926535897931 / 10.0); #endif /* End of Sin: '<Root>/Sine2' */ /* Sin: '<Root>/Sine4' incorporates: * Sin: '<Root>/Sine5' * Sum: '<Root>/Add1' */ #if W == 2 rtb_VariantMerge_For_Variant__e = sin((real_T) inline_variants_example_DW.counter_c * 2.0 * 3.1415926535897931 / 10.0) + sin((real_T)inline_variants_example_DW.counter_i * 2.0 * 3.1415926535897931 / 10.0); #endif /* End of Sin: '<Root>/Sine4' */ /* Sin: '<Root>/Sine1' */ #if V == 1 rtb_VariantMerge_For_Variant_So = sin((real_T) inline_variants_example_DW.counter_m * 2.0 * 3.1415926535897931 / 10.0); #endif /* End of Sin: '<Root>/Sine1' */ /* Outport: '<Root>/Outport' incorporates: * Gain: '<Root>/Gain1' */ inline_variants_example_Y.Outport = 3.0 * rtb_VariantMerge_For_Variant_So; /* Gain: '<Root>/Gain' */ #if W == 1 rtb_VariantMerge_For_Variant__e = 2.0 * rtb_VariantMerge_For_Variant_So; #endif /* End of Gain: '<Root>/Gain' */ /* Outport: '<Root>/Outport1' incorporates: * Gain: '<Root>/Gain2' */ inline_variants_example_Y.Outport1 = 4.0 * rtb_VariantMerge_For_Variant__e; /* Update for Sin: '<Root>/Sine2' incorporates: * Sin: '<Root>/Sine3' */ #if V == 2 inline_variants_example_DW.counter++; if (inline_variants_example_DW.counter == 10) { inline_variants_example_DW.counter = 0; } inline_variants_example_DW.counter_g++; if (inline_variants_example_DW.counter_g == 10) { inline_variants_example_DW.counter_g = 0; } #endif /* End of Update for Sin: '<Root>/Sine2' */ /* Update for Sin: '<Root>/Sine4' incorporates: * Sin: '<Root>/Sine5' */ #if W == 2 inline_variants_example_DW.counter_c++; if (inline_variants_example_DW.counter_c == 10) { inline_variants_example_DW.counter_c = 0; } inline_variants_example_DW.counter_i++; if (inline_variants_example_DW.counter_i == 10) { inline_variants_example_DW.counter_i = 0; } #endif /* End of Update for Sin: '<Root>/Sine4' */ /* Update for Sin: '<Root>/Sine1' */ #if V == 1 inline_variants_example_DW.counter_m++; if (inline_variants_example_DW.counter_m == 10) { inline_variants_example_DW.counter_m = 0; } #endif /* End of Update for Sin: '<Root>/Sine1' */ }
The variables rtb_VariantMerge_For_Variant_So
and
rtb_VariantMerge_For_Variant_e
hold the input values to the
Variant Source blocks. Notice that the code for these variables is
conditional. The variables inline_variants_example_Y.Outport
and
inline_variants_example_Y.Outport1
hold the output values of the
Variant Source blocks. Notice that the code for these variables is not
conditional.
Generate Code with Zero Active Variant Controls
You can generate code in which blocks connected to the input and the output of a Variant Source block are conditional.
For
Variant Source
, open the Block Parameters dialog box. Select the parameter Allow zero active variant controls.For
Variant Source 1
, open the Block Parameters dialog box. Select the parameter Allow zero active variant controls.
When you select the Allow zero active variant controls parameter, you can generate code for a model containing Variant Source and Variant Sink blocks even when you specify a value for a variant control variable that does not allow for an active variant. Choosing a value for a variant control variable that does not allow for an active variant and not selecting the Allow zero active variant controls parameter, produces an error.
Generate code for inline_variants_example
. Notice in the
inline_variants_example.c
file, that the code for the variables
inline_variants_example_Y.Outport1
and
inline_variants_example_Y.Outport2
is conditional.
/* Model step function */ void inline_variants_example_step(void) { ... #if V == 1 || V == 2 inline_variants_example_Y.Outport = 3.0 * rtb_VariantMerge_For_Variant_So; #endif ... #if (V == 1 && W == 1) || (V == 2 && W == 1) || W == 2 inline_variants_example_Y.Outport1 = 4.0 * rtb_VariantMerge_For_Variant__e; #endif ...