Real-Time Workshop | ![]() ![]() |
Tutorial 4: A First Look at Generated Code
In this tutorial, you examine code generated from a simple model, to observe the effects of some of the many code optimization features available in Real-Time Workshop.
Note You can view the code generated from this example using the MATLAB editor. You may also view the code in the MATLAB Help browser if you enable the Create HTML report option before generating code. See the following section, HTML Code Generation Reports for an introduction to using the HTML report feature. |
The source model, example.mdl
, is shown below.
Setting up the Model
First, create the model and set up basic Simulink and Real-Time Workshop parameters as follows:
example_codegen
and make it your working directory:
example.mdl
.
Fixed-step
. Select the ode5 (Dormand-Prince)
solver algorithm.
Leave the other Solver pane parameters set to their default values.
Target configuration
from the Category menu. Next, select the Generate code only option. This option causes Real-Time Workshop to generate code without invoking make
to compile and link the code. This option is convenient for this exercise, as we are only interested in looking at the generated code. Note that the Build button caption changes to Generate code.
Generating Code Without Buffer Optimization
When the block I/O optimization feature is enabled, Real-Time Workshop uses local storage for block outputs wherever possible. We now disable this option to see what the nonoptimized generated code looks like:
Signal storage reuse
option and select the Off radio button, as shown below.
Target configuration
from the Category menu. Then click the Generate code button.
example_grt_rtw
. The file example_grt_rtw\example.c
contains the output computation for the model. Open this file into the MATLAB editor:
The generated C code consists of procedures that implement the algorithms defined by your Simulink block diagram. Your target's execution engine executes the procedures as time moves forward. The modules that implement the execution engine and other capabilities are referred to collectively as the run-time interface modules. See Program Architecture" in Chapter 7 of the Real-Time Workshop documentation for a complete discussion of how Real-Time Workshop interfaces and executes application, system-dependent, and system-independent modules, in each of the two styles of generated code.
In our example, the generated MdlOutputs
function implements the actual algorithm for multiplying a sine wave by a gain. The MdlOutputs
function computes the model's block outputs. The run-time interface must call MdlOutputs
at every time step.
With buffer optimizations turned off, MdlOutputs
assigns unique buffers to each block output. These buffers (rtB.sin_out, rtB.gain_out) are members of a global data structure, rtB
. The code is shown below:
void MdlOutputs(int_T tid) { /* Sin Block: <Root>/Sine Wave */ rtB.sin_out = rtP.Sine_Wave_Amp * sin(rtP.Sine_Wave_Freq * ssGetT(rtS) + rtP.Sine_Wave_Phase) + rtP.Sine_Wave_Bias; /* Gain Block: <Root>/Gain */ rtB.gain_out = rtB.sin_out * rtP.Gain_Gain; /* Outport Block: <Root>/Out1 */ rtY.Out1 = rtB.gain_out; }
We now turn buffer optimizations on and observe how these optimizations improve the code.
Generating Code with Buffer Optimization
Enable buffer optimizations and regenerate the code as follows:
Signal storage reuse
option and select the On radio button.
General code generation options
from the Category menu.
General code generation options (cont.)
from the Category menu.
example_grt_rtw
directory. Note that the previously generated code is overwritten.
example_grt_rtw/example.c
, and examine the function MdlOutputs
.
With buffer optimizations enabled, the code in MdlOutputs
reuses rtb_temp0, a temporary buffer with local scope, rather than assigning global buffers to each input and output:
void MdlOutputs(int_T tid) { /* local block i/o variables */ real_T rtb_temp0; /* Sin Block: <Root>/Sine Wave */ rtb_temp0 = rtP.Sine_Wave_Amp * sin(rtP.Sine_Wave_Freq * ssGetT(rtS) + rtP.Sine_Wave_Phase) + rtP.Sine_Wave_Bias; /* Gain Block: <Root>/Gain * Gain value: rtP.Gain_Gain */ rtb_temp0 *= rtP.Gain_Gain; /* Outport Block: <Root>/Out1 */ rtY.Out1 = rtb_temp0; }
This code is more efficient in terms of memory usage. The efficiency improvement gained by enabling Buffer reuse and Local block outputs would be more significant in a large model with many signals.
A Further Optimization: Expression Folding
As a final optimization, we will turn on expression folding, a code optimization technique that minimizes the computation of intermediate results and the use of temporary buffers or variables.
Enable expression folding and regenerate the code as follows:
General code generation options (cont.)
from the Category menu, if you have not already done so.
example_grt_rtw
directory.
example_grt_rtw/example.c
, and examine the function MdlOutputs
.
In the previous examples, the Gain block computation was computed in a separate code statement and the result was stored in a temporary location before the final output computation.
With Expression folding selected, there is a subtle but significant difference in the generated code: the gain computation is incorporated (or "folded") directly into the Outport computation, eliminating the temporary location and separate code statement. This computation is on the last line of the MdlOutputs function:
void MdlOutputs(int_T tid) { /* local block i/o variables */ real_T rtb_sin_out; /* Sin Block: <Root>/Sine Wave */ rtb_sin_out = rtP.Sine_Wave_Amp * sin(rtP.Sine_Wave_Freq * ssGetT(rtS) + rtP.Sine_Wave_Phase) + rtP.Sine_Wave_Bias; /* Outport: <Root>/Out1 incorporates: * Gain: <Root>/Gain * * Regarding <Root>/Gain : * Gain value: rtP.Gain_Gain */ rtY.Out1 = (rtP.Gain_Gain * rtb_sin_out); }
In many cases, Expression folding can incorporate entire model computations into a single, highly optimized line of code. Expression folding is turned on by default. We strongly recommend that you use this option.
HTML Code Generation Reports
When the Generate HTML report option under General code generation options
is selected (see figure below), a navigable summary of source files is produced when the model is built.
Code generation causes Real-Time Workshop to produce an HTML file for each source file, plus a summary and an index file, in a directory named /html
within the build directory. Unless you are running MATLAB in -nodesktop
mode (a UNIX option only), the HTML summary and index are automatically loaded into the MATLAB Help browser and displayed, as the following figure illustrates. You can click on links in the report to inspect source and include files, and view relevant documentation. Block header comments in source files displayed in the browser have hyperlinks back to the model that cause the block that generated that section of code to be highlighted. To review any HTML report at a later time, use any Web browser to open the file html/
model
_codgen_rpt.html
within your build directory.
Note The contents of HTML reports for different target types will vary, and reports for models with subsystems will feature additional information. |
For further information, consult these sections of the Real-Time Workshop documentation:
model
.c
files, refer to Program Architecture of the Real-Time Workshop documentation.
HTML Report for Code Generated for a GRT Target
![]() | Tutorial 3: Code Validation | Tutorial 5: Getting Started with External Mode Using GRT | ![]() |