Initialization of Signal, State, and Parameter Data in the Generated Code
Signal lines, block parameters, and block states in a model can appear in the generated code as data, for example, as global variables. By default, the code initializes this data before execution of the primary algorithm. To match the numerics of simulation in Simulink®, the code generator chooses the initial values based on specifications that you make in the model.
By understanding how the generated code initializes data, you can:
Model a system that reinitializes states during execution, which means that the application can restart the entire system.
Store initial values in memory as variables, which can persist between execution runs. You can then overwrite these values before starting or restarting a system.
Generate efficient code by eliminating storage for invariant initial values and by preventing the generation of code that unnecessarily or redundantly initializes data.
For basic information about initializing signals and states in a model, see Initialize Signals and Discrete States.
Static Initialization and Dynamic Initialization
To initialize a data item such as a global variable, an application can use static or dynamic initialization.
Static initialization occurs in the same statement that defines (allocates memory for) the variable. The initialization does not occur inside a function definition.
The code can be more efficient because none of the generated model functions execute initialization statements.
Dynamic initialization occurs inside a function. For each model or nonvirtual subsystem, the code generator typically creates one or more functions that are dedicated to initialization.
The generated code or your code can restart a system by calling an initialization function during execution.
Real-World Ground Initialization Requiring Nonzero Bit Pattern
Each data item has a real-world ground value. This value can
depend on the data type of the item. For example, for a signal whose data type is
double
or int8
, the real-world ground value is zero.
For an enumeration, the ground value is the default enumeration member.
For some kinds of data, to represent a real-world ground value, a computer stores zero in memory (all bits zero). However, for some other data, a computer stores a nonzero value in memory. This data includes, for example:
Fixed-point data with bias. The code initializes such a data item to the stored integer value that, given the scaling and bias, represents real-world zero.
An enumeration whose default member maps to an integer value other than zero. For example, if the default member is
High
with an underlying integer value of 3, the code initializes such a data item toHigh
.
Initialization of Signal and State Data
In a model, you can control signal and state initial values through block parameters.
For example, to set the initial value of a Unit Delay block, you use the
Initial condition parameter. In some cases, you can also use the
InitialValue
property of a Simulink.Signal
object.
For most of these block parameters, the default value is 0
.
You can also initialize states by using State Writer blocks in Initialize Function subsystems and the Initial states model configuration parameter.
By default, the generated code dynamically initializes signal and state data (and other
data, such as the model error status) in the generated initialization function. The
function, named
by default,
performs signal and state initialization operations in this order:model
_initialize
Initializes the signal and state data in the default generated structures, such as the DWork structure, to a stored value of zero.
Initializes additional signal and state data that are not in the default generated structures to the relevant real-world ground value.
This initialization applies only to data that meet both of these criteria:
The generated code defines (allocates memory for) the data.
The data use a storage class other than
Auto
(the default storage class) orModel default
(when the Code Mapping Editor specifies theDefault
storage class, the default setting).
For example, the code applies this operation to data items that use the storage class
ExportedGlobal
.Initializes each signal and state to the real-world value that the model specifies, for example, through the Initial condition parameter of a Unit Delay block.
Initializes each state to the real-world value that you assign by using a State Writer block. The function performs this initialization only if you use an Initialize Function subsystem in the model.
Initializes each state to the real-world value that you specify with the configuration parameter Initial states.
After this initialization function executes, each data item has the last real-world
value that the function assigned. For example, if you use a State Writer
block to initialize a block state to 5
while also using the
Initial states configuration parameter to initialize the same state
to 10
, the state ultimately uses 10
as an initial
value.
memset
for Bulk Initialization
To initialize signal or state data items that have contiguous storage to a stored
value of zero, the generated code can call memset
in an initialization
function. Data items that have contiguous storage include the DWork structure, arrays, or
data items that use a multiword data type.
If your application requires it, you can prevent the generated code from using
memset
for initializing floating-point data to stored zero. See Use memset to initialize floats and doubles to 0.0.
Tunable Initial Values
You can configure the way that tunable block parameters, such as the Gain parameter of a Gain block, appear in the generated code. Most block parameters that set initial values (for example, Initial condition) are tunable. For example, the configuration parameter Default parameter behavior can determine whether the initial values appear in the generated code as inlined constants or as tunable global data. You can also use parameter objects and storage classes to control the representation of these initial values.
For tunable initial values, in the model initialization function, the right-hand side of the assignment statement is a global variable, structure field, or other data whose value you can change in memory.
To make initial values tunable in the generated code, see Control Signal and State Initialization in the Generated Code.
Initialization of Parameter Data
The generated code statically initializes parameter data to the values that you specify in Simulink.
To express the initial value of a tunable parameter (a global variable) as a mathematical expression involving system constants or other macros, which requires Embedded Coder®, see Initialization by Mathematical Expression (Embedded Coder).
Kinds of Parameter Data
These model elements appear in the generated code as parameter data:
Tunable block parameters, such as the Gain parameter of a Gain block, when you set Default parameter behavior to
Tunable
. Each parameter appears as a field of a dedicated global structure.Some tunable block parameters when you set Default parameter behavior to
Inlined
. When the code generator cannot inline the value of a parameter as a literal number, the parameter appears as a field of a dedicated globalconst
structure.Simulink.Parameter
objects to which you apply a storage class that has an exported data scope. For example, the built-in storage classExportedGlobal
has an exported data scope, but the storage classImportedExtern
does not.
Initialization by Mathematical Expression (Embedded Coder)
You can set the value of a parameter object (such as
Simulink.Parameter
) to a mathematical expression involving numbers,
MATLAB® variables, and other parameter objects. See Set Variable Value by Using a Mathematical Expression.
If you use this technique with Embedded Coder, you can generate code that initializes the corresponding parameter data (global variable) by using the specified expression. For an example, see Initialize Parameter Value From System Constant or Other Macro (Embedded Coder) (Embedded Coder). For general information, including limitations, see Code Generation of Parameter Objects With Expression Values.
Data Initialization in the Generated Code
This example shows how the generated code initializes signal, state, and parameter data.
Explore Example Model
Open the example model, CounterModel
and configure the model to use the grt.tlc
system target file.
open_system('CounterModel') set_param('CounterModel', 'SystemTargetFile', 'grt.tlc');
In the Apps gallery, click Simulink Coder.
Open the Model Data Editor. On the Modeling tab, click Model Data Editor.
Inspect the States tab. For the Unit Delay block state, the Initial Value is set to 0
, the default, which means the initial value of the state is zero. The state is named X
.
Set Initial Value to a nonzero number, for example, 5
.
set_param('CounterModel/X','InitialCondition','5')
Open the Code Mappings editor. In the C Code tab, select Code Interface > Individual Element Code Mappings.
On the Signals/States tab, under States set Storage Class for X
to ExportedGlobal
. With this setting, the block state appears in the generated code as a separate global variable.
coder.mapping.utils.create('CounterModel'); cm = coder.mapping.api.get('CounterModel'); setState(cm,'CounterModel/X','StorageClass','ExportedGlobal');
In the model, open the Amplifier
subsystem, which is a triggered subsystem.
In the Model Data Editor, inspect the Parameters tab. To set and inspect initial values of signals and states, you can use the Parameters tab instead of the States tab.
The Model Data Editor shows that for the Outport block, the Initial output (InitialOutput
) parameter is set to 0
, the default. This subsystem output requires an initial value because the subsystem executes conditionally. Leave the initial value at the default.
In the model, clear Configuration Parameters > Signal storage reuse. When you clear this setting, signal lines appear in the generated code as fields of a generated structure whose purpose is to store signal data. This representation of the signals makes it easier to see how the code generator initializes data.
set_param('CounterModel','OptimizeBlockIOStorage','off')
In the model, inspect the configuration parameter Configuration Parameters > Optimization > Default parameter behavior. The configuration parameter is set to Inlined
, which means block parameters, including initial values, appear in the generated code as inlined literals or as const
data.
Navigate to the root level of the model.
In the Model Data Editor, click the Show/refresh additional information button.
Near the Filter contents box, click the Filter using selection button.
In the model, click the Constant block labeled INC
. The Model Data Editor shows that the Constant value (Value
) parameter of the block is set to INC
. INC
is a MATLAB variable in the base workspace.
For INC
, set the value in the Value column to Simulink.Parameter(uint8(1))
. MATLAB converts INC
to a Simulink.Parameter
object.
In the Code Mappings editor, on the Parameters tab, apply the storage class ExportedGlobal
to INC
. With this setting, the generated code defines INC
as a global variable. Concerning initialization, INC
is an item of parameter data.
INC = Simulink.Parameter(INC);
INC.StorageClass = 'ExportedGlobal';
Generate and Inspect Code
To build the model and generate code, press Ctrl+B.
slbuild('CounterModel');
### Starting build procedure for: CounterModel ### Successful completion of build procedure for: CounterModel Build Summary Top model targets: Model Build Reason Status Build Duration =============================================================================================================== CounterModel Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 9.9532s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 10.764s
In the generated file CounterModel.c
, outside the definition of a function, the code statically initializes the parameter data INC
. The value of INC
is 1
.
file = fullfile('CounterModel_grt_rtw','CounterModel.c'); coder.example.extractLines(file,'/* Exported block parameters */','uint8_T INC = 1U;',1,1)
/* Exported block parameters */ uint8_T INC = 1U; /* Variable: INC
In the same file, inspect the definition of the CounterModel_initialize
function. First, the function uses memset
to initialize the internal signals in the model to a stored value of 0
.
coder.example.extractLines(file,'/* block I/O */','sizeof(B_CounterModel_T));',1,1)
/* block I/O */ (void) memset(((void *) &CounterModel_B), 0, sizeof(B_CounterModel_T));
The function then initializes the Unit Delay state, X
, to a ground value. In this case, the ground value is zero.
coder.example.extractLines(file,'/* exported global states */','X = 0U;',1,1)
/* exported global states */ X = 0U;
The function also initializes other data, including the root-level inputs and outputs (Inport and Outport blocks), to ground values.
coder.example.extractLines(file,'/* external inputs */','Amplifier_Trig_ZCE = POS_ZCSIG;',1,1)
/* external inputs */ CounterModel_U.Input = 0; /* external outputs */ CounterModel_Y.Output = 0; /* Matfile logging */ rt_StartDataLoggingWithStartTime(CounterModel_M->rtwLogInfo, 0.0, rtmGetTFinal (CounterModel_M), CounterModel_M->Timing.stepSize0, (&rtmGetErrorStatus (CounterModel_M))); CounterModel_PrevZCX.Amplifier_Trig_ZCE = POS_ZCSIG;
The function then initializes X
to the value that you specified in the Initial condition block parameter.
coder.example.extractLines(file,'/* InitializeConditions for UnitDelay: ''<Root>/X'' */',... 'X = 5U;',1,1)
/* InitializeConditions for UnitDelay: '<Root>/X' */ X = 5U;
Finally, the function initializes the output of the Amplifier
subsystem.
coder.example.extractLines(file,'SystemInitialize for Triggered SubSystem',... 'End of SystemInitialize for SubSystem',1,1)
/* SystemInitialize for Triggered SubSystem: '<Root>/Amplifier' */ /* SystemInitialize for Outport: '<Root>/Output' incorporates: * Outport: '<S1>/Out' */ CounterModel_Y.Output = 0;
Inspect Difference Between Stored Value and Real-World Value
For some data, even if the real-world initial value is zero, a computer stores a nonzero value in memory. To observe this difference, apply a slope-bias fixed-point data type to the block state, X
. To run this example, you must have Fixed-Point Designer™.
In the Model Data Editor, inspect the Signals tab.
In the model, click the output signal of the Switch block, switch_out
.
Use the Data Type column of the Model Data Editor to set the signal data type to fixdt(1,16,1,3)
. This expression represents a fixed-point data type with a slope of 1
and a bias of 3
.
set_param('CounterModel/Switch','OutDataTypeStr',... 'fixdt(1,16,1,3)')
In the model, select the Sum block. In the Property Inspector, under Signal Attributes, clear Require all inputs to have the same data type.
set_param('CounterModel/Sum','InputSameDT','off')
To prevent compilation errors on different platforms, select the model configuration parameter Generate code only. This setting causes the model to generate only code.
set_param('CounterModel','GenCodeOnly','on')
To build the model and generate code, press Ctrl+B.
slbuild('CounterModel')
### Starting build procedure for: CounterModel ### Successful completion of code generation for: CounterModel Build Summary Top model targets: Model Build Reason Status Build Duration ============================================================================== CounterModel Generated code was out of date. Code generated. 0h 0m 7.1632s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 7.8097s
The model initialization function first initializes X
to a real-world ground value, 0
. Due to the slope-bias data type, which has bias 3
, this real-world value corresponds to a stored value of -3
.
coder.example.extractLines(file,'/* exported global states */','X = -3;',1,1)
/* exported global states */ X = -3;
The function then initializes X
to the real-world initial value that you specified in the Initial condition block parameter, 5
. This real-world value corresponds to a stored value of 2
.
coder.example.extractLines(file,'/* InitializeConditions for UnitDelay: ''<Root>/X'' */',... 'X = 2;',1,1)
/* InitializeConditions for UnitDelay: '<Root>/X' */ X = 2;
Modeling Goals
Goal | More Information |
---|---|
Explicitly model initialization behavior by using blocks | You can explicitly model initialization and reset behavior by using Initialize Function and Reset Function subsystems. In the subsystems, use State Writer blocks to calculate and assign an initial value for a state dynamically. The corresponding code appears in the model initialization function. For more information, see Startup, Reset, and Shutdown Function Interfaces. |
Prevent generation of code that explicitly initializes data to zero | If your application environment already initializes global variables to zero, for more efficient code, you can prevent the generation of statements that explicitly initialize global variables to zero. This optimization applies only to signals and states whose initial values are stored in memory as zero. For example, the code generator does not apply the optimization to:
The optimization requires Embedded Coder. For more information, see Remove Zero-Initialization Code (Embedded Coder). |
Generate code that imports data from your external code | You can generate code that reuses (imports) data that your external
code defines. For example, you can apply the storage class
For more information, including how to prevent the generated code from initializing imported data, see Exchange Data Between External Calling Code and Generated Code. |