Skip to Main Content Skip to Search
Product Documentation

Component-Based Modeling

Subsystems

About Subsystems

The Simulink® Coder™ product allows you to control how code is generated for any nonvirtual subsystem. The categories of nonvirtual subsystems are:

See Systems and Subsystems in the Simulink documentation, and run the sl_subsys_semantics demo for more information on nonvirtual subsystems and atomic subsystems.

You can control the code generated from nonvirtual subsystems as follows:

Generate Code and Executables from Subsystems

The Simulink Coder software can generate code and build an executable from any subsystem within a model. The code generation and build process uses the code generation and build parameters of the root model.

To generate code and build an executable from a subsystem,

  1. Set up the desired code generation and build parameters in the Configuration Parameters dialog box, just as you would for code generation from a model.

  2. Select the desired subsystem block.

  3. Right-click the subsystem block and select Build Subsystem from the Code Generation submenu of the subsystem block's context menu.

    Alternatively, you can select Build Subsystem from the Code Generation submenu of the Tools menu. This menu item is enabled when a subsystem is selected in the current model.

      Note   If the model is operating in external mode when you select Build Subsystem, the Simulink Coder build process automatically turns off external mode for the duration of the build, then restores external mode upon its completion.

  4. The Build Subsystem window opens. This window displays a list of the subsystem parameters. The upper pane displays the name, class, and storage class of each variable (or data object) that is referenced as a block parameter in the subsystem. When you select a parameter in the upper pane, the lower pane shows all the blocks that reference the parameter and the parent system of each such block.

    The StorageClass column contains a popup menu for each row. The menu lets you set the storage class of any parameter or inline the parameter. To inline a parameter, select the Inline option from the menu. To declare a parameter to be tunable, set the storage class to any value other than Inline.

    In the previous figure, the parameter K2 is inlined, while the other parameters are tunable and have various storage classes.

    See Parameters for more information on tunable and inlined parameters and storage classes.

  5. After selecting tunable parameters, click the Build button. This initiates the code generation and build process.

  6. The build process displays status messages in the MATLAB® Command Window. When the build completes, the generated executable is in your working folder. The name of the generated executable is subsystem.exe (on PC platforms) or subsystem (on The Open Group UNIX® platforms), where subsystem is the name of the source subsystem block.

    The generated code is in a build subfolder, named subsystem_target_rtw, where subsystem is the name of the source subsystem block and target is the name of the target configuration.

When you generate code for a subsystem, you can generate an S-function by selecting Tools > Code Generation > Generate S-function, or you can use a right-click subsystem build. See Automate S-Function Generation and Generate S-Function Wrappers for more details.

Simulink Coder Subsystem Build Limitations.  The following limitations apply to building subsystems using the Simulink Coder software:

Nonvirtual Subsystem Code Generation Options

For any nonvirtual subsystem, you can choose the following code generation options from the Function packaging menu in the subsystem Block parameters dialog box:

The following sections discuss these options further.

Auto Option.  The Auto option is the default. It causes the code generator to inline the subsystem when there is only one instance of it in the model. When multiple instances of a subsystem exist, the Auto option results in a single copy of the function (as a reusable function). Otherwise, the result is as though you selected Inline (except for function call subsystems with multiple callers, which is handled as if you specified Function). Choose Inline to always inline subsystem code, or Function when you specifically want to generate a separate function without arguments for each instance, optionally in a separate file.

To use the Auto option,

  1. Select the subsystem block. Then select Subsystem Parameters from the Simulink model editor Edit menu. The Block Parameters dialog box opens.

    Alternatively, you can open the Block Parameters dialog box by

    • Shift-double-clicking the subsystem block

    • Right-clicking the subsystem block and selecting Subsystem parameters from the menu

  2. If the subsystem is virtual, select Treat as atomic unit. This makes the subsystem nonvirtual, and on the Code Generation tab, the Function packaging option becomes enabled.

    If the system is already nonvirtual, the Function packaging option is already enabled.

  3. Go to the Code Generation tab and select Auto from the Function packaging menu, as shown in the figure below.

  4. Click Apply and close the dialog box.

    The border of the subsystem thickens, indicating that it is nonvirtual.

Auto Optimization for Special Cases.  

Rather than reverting to Inline, the Auto option can optimize code in special situations in which identical subsystems contain other identical subsystems, by both reusing and inlining generated code. Suppose a model, such as the one shown in Reuse of Identical Nested Subsystems with the Auto Option, contains identical subsystems A1 and A2. A1 contains subsystem B1, and A2 contains subsystem B2, which are themselves identical. In such cases, the Auto option causes one function to be generated which is called for both A1 and A2, and this function contains one piece of inlined code to execute B1 and B2, ensuring that the resulting code will run as efficiently as possible.

Reuse of Identical Nested Subsystems with the Auto Option

Inline Option.  As noted above, you can choose to inline subsystem code when the subsystem is nonvirtual (virtual subsystems are always inlined).

Exceptions to Inlining.  

There are certain cases in which the Simulink Coder code generator does not inline a nonvirtual subsystem, even though the Inline option is selected. These cases are

To generate inlined subsystem code,

  1. Select the subsystem block. Then select Subsystem Parameters from the Simulink model editor Edit menu. The Block Parameters dialog box opens.

    Alternatively, you can open the Block Parameters dialog box by

    • Shift-double-clicking the subsystem block

    • Right-clicking the subsystem block and selecting Block parameters from the menu

  2. If the subsystem is virtual, select Treat as atomic unit as shown in the next figure. This makes the subsystem atomic, and on the Code Generation tab, the Function packaging menu becomes enabled.

    If the system is already nonvirtual, the Function packaging menu is already enabled.

  3. Go to the Code Generation tab and select Inline from the Function packaging menu as shown in the figure below.

  4. Click Apply and close the dialog box.

When you generate code from your model, the Simulink Coder code generator writes inline code within model.c or model.cpp (or in its parent system's source file) to perform subsystem computations. You can identify this code by system/block identification tags, such as the following.

/* Atomic SubSystem Block: <Root>/AtomicSubsys1 */

Function Option.  Choosing the Function or Reusable function option lets you direct the Simulink Coder code generator to generate a separate function and optionally a separate file for the subsystem. When you select the Function option, two additional options are enabled:

The figure below shows the Block Parameters dialog box with the Function option selected, with File name options set to User specified, and with a name specified for the generated file.

Subsystem Function Code Generation Option with User-Specified File Name

Function Name Options Menu.  

This menu offers the following choices, but the resulting identifiers are also affected by which General code appearance options are in effect for the model:

File Name Options Menu.  

This menu offers the following choices:

To generate both a separate subsystem function and a separate file,

  1. Select the subsystem block. Then select Subsystem Parameters from the Simulink model editor Edit menu, to open the Block Parameters dialog box.

    Alternatively, you can open the Block Parameters dialog box by

    • Shift-double-clicking the subsystem block

    • Right-clicking the subsystem block and selecting Subsystem parameters from the menu.

  2. If the subsystem is virtual, select Treat as atomic unit. On the Code Generation tab, the Function packaging menu becomes enabled.

    If the system is already nonvirtual, the Function packaging menu is already enabled.

  3. Go to the Code Generation tab and select Function from the Function packaging menu as shown in Subsystem Function Code Generation Option with User-Specified File Name.

  4. Set the function name, using the Function name options parameter, as described in Function Name Options Menu.

  5. Set the file name, using any File name options parameter value other than Auto (values are described in File Name Options Menu).

    Subsystem Function Code Generation Option with User-Specified File Name shows the use of the User Specified file name option.

  6. Click Apply and close the dialog box.

Modularity of Subsystem Code

Code generated from nonvirtual subsystems, when written to separate files, is not completely independent of the generating model. For example, subsystem code may reference global data structures of the model. Each subsystem code file contains include directives and comments explaining the dependencies. The Simulink Coder software checks for cyclic file dependencies and warns about them at build time. For descriptions of how generated code is packaged, see Generated Source Files and File Dependencies.

Referenced Models

About Code Generation for Referenced Models

This section describes model referencing considerations that apply specifically to code generation by the Simulink Coder. This section assumes that you understand referenced models and related terminology and requirements, as described in Referencing a Model.

When generating code for a referenced model hierarchy, the code generator produces a stand-alone executable for the top model, and a library module called a model reference target for each referenced model. When the code executes, the top executable invokes the model reference targets to compute the referenced model outputs. Model reference targets are sometimes called Simulink Coder targets.

Be careful not to confuse a model reference target (Simulink Coder target) with any of these other types of targets:

The code generator places the code for the top model of a hierarchy in the current working folder, and the code for submodels in a folder named slprj within the current working folder. Subfolders in slprj provide separate places for different types of files. See Project Folder Structure for Model Reference Targets for details.

By default, the product uses incremental code generation. When generating code, it compares structural checksums of referenced model files with the generated code files to determine whether you should regenerate model reference targets. To control when rebuilds occur, use the Configuration Parameters > Model Referencing > Rebuild. For details, see Rebuild.

In addition to incremental code generation, the Simulink Coder software uses incremental loading. The code for a referenced model is not loaded into memory until the code for its parent model executes and needs the outputs of the referenced model. The product then loads the referenced model target and executes. Once loaded, the target remains in memory until it is no longer used.

Most code generation considerations are the same whether or not a model includes any referenced models: the Simulink Coder code generator handles the details automatically insofar as possible. This chapter describes topics that you may need to consider when generating code for a model reference hierarchy.

Custom targets must declare themselves to be model reference compliant if they need to support Model blocks. See Support Model Referencing for details.

Generate Code for Referenced Models

About Generating Code for Referenced Models.  To generated code for referenced models, you

  1. Create a subsystem in an existing model.

  2. Convert the subsystem to a referenced model (Model block).

  3. Call the referenced model from the top model.

  4. Generate code for the top model and referenced model.

  5. Explore the generated code and the project folder.

You can accomplish some of these tasks automatically with a function called Simulink.Subsystem.convertToModelReference.

Create and Configure the Subsystem.  In the first part of this example, you define a subsystem for the vdp demo model, set configuration parameters for the model, and use the Simulink.Subsystem.convertToModelReference function to convert it into two new models — the top model (vdptop) and a referenced model vdpmultRM containing a subsystem you created (vdpmult).

  1. In the MATLAB Command Window, create a new working folder wherever you want to work and cd into it:

    mkdir mrexample
    cd mrexample
  2. Open the vdp demo model by typing:

    vdp
  3. Drag a box around the three blocks on the left to select them, as shown below:

  4. Choose Create Subsystem from the model's Edit menu.

    A subsystem block replaces the selected blocks.

  5. If the new subsystem block is not where you want it, move it to a preferred location.

  6. Rename the block vdpmult.

  7. Right-click the vdpmult block and select Subsystem Parameters.

    The Function Block Parameters dialog box appears.

  8. In the Function Block Parameters dialog box, select Treat as atomic unit, then click OK.

    The border of the vdpmult subsystem thickens to indicate that it is now atomic. An atomic subsystem executes as a unit relative to the parent model: subsystem block execution does not interleave with parent block execution. This property makes it possible to extract subsystems for use as stand-alone models and as functions in generated code.

    The block diagram should now appear as follows:

You must set several properties before you can extract a subsystem for use as a referenced model. To set the properties,

  1. Open Model Explorer by selecting Model Explorer from the model's View menu.

  2. In the Model Hierarchy pane, click the symbol preceding the model name to reveal its components.

  3. Click Configuration (Active) in the left pane.

  4. In the center pane, select Solver.

  5. In the right pane, under Solver Options change the Type to Fixed-step, then click Apply. You must use fixed-step solvers when generating code, although referenced models can use different solvers than top models.

  6. In the center pane, select Optimization. In the right pane, select the Signals and Parameters tab, and under Simulation and code generation, select Inline parameters. Click Apply.

  7. In the center pane, select Diagnostics. In the right pane:

    1. Select the Data Validity tab. In the Signals area, set Signal resolution to Explicit only.

    2. Select the Connectivity tab. In the Buses area, set Mux blocks used to create bus signals to error.

  8. Click Apply.

    The model now has the properties that model referencing requires.

  9. In the center pane, click Model Referencing. In the right pane, set Rebuild to If any changes in known dependencies detected. Click Apply. This setting prevents unnecessary code regeneration.

  10. In the vdp model window, choose File > Save as. Save the model as vdptop in your working folder. Leave the model open.

Convert a Model to Use Model Referencing.  In this portion of the example, you use the conversion function Simulink.SubSystem.convertToModelReference to extract the subsystem vdpmult from vdptop and convert vdpmult into a referenced model named vdpmultRM. To see the complete syntax of the conversion function, type at the MATLAB prompt:

help Simulink.SubSystem.convertToModelReference

For additional information, type:

doc Simulink.SubSystem.convertToModelReference

If you want to see a demo of Simulink.SubSystem.convertToModelReference before using it yourself, type:

sldemo_mdlref_conversion

Simulink also provides a menu command, Convert to Model Block, that you can use to convert a subsystem to a referenced model. The command calls Simulink.SubSystem.convertToModelReference with default arguments. See Converting a Subsystem to a Referenced Model in the Simulink documentation.

Extracting the Subsystem to a Referenced Model.  

To use Simulink.SubSystem.convertToModelReference to extract vdpmult and convert it to a referenced model, type:

Simulink.SubSystem.convertToModelReference...
('vdptop/vdpmult', 'vdpmultRM',...
'ReplaceSubsystem', true, 'BuildTarget', 'Sim')

This command:

  1. Extracts the subsystem vdpmult from vdptop.

  2. Converts the extracted subsystem to a separate model named vdpmultRM and saves the model to the working folder.

  3. In vdptop, replaces the extracted subsystem with a Model block that references vdpmultRM.

  4. Creates a simulation target for vdptop and vdpmultRM.

The converter prints a number of progress messages and terminates with

ans =
     1

The parent model vdptop now looks like this:

Note the changes in the appearance of the block vdpmult. These changes indicate that it is now a Model block rather than a subsystem. As a Model block, it has no contents of its own: the previous contents now exist in the referenced model vdpmultRM, whose name appears at the top of the Model block. Widen the Model block to expose the complete name of the referenced model.

If the parent model vdptop had been closed at the time of conversion, the converter would have opened it. Extracting a subsystem to a referenced model does not automatically create or change a saved copy of the parent model. To preserve the changes to the parent model, save vdptop.

Right-click the Model block vdpmultRM and choose Open Model 'vdpmultRM' to open the referenced model. The model looks like this:

Files Created and Changed by the Converter.  

The files in your working folder now consist of the following (not in this order).

File Description

vdptop.mdl

Top model that contains a Model block where the vdpmult subsystem was

vdpmultRM.mdl

Referenced model created for the vdpmult subsystem

vdpmultRM_msf.mexw32

Static library file (Microsoft® Windows® platforms only). The last three characters of the suffix are system-dependent and may differ. This file executes when the vdptop model calls the Model block vdpmult. When called, vdpmult in turn calls the referenced model vdpmultRM.

/slprj

Project folder for generated model reference code

Code for model reference simulation targets is placed in the slprj/sim subfolder. Generated code for GRT, ERT, and other Simulink Coder targets is placed in slprj subfolders named for those targets. You will inspect some model reference code later in this example. For more information on project folders, see Working with Project Folders.

Running the Converted Model.  

Open the Scope block in vdptop if it is not visible. In the vdptop window, click the Start tool or choose Start from the Simulation menu. The model calls the vdpmultRM_msf simulation target to simulate. The output looks like this:

Generate Model Reference Code for a GRT Target.  The function Simulink.SubSystem.convertToModelReference created the model and the simulation target files for the referenced model vdpmultRM. In this part of the example, you generate code for that model and the vdptop model, and run the executable you create:

  1. Verify that you are still working in the mrexample folder.

  2. If the model vdptop is not open, open it. Make sure it is the active window.

  3. Open Model Explorer by selecting Model Explorer from the model's View menu.

  4. In the Model Hierarchy pane, click the symbol preceding the vdptop model to reveal its components.

  5. Click Configuration (Active) in the left pane.

  6. In the center pane, select Data Import/Export.

  7. In the Save to workspace section of the right pane, check Time and Output and clear Data stores. Click Apply. The pane shows the following information:

    These settings instruct the model vdptop (and later its executable) to log time and output data to MAT-files for each time step.

  8. Generate GRT code (the default) and an executable for the top model and the referenced model by selecting Code Generation in the center pane and then clicking the Build button.

The Simulink Coder build process generates and compiles code. The current folder now contains a new file and a new folder:

FileDescription

vdptop.exe

The executable created by the Simulink Coder build process

vdptop_grt_rtw/

The Simulink Coder build folder, containing generated code for the top model

The Simulink Coder build process also generated GRT code for the referenced model, and placed it in the slprj folder.

To view a model's generated code in Model Explorer, the model must be open. To use the Model Explorer to inspect the newly created build folder, vdptop_grt_rtw:

  1. Open Model Explorer by selecting Model Explorer from the model's View menu.

  2. In the Model Hierarchy pane, click the symbol preceding the model name to reveal its components.

  3. Click the symbol preceding Code for vdptop to reveal its components.

  4. Directly under Code for vdptop, click This Model.

    A list of generated code files for vdptop appears in the Contents pane:

    rtmodel.h
    vdptop.c
    vdptop.h
    vdptop.mk
    vdptop_private.h
    vdptop_types.h

    You can browse code in any of these files by selecting a file of interest in the Contents pane.

    To open a file in a text editor, click a filename, and then click the hyperlink that appears in the gray area at the top of the Document pane. The figure below illustrates viewing code for vdptop.c, in a text editor. Your code may differ.

Working with Project Folders.  When you view generated code in Model Explorer, the files listed in the Contents pane can exist either in a build folder or a project folder. Model reference project folders (always rooted under slprj), like build folders, are created in your current working folder, and this implies certain constraints on when and where model reference targets are built, and how they are accessed.

The models referenced by Model blocks can be stored anywhere. A given top model can include models stored on different file systems or in different folders. The same is not true for the simulation targets derived from these models; under most circumstances, all models referenced by a given top model must be set up to simulate and generate model reference target code in a single project folder. The top and referenced models can exist anywhere on your path, but the project folder is assumed to exist in your current folder.

This means that, if you reference the same model from several top models, each stored in a different folder, you must either

The files in such multiple project folders are generally quite redundant. Therefore, to minimize code regeneration for referenced models, choose a specific working folder and remain in it for all sessions.

As model reference code generated for Simulink Coder targets as well as for simulation targets is placed in project folders, the same considerations as above apply even if you are generating target applications only. That is, code for all models referenced from a given model ends up being generated in the same project folder, even if it is generated for different targets and at different times.

Project Folder Structure for Model Reference Targets

Code for models referenced by using Model blocks is generated in project folders within the current working folder. The top-level project folder is always named /slprj. The next level within slprj contains parallel build area subfolders.

The following table lists principal project folders and files. In the paths listed, model is the name of the model being used as a referenced model, and target is the system target file acronym (for example, grt, ert , rsim, and so on).

Folders and FilesDescription
slprj/sim/model/Simulation target files for referenced models
slprj/sim/model/tmwinternalMAT-files used during code generation
slprj/target/model/referenced_model_includesHeader files from models referenced by this model
slprj/target/modelModel reference target files
slprj/target/model/tmwinternalMAT-files used during code generation
slprj/sl_proj.tmwMarker file
slprj/target/_sharedutilsUtility functions for model reference targets, shared across models
slprj/sim/_sharedutilsUtility functions for simulation targets, shared across models

If you are building code for more than one referenced model within the same working folder, model reference files for all such models are added to the existing slprj folder.

Configure Referenced Models

Minimize occurrences of algebraic loops by selecting the Minimize algebraic loop occurrences parameter on the Model Reference pane. The setting of this option affects only generation of code from the model. See Consider Platform Options for Development and Deployment in the Simulink Coder documentation for information on how this option affects code generation. For more information, see Model Blocks and Direct Feedthrough.

Use the Integer rounding mode parameter on your model's blocks to simulate the rounding behavior of the C compiler that you intend to use to compile code generated from the model. This setting appears on the Signal Attributes pane of the parameter dialog boxes of blocks that can perform signed integer arithmetic, such as the Product and n-D Lookup Table blocks.

For most blocks, the value of Integer rounding mode completely defines rounding behavior. For blocks that support fixed-point data and the Simplest rounding mode, the value of Signed integer division rounds to also affects rounding. For details, see Rounding in the Simulink Fixed Point User's Guide.

When models contain Model blocks, all models that they reference must be configured to use identical hardware settings. For information on the Model Referencing pane options, see Referencing a Model in the Simulink documentation.

Build Model Reference Targets

By default, the Simulink engine rebuilds simulation targets before the Simulink Coder software generates model reference targets. You can change the rebuild criteria or specify that the engine always or never rebuilds targets. See Rebuild for details.

The Simulink Coder software generates a model reference target directly from the Simulink model. The product automatically generates or regenerates model reference targets.

You can command the Simulink and Simulink Coder products to generate a simulation target for an Accelerator mode referenced model, and a model reference target for any referenced model, by executing the slbuild command with arguments in the MATLAB Command Window.

The Simulink Coder software generates only one model reference target for all instances of a referenced model. See Reusable Code and Referenced Models for details.

Reduce Change Checking Time.  You can reduce the time that the Simulink and Simulink Coder products spend checking whether any or all simulation targets and model reference targets need to be rebuilt by setting configuration parameter values as follows:

These parameter values exist in a referenced model's configuration set, not in the individual Model block, so setting either value for any instance of a referenced model sets it for all instances of that model.

Simulink Coder Model Referencing Requirements

A model reference hierarchy must satisfy various Simulink Coder requirements, as described in this section. In addition to these requirements, a model referencing hierarchy to be processed by the Simulink Coder software must satisfy:

Configuration Parameter Requirements.  A referenced model uses a configuration set in the same way that any other model does, as described in Manage a Configuration Set. By default, every model in a hierarchy has its own configuration set, which it uses in the same way that it would if the model executed independently.

Because each model can have its own configuration set, configuration parameter values can be different in different models. Furthermore, some parameter values are intrinsically incompatible with model referencing. The response of the Simulink Coder software to an inconsistent or unusable configuration parameter depends on the parameter:

When a model reference hierarchy contains many submodels that have incompatible parameter values, or a changed parameter value must propagate to many submodels, manually eliminating all configuration parameter incompatibilities can be tedious. You can control or eliminate such overhead by using configuration references to assign an externally-stored configuration set to multiple models. See Manage a Configuration Reference for details.

The following tables list configuration parameters that can cause problems if set in certain ways, or if set differently in a referenced model than in a parent model. Where possible, the Simulink Coder software resolves violations of these requirements automatically, but most cases require changes to the parameters in some or all models.

Configuration Requirements for Model Referencing with All System Targets

Dialog Box PaneOptionRequirement
SolverStart timeSome system targets require the start time of all models to be zero.

Hardware Implementation

Emulation hardware options

All values must be the same for top and referenced models.

Code Generation

System target file

Must be the same for top and referenced models.

LanguageMust be the same for top and referenced models.

Generate code only

Must be the same for top and referenced models.

Symbols

Maximum identifier length

Cannot be longer for a referenced model than for its parent model.

Interface

Code replacement library

Must be the same for top and referenced models.

Data exchange > Interface

C API

The C API check boxes for signals, parameters, and states must be the same for top and referenced models.

ASAP2

Can be on or off in a top model, but must be off in a referenced model. If it is not, the Simulink Coder software temporarily sets it to off during code generation.

Configuration Requirements for Model Referencing with ERT System Targets

Dialog Box PaneOptionRequirement

Code Generation

Ignore custom storage classes

Must be the same for top and referenced models.

Symbols

Global variables
Global types
Subsystem methods
Local temporary variables
Constant macros
$R token must appear.

Signal naming

Must be the same for top and referenced models.

M-functionIf specified, must be the same for top and referenced models.

Parameter naming

Must be the same for top and referenced models.

#define naming

Must be the same for top and referenced models.

Interface

Support floating-point numbers

Must be the same for both top and referenced models

Support non-finite numbers

If off for top model, must be off for referenced models.

Support complex numbers

If off for top model, must be off for referenced models.

Suppress error status in real-time model

If on for top model, must be on for referenced models.

Templates

Target operating system

Must be the same for top and referenced models.

Data Placement

Module Naming

Must be the same for top and referenced models.

Module Name (if specified)

If set, must be the same for top and referenced models.

Signal display level

Must be the same for top and referenced models.

Parameter tune level

Must be the same for top and referenced models.

Naming Requirements.  Within a model that uses model referencing, there can be no collisions between the names of the constituent models. When you generate code from a model that uses model referencing, the Maximum identifier length parameter must be large enough to accommodate the root model name and the name mangling string. A code generation error occurs if Maximum identifier length is not large enough.

When a name conflict occurs between a symbol within the scope of a higher-level model and a symbol within the scope of a referenced model, the symbol from the referenced model is preserved. Name mangling is performed on the symbol from the higher-level model.

Embedded Coder Naming Requirements.  

The Embedded Coder™ product provides a Symbol format field that lets you control the formatting of generated symbols in much greater detail. When generating code with an ERT target from a model that uses model referencing:

See Code Generation Pane: Symbols and for more information.

Custom Target Requirements.  A custom target must meet various requirements in order to support model referencing. See Support Model Referencing for details.

Storage Classes for Signals Used with Model Blocks

Models containing Model blocks can use signals of storage class Auto without restriction. However, when you declare signals to be global, you must be aware of how the signal data will be handled.

A global signal is a signal with a storage class other than Auto:

The above are distinct from SimulinkGlobal signals, which are treated as test points with Auto storage class.

Global signals are declared, defined, and used as follows:

Custom storage classes also follow the above rules. However, certain custom storage classes are not currently supported for use with model reference. See Custom Storage Class Limitations for details.

Storage Classes for Parameters Used with Model Blocks.  All storage classes are supported for both simulation and code generation, and all except Auto are tunable. The supported storage classes thus include

Note the following restrictions on parameters in referenced models:

Note the following considerations concerning how global tunable parameters are declared, defined, and used in code generated for targets:

Certain custom storage classes for parameters are not currently supported for model reference. See Custom Storage Class Limitations for details.

Parameters used as Model block arguments must be defined in the referenced model's workspace. See Parameterizing Model References in the Simulink documentation for specific details.

Effects of Signal Name Mismatches.  Within a parent model, the name and storage class for a signal entering or leaving a Model block might not match those of the signal attached to the root inport or outport within that referenced model. Because referenced models are compiled independently without regard to any parent model, they cannot adapt to all possible variations in how parent models label and store signals.

The Simulink Coder software accepts all cases where input and output signals in a referenced model have Auto storage class. When such signals are test pointed or are global, as described above, certain restrictions apply. The following table describes how mismatches in signal labels and storage classes between parent and referenced models are handled:

Relationships of Signals and Storage Classes Between Parent and Referenced Models

Referenced Model

Parent Model

Signal Passing Method

Signal Mismatch Checking

Auto

Any

Function argument

None

SimulinkGlobal or resolved to Signal Object

Any

Function argument

Label Mismatch Diagnostic (none / warning / error)

Global

Auto or SimulinkGlobal

Global variable

Label Mismatch Diagnostic (none / warning / error)

Global

Global

Global variable

Labels and storage classes must be identical (else error)

To summarize, the following signal resolution rules apply to code generation:

You can set the Signal Mismatch diagnostic to error, warning, or none in the Configuration Parameters > Diagnostics > Connectivity dialog.

Inherited Sample Time for Referenced Models

See Inheriting Sample Times in the Simulink documentation for information about Model block sample time inheritance. In generated code, you can control inheriting sample time by using ssSetModelReferenceSampleTimeInheritanceRule in different ways:

The above code uses the sample times of the block, but only for determining whether there is a hit. Therefore, this S-function should set

ssSetModelReferenceSampleTimeInheritanceRule
(S, USE_DEFAULT_FOR_DISCRETE_INHERITANCE);

Customize the Library File Suffix, Including the File Type Extension

You can control the library file suffix, including the file type extension, that the Simulink Coder code generator uses to name generated model reference libraries by specifying the string for the suffix with the model configuration parameter TargetLibSuffix. The string must include a period (.). If you do not set this parameter,

On a...The Simulink Coder Software Names the Libraries...
MicrosoftWindows systemmodel_rtwlib.lib
The Open Group UNIX systemmodel_rtwlib.a

Simulink Coder Model Referencing Limitations

The following Simulink Coder limitations apply to model referencing. In addition to these limitations, a model reference hierarchy used for code generation must satisfy:

Customization Limitations.  

Data Logging Limitations.  

State Initialization Limitation.  When a top model uses the Load from workspace > Initial state option to specify initial conditions, the Simulink Coder software does not initialize the states of any referenced models.

Reusability Limitations.  If a referenced model used for code generation has any of the following properties, the model must specify Configuration Parameters > Model Referencing > Total number of instances allowed per top model as One, and no other instances of the model can exist in the hierarchy. If the parameter is not set as required, or more than one instance of the model exists in the hierarchy, an error occurs. The properties are:

S-Function Limitations.  

For additional information, in the Simulink documentation, see Using S-Functions with Model Referencing.

Simulink Tool Limitations.  

Subsystem Limitations.  

Target Limitations.  

Other Limitations.  

Reusable Components

Reusable Function Option

The difference between functions and reusable functions is that the latter have data passed to them as arguments (enabling them to be reentrant), while the former communicate by using global data. Choosing the Reusable function option directs the Simulink Coder code generator to generate a single function (optionally in a separate file) for the subsystem, and to call that code for each identical subsystem in the model, if possible.

For a summary of code reuse limitations, see Code Reuse Limitations.

Reusable Code and Referenced Models

Models that employ model referencing might require special treatment when generating and using reusable code. The following sections identify general restrictions and discuss how reusable functions with inputs or outputs connected to a referenced model's root Inport or Outport blocks can affect code reuse.

General Considerations.  You can generate code for subsystems that contain referenced models using the same procedures and options described in Subsystems. However, the following restrictions apply to such builds:

Code Reuse and Model Blocks with Root Inport or Outport Blocks.  Reusable functions with inputs or outputs connected to a referenced model's root Inport or Outport block can affect code reuse. This means that code for certain atomic subsystems cannot be reused in a model reference context the same way it is reused in a standalone model.

For example, suppose you create the following subsystem and make the following changes to the subsystem's block parameters:

Suppose you then create the following model, which includes three instances of the preceding subsystem.

With the Inline parameters option enabled in this stand-alone model, the Simulink Coder code generator can optimize the code by generating a single copy of the function for the reused subsystem, as shown below.

void reuse_subsys1_Subsystem1(
                   real_T rtu_0,
                   rtB_reuse_subsys1_Subsystem1 *localB)
{

  /* Gain: '<S1>/Gain' */
  localB->Gain_k = rtu_0 * 3.0;
}

When generated as code for a Model block (into an slprj project folder), the subsystems have three different function signatures:

/* Output and update for atomic system: '<Root>/Subsystem1' */
void reuse_subsys1_Subsystem1(const real_T *rtu_0, 
rtB_reuse_subsys1_Subsystem1
 *localB)
{
  /* Gain: '<S1>/Gain' */
  localB->Gain_w = (*rtu_0) * 3.0;
}

/* Output and update for atomic system: '<Root>/Subsystem2' */
void reuse_subsys1_Subsystem2(real_T rtu_In1, 
rtB_reuse_subsys1_Subsystem2
 *localB)
{
  /* Gain: '<S2>/Gain' */
  localB->Gain_y = rtu_In1 * 3.0;
}

/* Output and update for atomic system: '<Root>/Subsystem3' */
void reuse_subsys1_Subsystem3(real_T rtu_In1, real_T *rty_0)
{
  /* Gain: '<S3>/Gain' */
  (*rty_0) = rtu_In1 * 3.0;
}

One way to make all the function signatures the same for code reuse, is to insert Signal Conversion blocks. Place one between the Inport and Subsystem1 and another between Subsystem3 and the Outport of the referenced model.

The result is a single reusable function:

void reuse_subsys2_Subsystem1(real_T rtu_In1,
                   rtB_reuse_subsys2_Subsystem1 *localB)
{

  /* Gain: '<S1>/Gain' */
  localB->Gain_g = rtu_In1 * 3.0;
}

You can achieve the same result (reusable code) with only one Signal Conversion block. You can omit the Signal Conversion block connected to the Inport block if you select the Pass fixed-size scalar root inputs by value check box at the bottom of the Model Referencing pane of the Configuration Parameters dialog box. When you do this, you still need to insert a Signal Conversion block before the Outport block.

Generate Reusable Code from Stateflow Charts

You can generate reusable code from a Stateflow chart, or from a subsystem containing a chart, except in the following cases:

Generate Reusable Code for Subsystems Containing S-Function Blocks

Regarding S-Function blocks, there are several requirements that need to be met in order for subsystems containing them to be reused. See Write S-Functions That Support Code Reuse for the list of requirements.

When you select the Reusable function option, two additional options are enabled, Function name options and File name options. See Function Option for descriptions of these options and fields. If you use these fields to enter a function name and/or a file name, you must specify exactly the same function name and file name for each instance of identical subsystems for the Simulink Coder software to be able to reuse the subsystem code.

Subsystem Reusable Function Code Generation Option

To request that the Simulink Coder software generate reusable subsystem code,

  1. Select the subsystem block. Then select Subsystem Parameters from the Simulink model editor Edit menu. The Block Parameters dialog box opens.

    Alternatively, you can open the Block Parameters dialog box by:

    • Shift-double-clicking the subsystem block

    • Right-clicking the subsystem block and selecting Subsystem parameters from the menu.

  2. If the subsystem is virtual, select Treat as atomic unit. On the Code Generation tab, the Function packaging menu becomes enabled.

    If the system is already nonvirtual, the Function packaging menu is already enabled.

  3. Go to the Code Generation tab and select Reusable function from the Function packaging menu as shown in Subsystem Reusable Function Code Generation Option.

  4. If you want to give the function a specific name, set the function name, using the Function name options parameter, as described in Function Name Options Menu.

    If you do not choose Auto for the Function name options parameter, and want code to be reused, you must assign exactly the same function name to all other subsystem blocks that you want to share this code.

  5. If you want to direct the generated code to a specific file, set the file name using any File name options parameter value other than Auto (options are described in File Name Options Menu).

    In order for code to be reused, you must repeat this step for all other subsystem blocks that you want to share this code, using the same file name.

  6. Click Apply and close the dialog box.

Code Reuse Limitations

The Simulink Coder software uses a checksum to determine whether subsystems are identical. You cannot reuse subsystem code if:

Some of these situations can arise even when you copy and paste subsystems within or between models or you construct them manually such that they are identical. If you select Reusable function and the Simulink Coder software determines that code for a subsystem cannot be reused, it generates a separate function that is not reused. The code generation report can show that the separate function is reusable, even if it is used by only one subsystem. If you prefer that subsystem code be inlined in such circumstances rather than deployed as functions, you choose Auto for the Function packaging option.

Use of the following blocks in a subsystem can also prevent its code from being reused:

Determine Why Subsystem Code Is Not Reused

Due to the limitations noted in Code Reuse Limitations, the Simulink Coder software might not reuse generated code as you expect. To determine why code generated for a subsystem is not reused,

  1. Review the Subsystems section of the HTML code generation report

  2. If you cannot determine why based on the report, compare subsystem checksum data

Review the Subsystems Section of the HTML Code Generation Report.  If you determine that the Simulink Coder code generator does not generate code for a subsystem as reusable code and you specified the subsystem as reusable, examine the Subsystems section of the HTML code generation report (see Generate an HTML Code Generation Report). The Subsystems section contains

In addition to diagnosing exceptions, the Subsections section also indicates the mapping of each noninlined subsystem in the model to functions or reused functions in the generated code. For an example, open and build the rtwdemo_atomic demo model.

Compare Subsystem Checksum Data.  If the HTML code generation report indicates that no code reuse exceptions occurred and code for a subsystem you expect to be reused is not reused, you can determine why by accessing and comparing subsystem checksum data. The Simulink Coder software determines whether subsystems are identical by comparing subsystem checksums, as noted in Code Reuse Limitations.

Consider the demo model, rtwdemo_ssreuse.

SS1 and SS2 are instances of the same subsystem, and in both instances the subsystem parameter Function packaging is set to Reusable function.

The following example demonstrates how to use the method Simulink.SubSystem.getChecksum to get the checksum for a subsystem and compare the results to determine why code is not reused.

  1. Open the model rtwdemo_ssreuse and save a copy of the demo in a folder where you have write access.

  2. Select subsystem SS1 in the model window and in the command window enter

    SS1 = gcb;
  3. Select subsystem SS2 in the model window and in the command window enter

    SS2 = gcb;
  4. Use the method Simulink.SubSystem.getChecksum to get the checksum for each subsystem. This method returns two output values: the checksum value and details on the input used to compute the checksum.

    [chksum1, chksum1_details] = ...
    Simulink.SubSystem.getChecksum(SS1);
    [chksum2, chksum2_details] = ...
    Simulink.SubSystem.getChecksum(SS2);
  5. Compare the two checksum values. They should be equal based on the subsystem configurations.

    isequal(chksum1, chksum2)
    ans =
         1
  6. To see how you can use Simulink.SubSystem.getChecksum to determine why the checksums of two subsystems differ, change the data type mode of the output port of SS1 so that it differs from that of SS2.

    1. Look under the mask of SS1 by right-clicking the subsystem and selecting Look Under Mask in the context menu. A block diagram of the subsystem appears.

    2. Double-click the Lookup Table block to open the Block Parameters dialog box.

    3. Click Signal Attributes.

    4. Select int8 for Output data type and click OK.

  7. Get the checksum for SS1 again and compare the checksums for the two subsystems again. This time, the checksums should not be equal.

    [chksum1, chksum1_details] = ...
    Simulink.SubSystem.getChecksum(SS1);
    isequal(chksum1, chksum2)
    ans =
         0
  8. After you determine that the checksums are different, find out why. The Simulink engine uses information, such as signal data types, some block parameter values, and block connectivity information, to compute the checksums. To determine why checksums are different, you compare the data used to compute the checksum values. You can get this information from the second value returned by Simulink.SubSystem.getChecksum, which is a structure array with four fields.

    Look at the structure chksum1_details.

    chksum1_details
    
    chksum1_details = 
              ContentsChecksum: [1x1 struct]
             InterfaceChecksum: [1x1 struct]
         ContentsChecksumItems: [221x1 struct]
        InterfaceChecksumItems: [91x1 struct]

    ContentsChecksum and InterfaceChecksum are component checksums of the subsystem checksum. The remaining two fields ContentsChecksumItems and InterfaceChecksumItems contain the checksum details.

  9. Determine whether a difference exists in the subsystem contents, interface, or both. For example:

    isequal(chksum1_details.ContentsChecksum.Value,...
            chksum2_details.ContentsChecksum.Value)
    ans =
         0
    isequal(chksum1_details.InterfaceChecksum.Value,...
            chksum2_details.InterfaceChecksum.Value)
    ans =
         0

    In this case, differences exist in both the contents and interface.

  10. Write a script like the following to find the differences.

    idxForCDiffs=[];
    for idx = 1:length(chksum1_details.ContentsChecksumItems)
        if (~strcmp(chksum1_details.ContentsChecksumItems(idx).Identifier, ...
                    chksum2_details.ContentsChecksumItems(idx).Identifier))
                disp(['Identifiers different for contents item ', num2str(idx)]); 
                idxForCDiffs=[idxForCDiffs, idx];
        end
        if (ischar(chksum1_details.ContentsChecksumItems(idx).Value))
                if (~strcmp(chksum1_details.ContentsChecksumItems(idx).Value, ...
                            chksum2_details.ContentsChecksumItems(idx).Value))
                disp(['String values different for contents item ', num2str(idx)]); 
                idxForCDiffs=[idxForCDiffs, idx];
                end
        end
        if (isnumeric(chksum1_details.ContentsChecksumItems(idx).Value))
                if (chksum1_details.ContentsChecksumItems(idx).Value ~= ...
                            chksum2_details.ContentsChecksumItems(idx).Value)
                disp(['Numeric values different for contents item ', num2str(idx)]); 
                idxForCDiffs=[idxForCDiffs, idx];
                end
        end
    end
    
    idxForIDiffs=[];
    for idx = 1:length(chksum1_details.InterfaceChecksumItems)
        if (~strcmp(chksum1_details.InterfaceChecksumItems(idx).Identifier, ...
                    chksum2_details.InterfaceChecksumItems(idx).Identifier))
                disp(['Identifiers different for interface item ', num2str(idx)]); 
                idxForIDiffs=[idxForIDiffs, idx];
        end
        if (ischar(chksum1_details.InterfaceChecksumItems(idx).Value))
                if (~strcmp(chksum1_details.InterfaceChecksumItems(idx).Value, ...
                            chksum2_details.InterfaceChecksumItems(idx).Value))
                disp(['String values different for interface item ', num2str(idx)]); 
                idxForIDiffs=[idxForIDiffs, idx];
                end
        end
        if (isnumeric(chksum1_details.InterfaceChecksumItems(idx).Value))
                if (chksum1_details.InterfaceChecksumItems(idx).Value ~= ...
                            chksum2_details.InterfaceChecksumItems(idx).Value)
                disp(['Numeric values different for interface item ', num2str(idx)]); 
                idxForIDiffs=[idxForIDiffs, idx];
                end
        end
     end
  11. Run the script. The following example assumes you named the script check_details.

    check_details
    String values different for contents item 64
    String values different for contents item 75
    String values different for contents item 81
    String values different for interface item 46

    The results indicate that differences exist for index items 64, 75, and 81 in the subsystem contents and for item 46 in the subsystem interfaces.

  12. Use the returned index values to get the handle , identifier, and value details for each difference found.

    chksum1_details.ContentsChecksumItems(64)
    ans = 
            Handle: 'my_ssreuse/SS1/Lookup Table Output1'
        Identifier: 'CompiledPortAliasedThruDataType'
             Value: 'int8'
    chksum2_details.ContentsChecksumItems(64)
    ans = 
            Handle: 'my_ssreuse/SS2/Lookup Table Output1'
        Identifier: 'CompiledPortAliasedThruDataType'
             Value: 'double'
    chksum1_details.ContentsChecksumItems(75)
    ans = 
            Handle: 'my_ssreuse/SS1/Lookup Table'
        Identifier: 'RunTimeParameter{'OutputValues'}.DataType'
             Value: 'int8'
    chksum2_details.ContentsChecksumItems(75)
    ans = 
            Handle: 'my_ssreuse/SS2/Lookup Table'
        Identifier: 'RunTimeParameter{'OutputValues'}.DataType'
             Value: 'double'
    chksum1_details.ContentsChecksumItems(81)
    ans = 
            Handle: 'my_ssreuse/SS1/Lookup Table'
        Identifier: 'OutDataTypeMode'
             Value: 'int8'
    chksum2_details.ContentsChecksumItems(81)
    ans = 
            Handle: 'my_ssreuse/SS2/Lookup Table'
        Identifier: 'OutDataTypeMode'
             Value: 'Same as input'
    chksum1_details.InterfaceChecksumItems(46)
    ans = 
            Handle: 'my_ssreuse/SS1'
        Identifier: 'CanonicalParameter(1).DataType'
             Value: 'int8'
    chksum2_details.InterfaceChecksumItems(46)
    ans = 
            Handle: 'my_ssreuse/SS2'
        Identifier: 'CanonicalParameter(1).DataType'
             Value: 'double'

    As expected, the details identify the Lookup Table block and data type parameters as areas on which to focus for debugging a subsystem reuse issue.

  13. Fix the problem by changing the output data type mode for the subsystems such that they match.

Combined Models

If you want to combine several models (or several instances of the same model) into a single executable, the Simulink Coder product offers several options.

The most powerful solution is to use Model blocks. Each instance of a Model block represents another model, called a referenced model. For code generation, the referenced model effectively replaces the Model block that references it. For details, see Referencing a Model and Referenced Models.

When developing embedded systems using the Embedded Coder product, you can interface the code for several models to a common harness program by directly calling the entry points to each model. However, the Embedded Coder target has certain restrictions that might not apply to your application. For more information, see the Embedded Coder documentation.

The GRT malloc target is a another possible solution. Use it in situations where you want to:

To summarize by target, your options are as follows:

TargetSupport for Combining Multiple Models?

Generic Real-Time Target (grt.tlc)

Yes (using Model blocks)

Generic Real-Time Target with dynamic memory allocation (grt_malloc.tlc)

Yes

Embedded Coder (ert.tlc)

Yes

S-function Target (rtwsfcn.tlc)

No

Use GRT Malloc to Combine Models

This section discusses how to use the GRT malloc target to combine models into a single program.

Building a multiple-model executable is fairly straightforward:

  1. Generate and compile code from each of the models that are to be combined.

  2. Combine the makefiles for each of the models into one makefile for creating the final multimodel executable.

  3. Create a combined simulation engine by modifying grt_malloc_main.c to initialize and call the models.

  4. Run the combination makefile to link the object files from the models and the main program into an executable.

Share Data Across Models.  Use unidirectional signal connections between models. This affects the order in which models are called. For example, if an output signal from modelA is used as input to modelB, modelA's output computation should be called first.

Timing Issues.  You must generate all the models you are combining with the same solver mode (either all single-tasking or all multitasking.) In addition, if the models employ continuous states, the same solver should be used for all models.

Because each model has its own model-specific definition of the rtModel data structure, you must use an alternative mechanism to control model execution, as follows:

If the base rates for the models are not the same, the main program (such as grt_malloc_main) must set up the timer interrupt to occur at the greatest common divisor rate of the models. The main program is responsible for calling each of the models at a time interval.

Data Logging and External Mode Support.  A multiple-model program can log data to separate MAT-files for each model.

Only one of the models in a multiple-model program can use external mode.


[1] VxWorks is a registered trademark of Wind River® Systems, Inc.

  


Related Products & Applications

Learn more about Simulink through this collection of videos, articles, technical literature and the Getting Started with Simulink Guide.

 © 1984-2012- The MathWorks, Inc.    -   Site Help   -   Patents   -   Trademarks   -   Privacy Policy   -   Preventing Piracy   -   RSS