For variant systems, conditional expressions called variant controls determine which variant
choice is active. You can specify a variant control as a condition expression, a Simulink.Variant
object specifying a condition expression, a MATLAB® variable, or a Simulink.Parameter
object. This example shows
how to define variant controls as Simulink.Parameter
objects.
Open the Model Explorer. Select the base workspace.
In the Model Explorer, select Add > Simulink Parameter. Specify a name for the new parameter.
Use the function Simulink.VariantManager.findVariantControlVars
to find and
convert MATLAB variables used in variant control expressions into
Simulink.Parameter
objects. For an example, see Convert Variant Control Variables into Simulink.Parameter Objects.
On the Simulink.Parameter
property dialog box, specify the
Value and Data type.
Select one of these Storage class values.
Define
ImportedDefine(Custom)
CompilerFlag(Custom)
A storage class created using the Custom Storage Class
Designer. Your storage class must have the Data initialization parameter
set to Macro
and the Data scope parameter
set to Imported
. See Control Data Representation by Configuring Storage Class Properties for more information.
Specify the value of the variant control. If the storage
class is ImportedDefine(Custom)
, do the following:
Specify the Header File parameter as an external header file in the
Custom Attributes section of the Simulink.Parameter
property
dialog box.
Enter the values of the variant controls in the external header file.
Note
The generated code refers to a variant control as a user-defined macro. The generated code does not contain the value of the macro. The value of the variant control determines the active variant in the compiled code.
If the variant control is a CompilerFlag
custom
storage class, the value of the variant control is set at compile
time. Use the Configuration Parameters > Code Generation > Custom Code > Additional build information > Defines parameter to add a list of variant controls (macro definitions)
to the compiler command line. For example, for variant control VSSMODE
,
in the text field for the Defines parameter,
enter:
-DVSSMODE=1
If you want to modify the value of the variant control after generating a makefile, use a makefile option when compiling your code. For example, at a command line outside of MATLAB, enter:
makecommand -f model.mk DEFINES_CUSTOM="-DVSSMODE=1"
Note
You can define the variant controls using Simulink.Parameter
object
of enumerated type. This approach provides meaningful names and improves the readability
of the conditions. The generated code includes preprocessor conditionals to check that the
variant condition contains valid values of the enumerated type.
Open the Configuration Parameters dialog box.
Select the Code Generation pane,
and set System target file as ert.tlc
.
In the Report pane, select Create code generation report.
In the Configuration Parameters dialog box, clear the Ignore custom storage classes parameter. In order to generate preprocessor conditionals, you must use custom storage classes.
In the Variant Subsystem, Variant Source, or Variant Sink block parameter dialog
boxes, set the Variant activation time parameter to
code compile
.
Generate code.
The port numbers and names for each child variant subsystem must belong to a subset of the port numbers and names of the parent Variant Subsystem block.
The code generation process checks that there is at least one active variant by using the
variant control values stored in the base workspace. The variant control that evaluates
to true
becomes the active variant. If
none of the variant
controls evaluates to true
, the default variant, if specified,
becomes the active variant. The code generation process issues an error if an active
variant does not exist.
Implement the condition expressions of the variant
objects such that only one evaluates to true
. The
generated code includes a test of the variant objects to determine
that there is only one active variant. If this test fails, your code will
not compile.
If you comment out child subsystems listed in the Variant Choices table in the Variant Subsystem block parameter dialog box, the code generator does not generate code for the commented out subsystems.
If the sample time for a default variant differs from that
of the other variant choices, the #else
preprocessor
conditional is not generated for the default variant. Instead, an #if
!(
is
generated.<variant conditions>
)
For Variant Subsystems, the model_private.h
file contains conditional
parameter definitions. For example, if the value of a Constant block is a
Simulink.Parameter
with an ImportedDefine
custom
storage class, and the Constant block is in a Variant Subsystem, the conditional
definition of the Simulink.Parameter
is in the
model_private.h
file.
This example shows how to aggregate multiple variant control macros (#define
) into the same generated header file. This aggregation makes it easier for you to manage the complexities inherent in a system with multiple interacting variant conditions.
Explore Example Model
Run the script prepare_rtwdemo_preproc_subsys
, which opens the model rtwdemo_preprocessor_subsys
and prepares it for this example.
run(fullfile(matlabroot,'examples','ecoder','main','prepare_rtwdemo_preproc_subsys'));
The model contains two Variant Subsystem blocks.
Navigate inside the variant subsystems. The subsystems each have a linear and a nonlinear algorithm variant.
At the root level of the model, open the block dialog box of the variant subsystem labeled LeftController
. The algorithm variants in the subsystem activate based on the states of two Simulink.Variant
objects, LINEAR
and NONLINEAR
, in the base workspace.
The state of each object depends on the values of two variant control variables, MODE_A
and MODE_B
, which are Simulink.Parameter
objects in the base workspace. The parameter objects use the custom storage class Define
and are configured to appear in the generated code as C-code macros in macros.h
.
Change Name of Generated Header File Through Model Data Editor
In this example, change the name of the generated header file from macros.h
to variant_controls.h
. You must change the file name in each parameter object.
In the model, select Modeling > Model Data Editor.
In the Model Data Editor, select the Parameters tab.
Click the Show/refresh additional information button.
Set the Change view drop-down list to Code
.
In the Filter contents box, enter MODE
. The Model Data Editor shows two rows that correspond to the parameter objects.
Select both rows. Then, for one of the rows, use the Header File column to change the header file name from macros.h
to variant_controls.h
. The Model Data Editor applies the change to both rows.
Reduce Maintenance Effort by Creating Custom Storage Class
To change the name of the header file, you must change the configuration of each parameter object. You can use the Model Data Editor to perform batch editing, but when you add a new variant control variable (parameter object), you must remember to specify the name of the header file for that object. Also, the Model Data Editor shows the parameter objects used by only one model at a time.
Instead, you can create a custom storage class and specify the name of the header file only once: In the definition of the custom storage class.
Set your current folder to a writable location.
At the command prompt, copy the built-in SimulinkDemos
package into your current folder as myPackage
.
copyfile(fullfile(matlabroot,... 'toolbox','simulink','simdemos','dataclasses','+SimulinkDemos'),... '+myPackage','f')
Navigate inside the +myPackage
folder to the file Parameter.m
and open the file.
Uncomment the methods
section that defines the method setupCoderInfo
. In the call to the function useLocalCustomStorageClasses
, replace 'packageName'
with 'myPackage'
. When you finish, the section appears as follows:
methods function setupCoderInfo(h) % Use custom storage classes from this package useLocalCustomStorageClasses(h, 'myPackage'); end end % methods
Save and close the file.
Set your current folder to the folder that contains the package myPackage
.
Open the Custom Storage Class Designer.
cscdesigner('myPackage')
Select the custom storage class Define
.
Click Copy. A new custom storage class, Define_1
, appears. Select this new custom storage class.
Set Name to VariantControlVar
.
Set Header file to Specify
. In the text box, enter variant_controls.h
.
Click Apply, Save, and OK.
At the command prompt, replace the Simulink.Parameter
objects MODE_A
and MODE_B
with myPackage.Parameter
objects. Apply the new custom storage class VariantControlVar
.
MODE_A = myPackage.Parameter; MODE_A.Value = 1; MODE_A.DataType = 'int32'; MODE_A.CoderInfo.StorageClass = 'Custom'; MODE_A.CoderInfo.CustomStorageClass = 'VariantControlVar'; MODE_B = myPackage.Parameter; MODE_B.Value = 1; MODE_B.DataType = 'int32'; MODE_B.CoderInfo.StorageClass = 'Custom'; MODE_B.CoderInfo.CustomStorageClass = 'VariantControlVar';
Now, to indicate that a parameter object represents a variant control variable, you can apply the custom storage class VariantControlVar
. To change the name of the header file, use the Custom Storage Class Designer.