Generate Modular Function Code
The Embedded Coder®software provides a Subsystem Parameters dialog box option,傅nction with separate data, that allows you to generate modular function code for nonvirtual subsystems, including atomic subsystems and conditionally executed subsystems.
By default, the generated code for a nonvirtual subsystem does not separate a subsystem's internal data from the data of its parent Simulink®model. This can make it difficult to trace and test the code, particularly for nonreusable subsystems. Also, in large models containing nonvirtual subsystems, data structures can become large and potentially difficult to compile.
About Nonvirtual Subsystem Code Generation
傅nction with separate dataallows you to generate subsystem function code in which the internal data for a nonvirtual subsystem is separated from its parent model and is owned by the subsystem. The subsystem data structure is declared independently from the parent model data structures. A subsystem with separate data has its own block I/O andDWork
data structure. As a result, the generated code for the subsystem is easier to trace and test. The data separation also tends to reduce the maximum size of global data structures throughout the model, because they are split into multiple data structures.
To use the傅nction with separate dataparameter,
Your model must use an ERT-based system target file (requires a Embedded Coder license).
Your subsystem must be configured to be atomic or conditionally executed. For more information, seeSystems and Subsystems(Simulink).
Your subsystem must use the
Nonreusable function
setting forCode Generation>傅nction packaging.
To configure your subsystem for generating modular function code, you invoke the Subsystem Parameters dialog box and make a series of selections to display and enable the傅nction with separate dataoption. SeeConfigure Subsystem for Generating Modular Function CodeandModular Function Code for Nonvirtual Subsystemsfor details. For limitations that apply, seeNonvirtual Subsystem Modular Function Code Limitations.
For more information about generating code for atomic subsystems, see the sectionsControl Generation of Subsystem Functions(Simulink Coder) andGenerate Code and Executables for Individual Subsystems(Simulink Coder).
Configure Subsystem for Generating Modular Function Code
This section summarizes the steps to configure a nonvirtual subsystem in a Simulink model for modular function code generation.
Verify that the Simulink model containing the subsystem uses an ERT-based system target file (see theSystem target fileparameter on theCode Generationpane of the Configuration Parameters dialog box).
In your Simulink model, select the subsystem for which you want to generate modular function code and open the Subsystem Parameters dialog box (for example, right-click the subsystem and selectBlock Parameters (Subsystem)). The dialog box for an atomic subsystem is shown below. (In the dialog box for a conditionally executed subsystem, the dialog box optionTreat as atomic unitis greyed out, and you can skip Step 3.)
If the Subsystem Parameters dialog box optionTreat as atomic unitis available for selection but not selected, the subsystem is neither atomic nor conditionally executed. Select the optionTreat as atomic unit, which enables傅nction packagingon theCode Generationtab. Select theCode Generationtab.
For the傅nction packagingparameter, select the value
Nonreusable function
. After you make this selection, the傅nction with separate dataoption is displayed.Note
Before you generate nonvirtual subsystem function code with the傅nction with separate dataoption selected, you might want to generate function code with the optiondeselectedand save the generated function
.c
and.h
files in a separate directory for later comparison.Select the傅nction with separate dataoption. After you make this selection, additional configuration parameters are displayed.
Note
To control the naming of the subsystem function and the subsystem files in the generated code, you can modify the subsystem parameters傅nction name optionsandFile name options.
To save your subsystem parameter settings and exit the dialog box, clickOK.
This completes the subsystem configuration for generating modular function code. You can now generate the code for the subsystem and examine the generated files, including the function.c
and.h
files named according to your subsystem parameter specifications. For more information on generating code for nonvirtual subsystems, seeControl Generation of Subsystem Functions(Simulink Coder). For examples of generated subsystem function code, seeModular Function Code for Nonvirtual Subsystems.
Modular Function Code for Nonvirtual Subsystems
To illustrate the selection of the傅nction with separate data选择nonvirtual子系统,下面的procedure generates atomic subsystem function code with and without the option selected and compares the results.
Open MATLAB®and open the model
rtwdemo_atomic
using the MATLAB commandrtwdemo_atomic
.Examine the Simulink model. This model shows how to preserve the boundary of a virtual subsystem. By selecting the Subsystem Parameters optionTreat as atomic unit, you guarantee that the code for that subsystem executes as an atomic unit. When a system is marked as atomic, you can specify how the subsystem is represented in code with the Subsystem Parameters optionCode Generation Function Packaging. You can specify that the subsystem is translated to any of the following types of implementation:
Inline
: Inline the subsystem code at the call sites傅nction
: A void/void function with I/O and internal data in global data structureReusable Function
: A reentrant function with data passed in as part of function argumentsAuto
: Let the code generator optimize the implementation based on context
Double-click the SS1 subsystem and examine the contents.
Close the subsystem window when you are finished.
Right-click the SS1 subsystem, select Block Parameters (Subsystem) from the context menu, and examine the settings. Simulink and the code generator can avoid "artificial" algebraic loops when the subsystem is made atomic with the subsystem optionMinimize algebraic loop occurrences.
Close the Block Parameters dialog box when you are finished.
Change theSystem target filefor the mode from
grt.tlc
toert.tlc
. Select theConfiguration Parameters>Code Generationtab and specifyert.tlc
for theSystem target fileparameter. ClickOKtwice to confirm the change. Using the ERT target provides more code generation options for the atomic subsystem.Create a variant of
rtwdemo_atomic
that illustrates function codewithoutdata separation.In the
rtwdemo_atomic
model, right-click the SS1 subsystem and selectBlock Parameters (Subsystem). In the Subsystem Parameters dialog box that appears, verify thatOn theMaintab,Treat as atomic unitis selected
On theCode Generationtab,
User specified
is selected for傅nction name optionsOn theCode Generationtab,
myfun
is specified for傅nction name
In the Subsystem Parameters dialog box, on theCode Generationtab verify that
Nonreusable function
is selected for the傅nction packagingparameter. After this selection, additional parameters and options appear.Use function name
is selected for theFile name optionsparameter. This selection is optional but simplifies the later task of code comparison by causing the atomic subsystem function code to be generated into the filesmyfun.c
andmyfun.h
.
Donotselect the option傅nction with separate data. ClickApplyto apply the changes and clickOKto exit the dialog box.
Save this model variant to a personal work directory, for example,
rtwdemo_atomic1
ind:/atomic
.
Create a variant of
rtwdemo_atomic
that illustrates function codewithdata separation.In the
rtwdemo_atomic1
model (orrtwdemo_atomic
with step 3 reapplied), right-click the SS1 subsystem and selectBlock Parameters (Subsystem). In the Subsystem Parameters dialog box, verify thatOn theMaintab,Treat as atomic unitis selected
On theCode Generationtab,
傅nction
is selected for傅nction packagingOn theCode Generationtab,
User specified
is selected for傅nction name optionsOn theCode Generationtab,
myfun
is specified for傅nction nameOn theCode Generationtab,
Use function name
is specified forFile name options
In the Subsystem Parameters dialog box, on theCode Generationtab, select the option傅nction with separate data. ClickApplyto apply the change and clickOKto exit the dialog box.
Save this model variant, using a different name than the first variant, to a personal work directory, for example,
rtwdemo_atomic2
ind:/atomic
.
Generate code for each model,
rtwdemo_atomic1
andrtwdemo_atomic2
.In the generated code directories, compare the
/model
.c.h
andmyfun.c
/.h
files generated for the two models. For code comparison discussion, seeH File Differences for Nonvirtual Subsystem Function Data SeparationandH File Differences for Nonvirtual Subsystem Function Data SeparationC File Differences for Nonvirtual Subsystem Function Data Separation.In this example, there are not significant differences in the generated variants of
ert_main.c
,
,model
_private.h
, ormodel
_types.hrtwtypes.h
.
H File Differences for Nonvirtual Subsystem Function Data Separation
The differences between the H files generated forrtwdemo_atomic1
andrtwdemo_atomic2
help illustrate the selection of the傅nction with separate dataoption for nonvirtual subsystems.
Selecting傅nction with separate datacauses
typedef
s for subsystem data to be generated in themyfun.h
file forrtwdemo_atomic2
:/* Block signals for system '
/SS1' */ typedef struct { real_T Integrator; /* ' /Integrator' */ } rtB_myfun; /* Block states (auto storage) for system ' /SS1' */ typedef struct { real_T Integrator_DSTATE; /* ' /Integrator' */ } rtDW_myfun; By contrast, for
rtwdemo_atomic1
,typedef
s for subsystem data belong to the model and appear inrtwdemo_atomic1.h
:/* Block signals (auto storage) */ typedef struct { ... real_T Integrator; /* '
/Integrator' */ } BlockIO_rtwdemo_atomic1; /* Block states (auto storage) for system ' ' */ typedef struct { real_T Integrator_DSTATE; /* ' /Integrator' */ } D_Work_rtwdemo_atomic1; Selecting傅nction with separate datagenerates the following external declarations in the
myfun.h
file forrtwdemo_atomic2
:/* Extern declarations of internal data for 'system '
/SS1'' */ extern rtB_myfun rtwdemo_atomic2_myfunB; extern rtDW_myfun rtwdemo_atomic2_myfunDW; extern void myfun_initialize(void); By contrast, the generated code for
rtwdemo_atomic1
contains model-level external declarations for the subsystem'sBlockIO
andD_Work
data, inrtwdemo_atomic1.h
:/* Block signals (auto storage) */ extern BlockIO_rtwdemo_atomic1 rtwdemo_atomic1_B; /* Block states (auto storage) */ extern D_Work_rtwdemo_atomic1 rtwdemo_atomic1_DWork;
C File Differences for Nonvirtual Subsystem Function Data Separation
The differences between the C files generated forrtwdemo_atomic1
andrtwdemo_atomic2
illustrate the selection of the傅nction with separate dataoption for nonvirtual subsystems.
Selecting傅nction with separate datacauses a separate subsystem initialize function,
myfun_initialize
, to be generated in themyfun.c
file forrtwdemo_atomic2
:void myfun_initialize(void) { { ((real_T*)&rtwdemo_atomic2_myfunB.Integrator)[0] = 0.0; } rtwdemo_atomic2_myfunDW.Integrator_DSTATE = 0.0; }
The subsystem initialize function in
myfun.c
is invoked by the model initialize function inrtwdemo_atomic2.c
:/* Model initialize function */ void rtwdemo_atomic2_initialize(void) { ... /* Initialize subsystem data */ myfun_initialize(); }
By contrast, for
rtwdemo_atomic1
initi、子系统初始化的数据模型alize function inrtwdemo_atomic1.c
:/* Model initialize function */ void rtwdemo_atomic1_initialize(void) { ... /* block I/O */ { ... ((real_T*)&rtwdemo_atomic1_B.Integrator)[0] = 0.0; } /* states (dwork) */ rtwdemo_atomic1_DWork.Integrator_DSTATE = 0.0; ... }
Selecting傅nction with separate datagenerates the following declarations in the
myfun.c
file forrtwdemo_atomic2
:/* Declare variables for internal data of system '
/SS1' */ rtB_myfun rtwdemo_atomic2_myfunB; rtDW_myfun rtwdemo_atomic2_myfunDW; By contrast, the generated code for
rtwdemo_atomic1
contains model-level declarations for the subsystem'sBlockIO
andD_Work
data, inrtwdemo_atomic1.c
:/* Block signals (auto storage) */ BlockIO_rtwdemo_atomic1 rtwdemo_atomic1_B; /* Block states (auto storage) */ D_Work_rtwdemo_atomic1 rtwdemo_atomic1_DWork;
Selecting傅nction with separate datagenerates identifier naming that reflects the subsystem orientation of data items. Notice the references to subsystem data in subsystem functions such as
myfun
andmyfun_update
or in the model's
function. For example, compare this code frommodel
_stepmyfun
forrtwdemo_atomic2
/* DiscreteIntegrator: '
/Integrator' */ rtwdemo_atomic2_myfunB.Integrator = rtwdemo_atomic2_myfunDW.Integrator_DSTATE; to the corresponding code from
myfun
forrtwdemo_atomic1
./* DiscreteIntegrator: '
/Integrator' */ rtwdemo_atomic1_B.Integrator = rtwdemo_atomic1_DWork.Integrator_DSTATE;
Nonvirtual Subsystem Modular Function Code Limitations
The nonvirtual subsystem option傅nction with separate datahas the following limitations:
The傅nction with separate dataoption is available only in ERT-based Simulink models (requires a Embedded Coder license).
The nonvirtual subsystem to which the option is applied cannot have multiple sample times or continuous sample times; that is, the subsystem must be single-rate with a discrete sample time.
The nonvirtual subsystem cannot contain continuous states.
The nonvirtual subsystem cannot output function call signals.
The nonvirtual subsystem cannot contain noninlined S-functions.
The generated files for the nonvirtual subsystem will reference model-wide header files, such as
andmodel
.h
.model
_private.hThe傅nction with separate dataoption is incompatible with theClassic call interfaceoption, located on theCode Generation>Interfacepane of the Configuration Parameters dialog box. Selecting both generates an error.
The傅nction with separate dataoption is incompatible with settingCode interface packagingto
Reusable function
(Code Generation>Interfacepane). Selecting both generates an error.
When you select傅nction with separate datafor a subsystem, the model that contains the subsystem cannot contain aData Store Memoryblock withShare across model instancesselected. SeeData Store Memory.