Generate Reentrant Code from Subsystems
You can reduce the amount of code that the code generator produces for identical
atomic subsystems by configuring the subsystems as reusable functions that pass data
as arguments (for example, rtB_* for block input and output,
rtDW_* for continuous states, and
rtP_* for parameters). By default, the code generator
produces subsystem code that communicates with other code by sharing access to
global data structures that reside in shared memory. By passing data as arguments,
the code can be reentrant, which allows multiple callers to call the code
simultaneously. Each instance of the code maintains its own unique data.
To configure subsystems for reusability and reentrancy, configure mask and block parameters of the identical subsystems the same way and connect them to identical interfaces. The code generator compares checksums to determine whether subsystems are identical and whether the code is reusable. If the code is reusable, the code generator produces a single instance of reusable, reentrant function code.
Considerations
Subsystem checksums account for both the contents and interfaces of the subsystems. For example, consider two subsystems that have the same checksum. If you change a parameter for one block inside one of the subsystems or change a mask parameter for one of the subsystems, the checksums become unequal because the subsystems no longer have identical contents. If you leave the contents identical but instead connect the subsystems to signals that have different data types, the subsystem checksums become unequal because the subsystems have different interfaces. If you are unsure why the code generator considers subsystems in your model to be unequal, see Resolve Issues with Reusable Subsystems Generating Separate Functions.
Code reuse is an optimization feature that is not guaranteed. Even if
subsystems have equal checksums, the code generator might not generate
reusable code due to how the subsystems relate to other blocks in the model
or model reference hierarchy, such as if a subsystem connects to a root
Inport or Outport block. In some
cases, the code generator generates a nonreusable function and produces a
Simulink:Engine:SwitchedReusedToNonreused
warning. In some other cases, the Subsystems section of the Code Generation
Report (see Reports for Code Generation) contains explanations of conditions
that caused the code generator to generate nonreusable code. If you do not
know why the code generator did not generate a shared function for
subsystems that have equal checksums, see Use Signal Conversion or Bias Blocks to Resolve Issues with Reusable Code Generation for troubleshooting
steps.
Configure Subsystems to Generate Reusable Code
To configure a subsystem to generate reusable code, apply the following configuration steps. To generate a shared function for multiple subsystems that have equal checksums, use the same configuration values for each subsystem.
Select the Treat as atomic unit block parameter to enable function packaging parameters.
Set the Function packaging block parameter to
Reusable function. The code generator produces a separate function with arguments for each subsystem. SelectingReusable functionalso enables additional parameters that you can use to control the names of the function and file that the code generator produces for the subsystem code.Select a value for the Function name options block parameter. Use the same value for each subsystem.
To let the code generator determine the function name, select
Auto.To use the subsystem name or, for a library block, the name of the library block, select
Use subsystem name.To use a custom name, select
User specifiedto enable the Function name block parameter, then set that parameter to a unique, valid C/C++ function name.
Other considerations:
If multiple instances of an identical subsystem exist within a model reference hierarchy, select
Auto.If you are using Embedded Coder®, you can use identifier format controls. See Identifier Format Control.
Select a value for the File name options block parameter. Use the same value for each subsystem.
To let the code generator determine the file name, select
Auto.To use the subsystem name or, for a library block, the name of the library block, select
Use subsystem name.To use the function name that you specify with the Function name options block parameter, select
Use function name.To use a custom name, select
User specifiedto enable the File name block parameter, then set that parameter to a custom file name.
Other considerations:
If multiple instances of an identical subsystem exist within a model reference hierarchy, select
Auto.If the code generator does not generate a separate file for a subsystem, the function code appears in the file generated from the subsystem's parent system. If the parent is the model itself, the code generator places the function code in
ormodel.c.model.cppIf your generated code is under source control, specify a value other than
Auto. TheAutosetting prevents the generated file name from changing when you modify and rebuild the model.If you select
Use subsystem nameand the model contains Model blocks or generates a model reference target, the code generator uses the file name, then mangles the file name as necessary to prevent duplicate generated file names.modelsubsystem.c
Limitations
Code reuse for subsystems is an optimization feature and is not guaranteed. The following list of limitations on code reuse in subsystems is nonexhaustive.
The code generator uses a checksum to determine whether subsystems are identical and reusable. Subsystem code is not reused if:
In blocks and data objects, you use symbols to specify dimensions.
A port has different sample times, data types, complexity, frame status, or dimensions across subsystems.
The output of a subsystem is marked as a global signal.
Subsystems contain identical blocks with different names or parameter settings.
The output of a subsystem is connected to a Merge block, and the output of the Merge block is configured with a custom storage class that is implemented in the C code as nonaddressable memory (for example,
BitField).The input of a subsystem is nonscalar and is configured with a custom storage class that is implemented in the C code as nonaddressable memory.
A masked subsystem has a parameter that is nonscalar and is configured with a custom storage class that is implemented in the C code as nonaddressable memory.
A function-call subsystem uses mask parameters when you set the model configuration parameter Default parameter behavior to
Tunable. To reuse the masked function-call subsystem, place it inside a new atomic subsystem without a mask. Then move the Trigger block from the masked subsystem into the atomic subsystem.A block in a subsystem uses a partially tunable expression. Some partially tunable expressions disable code reuse.
You configure a subsystem for reuse across model references and that subsystem contains a built-in S-function.
Partially tunable expressions are expressions that contain one or more tunable variables and an expression that is not tunable. For example, suppose that you create the tunable variable
Kwith value15.23and the tunable variablePwith value[5;7;9]. The expressionK+P'is a partially tunable expression because the expressionP'is not tunable. For more information about tunable expression limitations, see Tunable Expression Limitations.
For subsystems that contain S-function blocks that are reusable, the blocks must meet the requirements listed in S-Functions for Code Reuse.
If you select
Reusable function, and the code generator determines that you cannot reuse the code for a subsystem, it generates a separate function that is not reused. The code generation report might show that the separate function is reusable, even if only one subsystem uses it. If you prefer that the code generator inline subsystem code in such cases (rather than deployed as functions), set Function packaging toAuto.If a reusable subsystem uses a shared local data store and you configure default mapping for model data elements, leave the default storage class mapping for category Shared local data stores set to
Default.Use of these blocks in a subsystem can prevent the subsystem code from being reused:
Scope blocks (with data logging enabled)
S-Function blocks that fail to meet certain criteria (see S-Functions for Code Reuse)
To File blocks (with data logging enabled)
To Workspace blocks (with data logging enabled)
For reusable library subsystems (subsystems shared across reference models), the code generator places the reusable library subsystem code in the shared utilities folder. The reusable code is independent of the generated code of the top model or the reference model. For example, the reusable library subsystem code does not include
ormodel.h.model_types.hReusable code that the code generator places in the shared utilities folder and is dependent on the model code does not compile. If the code generator determines that the reusable library subsystem code is dependent on the model code, the reusable subsystem code is not placed in the shared utilities folder. The code generator produces code that is dependent on the model code when the reusable library subsystem:
Contains a block that uses time-related functionality, such as a Step block, or continuous time or multirate blocks
Contains one or more Model blocks
Contains a subsystem that is not inlined or a reusable library subsystem
Contains a signal or parameter with a storage class that places the data declaration in a file under
model_ert_rtw(For example,ExportedGlobalstorage class places data inmodel.c)Contains a user-defined storage class like Enumeration, Simulink.Signal, Simulink.Parameter, and so on where Data Scope is not set to
Exported. The code generator might place the type definition in.model_types.hIs a variant subsystem that generates preprocessor conditionals. The code generator places preprocessor directives that define the variant objects in
.model_types.h
The code generator does not generate reusable library subsystem code for models where you specify a default mapping for constants that uses a memory section other than
None.Two reusable subsystems that have different checksums cannot share the same function in the generated code. When you specify the same function name for both subsystems in Block Parameters (Subsystem) > Code Generation > Function name:
If the subsystems are library-linked, the code generator mangles the function name to generate unique function names. The code generator uses the subsystem naming rules to generate the function names.
If the subsystems are not library-linked, the code generator issues an error.
The preceding limitations also apply for library-based code generation. For more information, see Library-Based Code Generation for Reusable Library Subsystems.