Main Content

Generate Code from Variant Blocks with Startup Activation Time

This example shows you how to generate code with startup variant activation time. The generated code contains all variant choices with regular if statements.

Model

Open the model slexVariantSourceAndSinkWithStartup.slx. The Variant Source1 has conditions X==1 and X==2 for its input ports. The block named Variant Source1 has an update diagram activation time. X is a variant control variable and is defined in the PostLoadFcn of File -> Model Properties -> Callbacks. The Sine3 block is active when X==1 is true, and the Sine4 block is active when X==2 is true.

In the block named Variant Source2 block, the first input port is active when V==1 is true.The second input port is active when V==2 is true. The Variant Source2 has a startup activation time.

The block named Variant Sink has the conditions W==1 and W==2 on its output ports. These conditions are propagated to the connected blocks. The Gain5 block is assigned the condition W==1.The second output port of the Variant Sink block has the condition W==2. This condition is propagated to the Out4 block. If you select Allow zero active variant controls on the Variant Sink block, then the Sine5 and Gain4 blocks will be assigned the variant condition W==1|W==2.

open_system('slexVariantSourceAndSinkWithStartup.slx');

Generate Code

You can generate code by clicking on Build ERT or Build GRT. The inline variant blocks Variant Source2 and Variant Sink use the variant condition expression with parameters V and W. These parameters have an 'ExportedGlobal' storage class specification. When you specify a condition expression to determine the active choice, each variant control variable of the expression has a storage class associated with it. By using storage classes, you can control the appearance and placement of the variant control variables in the generated code. Storage classes also prevent the optimizations such as elimination of the storage for variant control variables in the generated code. The variables used in the variant condition expressions must satisfy certain criteria to generate code with Simulink Coder or Embedded Coder. For more information on the storage class specifications with startup activation time, see Storage Classes for Different Variant Activation Times.

Since the Variant Source2 and Variant Sink blocks have startup activation time, all choices are available, and the generated code from Embedded Coder (ERT) or Simulink Coder (GRT) will have regular if conditions.

The code generated with Embedded Coder runs the selected variant.

  if(V == 2) {
      rtb_Gain5 = sin((real_T)slexVariantSourceAndSinkWith_DW.counter * 2.0 *
                   3.1415926535897931 / 10.0);
      rtb_Gain4 = sin((real_T)slexVariantSourceAndSinkWith_DW.counter_h * 2.0 *
                   3.1415926535897931 / 10.0);
      rtb_Sine6 = rtb_Gain5 + rtb_Gain4;
    } else if(V == 1) {
       /* Sin: '<Root>/Sine1' */
       rtb_Sine6 = sin((real_T)slexVariantSourceAndSinkWith_DW.counter_c * 2.0 *
                   3.1415926535897931 / 10.0);
    }
  if((V == 1) || (V == 2)) {
      slexVariantSourceAndSinkWithS_Y.Out1 = 3.0 * rtb_Sine6;
    }

You can select the active variant using custom code via the System Initiliaze block. To change the value of V and W using custom code, navigate to Model Settings > Code Generation > Custom Code. Specify #include "ReadVarControl.h" under Header file and ReadVarControl.c under Source file.

The source file ReadVarControl.c should contain some code to read the value of V or W based on the requirement and set the active variant values.

  #include "rtwtypes.h"
  extern int32_T V;
  extern int32_T W;
  void SetValueOfVarControls()
  {
    // The values of V and W can be read from a sensor or hardware
    // for simplicity it is hardcoded.
    V = 2;
    W = 2;
  }

In the model initialize function, you may find code that sets the values for desired V and W, as shown below.

  void slexVarinatSourceAndSinkWithStartup_initialize(void)
  {
    SetValueOfVarControls();
    utAssert((W == 1) + (W == 2) == 1);
    utAssert((V == 1) + (V == 2) <= 1);
  }

NOTE -

1 The model initialize functions are not guarded in the generated code.

2 The SetUpRuntimeResources, Start, and Initialize methods of blocks are called irrespective of startup variant activation. The methods are not guarded conditionally in code generation.

3 Parameters used as variant control variables in startup activation will not appear in the generated CAPI or ASAP2 interfaces.

Once the model is initialized, the values of V and W do not change in the step method. If you have a requirement to ensure that value of variant control does not change in step, then you must add a check to the generated code to ensure that the variant control value does not change in step.

The utAssert statements in the model initialize function ensure that the generated code behavior for variant blocks matches with simulation. For example, utAssert((V == 1) + (V == 2) <= 1) ensures that you cannot have more than one active variant for Variant Source2.

If Allow zero active variant control is not selected, the utAssert statement checks that at least one variant choice is active for such variant blocks. If Allow zero active variant control is selected, it generates code to ensure that you cannot have more than one active variant.