Code Generation for Variant Blocks
The code generator produces code from a Simulink® model containing one or more Variant Subsystem, Variant Model, Variant Source, and Variant Sink blocks. To learn how to create a model containing variant blocks, see Create a Simple Variant Model. To learn how to create a custom Model Advisor check that evaluates the generated code from active and inactive variant paths in a variant system model, see Create Custom Check to Evaluate Active and Inactive Variant Paths from a Model (Simulink Check).
During code generation, a warning related to 'Code generation function packaging' for
the variant block might be displayed. In the block parameters dialog of the variant block,
click Code Generation and then select
function from the Function packaging list to solve
Code is generated for different variant choices, the active variant, and the default variant. To generate code for variants, set the following conditions in the Variant Subsystem, Variant Source, or Variant Sink block:
Expressionas Variant control mode.
code compileas Variant activation time.
Code generated for Variant Subsystem blocks is surrounded by C preprocessor
#endif. Code generated for Variant Source and
Variant Sink blocks is surrounded by C preprocessor conditionals
#endif. Therefore, the active variant is
selected at compile time and the preprocessor conditionals determine which sections of the
code to execute.
To construct variant models and generate preprocessor directives in the generated code, see the example Use Variant Models to Generate Code That Uses C Preprocessor Conditionals.
To construct variant subsystems and generate preprocessor directives in the generated code, see the example Use Variant Subsystem to Generate Code That Uses C Preprocessor Conditionals.
To construct models with variant sources and sinks and generate preprocessor directives in the generated code, see the example Represent Variant Source and Sink Blocks in Generated Code.
Restrictions on Variant Subsystem Code Generation
To generate preprocessor conditionals, the types of blocks that you can place within the child
subsystems of a Variant Subsystem block are limited. Connections are not
allowed in the Variant Subsystem block diagram. However, during the code
generation process, one
VariantMerge block is placed at the input of each
Outport block within the Variant Subsystem block diagram.
All of the child subsystems connect to each of the
In the figure below, the code generation process makes the following connections and adds
VariantMerge blocks to the
When compared to a generic Merge block the
block can have only one parameter which is the number of inputs. The
VariantMerge block is used for code generation in variant subsystems
internally, and is not available externally to be used in models. The number of inputs for
VariantMerge is determined and wired as shown in the figure below.
The child subsystems of the Variant Subsystem block must be atomic subsystems.
Select Treat as atomic unit parameter in the Subsystem
block parameters dialog box, to make the subsystems atomic. The
VariantMerge blocks are inserted at the outport of the subsystems if
more than one child subsystems are present. If the source block of a
VariantMerge block input is nonvirtual, an error message will be
displayed during code generation. You must make the source block contiguous, by inserting
Signal Conversion blocks inside the variant choices. The signals that enter
a Variant Subsystem block must have the same signal properties (for example,
signal dimensions, port width, and storage class). The
does not support different signal properties because the input ports and output ports share
the same memory. You can use symbolic dimensions to generate code for a variant subsystem
with child subsystems of different output signal dimensions.
Generated Code Components Not Compiled Conditionally
The following components are not conditionally compiled even if only code for variant subsystems or models that are conditionally compiled reference them.
rtModeldata structure fields
#include's of utility files
Global constant parameter structure fields that are referenced by multiple subsystems activated by different variants
Parameters that are configured to use an imported, exported, or custom code generation storage class, and are referenced by multiple subsystems that are activated by different variants
Parameters that are configured to use an imported, exported, or custom code generation storage class, and are used by variant model blocks
Code Generation for Variant Blocks with One Variant Choice
For modeling patterns in which a root Inport block connects to a variant block
with one variant choice, the software inserts a hidden block combination of a
Ground block, Signal Conversion block, and Variant
Merge block. If the variant choice evaluates to false, this block combination
produces an output of
For example, the model
Varianttoground contains a Variant
Source block with one variant choice. When the variant control
SYSCONST_A==6 evaluates to true, the input to
Subsystem is a sine wave. When
evaluates to false, the input to
varianttoground.c file contains this
* Sin: '<Root>/Sine Wave' incorporates: * SignalConversion generated from: '<Root>/Subsystem' */ #if SYSCONST_A == 6 Varianttoground_B.VM_Conditional_Signal_Subsystem_0 = sin (Varianttoground_M->Timing.t); #else /* SignalConversion generated from: '<Root>/Subsystem' */ Varianttoground_B.VM_Conditional_Signal_Subsystem_0 = 0.0; #endif /* End of Sin: '<Root>/Sine Wave' */
The comments in the generated code indicate the presence of the hidden signal conversion block. In the hyperlinked comments, you can trace to the original block in the model that triggered the insertion of the hidden block. The code does not contain a comment for the Variant Merge block because this block does not have associated generated code. The Variant Merge block is used internally and is not in the Simulink library.
Global Data Guarding: Signals and States
When a model has variant blocks, the global signals and states are guarded in the generated code with their corresponding variant condition.
Consider a model containing a Variant Source block. The Variant
Source block has conditions
In the generated code, global signals are guarded in declaration, model initialization, and definition of data as shown below.
/* Exported block signals */ #if V == 1 || V == 2 real_T myOutput; /* '<Root>/Gain3' */ #endif
/* exported global signals */ #if V == 1 || V == 2 myOutput = 0.0; #endif
Definition of data:
* Exported Global Signals * * Note: Exported global signals are block signals with an exported global * storage class designation. Code generation will declare the memory for * these signals and export their symbols. * */ #if V == 1 || V == 2 extern real_T myOutput; /* '<Root>/Gain3' */ #endif
Global Data Guarding: Parameters
When you generate code for a model containing variant blocks, the parameters are guarded in the generated code.
Consider a model with Constant block attached to a Variant Source block.
In the generated code, the parameter of the Constant block is guarded in the header file.
/* Exported data definition */ /* Const memory section */ /* Definition for custom storage class: Const */ #if V == 2 const int32_T Parameter2 = 1; #endif
Guarding Referenced Model Headers
When a model has Model blocks that are conditional due to inline variants, the header file and the instances referring to the Model blocks are guarded.
Consider this model with two Model blocks that are conditional due to inline variants.
When you generate code for this model, the header file and instances referring to the Model blocks are guarded.
#include "mWithTwoModelBlocks_Top_types.h" #include "multiword_types.h" #if (A == 1) //Guarding #include "mWithTwoModelBlocks_Ref2.h" #endif #if (B == 1) //Guarding #include "mWithTwoModelBlocks_Ref1.h" #endif
Guarding S-Function Block Headers
When a model has an S-Function block that is conditional due to any connected variant blocks, the software guards the header files associated with the S-Function block with the corresponding variant condition in the generated code.
Consider a model with an S-Function block connected to a Variant Source block. In the generated code, the header file is guarded with the variant condition.
#ifndef mSFunctionInclude_COMMON_INCLUDES_ #define mSFunctionInclude_COMMON_INCLUDES_ #include "rtwtypes.h" #include "rt_logging.h" #if V == 1 //Guarding #include "myHeader.h" #endif #endif /* mSFunctionInclude_COMMON_INCLUDES_ */