Generate Reentrant Code from Top Models
By default, for top models, the code generator produces code that is not reentrant. Entry-point functions have a void-void interface. Code communicates with other code by sharing access to global data structures that reside in shared memory.
For applications that can benefit from reuse and require that each use or instance of the
code maintains its own unique data, configure a model such that the code generator produces
reentrant code. To generate reentrant code, set the model configuration parameter Code interface packaging to
Reusable function
. If you are using Embedded Coder® and generating C++ code, alternatively, you can set the parameter to
C++ class
.
When Code interface packaging is set to Reusable
function
, the code generator:
Packages model data, such as block I/O, DWork vectors, and parameters, in the real-time model data structure (
rtModel
).Passes the real-time model data structure as an input argument, by reference, to generated model entry-point functions.
Passes root-level input and output arguments to generated model entry-point functions as individual arguments.
Allocates memory for model data structures statically.
Exports the real-time model data structure in the generated header file
.model
.h
Apply additional diagnostic and code generation control by setting these model configuration parameters:
To select the severity level for diagnostic messages that the code generator displays when a model does not meet requirements for multi-instance code, set parameter Multi-instance code error diagnostic to
None
,Warning
, orError
. Set the parameter toError
unless you need to alter the severity level for diagnostics displayed when a model violates requirements for generating multi-instance code.To control how the generated code passes root-level model input and output to the reusable execution (step) function (requires Embedded Coder), set parameter Pass root-level I/O as (Embedded Coder) to
Individual arguments
,Structure reference
, orPart of model data structure
.When you set Code interface packaging to
Reusable function
, the code generator packages model data (such as block I/O, Dwork, and parameters) into the real-time model data structure, and passes the model structure to generated model entry-point functions. If you set Pass root-level I/O as (Embedded Coder) toPart of model data structure
, the code generator packages root-level model input and output into the real-time model data structure also.To reduce memory usage by omitting the error status field from the real-time model data structure (requires Embedded Coder), select model configuration parameter Remove error status field in real-time model data structure.
To include a function in the generated file
that usesmodel
.cmalloc
to dynamically allocate memory for model instance data (requires Embedded Coder), select model configuration parameter Use dynamic memory allocation for model initialization. If you do not select this parameter, the generated code statically allocates memory for model data structures.
Generate Reentrant, Multi-Instance Code
This example shows you how to configure a model for reentrant, multi-instance code generation. Multiple programs can use reentrant code simultaneously. When you configure a model for reentrancy, the execution (step) entry-point function uses root-level input and output arguments instead of global data structures. After examining the configuration settings, generate and review the generated code.
Open the Model
Open the model Reusable
. The model contains two root Inport blocks and a root Outport block.
model='Reusable';
open_system(model);
Examine Relevant Model Configuration Parameter Settings
1. Open the Embedded Coder app.
2. Open the Model Configuration Parameters dialog box.
3. Model configuration parameter System target file is set to ert.tlc
. Although you can generate reentrant code for a model configured with System target file set to grt.tlc
, ERT and ERT-based system target files provide more control over how the code passes root-level I/O.
4. Open the Code Generation > Interface pane and explore relevant model configuration parameter settings.
Code interface packaging is set to
Reusable function
. This parameter setting instructs the code generator to produce reusable, multi-instance code.Setting of
Reusable function
displays parameter Multi-instance code error diagnostic. That parameter is set toError
, indicating that the code generator abort if the model violates requirements for generating multi-instance code.Pass root-level I/O as is set to
Part of model data structure
. This setting packages root-level model input and output into the real-time model data structure (rtModel
), which is an optimized data structure that replacesSimStruct
as the top-level data structure for a model.Remove error status field in real-time model data structure is selected. This parameter setting reduces memory usage by omitting the error status field from the generated real-time model data structure.
Generate and Review Code
slbuild(model);
### Starting build procedure for: Reusable ### Successful completion of build procedure for: Reusable Build Summary Top model targets: Model Build Reason Status Build Duration =========================================================================================================== Reusable Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 9.4164s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 10.126s
Review the Generated Code
ert_main.c
is an example main program (execution framework) for the model. This code controls model code execution by calling the entry-point functionReusable_step
. Use this file as a starting point for coding your execution framework.Reusable.c
contains entry points for the code that implements the model algorithm. This file includes the rate scheduling code.Reusable.h
declare model data structures and a public interface to the model entry points and data structures.rtwtypes.h
defines data types, structures, and macros that the generated code requires.
Code Interface
Open and review the Code Interface Report. Use the information in that report to write the interface code for your execution framework.
1. Include the generated header file by adding directive #include Reusable.h
.
2. Write input data to the generated code for model Inport blocks.
3. Call the generated entry-point functions.
4. Read data from the generated code for the model Outport block.
Input ports:
<Root>/In1
of datareal_T
with dimension of 1<Root>/In2
of datareal_T
with dimension of 1
Entry-point functions:
Initialization entry-point function,
void Reusable_initialize(RT_MODEL *const rtM)
. At startup, call this function once.Output and update (step) entry-point function,
void Reusable_step(RT_MODEL *const rtM)
. Call this function periodically at the fastest rate in the model. For this model, call the function every second. To achieve real-time execution, attach this function to a timer.
Output port:
<Root>/Out1
of data typereal_T
with dimension of 1
Examine the Step Function
Examine the |Reusable_step| function code in |Reusable.c|.
cfile = fullfile('Reusable_ert_rtw','Reusable.c'); coder.example.extractLines(cfile,'/* Model step function', '/* Model initialize function ', 1, 0);
/* Model step function */ void Reusable_step(RT_MODEL *const rtM) { D_Work *rtDWork = rtM->dwork; ExternalInputs *rtU = (ExternalInputs *) rtM->inputs; ExternalOutputs *rtY = (ExternalOutputs *) rtM->outputs; /* Outport: '<Root>/Out1' incorporates: * UnitDelay: '<Root>/Delay' */ rtY->Out1 = rtDWork->Delay_DSTATE; /* Gain: '<Root>/Gain' incorporates: * Sum: '<Root>/Sum' * UnitDelay: '<Root>/Delay' */ rtDWork->Delay_DSTATE = (rtU->In1 + rtU->In2) * rtP.k1; }
The code generator passes model data to the Reusable_step
function as part of the real-time model data structure. Try different settings for model configuration parameters Code interface packaging and Pass root-level I/O and regenerate code. Observe how the function prototype changes.
Close the Model and Report
Close the model and the code generation report.
bdclose(model)
Share Data Between Instances
When your code calls a reentrant model entry-point function multiple times, each call represents an instance of the model. By default, the code generator generates code that assumes each instance reads from and writes to a separate copy of the signals, block states, and parameters in the model.
To share a piece of parameter data between the instances (for example, to share a setpoint for a reusable PID control algorithm), use a parameter object, such as
Simulink.Parameter
. Then, configure the parameter with a storage class other thanAuto
or in the Code Mappings editor, set the default storage class for the corresponding category of parameter dataDefault
(the default setting) toModel default
. The parameter object appears in the code as a global symbol, such as a global variable, that the function accesses directly. For more information, see C Data Code Interface Configuration for Model Interface Elements.To share a piece of nonparameter data between the instances (for example, to share a fault indication or an accumulator), use a data store. You can configure the data store to appear in the code as a global symbol, such as a global variable, that the function accesses directly. Create a global data store by using a
Simulink.Signal
object or use a Data Store Memory block and select block parameter Share across model instances. For more information, see Model Global Data by Creating Data Stores and Data Store Memory.