Main Content

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 to High.

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 model_initialize by default, performs signal and state initialization operations in this order:

  1. Initializes the signal and state data in the default generated structures, such as the DWork structure, to a stored value of zero.

  2. 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) or Model default (when the Code Mapping Editor specifies the Default storage class, the default setting).

    For example, the code applies this operation to data items that use the storage class ExportedGlobal.

  3. 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.

  4. 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.

  5. 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 global const structure.

  • Simulink.Parameter objects to which you apply a storage class that has an exported data scope. For example, the built-in storage class ExportedGlobal has an exported data scope, but the storage class ImportedExtern 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

GoalMore 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:

  • Data for which you specify a nonzero initial value by using a block parameter.

  • Data whose real-world initial value is zero but whose corresponding stored value is not zero.

  • Enumerated data whose default member maps to a nonzero integer.

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 ImportedExtern to a signal line, block state, or parameter object. For imported data:

  • The generated code does not initialize parameter data. Your code must initialize imported parameter data.

  • The generated initialization functions dynamically initialize some signal and state data. Unlike data that the generated code allocates, the code does not initialize imported signal or state data to a stored value of zero. Instead, the code immediately initializes the data to the real-world value that you specify in Simulink.

For more information, including how to prevent the generated code from initializing imported data, see Exchange Data Between External Calling Code and Generated Code.

See Also

Related Topics