Generate Efficient Code by Specifying Data Types for Block Parameters

To generate more efficient code, match the data types of block parameters (such as the Gain parameter of a Gain block) with signal data types. Alternatively, you can store parameters in smaller data types.

Eliminate Unnecessary Typecasts and Shifts by Matching Data Types

These examples show how to generate efficient code by configuring a block parameter to use the same data type as a signal that the block operates on.

Store Data Type Information in Model

Open the example model rtwdemo_basicsc and configure it to show the generated names of blocks.

load_system('rtwdemo_basicsc')
set_param('rtwdemo_basicsc','HideAutomaticNames','off')
open_system('rtwdemo_basicsc')

Identify the Gain block in the model, which uses the base workspace variable K1 to set the value of the Gain parameter. The input signal of this block uses the data type single.

On the Modeling tab, click Model Data Editor.

In the Model Data Editor, select the Parameters tab.

In the model, select the Gain block. In the Model Data Editor, the Data Type column shows that the data type of the Gain parameter of the block is set to Inherit: Same as input. With this setting, the Gain parameter of this block uses the same data type as the input signal.

In the Model Data Editor, set the Change view drop-down list to Code.

Update the block diagram. Now, in the Model Data Editor, the data table shows rows that correspond to workspace variables that the model uses, including K1.

In the Model Data Editor, find the row that corresponds to K1. For that row, in the Storage Class column, select Convert to parameter object. Simulink converts K1 to a Simulink.Parameter object.

Use the Storage Class column to apply the storage class ExportedGlobal. With this setting, the object appears in the generated code as a global variable.

In the Model Data Editor, set Change view to Design.

In the data table, for the row that represents K1, in the Data Type column, select auto. With this setting, the parameter object acquires its data type from the block parameters that use the object (in this case, the Gain block parameter).

Alternatively, to create and configure the object, use these commands at the command prompt:

K1 = Simulink.Parameter(2);
K1.CoderInfo.StorageClass = 'ExportedGlobal';

Generate code from the model.

rtwbuild('rtwdemo_basicsc')
### Starting build procedure for: rtwdemo_basicsc
### Successful completion of build procedure for: rtwdemo_basicsc

The generated file rtwdemo_basicsc.c defines the global variable K1 by using the data type real32_T, which corresponds to the data type single in Simulink.

file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* Exported block parameters */','real32_T K1 = 2.0F;',1,1)
/* Exported block parameters */
real32_T K1 = 2.0F;                    /* Variable: K1

The generated code algorithm in the model step function uses K1 directly without typecasting.

rtwdemodbtype(file,' rtwdemo_basicsc_DW.X = K1',...
    ' rtCP_Table1_bp01Data, rtCP_Table1_tableData,',1,1)
    rtwdemo_basicsc_DW.X = K1 * look1_iflf_binlx(rtwdemo_basicsc_U.input2,
      rtCP_Table1_bp01Data, rtCP_Table1_tableData, 10U);

On the Model Data Editor Parameters tab, you can optionally set the data type of the Gain block parameter to Inherit: Inherit via internal rule (the default). In this case, the block parameter chooses the same data type as the input signal, single. However, when you use Inherit: Inherit via internal rule, under other circumstances (for example, when you use fixed-point data types), the block parameter might choose a different data type.

Store Data Type Information in Parameter Object

When you use a Simulink.Parameter object to export or import parameter data from the generated code to your external code, for example by applying the storage class ImportedExtern, you can specify data type information in the parameter object. To match the data type of the parameter object with a signal data type, create a Simulink.NumericType or Simulink.AliasType object. You can strictly control the data type that the parameter object uses in the generated code, eliminating the risk that Simulink chooses a different data type when you make changes to the model.

At the command prompt, create a Simulink.NumericType object that represents the data type single.

myType = Simulink.NumericType;
myType.DataTypeMode = 'Single';

Use the Model Data Editor Data Type column to set these data types to myType:

  • The parameter object. Use the Parameters tab.

  • The Inport block named In2. Use the Inports/Outports tab. Due to data type propagation, the input signal of the Gain block also uses myType.

Use the Model Data Editor Parameters tab to set the data type of the Gain block parameter to Inherit: Inherit from 'Gain'. Use this data type object as the data type of the parameter object.

Alternatively, to configure the object and the blocks, use these commands at the command prompt:

K1.DataType = 'myType';
set_param('rtwdemo_basicsc/In2','OutDataTypeStr','myType')
set_param('rtwdemo_basicsc/Gain','ParamDataTypeStr','Inherit: Inherit from ''Gain''')

Generate code from the model.

rtwbuild('rtwdemo_basicsc')
### Starting build procedure for: rtwdemo_basicsc
### Successful completion of build procedure for: rtwdemo_basicsc

The global variable K1 continues to use the data type real32_T.

file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* Exported block parameters */','real32_T K1 = 2.0F;',1,1)
/* Exported block parameters */
real32_T K1 = 2.0F;                    /* Variable: K1

Reduce Memory Consumption by Storing Parameter Value in Small Data Type

When you use a parameter object (for example, Simulink.Parameter) to set block parameter values, you can configure the object to appear in the generated code as a tunable global variable. By default, the parameter object and the corresponding global variable typically uses the same data type as the signal or signals on which the block operates. For example, if the input signal of a Gain block uses the data type int16, the parameter object typically use the same data type. To reduce the amount of memory that this variable consumes, specify that the variable use a smaller integer data type such as int8.

Store Parameter Value in Integer Data Type

Run the script prepare_rtwdemo_basicsc_2, which prepares the model rtwdemo_basicsc for this example.

run(fullfile(matlabroot,'examples','simulinkcoder',...
    'main','prepare_rtwdemo_basicsc_2'))

Many of the signals in the model use the data type single.

On the Modeling tab, click Model Data Editor.

In the Model Data Editor, inspect the Parameters tab.

Click the Show/refresh additional information button.

Next to the Filter contents box, activate the Filter using selection button.

In the model, click the Gain block. The Model Data Editor shows one row that corresponds to the Gain parameter of the block and one row that corresponds to the MATLAB variable K1, which sets the parameter value to 2. K1 resides in the base workspace.

In the Model Data Editor, set the Change view drop-down list to Code.

In the data table, for the row that corresponds to K1, in the Storage Class column, from the drop-down list, select Convert to parameter object. Simulink converts K1 to a Simulink.Parameter object.

K1 = Simulink.Parameter(K1);

Use the Storage Class column to apply the storage class ExportedGlobal to K1. With this setting, K1 appears in the generated code as a global variable.

K1.CoderInfo.StorageClass = 'ExportedGlobal';

In the Model Data Editor, set Change view to Design and use the Data Type column to apply the data type int8 to K1.

K1.DataType = 'int8';

For the row that represents the Gain block parameter, in the Data Type column, set the drop-down list to Inherit: Inherit from 'Gain'. With this setting, the Gain parameter of the block inherits the int8 data type from the parameter object.

set_param('rtwdemo_basicsc/Gain','ParamDataTypeStr',...
    'Inherit: Inherit from ''Gain''')

Generate code from the model.

rtwbuild('rtwdemo_basicsc')
### Starting build procedure for: rtwdemo_basicsc
### Successful completion of build procedure for: rtwdemo_basicsc

The generated file rtwdemo_basicsc.c defines the global variable K1 by using the data type int8_T, which corresponds to the data type int8 in Simulink.

file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* Exported block parameters */','int8_T K1 = 2;',1,1)
/* Exported block parameters */
int8_T K1 = 2;                         /* Variable: K1

The code algorithm in the model step function uses K1 to calculate the output of the Gain block. The algorithm casts K1 to the data type real32_T (single) because the signals involved in the calculation use the data type real32_T.

rtwdemodbtype(file,' rtwdemo_basicsc_DW.X =','10U);',1,1)
    rtwdemo_basicsc_DW.X = (real32_T)K1 * look1_iflf_binlx
      (rtwdemo_basicsc_U.input2, rtCP_Table1_bp01Data, rtCP_Table1_tableData,
       10U);

Store Fixed-Point Parameter Value in Smaller Integer Data Type

Suppose you configure the signals in your model to use fixed-point data types. You want a gain parameter to appear in the generated code as a tunable global variable. You know the range of real-world values that you expect the parameter to assume (for example, between 0 and 4). If you can meet your application requirements despite reduced precision, you can reduce memory consumption by configuring the parameter to use a different data type than the input and output signals of the block.

Open the example model fxpdemo_direct_form2 and configure it to show the generated names of blocks.

load_system('fxpdemo_direct_form2')
set_param('fxpdemo_direct_form2','HideAutomaticNames','off')
open_system('fxpdemo_direct_form2')

Update the block diagram. Signals in this model use signed fixed-point data types with a word length of 16 and binary-point-only scaling.

Open the Gain5 block dialog box. The Gain parameter is set to 1.85. Suppose you want to configure this parameter.

Set Gain to myGainParam and click Apply.

Click the action button (with three vertical dots) next to the parameter value. Select Create.

In the Create New Data dialog box, set Value to Simulink.Parameter(1.85) and click Create. The Simulink.Parameter object myGainParam appears in the base workspace.

In the myGainParam property dialog box, set Storage class to ExportedGlobal and click OK. With this setting, myGainParam appears in the generated code as a global variable.

In the block dialog box, on the Parameter Attributes tab, set Parameter minimum to 0 and Parameter maximum to 4.

Set Parameter data type to fixdt(0,8) and click Apply.

Click the Show Data Type Assistant button. The Data Type Assistant shows that the expression fixdt(0,8) specifies an unsigned fixed-point data type with a word length of 8 and best-precision scaling. When you simulate or generate code, the block parameter chooses a fraction length (scaling) that enables the data type to represent values between the parameter minimum and maximum (0 and 4) with the best possible precision.

In the Data Type Assistant, set Scaling to Binary point. Click Calculate Best-Precision Scaling, Fixed-point details, and Refresh Details. The information under Fixed-point details shows that a fraction length of 5 can represent the parameter values with a precision of 0.03125.

Set Scaling back to Best precision and click OK. In this example, when you simulate or generate code, the block parameter chooses a fraction length of 5.

Alternatively, you can use these commands at the command prompt to create the object and configure the block:

myGainParam = Simulink.Parameter(1.85);
myGainParam.CoderInfo.StorageClass = 'ExportedGlobal';
set_param('fxpdemo_direct_form2/Gain5','Gain','myGainParam')
set_param('fxpdemo_direct_form2/Gain5','ParamMin','0','ParamMax','4')
set_param('fxpdemo_direct_form2/Gain5','ParamDataTypeStr','fixdt(0,8)')

Configure the model to produce a code generation report. To reduce clutter in the Command Window, clear the configuration parameter Verbose build.

set_param('fxpdemo_direct_form2','GenerateReport','on',...
    'LaunchReport','on','RTWVerbose','off')

Generate code from the model.

evalc('rtwbuild(''fxpdemo_direct_form2'')');

The generated file fxpdemo_direct_form2.c defines the global variable myGainParam by using the data type uint8_T, which corresponds to the specified word length, 8. The code initializes the variable by using an integer value that, given the fraction length of 5, represents the real-world parameter value 1.85.

file = fullfile('fxpdemo_direct_form2_grt_rtw','fxpdemo_direct_form2.c');
rtwdemodbtype(file,'/* Exported block parameters */','uint8_T myGainParam = 59U;',1,1)
/* Exported block parameters */
uint8_T myGainParam = 59U;             /* Variable: myGainParam

The code algorithm uses myGainParam to calculate the output of the Gain5 block. The algorithm uses a C shift to scale the result of the calculation.

rtwdemodbtype(file,'/* Gain: ''<Root>/Gain5'' */',...
'/* Gain: ''<Root>/Gain'' incorporates:',1,0)
  /* Gain: '<Root>/Gain5' */
  fxpdemo_direct_form2_B.Gain5 = (int16_T)((myGainParam *
    fxpdemo_direct_form2_B.UnitDelay1) >> 5);

Related Topics