Preserve Variables in Generated Code

As you iteratively develop a model, you capture the values of signals and states that
model execution generates. You also tune parameter values during execution to observe results
on the signals and states. You can then base your design decisions upon analysis of these
outputs. To access signal, state, and parameter data in a rapid prototyping environment, you
can configure the generated code to store the data in addressable memory.

Depending on the system target file that you use (such as grt.tlc), by
default, optimization settings can make the generated code more efficient by:

Eliminating unnecessary global and local storage for signals and some states.

However, the optimizations do not eliminate storage for root-level
Inport and Outport blocks, which represent the primary
inputs and outputs of a system. To access this data, you do not need to take
optimizations into consideration.

Inlining the numeric values of block parameters. The code does not store the
parameters in memory, so you cannot interact with the parameters during code
execution.

To generate code that instead allocates addressable memory for this data, you can disable
the optimizations, or override the optimizations by specifying code generation settings for
individual data items.

Access Signal, State, and Parameter Data During Execution

As you iteratively develop a model, you capture output signal and state data that model execution generates. You also tune parameter values during execution to observe results on the outputs. You can then base your design decisions upon analysis of these outputs. To access this signal, state, and parameter data in a rapid prototyping environment, you can configure the generated code to store the data in addressable memory.

By default, optimization settings make the generated code more efficient by eliminating unnecessary signal storage and inlining the numeric values of block parameters. To generate code that instead allocates addressable memory for this data, you can disable the optimizations or specify code generation settings for individual data items.

Explore Example Model

Run a script that prepares the model rtwdemo_basicsc for this example.

The model loads numeric MATLAB variables into the base workspace. The workspace variables set some block parameters in the model. However, The Gain block in the model uses the literal value 2.

Disable Optimizations

1. In the model, clear the model configuration parameter Signal storage reuse. When you clear this optimization and other optimizations such as Eliminate superfluous local variables (expression folding), the generated code allocates memory for signal lines. Clearing Signal storage reuse disables most of the other optimizations.

set_param('rtwdemo_basicsc','OptimizeBlockIOStorage','off')

2. Set the model configuration parameter Default parameter behavior to Tunable. When set to Tunable, this configuration parameter causes the generated code to allocate memory for block parameters and workspace variables.

4. In the code generation report, view the file rtwdemo_basicsc.h. This header file defines a structure type that contains signal data. The structure contains fields that each represent a signal line in the model. For example, the output signal of the Gain block, whose name is Gain, appears as the field Gain.

The file defines a structure type that contains block parameter data. For example, the Gain parameter of the Gain block appears as the field Gain_Gain. The other fields of the structure represent other block parameters and workspace variables from the model, including initial conditions for signals and states.

The code algorithm in the model step function calculates the signal values. It then assigns these values to the fields of the signal structure. To perform the calculations, the algorithm uses the parameter values from the fields of the parameter structure.

Exclude Data Items from Optimizations

When you want to select code generation optimizations such as Signal storage reuse, you can preserve individual data items from the optimizations. The generated code then allocates addressable memory for the items.

8. In the Model Data Editor, use the Value column to set the gain value to K1.

10. Next to K1, click the action button (with three vertical dots) and select Create.

11. In the Create New Data dialog box, set Value to Simulink.Parameter(2) and click Create. A Simulink.Parameter object named K1, with value 2, appears in the base workspace.

12. In the property dialog box for K1, apply a storage class other than Auto by using Storage class. For example, use the storage class Model default to represent the parameter object as a field of the global parameters structure.

14. In the code generation report, view the file rtwdemo_basicsc.h. The structure that contains signal data now defines only one field, Gain, which represents the test-pointed output of the Gain block.

You can configure the generated code to contain extra code and files so that you can access model data through standardized interfaces. For example, use the C API to log signal data and tune parameters during execution.

`. Copy this custom source code into a file named ex_myHandCode.c in your current folder.

10. In the code generation report, view the interface file rtwdemo_basicsc_capi.c. This file initializes the arrays of structures that you can use to interact with data items through the C API. For example, in the array of structures rtBlockSignals, the first structure (index 0) describes the test-pointed output signal of the Gain block in the model.

The fields of the structure, such as addrMapIndex, indicate indices into other arrays of structures, such as rtDataAddrMap, that describe the characteristics of the signal. These characteristics include the address of the signal data (a pointer to the data), the numeric data type, and the dimensions of the signal.

11. In the file rtwdemo_basicsc.c, view the code algorithm in the model step function. The algorithm first executes the code that you specified in the System Outputs block.

This code first perturbs the input signal input2 by incrementing the value of the signal each time the step function executes. The code then uses the built-in macro rtmGetDataMapInfo to extract model mapping information from the model data structure rtwdemo_basicsc_M. The pointer MMI points to the extracted mapping information, which allows the functions tuneFcn and logFcn to access the information contained in the arrays of structures that the C API file rtwdemo_basicsc_capi.c defines.

12. View the function tuneFcn in the file ex_myHandCode.c. This function uses the C API (through the model mapping information mmi) and a pointer to the simulation time to print the value of the parameter K1 at specific times during code execution. When the simulation time reaches 5 seconds, the function changes the parameter value in memory. By using a switch case block, the function can access the parameter data whether the data type is int8 or double.

13. View the code algorithm in the model step function again. Near the end of the function, the algorithm executes the code that you specified in the System Outputs block. This code calls the function logFcn.

14. View the function logFcn in the file ex_myHandCode.c. The function uses the C API to print the value of the test-pointed signal. The function can access the signal data whether the data type is single or double.

15. At the command prompt, run the generated executable rtwdemo_bascisc.exe.

Preserve accessibility and tunability of a data item after you select
optimizations

You can generate more efficient code by selecting optimizations such as
Signal storage reuse, but the code generator eliminates
storage for as many data items as possible. To exclude individual data items
from the optimizations:

Configure a signal as a test point (see Configure Signals as Test Points (Simulink)) or apply a storage class such as
ExportedGlobal to the signal (see Apply Storage Classes to Individual Signal, State, and Parameter Data Elements). If you use test points, when you later configure the model for
efficient production code, you can subject the test-point signals to
optimizations by selecting the model configuration parameter
Ignore test point signals. Apply a storage class
only when you need to control the representation of the signal in the
code.

Represent a data item as a separate global variable in the generated
code

When you disable optimizations, signal lines, block states, and
parameters appear in the generated code as fields of structures. You cannot
control the names of the structures without Embedded
Coder®. To instead store a data item in a separate global variable whose
name, file placement, and other characteristics you can control, apply a storage
class to a signal, state, or Simulink.Parameter object. See
Apply Storage Classes to Individual Signal, State, and Parameter Data Elements.

When you generate code and an external executable from a model, you can
simulate the model in external mode to communicate with the running executable.
You can tune parameters and monitor signals during the simulation. However, in
this simulation mode, parameter tunability limitations that apply to code
generation also apply to the simulation. For information about the code
generation limitations, see Limitations for Block Parameter Tunability in Generated Code.

If you have Simulink
Real-Time, you can tune parameters and monitor signals during execution of
your real-time application. Make signals accessible and parameters tunable by
clearing optimizations and applying test points and storage classes. See Parameter Tuning with Simulink Real-Time Explorer (Simulink Real-Time).