Main Content

Generate Code for Variant Elements Within Buses

This example explains how to generate code for buses with elements having different variant conditions.

Explore the Model

Open the slexVariantBus model from the Variant Elements Within Buses example.

model = "slexVariantBus";
open_system(model)

The model consists of two signals, a and b, which are merged into a bus. These signals have variant conditions, V == 1 and W == 1, respectively. During simulation, the bus selector receives two signals with variant conditions V == 1 and W == 1. Simulate the model.

sim(model)

When you select individual signals from the bus using the bus selector, the corresponding variant condition is also selected. There is no difference in the propagation behavior of variant conditions when passing through virtual or nonvirtual buses. For more information on buses, see Explore Simulink Bus Capabilities.

Generate Code for Variant Buses with Regular Conditions if and else if

1. To generate code with the variant choices guarded by conditions if and else if, specify the Variant activation time of the variant blocks to startup.

set_param(model+"/VS2","VariantActivationTime","startup");
set_param(model+"/VS3","VariantActivationTime","startup");

3. On the Apps tab of toolstrip, click Simulink Coder. In the C code tab, select Build > Generate code. Alternatively, enter this command in the Command Window.

slbuild(model);

Note

When generating code with conditions, the bus types and hierarchies of all bus inputs must be the same. For information on bus hierarchies, see View Bus Hierarchy.

Virtual and Nonvirtual Bus in Conditions if and else if

A virtual bus does not appear as a structure or any other coherent unit in the generated code. A separate copy of any algorithm that manipulates the bus exists for each bus element. In general, virtual buses do not affect the generated code. In this example, the buses a and b pass through a Unit Delay block. The generated slexVariantBus.h file defines one Unit Delay block for each element of the virtual bus. The Unit Delay blocks are defined unconditionally to avoid code execution with incorrect or unintended values when variant conditions are not met.

/* Block states (default storage) for system '<Root>' */
typedef struct {
 real_T UnitDelay_1_DSTATE;           /* '<Root>/Unit Delay' */
 real_T UnitDelay_2_DSTATE;           /* '<Root>/Unit Delay' */
} DW_slexVariantBus_T;
/* External inputs (root inport signals with default storage) */
typedef struct {
 real_T a;                            /* '<Root>/In1' */
 real_T b;                            /* '<Root>/In2' */
} ExtU_slexVariantBus_T;
/* External outputs (root outports fed by signals with default storage) */
typedef struct {
 real_T Out2;                         /* '<Root>/Out2' */
 real_T Out1;                         /* '<Root>/Out1' */
} ExtY_slexVariantBus_T;
/* Parameters (default storage) */
struct P_slexVariantBus_T_ {
 int32_T V;                           /* Variable: V
                                       * Referenced by:
                                       *   '<Root>/In1'
                                       *   '<Root>/Bus Creator1'
                                       *   '<Root>/Bus Selector'
                                       *   '<Root>/Unit Delay'
                                       *   '<Root>/Out2'
                                       *   '<Root>/V'
                                       */
 int32_T W;                           /* Variable: W
                                       * Referenced by:
                                       *   '<Root>/In2'
                                       *   '<Root>/Bus Creator1'
                                       *   '<Root>/Bus Selector'
                                       *   '<Root>/Unit Delay'
                                       *   '<Root>/Out1'
                                       *   '<Root>/W'
                                       */
};

The variant choices are enclosed in conditions if and else if.

/* Model step function */
void slexVariantBus_step(void)
{
 real_T rtb_a;
 real_T rtb_b;
 real_T rtb_b_b;
/* UnitDelay generated from: '<Root>/Unit Delay' incorporates:
 *  SignalConversion generated from: '<Root>/Unit Delay'
 */
if (slexVariantBus_P.V == 1) {
  rtb_b_b = slexVariantBus_DW.UnitDelay_1_DSTATE;
} else if ((slexVariantBus_P.W == 1) && (slexVariantBus_P.V != 1)) {
  /* SignalConversion generated from: '<Root>/Unit Delay' */
  rtb_b_b = 0.0;
}
/* Outport: '<Root>/Out2' */
if (slexVariantBus_P.V == 1) {
  slexVariantBus_Y.Out2 = rtb_b_b;
}
/* End of Outport: '<Root>/Out2' */
/* UnitDelay generated from: '<Root>/Unit Delay' incorporates:
 *  SignalConversion generated from: '<Root>/Unit Delay'
 */
if (slexVariantBus_P.W == 1) {
  rtb_b_b = slexVariantBus_DW.UnitDelay_2_DSTATE;
} else if ((slexVariantBus_P.V == 1) && (slexVariantBus_P.W != 1)) {
  /* SignalConversion generated from: '<Root>/Unit Delay' */
  rtb_b_b = 0.0;
}
/* Outport: '<Root>/Out1' incorporates:
 *  Inport: '<Root>/In2'
 *  SignalConversion generated from: '<Root>/Bus Creator1'
 */
if (slexVariantBus_P.W == 1) {
  slexVariantBus_Y.Out1 = rtb_b_b;
  rtb_b = slexVariantBus_U.b;
}
/* End of Outport: '<Root>/Out1' */
/* SignalConversion generated from: '<Root>/Bus Creator1' incorporates:
 *  Inport: '<Root>/In1'
 */
if (slexVariantBus_P.V == 1) {
  rtb_a = slexVariantBus_U.a;
} else if ((slexVariantBus_P.W == 1) && (slexVariantBus_P.V != 1)) {
  /* SignalConversion generated from: '<Root>/Bus Creator1' */
  rtb_a = 0.0;
}
/* End of SignalConversion generated from: '<Root>/Bus Creator1' */
/* SignalConversion generated from: '<Root>/Bus Creator1' */
if ((slexVariantBus_P.V == 1) && (slexVariantBus_P.W != 1)) {
  rtb_b = 0.0;
}
/* End of SignalConversion generated from: '<Root>/Bus Creator1' */
/* Update for UnitDelay generated from: '<Root>/Unit Delay' */
if (slexVariantBus_P.V == 1) {
  slexVariantBus_DW.UnitDelay_1_DSTATE = rtb_a;
}
/* Update for UnitDelay generated from: '<Root>/Unit Delay' */
if (slexVariantBus_P.W == 1) {
  slexVariantBus_DW.UnitDelay_2_DSTATE = rtb_b;
}
...
 }
}

A nonvirtual bus appears as a structure in the generated code, and only one copy exists of any algorithm that uses the bus. The use of a structure in the generated code can be helpful when tracing the correspondence between the model and the code. In this example, the buses a and b pass through a Unit Delay block. The Simulink.Bus object myBus appears in the generated slexVariantBus_types.h file as a structure for the nonvirtual buses. The bus object used in the bus is unconditional and it generates unguarded code, as shown below. For more information on bus objects, see Specify Bus Properties with Bus Objects.

typedef struct {
real_T a;
real_T b;
} myBus;

The generated slexVariantBus.h file defines one Unit Delay block for the nonvirtual bus, using the myBus structure.

/* Block states (default storage) for system '<Root>' */
typedef struct {
  myBus UnitDelay_DSTATE;              /* '<Root>/Unit Delay' */
} DW_slexVariantBus_T;

Virtual and Nonvirtual Bus in Preprocessor Conditionsals #if and #elif

When you generate code with the code compile variant activation time for a model using a ERT-based system target file, such as ert.tlc, the number of copies and the data type of the Unit Delay block in the generated code are the same as those for the startup activation time. Unlike with startup activation time, each definition of the Unit Delay block is enclosed in the preprocessor conditional #if of the corresponding element.

This is a sample of the code generated for a virtual variant bus:

/* Block states (default storage) for system '<Root>' */
typedef struct {
#if V == 1
 real_T UnitDelay_1_DSTATE;           /* '<Root>/Unit Delay' */
#define DW_SLEXVARIANTBUS_T_VARIANT_EXISTS
#endif
#if W == 1
 real_T UnitDelay_2_DSTATE;           /* '<Root>/Unit Delay' */
#define DW_SLEXVARIANTBUS_T_VARIANT_EXISTS
#endif
#ifndef DW_SLEXVARIANTBUS_T_VARIANT_EXISTS
 uchar_T rt_unused;
#endif
} DW_slexVariantBus_T;
/* External inputs (root inport signals with default storage) */
typedef struct {
#if V == 1
 real_T a;                            /* '<Root>/In1' */
#define EXTU_SLEXVARIANTBUS_T_VARIANT_EXISTS
#endif
#if W == 1
 real_T b;                            /* '<Root>/In2' */
#define EXTU_SLEXVARIANTBUS_T_VARIANT_EXISTS
#endif
#ifndef EXTU_SLEXVARIANTBUS_T_VARIANT_EXISTS
 uchar_T rt_unused;
#endif
} ExtU_slexVariantBus_T;
/* External outputs (root outports fed by signals with default storage) */
typedef struct {
#if V == 1
 real_T Out2;                         /* '<Root>/Out2' */
#define EXTY_SLEXVARIANTBUS_T_VARIANT_EXISTS
#endif
#if W == 1
 real_T Out1;                         /* '<Root>/Out1' */
#define EXTY_SLEXVARIANTBUS_T_VARIANT_EXISTS
#endif
#ifndef EXTY_SLEXVARIANTBUS_T_VARIANT_EXISTS
 uchar_T rt_unused;
#endif
} ExtY_slexVariantBus_T;

The generated slexVariantBus.h file defines one Unit Delay block for the nonvirtual bus, using the myBus structure. The Unit delay block is enclosed in a logical OR of the variant conditions, V == 1 and W == 1, from all the elements of the nonvirtual bus.

/* Block states (default storage) for system '<Root>' */
typedef struct {
#if V == 1 || W == 1
  myBus UnitDelay_DSTATE;              /* '<Root>/Unit Delay' */
#define DW_SLEXVARIANTBUS_T_VARIANT_EXISTS
#endif
#ifndef DW_SLEXVARIANTBUS_T_VARIANT_EXISTS
 uchar_T rt_unused;
#endif
} DW_slexVariantBus_T;

Variant Bus with Model Block

Consider this model containing a Model block.

This model has two signals a and b that have variant conditions, V == 1 and V == 2 respectively. The Model block provides the bus selector with two signals having two different variant conditions (V == 1 and V == 2). During simulation, the Model block propagates the variant conditions received from the referenced model mVarBus_bot at its output ports. The variant condition at each output port is the logical OR of the variant conditions, V == 1 || V == 2 from the variant choices of the mVarBus_bot model. For more information on variant condition propagation with Model blocks, see Propagate Variant Conditions to Enable or Disable Model or Subsystem References in Hierarchy.

Limitations

States logging for blocks (for example, Unit Delay) that accept buses with inactive elements is not supported. For detailed information on generating code for buses, see Generate Code for Nonvirtual Buses.