Skip to Main Content Skip to Search
File Exchange
MATLAB Newsgroup
Link Exchange
  Blogs  
 Contest 
MathWorks.com

Seth on Simulink

May 7th, 2008

Bus Signals in the Generated Code

Blog reader Paul J. shared with us his mental model of the bus as a structure. While this isn’t true of virtual buses, it is precisely true of nonvirtual buses. In fact, when you generate the code for a nonvirtual bus using Real-Time Workshop, the result is a structure.

Focus on the boundaries

In a previous post about nonvirtual bus signals I talked about memory allocated for the bus. The places we have to think about memory allocation are the boundaries of systems. Here is the simplebusdemo_nv.mdl

Simple bus demo diagram with a nonvirtual bus

This model has the root level boundaries defined by the inport and outport blocks. It also has a boundary at the edge of the ReusableFcn subsystem. The main_bus crosses this boundary and the generated code is different if the bus is virtual versus nonvirtual.

The ReusableFcn subsystem contains a Bus Selector and two gain blocks.

ReusableFcn subsystem with nonvirtual bus input

I configured the subsystem to generate a reusable function. Here are the settings for the subsystem:

ReusableFcn subsystem parameters

Basically, I have specified how Real-Time Workshop should wrap up the algorithm implemented inside this system. By specifying “Treat as atomic unit”, the blocks inside the system execute together. Real-Time Workshop will generate reusable function code with my specified name (ReusableFcn) into a file of the same name (ReusableFcn.c). The reusable function code will pass input and output signals as arguments to the function.

I can now picture what this will look like:

ReusableFcn(inputs..., outputs...)

Virtual buses pass every element separately

ReusableFcn subsystem with virtual bus input

When the bus signal is virtual at the inport to the ReusableFcn, only the elements of the bus that are used in the system need to be passed through the boundary. Here is the actual code for the function call:

30   /* Outputs for atomic SubSystem: '<Root>/ReusableFcn' */
31   ReusableFcn(simplebusdemo_vir_U.Pulse, simplebusdemo_vir_U.Chirp,
32               &simplebusdemo_vir_B.ReusableFcn_m);
33 

Notice, there is no evidence in the code that a bus signal exists. At compile-time, direct connections between sources and destinations replace the virtual bus.

19 /* Output and update for atomic system: '<Root>/ReusableFcn' */
20 void ReusableFcn(real32_T rtu_0, real_T rtu_1, rtB_ReusableFcn *localB)
21 {
22   /* Gain: '<S1>/Gain' */
23   localB->Gain = 2.0F * rtu_0;
24 
25   /* Gain: '<S1>/Gain1' */
26   localB->Gain1 = 3.0 * rtu_1;
27 }

Nonvirtual buses are structures

ReusableFcn subsystem with nonvirtual bus input

The nonvirtual bus is a contiguous block of memory. This is assembled and passed into the ReusableFcn.

30   /* local block i/o variables */
31   main_bus rtb_main_bus;
32 
33   /* BusCreator: '<Root>/Bus Creator' incorporates:
34    *  BusCreator: '<Root>/BusConversion_InsertedFor_Bus Creator_at_inport_0'
35    *  BusCreator: '<Root>/BusConversion_InsertedFor_Bus Creator_at_inport_1'
36    *  Inport: '<Root>/In1'
37    *  Inport: '<Root>/In2'
38    *  Inport: '<Root>/In3'
39    *  Inport: '<Root>/In4'
40    *  Inport: '<Root>/In5'
41    */
42   rtb_main_bus.bus1.Chirp = simplebusdemo_nv_U.Chirp;
43   rtb_main_bus.bus1.Constant[0] = simplebusdemo_nv_U.Constant[0];
44   rtb_main_bus.bus1.Constant[1] = simplebusdemo_nv_U.Constant[1];
45   rtb_main_bus.bus1.Constant[2] = simplebusdemo_nv_U.Constant[2];
46   rtb_main_bus.bus2.Clock = simplebusdemo_nv_U.Clock;
47   rtb_main_bus.bus2.Pulse = simplebusdemo_nv_U.Pulse;
48   rtb_main_bus.bus2.Sine[0] = simplebusdemo_nv_U.Sine[0];
49   rtb_main_bus.bus2.Sine[1] = simplebusdemo_nv_U.Sine[1];
50 
51   /* Outputs for atomic SubSystem: '<Root>/ReusableFcn' */
52   ReusableFcn(&rtb_main_bus, &simplebusdemo_nv_B.ReusableFcn_a);

Each of the input signals is being copied into the rtb_main_bus variable, which is an instance of the main_bus type. This structure matches the bus object definition specified by main_bus, bus1, and bus2.

I notice that the ReusableFcn has a shorter interface. Now the only input signal is a pointer to the rtb_main_bus, which is allocated locally.

ReusableFcn subsystem with nonvirtual bus input

19 /* Output and update for atomic system: '<Root>/ReusableFcn' */
20 void ReusableFcn(const main_bus *rtu_In1, rtB_ReusableFcn *localB)
21 {
22   /* Gain: '<S1>/Gain' */
23   localB->Gain = 2.0F * (*rtu_In1).bus2.Pulse;
24 
25   /* Gain: '<S1>/Gain1' */
26   localB->Gain1 = 3.0 * (*rtu_In1).bus1.Chirp;
27 }

In the case of nonvirtual bus signals, the concept of interface specification using the bus object carries all the way down to the generated code.

Now it’s your turn

We have now covered most of the important topics on bus signals. What questions remain about bus signals and their use in your models? Post a comment here.

3 Responses to “Bus Signals in the Generated Code”

  1. Bob replied on :

    Any particular reason you chose to specify the name of the atomic subsystem? I try to avoid that in case I’ve used the block twice with different I/O data types, and usually find the name in the generated code comes close enough to the subsystem name to make traceability possible.

  2. Bob replied on :

    Occasionally we’ve used busses to parameterize a model. To cut down on function interface overhead, the non-virtual bus makes sense. But if you use a set of Constant blocks to feed a Bus Creator outputting a non-virtual bus, the generated code looks like:
    rtb_bus.bus1.Parameter1 = 7;
    rtb_bus.bus1.Parameter2 = FRED;
    rtb_bus.bus2.Parameter3 = 8;
    instead of:
    rtb_bus = { {7, FRED}, {8} };
    And this usually appears in the step, not the initialize.

    Is there a way to get the preferred output?

  3. Seth replied on :

    @Bob - I chose to specify the name because I wanted to shorten things up for the blog post. When I used the Auto or Subsystem Name option I got this:


    19 /* Output and update for atomic system: ‘<Root>/ReusableFcn’ */
    20 void simplebusdemo_nv_ReusableFcn(const main_bus *rtu_0,
    21 rtB_ReusableFcn_simplebusdemo_n *localB)
    22 {

    I was just trying to avoid the line wrap.

    Regarding parameterization using bus signals, this is a limitation of the current behavior of bus signals. Currently, bus signals can not inherit the Inf sample time, so they end up in the step function even if the inputs are constant. It should be possible to use a custom storage class to control the generation of the code for the bus and put the code into the initialization section.

Leave a Reply


Seth Popinchalk is an Application Engineer for The MathWorks. He writes here about Simulink and other MathWorks tools used in Model-Based Design.
  • Kai: I’m using R14sp3. The latter mentioned trick “right click option to align, distribute and resize...
  • Bob: I’ve done a few more advanced blocks like this. While a bit more complex than regular blocks, I’ve...
  • Gernot Grabmair: large number of parameters: I’m looking for this discussion since some weeks and...
  • Mapa Ustka: Nice Blog!Very good Blog!
  • Kevin: Hi Seth, Thank you for much for the great tutorial. I am using MATLAB R2007a, and I have successfully added my...
  • resodad: Hi Seth, I would like to use gumstix or robostix (www.gumstix.com) for a real time target. They are small...
  • Paul J.: Seth, “doc slblocks” is not very enlightening (at least in 2007b). It basically says to grab a...
  • Georg Wiedermann: Dear Seth, as Kieran I often wondered how people bring large numbers of parameters into model. I...
  • Kieran Parsons: I think that a very useful future block post would be how to build and maintain large models with a...
  • Kieran Parsons: I do use libraries regularly and share that code with others in my team. One issue (Thread: 1-6A8141)...

These postings are the author's and don't necessarily represent the opinions of The MathWorks.

Related Topics