Embedded Coder Users Guide R2018a PDF
Embedded Coder Users Guide R2018a PDF
User's Guide
R2018a
How to Contact MathWorks
Phone: 508-647-7000
The bug reports are an integral part of the documentation for each release. Examine
periodically all bug reports for a release, as such reports may identify inconsistencies
between the actual behavior of a release you are using and the behavior described in this
documentation.
In addition to reviewing bug reports, you should implement a verification and validation
strategy to identify potential bugs in your design, code, and tools.
Contents
vii
Modeling in Simulink Coder
2
Configure a Model for Code Generation . . . . . . . . . . . . . . 2-2
viii Contents
Generate Code and Executables for Individual
Subsystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-4
Subsystem Build Limitations . . . . . . . . . . . . . . . . . . . . . . 3-6
ix
Storage Classes for Signals Used with Model Blocks . . . 4-21
Storage Classes for Parameters Used with Model
Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-21
Signal Name Mismatches Across Model Reference
Boundary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-22
x Contents
What Is Reentrant Code? . . . . . . . . . . . . . . . . . . . . . . . . . . 6-4
xi
Generate Reusable Code from Library Subsystems Shared
Across Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-53
What Is a Reusable Library Subsystem? . . . . . . . . . . . . 6-53
Reusable Library Subsystem Code Placement and
Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-54
Configure Reusable Library Subsystem . . . . . . . . . . . . . 6-54
Configure Models That Include Reusable Library
Subsystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-55
Generate Reusable Code for Subsystems Shared Across
Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-55
xii Contents
Configure Model Parameters for Simulink Coder
7
Configure Run-Time Environment Options . . . . . . . . . . . . 7-2
Configure Production and Test Hardware . . . . . . . . . . . . 7-3
Production Hardware Considerations . . . . . . . . . . . . . . 7-13
Test Hardware Considerations . . . . . . . . . . . . . . . . . . . 7-14
Example Production Hardware Setting That Affects Normal
Mode Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-14
xiii
Save Base Workspace Definitions . . . . . . . . . . . . . . . . . . . 8-24
xiv Contents
Specify Code Generation Parameters . . . . . . . . . . . . . 10-10
Generate Code for Only the Atomic Subchart . . . . . . . 10-11
xv
Integrate External C Code Into Generated Code By Using
Custom Code Blocks and Model Configuration
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-53
Integrate External C Code Into Generated Code By Using
Custom Code Blocks and Model Configuration
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-56
Insert External C and C++ Code Into Stateflow Charts for
Code Generation . . . . . . . . . . . . . . . . . . . . . . . . . . 11-59
xvi Contents
IEC 61508 Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-9
Apply Simulink and Embedded Coder to the IEC 61508
Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-9
Check for IEC 61508 Standard Compliance Using the
Model Advisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-9
Validate Traceability . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-9
xvii
MISRA C:2012 Compliance and Deviations for
Code Generated by Using Embedded Coder
13
Using This Documentation When Developing a MISRA C:
2012 Compliance Statement . . . . . . . . . . . . . . . . . . . . . 13-2
MathWorks Process for Identifying Violations of MISRA C:
2012 Guidelines in Generated C Code . . . . . . . . . . . . 13-2
xviii Contents
Definition, Initialization, and Declaration of
Parameter Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-7
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-7
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-7
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-8
Enumeration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-23
xix
If-Else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-27
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-27
Modeling Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-27
Modeling Pattern for If-Else: Switch block . . . . . . . . . 14-27
Modeling Pattern for If-Else: Stateflow Chart . . . . . . . 14-29
Modeling Pattern for If-Else: MATLAB Function
Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-30
Switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-32
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-32
Modeling Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-32
Modeling Pattern for Switch: Switch Case block . . . . . 14-32
Modeling Pattern for Switch: MATLAB Function
block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-35
Convert If-Elseif-Else to Switch statement . . . . . . . . . 14-36
xx Contents
Function Call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-59
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-59
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-59
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-60
Typedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-75
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-75
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-75
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-76
Bitfields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-89
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-89
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-89
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-90
xxi
Arrays for Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-92
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-92
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-92
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-92
Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-96
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-96
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-96
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-96
xxii Contents
Step 3: Configure Model for Generating Preprocessor
Conditionals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-29
Step 4: Review Generated Code . . . . . . . . . . . . . . . . . 15-30
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-33
xxiii
Timers in Simulink Coder
16
Absolute and Elapsed Time Computation . . . . . . . . . . . . 16-2
About Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-2
Timers for Periodic and Asynchronous Tasks . . . . . . . . . 16-3
Allocation of Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-3
Integer Timers in Generated Code . . . . . . . . . . . . . . . . 16-3
Elapsed Time Counters in Triggered Subsystems . . . . . 16-4
xxiv Contents
Multitasking Execution . . . . . . . . . . . . . . . . . . . . . . . . 17-16
xxv
Generate Interrupt Service Routines . . . . . . . . . . . . . . . . 18-6
Connecting the Async Interrupt Block . . . . . . . . . . . . . . 18-6
Requirements and Restrictions . . . . . . . . . . . . . . . . . . . 18-7
Performance Considerations . . . . . . . . . . . . . . . . . . . . . 18-7
Using the Async Interrupt Block in Simulation and Code
Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-8
Dual-Model Approach: Simulation . . . . . . . . . . . . . . . . . 18-9
Dual-Model Approach: Code Generation . . . . . . . . . . . . 18-9
xxvi Contents
Scheduling Considerations in Embedded Coder
19
Use Discrete and Continuous Time . . . . . . . . . . . . . . . . . 19-2
Support for Discrete and Continuous Time Blocks . . . . . 19-2
Support for Continuous Solvers . . . . . . . . . . . . . . . . . . 19-2
Support for Stop Time . . . . . . . . . . . . . . . . . . . . . . . . . 19-2
xxvii
Migrate Definitions from Model File to Shared
Data Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-9
Definitions in Shared Dictionary Do Not Appear in Code
Mapping Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-12
Make Shared Definitions in a Data Dictionary Available to
New Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-12
Use Data Dictionary to Store Code Definitions but Not
Design Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-13
Opening Code Perspective Generates Error . . . . . . . . 20-13
Limitations for Definitions in a Simulink
Data Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-13
xxviii Contents
Configure Default Code Generation for Categories of
Model Data and Functions . . . . . . . . . . . . . . . . . . . . . . 21-7
Configure Default Data and Function Configurations in
Model Editing Environment . . . . . . . . . . . . . . . . . . . 21-7
Configure Default Code Generation for Data . . . . . . . . . 21-8
Configure Default Code Generation for Functions . . . . 21-15
Configure Default Data and Function Code Generation with
Definitions Stored in Shared Data Dictionary . . . . . 21-20
Configure Default Data and Function Code Generation
Programmatically . . . . . . . . . . . . . . . . . . . . . . . . . . 21-22
Unresolved Storage Classes, Function Customization
Templates, and Memory Sections . . . . . . . . . . . . . . 21-31
Elimination of Parameters and Other Internal Data by
Optimizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21-32
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21-33
xxix
Control Data and Function Interface in Generated
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-42
Control Type Names, Field Names, and Variable Names of
Standard I/O Structures (Embedded Coder) . . . . . . 22-42
Control Names of Generated Entry-Point Functions
(Embedded Coder) . . . . . . . . . . . . . . . . . . . . . . . . . 22-42
Control Data Interface for Nonreentrant Code . . . . . . 22-43
Control Data Interface for Reentrant Code . . . . . . . . . 22-46
Prevent Unintended Changes to the Interface . . . . . . . 22-46
Reduce Number of Arguments by Using Structures . . 22-47
Control Data Types of Arguments . . . . . . . . . . . . . . . . 22-48
Promote Data Item to the Interface . . . . . . . . . . . . . . . 22-48
xxx Contents
Techniques to Apply Storage Classes
Programmatically . . . . . . . . . . . . . . . . . . . . . . . . . . 22-87
Parameter Object Configuration Quick
Reference Diagram . . . . . . . . . . . . . . . . . . . . . . . . . 22-89
xxxi
Initialize Parameter Value From System Constant or Other
Macro (Embedded Coder) . . . . . . . . . . . . . . . . . . . 22-129
Code Generation Impact of Storage Location for Parameter
Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-130
Configure Accessibility of Signal Data . . . . . . . . . . . 22-131
Programmatic Interfaces for Tuning Parameters . . . . 22-131
Set Tunable Parameter Minimum and Maximum
Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-132
Considerations for Other Modeling Goals . . . . . . . . . 22-132
xxxii Contents
Organize Data into Structures in Generated Code . . . 22-177
Techniques to Create Structures . . . . . . . . . . . . . . . . 22-181
Default Application of Structured Storage Class . . . . 22-182
Direct Application of Structured Storage Class . . . . . 22-183
Nonvirtual Buses and Parameter Structures . . . . . . . 22-183
Combine Techniques to Work Around Limitations . . . 22-194
Arrays of Structures . . . . . . . . . . . . . . . . . . . . . . . . . 22-194
Structure Padding . . . . . . . . . . . . . . . . . . . . . . . . . . 22-194
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-195
xxxiii
Optimize Generated Code Using Fixed-Point Data with
Simulink®, Stateflow®, and MATLAB® . . . . . . . . . 22-241
xxxiv Contents
Data Types in Embedded Coder
24
Control Data Type Names in Generated Code . . . . . . . . . 24-2
Control Names of Primitive Data Types . . . . . . . . . . . . . 24-2
Control Names of Structure Types . . . . . . . . . . . . . . . 24-11
Generate Code That Reuses Data Types From External
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24-11
Create Data Type Alias in the Generated Code . . . . . . 24-12
Create a Named Fixed-Point Data Type in the Generated
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24-17
Rename Data Type Object . . . . . . . . . . . . . . . . . . . . . 24-21
Display Signal Data Types on Block Diagram . . . . . . . 24-21
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24-21
xxxv
Specify Boolean and Data Type Limit Identifiers . . . . . 24-42
Data Type Limit Identifiers . . . . . . . . . . . . . . . . . . . . . 24-42
Boolean Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . 24-43
Boolean and Data Type Limit Identifier Header Files . 24-43
xxxvi Contents
Create Custom Storage Classes by Using the Custom
Storage Class Designer . . . . . . . . . . . . . . . . . . . . . . . . 26-26
Create and Apply a Custom Storage Class . . . . . . . . . 26-26
Modify a Built-In Custom Storage Class . . . . . . . . . . . 26-30
Control Data Representation by Configuring Custom
Storage Class Properties . . . . . . . . . . . . . . . . . . . . 26-31
Avoid Errors During Code Generation by Validating Custom
Storage Class Configuration . . . . . . . . . . . . . . . . . . 26-35
Make Custom Storage Classes Available Outside the
Current Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-35
Share Custom Storage Class Between Packages . . . . . 26-35
Control Appearance of Storage Class Drop-Down
List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-36
Protect Custom Storage Class Definitions . . . . . . . . . . 26-37
Further Customize Generated Code by Writing TLC
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-37
xxxvii
Configure Generated Code According to Interface Control
Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-83
xxxviii Contents
Generate C++ Class Interface to Nonvirtual Subsystem
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-10
C++ Class Interface Limitations . . . . . . . . . . . . . . . . . 28-11
xxxix
Configure C Initialize and Step Function Interfaces
Programmatically . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-19
Create and Validate Function Interface . . . . . . . . . . . . 29-21
Modify and Validate an Existing Function Interface . . 29-21
Create and Validate Function Interface Starting With
Default Configuration From Model . . . . . . . . . . . . . 29-22
Reset Model Function Interface to Default ERT Function
Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-22
Sample Script for Configuring Function Interfaces . . . 29-22
xl Contents
Memory Sections in Embedded Coder
30
Control Data and Function Placement in Memory by
Inserting Pragmas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30-2
Insert Pragmas by Using Memory Sections . . . . . . . . . . 30-2
Configure Pragma to Surround Groups of Definitions . . 30-9
Override Default Memory Placement for Individual Data
Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30-9
Choose Where to Create and Store Memory Section Definit
ion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30-10
Share Memory Section Definition Between Models . . . 30-10
Share Memory Section Between Packages (Package
Memory Sections Only) . . . . . . . . . . . . . . . . . . . . . 30-10
Control Appearance of Memory Section Drop-Down List
(Package Memory Sections Only) . . . . . . . . . . . . . . 30-11
Protect Definitions of Package Memory Sections (Package
Memory Sections Only) . . . . . . . . . . . . . . . . . . . . . 30-11
Override Default Memory Placement for Subsystem
Functions and Data . . . . . . . . . . . . . . . . . . . . . . . . 30-12
Create Fewer Custom Storage Classes (Package Memory
Sections Only) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30-14
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30-14
Insert Pragmas for Functions and Data in Generated
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30-15
xli
Code Generation
xlii Contents
Specify Identifier Length to Avoid Naming Collisions . 31-28
Debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31-34
xliii
Configuration Variations . . . . . . . . . . . . . . . . . . . . . . . . . 32-22
xliv Contents
Internationalization Support in Simulink Coder
34
Internationalization and Code Generation . . . . . . . . . . . 34-2
Locale Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34-2
Prepare to Generate Code for Mixed Languages and
Locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34-2
Character Set Limitations . . . . . . . . . . . . . . . . . . . . . . . 34-3
XML Escape Sequence Replacements . . . . . . . . . . . . . . 34-3
Generate and Review Code with Mixed Languages and
Mixed Locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34-3
xlv
Configure Model and Generate Code . . . . . . . . . . . . . . . 36-13
About This Example . . . . . . . . . . . . . . . . . . . . . . . . . . 36-13
Configure the Model for Code Generation . . . . . . . . . . 36-14
Save Your Model Configuration as a
MATLAB Function . . . . . . . . . . . . . . . . . . . . . . . . . 36-15
Check Model Conditions and Configuration Settings . . 36-16
Generate Code for the Model . . . . . . . . . . . . . . . . . . . 36-16
Review the Generated Code . . . . . . . . . . . . . . . . . . . . 36-17
Generate an Executable . . . . . . . . . . . . . . . . . . . . . . . 36-18
Key Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-18
xlvi Contents
Code Generator Header Files . . . . . . . . . . . . . . . . . . . 36-57
xlvii
Source Code Generation in Embedded Coder
37
Generate Code Using Embedded Coder® . . . . . . . . . . . . 37-2
xlviii Contents
View Code Generation Report in Model Explorer . . . . . 38-11
xlix
Open the Report Generator . . . . . . . . . . . . . . . . . . . . 38-51
Set Report Name, Location, and Format . . . . . . . . . . . 38-53
Include Models and Subsystems in a Report . . . . . . . . 38-54
Customize the Report . . . . . . . . . . . . . . . . . . . . . . . . . 38-55
Generate the Report . . . . . . . . . . . . . . . . . . . . . . . . . . 38-56
l Contents
Avoid Identifier Name Collisions with
Referenced Models . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-32
Use Model Advisor to Detect Identifier Names Changed
During Code Generation . . . . . . . . . . . . . . . . . . . . . 39-32
li
Generate Source and Header Files with a Custom File
Processing (CFP) Template . . . . . . . . . . . . . . . . . . . . . 39-73
Generate Code with a CFP Template . . . . . . . . . . . . . . 39-73
Analysis of the Example CFP Template and Generated
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-75
Generate a Custom Section . . . . . . . . . . . . . . . . . . . . 39-78
Custom Tokens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-80
lii Contents
Code Replacement in Simulink Coder
40
What Is Code Replacement? . . . . . . . . . . . . . . . . . . . . . . . 40-2
Code Replacement Libraries . . . . . . . . . . . . . . . . . . . . . 40-2
Code Replacement Terminology . . . . . . . . . . . . . . . . . . 40-4
Code Replacement Limitations . . . . . . . . . . . . . . . . . . . 40-7
liii
Deployment
liv Contents
Build Support for S-Functions . . . . . . . . . . . . . . . . . . 42-45
lv
Generate Code That Matches Appearance of External
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-106
lvi Contents
Template Makefiles for the Microsoft Visual C+
+ Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-28
Template Makefiles for the LCC Compiler . . . . . . . . . . 43-30
lvii
Profile Hook Function Interface Limitation . . . . . . . . . 43-75
lviii Contents
Configure Host Archiving of Target Program
Signal Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-60
Blocks and Subsystems Compatible with External
Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-63
External Mode Mechanism for Downloading Tunable
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-66
Choose Communication Protocol for Client and
Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-69
Use External Mode Programmatically . . . . . . . . . . . . . 44-77
Animate Stateflow Charts in External Mode . . . . . . . . 44-84
TCP/IP and Serial External Mode Limitations . . . . . . . 44-85
lix
Generate C API Files . . . . . . . . . . . . . . . . . . . . . . . . . . 46-3
Description of C API Files . . . . . . . . . . . . . . . . . . . . . . . 46-5
Generate C API Data Definition File for Exchanging Data
with a Target System . . . . . . . . . . . . . . . . . . . . . . . 46-20
C API Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46-22
lx Contents
Desktops in Simulink Coder
49
Accelerate, Refine, and Test Hybrid Dynamic System on
Host Computer by Using RSim System Target File . . . 49-2
About Rapid Simulation . . . . . . . . . . . . . . . . . . . . . . . . 49-2
Rapid Simulation Advantage . . . . . . . . . . . . . . . . . . . . . 49-2
General Rapid Simulation Workflow . . . . . . . . . . . . . . . 49-3
Identify Rapid Simulation Requirements . . . . . . . . . . . . 49-4
Configure Inports to Provide Simulation
Source Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49-6
Configure and Build Model for Rapid Simulation . . . . . . 49-6
Set Up Rapid Simulation Input Data . . . . . . . . . . . . . . . 49-8
Scripts for Batch and Monte Carlo Simulations . . . . . . 49-19
Run Rapid Simulations . . . . . . . . . . . . . . . . . . . . . . . . 49-19
Tune Parameters Interactively During Rapid
Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49-30
Rapid Simulation Target Limitations . . . . . . . . . . . . . . 49-33
lxi
Desktops in Embedded Coder
50
Package Generated Code as Shared Libraries . . . . . . . . . 50-2
About Generated Shared Libraries . . . . . . . . . . . . . . . . 50-2
Generate Shared Library Version of Model Code . . . . . . 50-2
Create Application Code to Use Shared Library . . . . . . 50-3
Shared Library Limitations . . . . . . . . . . . . . . . . . . . . . . 50-7
lxii Contents
Generate Code That Dereferences Data from a Literal
Memory Address . . . . . . . . . . . . . . . . . . . . . . . . . . 52-21
lxiii
Quick Start Code Replacement Library Development -
Simulink® . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-28
lxiv Contents
Review Library Content . . . . . . . . . . . . . . . . . . . . . . . 54-80
Review Table Content . . . . . . . . . . . . . . . . . . . . . . . . . 54-82
Review Code Replacements . . . . . . . . . . . . . . . . . . . . 54-85
lxv
Programmatic External Function Call Replacement Specifi
cation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-150
lxvi Contents
Subtraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-208
Multiplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-208
Division . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-209
Data Type Conversion (Cast) . . . . . . . . . . . . . . . . . . 54-210
Shift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-211
lxvii
Quick Start Library Development . . . . . . . . . . . . . . . . . . 55-16
lxviii Contents
Review Table Content . . . . . . . . . . . . . . . . . . . . . . . . . 55-68
Review Code Replacements . . . . . . . . . . . . . . . . . . . . 55-71
lxix
Customize Match and Replacement Process . . . . . . . . 55-113
Customize Match and Replacement Process for
Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-114
lxx Contents
Multiplication and Division with Rounding Mode and
Additional Implementation Arguments . . . . . . . . . 55-167
Performance
lxxi
Optimize Generated Code by Combining Multiple for
Constructs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-15
lxxii Contents
Generate Target Optimizations Within Algorithm
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-57
lxxiii
Disable Dynamic Memory Allocation for MATLAB Function
Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-91
Modify the Dynamic Memory Allocation Threshold . . . 56-91
lxxiv Contents
Reuse Global Block Outputs in the Generated Code . . 58-14
Data Copy Reduction for Data Store Read and Data Store
Write Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-35
lxxv
Remove Initialization Code . . . . . . . . . . . . . . . . . . . . . . . . 59-4
Remove Zero Initialization Code for Internal Data . . . . . 59-4
Remove Initialization Code for Root-Level Inports and
Outports Set to Zero . . . . . . . . . . . . . . . . . . . . . . . . . 59-6
Additional Information . . . . . . . . . . . . . . . . . . . . . . . . . 59-9
lxxvi Contents
Memory Usage in Embedded Coder
60
Optimize Generated Code Using Minimum and Maximum
Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60-2
Configure Your Model . . . . . . . . . . . . . . . . . . . . . . . . . . 60-2
Optimize Generated Code Using Specified Minimum and
Maximum Values . . . . . . . . . . . . . . . . . . . . . . . . . . . 60-3
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60-7
lxxvii
Profiling for Atomic Subsystems and Model Reference
Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61-4
lxxviii Contents
Verification
lxxix
Link Generated Code to Requirements . . . . . . . . . . . . . 64-29
lxxx Contents
Imported Data and Function Definitions . . . . . . . . . . . 67-10
lxxxi
Test an rtiostream Driver . . . . . . . . . . . . . . . . . . . . . . 67-50
Word Addressable Target Hardware . . . . . . . . . . . . . . 67-52
lxxxii Contents
Reasons for Block-Level Numerical Differences . . . . . . 68-5
lxxxiii
Verification of Code Generation Assumptions . . . . . . . . 69-34
lxxxiv Contents
Code Coverage Summary and Annotations . . . . . . . . . . 70-20
LDRA Testbed Coverage . . . . . . . . . . . . . . . . . . . . . . . 70-20
BullseyeCoverage Information . . . . . . . . . . . . . . . . . . 70-23
lxxxv
Run-Time Data Interface Extensions in Simulink
Coder
72
Customize Generated ASAP2 File . . . . . . . . . . . . . . . . . . . 72-2
About ASAP2 File Customization . . . . . . . . . . . . . . . . . 72-2
ASAP2 File Structure on the MATLAB Path . . . . . . . . . . 72-2
Customize the Contents of the ASAP2 File . . . . . . . . . . 72-3
ASAP2 Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72-4
Customize Computation Method Names . . . . . . . . . . . . 72-6
Suppress Computation Methods for FIX_AXIS . . . . . . . . 72-7
lxxxvi Contents
Configure Generated Code with TLC . . . . . . . . . . . . . . . 73-21
About Configuring Generated Code with TLC . . . . . . . 73-21
Assigning Target Language Compiler Variables . . . . . . 73-21
Set Target Language Compiler Options . . . . . . . . . . . . 73-23
lxxxvii
Custom Target Development in Simulink Coder
74
About Embedded Target Development . . . . . . . . . . . . . . . 74-2
Custom Targets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74-2
Types of Targets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74-2
Recommended Features for Embedded Targets . . . . . . . 74-4
lxxxviii Contents
Controlling Configuration Option Value Agreement . . . 74-89
Supporting the Shared Utilities Folder . . . . . . . . . . . . 74-89
Verifying Worker Configuration for Parallel Builds of Model
Reference Hierarchies (Optional) . . . . . . . . . . . . . . 74-93
Preventing Resource Conflicts (Optional) . . . . . . . . . . 74-95
lxxxix
Project and Build Configurations for Embedded
Targets in Embedded Coder
75
Model Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75-2
Block Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75-2
Configure Target Hardware Resources . . . . . . . . . . . . . 75-3
Configuration Parameters . . . . . . . . . . . . . . . . . . . . . . . 75-5
Model Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75-7
xc Contents
Execution-Time Profiling During PIL Simulation . . . . . 76-19
xci
Code Generation Template Files for MATLAB Code . . . . 78-9
Default CGT File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-9
CGT File Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-9
Components of the CGT File Sections . . . . . . . . . . . . . 78-11
xcii Contents
Choose a Code Replacement Library . . . . . . . . . . . . . . . . 79-8
About Choosing a Code Replacement Library . . . . . . . . 79-8
Explore Available Code Replacement Libraries . . . . . . . 79-8
Explore Code Replacement Library Contents . . . . . . . . 79-8
xciii
PIL Execution with ARM Cortex-A at the Command
Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81-10
xciv Contents
Model Architecture and Design
95
1
In this section...
“Application Algorithms and Run-Time Environments” on page 1-2
“Software Execution Framework for Generated Code” on page 1-3
“Map Embedded System Architecture to Simulink Modeling Environment” on page 1-5
“Model Templates for Code Generation” on page 1-14
1-2
Design Models for Generated Embedded Code Deployment
As you design models to generate C or C++ code for rapid prototyping or production
deployment, keep in mind the execution environment. Generate code that meets
implementation requirements and avoids potential design rework. As the preceding table
reflects, the execution environment for code that you generate can range from relatively
simple to complex. For example, a simple case is code that you generate from a single,
single-tasking model that runs on a single-core microprocessor. A complex case is code
that generate from a model partitioned to run as a distributed system on a multicore
microprocessor and an FPGA.
• Generate code from a single top model, which represents the algorithms intended to
run in the execution environment.
• Generate code from a model, which represents part of an overall algorithm. You can
mix the generated code with code written manually and code generated from other
sources or releases of MathWorks® products.
For a single top model, the software execution framework is responsible for running
generated code the same way that Simulink simulates the model. Functions in the
1-3
1 Modeling Environment for Embedded Coder
generated code are highly coordinated and optimized because Simulink is aware of
dependencies. The framework interfaces with code generated for the top model only.
Code generated for a top model handles interfacing with code for referenced Model
blocks.
Consider the following example, where a single top model is mapped to tasks that run on
a single-core CPU.
For this system, you map model clock rates to tasks that run on the hardware. You can
choose for Simulink to map the rates implicitly or you can map them explicitly in your
model. You can model latency effects resulting from how you map rates in a model to
single-tasking or multitasking execution environments. Simulink schedules the tasks
properly based on rates in the model and data dependencies between tasks. The code
generator implements the same dependencies in the code that it generates. The software
execution framework invokes generated entry-point functions at rates based on system
timers and interrupts. The generated code executes in the same manner that Simulink
simulates the model, and contains code dedicated to communicating data between
functions running at different rates.
When you generate code from multiple top models separately and mix that code with code
acquired in other ways, the execution environment of the application takes on more
software execution framework responsibility. For this modeling scenario, you generate
code for standalone, atomic reusable components.
1-4
Design Models for Generated Embedded Code Deployment
With this scenario, Simulink is not aware of model dependencies. Functions in code
generated from the different models are minimally coordinated and optimized. For
example, the models might share generated utility functions. Potential optimizations that
cross model boundaries are not possible. You must design the software execution
framework taking into account dependencies between units of code, including execution
order. For an application that requires concurrent execution across multiple cores, you
must consider data latency effects across the cores.
The code generator helps you address software execution framework challenges, such as
sharing global data and avoiding identifier conflicts. The code generated for a each model
handles the interfacing for referenced Model blocks.
“Modeling Given initial state and input, a set of tasks or instructions that
Algorithms” on efficiently produce the results that you want.
page 1-6
“Modeling Mechanisms that enable algorithm components to communicate and
Interfaces” on exchange information across component boundaries.
page 1-7
“Modeling Collection of algorithm components that achieve a higher-level,
Systems” on page domain-specific goal or result. Components often share resources.
1-9
1-5
1 Modeling Environment for Embedded Coder
Modeling Algorithms
1-6
Design Models for Generated Embedded Code Deployment
Modeling Interfaces
1-7
1 Modeling Environment for Embedded Coder
1-8
Design Models for Generated Embedded Code Deployment
Modeling Systems
1-9
1 Modeling Environment for Embedded Coder
1-10
Design Models for Generated Embedded Code Deployment
1-11
1 Modeling Environment for Embedded Coder
1-12
Design Models for Generated Embedded Code Deployment
1-13
1 Modeling Environment for Embedded Coder
Template Description
Code Generation Basic model consisting of an Inport block and Output block.
System
Exported Model for generating code from function-call subsystems. You can
functions export each function-call subsystem separately by right-clicking a
subsystem, selecting C/C++ Code > Export Functions, and clicking
Build.
Fixed-step, Fixed-step model that uses multiple rates and consists of Inport
multirate blocks, an Outport block, and a Sum block. The model is configured to
use a fixed-step discrete solver and to use two rates with Periodic
sample time constraint set to Unconstrained and the Treat each
discrete rate as a separate task option selected. Simulink inserts a
Rate Transition block to handle the two sample rates.
Fixed-step, single Fixed-step model that uses a single rate and consists of Inport blocks,
rate an Outport block, and a Sum block. The model is configured to use a
fixed-step discrete solver.
For more information, for example to create and use a template as a reference design, see
“Create a Template from a Model” (Simulink).
1-14
See Also
See Also
More About
• “Model Single-Core, Single-Tasking Platform Execution” on page 1-16
• “Model Single-Core, Multitasking Platform Execution” on page 1-21
• “Model Concurrent Execution for Symmetric Multicore CPU Platforms” on page 1-
26
• “Model Explicit Function Invocation with Atomic Subsystems” on page 1-34
• “Model Explicit Function Invocation with Function-Call Subsystems” on page 1-39
• “Modeling Patterns for AUTOSAR Runnables” on page 1-44
1-15
1 Modeling Environment for Embedded Coder
1-16
Model Single-Core, Single-Tasking Platform Execution
• Sample times for Inport blocks In1_1s and In2_2s are set to 1 and 2 seconds,
respectively.
• To provide clean partitioning of rates, sample times for subsystems SS1 and SS2 are
set to 1.
1-17
1 Modeling Environment for Embedded Coder
Scheduling
Simulink® simulates the model based on the model configuration. Code generated from
the model implements the same execution semantics. Simulink propagates and uses the
Inport block sample times to order block execution based on a single-core, single-tasking
execution platform.
For this model, the sample time legend shows an implicit rate grouping. Red represents
the fastest discrete rate. Green represents the second fastest discrete rate.
The generated code schedules subrates in the model. In this example, the rate for Inport
block In2_2s, the green rate, is a subrate. The generated code properly transfers data
between tasks running at the different rates.
Your execution framework can communicate with external devices for reading and writing
model input. For example, model external devices by using Simulink S-Function blocks.
Generate code for those blocks with the rest of the algorithm.
Generate code and a code generation report. The example model generates a report.
1-18
Model Single-Core, Single-Tasking Platform Execution
• ert_main.c is an example main program (execution framework) for the model. This
code controls model code execution by calling the entry-point function
rtwdemo_multirate_singletasking_step. Use this file as a starting point for
coding your execution framework.
• rtwdemo_multirate_singletasking.c contains entry points for the code that
implements the model algorithm. This file includes the rate scheduling code.
• rtwdemo_multirate_singletasking.h declares 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:
Input ports:
Entry-point functions:
Output ports:
1-19
1 Modeling Environment for Embedded Coder
More About
1-20
Model Single-Core, Multitasking Platform Execution
1-21
1 Modeling Environment for Embedded Coder
• Sample times for Inport blocks In1_1s and In2_2s are set to 1 and 2 seconds,
respectively.
• To provide a clear partitioning of rates, sample times for subsystems SS1 and SS2 are
set to 1.
1-22
Model Single-Core, Multitasking Platform Execution
• The Rate Transition block models an explicit rate transition. Alternatively, instruct
Simulink to insert Rate Transition blocks for you by selecting model configuration
parameter Solver > Automatically handle rate transition for data transfer.
Scheduling
Simulink® simulates the model based on the model configuration. Code that this model
generates implements the same execution semantics. Simulink propagates and uses the
Inport block sample times to order block execution based on a single-core, multitasking
execution platform.
For this model, the sample time legend shows an implicit rate grouping. Red represents
the fastest discrete rate. Green represents the second fastest discrete rate. Yellow
represents the mixture of the two rates.
The generated code schedules subrates in the model. In this example, the rate for Inport
block In2_2s, the green rate, is a subrate. The generated code properly transfers data
between tasks that run at the different rates.
• Simulink does not impose architectural constraints on the model. Create a model
without imposing software architecture constraints within the model.
• Your execution framework does not require details about underlying function
scheduling and data transfers between rates. Therefore, the model interface
requirements are simplified. The execution framework uses generated interface code
to write input, call the model step function, and read output.
• The code generator optimizes code across rates based on multitasking execution
semantics.
• Data transfers occur between a single read task and a single write task.
• When data transfers between two tasks, only one task can preempt the other task.
1-23
1 Modeling Environment for Embedded Coder
• For periodic tasks, a task with a faster rate has a higher priority than a task with a
slower rate. In addition, a task with the faster rate, preempts a task with a slower rate.
• Tasks run on a single processor.
• Time slicing, use of a defined time period during which a task can run in a preemptive
multitasking system, is not allowed.
• Processes do not crash or restart, especially during data transfers between tasks.
• Read and write operations on byte-sized variables are atomic.
Your execution framework communicates with external devices for reading and writing
model input. For example, model external devices by using Simulink S-Function blocks.
Generate code for those blocks with the rest of the algorithm.
Generate code and a code generation report. The example model generates a report.
• ert_main.c is an example main program (execution framework) for the model. This
code controls model code execution by calling the entry-point functions
rtwdemo_multirate_multitasking_step0 and
rtwdemo_multirate_multitasking_step1. Use this file as a starting point for
coding your execution framework.
• rtwdemo_multirate_multitasking.c contains entry points for the code that
implements the model algorithm. This file includes the rate scheduling code.
• rtwdemo_multirate_multitasking.h declares 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-24
Model Single-Core, Multitasking Platform Execution
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 model Outport blocks.
Input ports:
Entry-point functions:
Output ports:
More About
1-25
1 Modeling Environment for Embedded Coder
1-26
Model Concurrent Execution for Symmetric Multicore CPU Platforms
1-27
1 Modeling Environment for Embedded Coder
Explicit partitioning:
Consider the following periodic multirate model that is set up for multitasking execution.
1-28
Model Concurrent Execution for Symmetric Multicore CPU Platforms
• Sample times for Inport blocks In1_1s and In2_2s are set to 1 and 2 seconds,
respectively.
• To provide a clear partitioning of rates, sample times for models SS1 and SS2 are set
to 1.
• The Rate Transition block explicitly models a rate transition.
• The Integrator block is in a Model block configured with a fixed-step discrete solver
and a step size of two seconds.
• Subsystems SS1 and SS2 were converted to Model blocks configured with a fixed-step
discrete solver and a step size of one second.
• The Sum block is in a Model block configured with a fixed-step discrete solver and a
step size of one second. Another option for the Sum block is to place it in SS1 or SS2
and compute its value coincident with the Model block. For concurrent execution of
tasks, only connection blocks, Model blocks, and Subsystem blocks can be at the root
level of a model.
• The Rate Transition block was removed.
Open the Concurrent Execution dialog box by clicking Configure Tasks on the
Configuration Parameters Solver pane. Selecting Allow tasks to execute concurrently
on target enables the Configure Tasks button.
When selected, the Enable explicit model partitioning for concurrent behavior
parameter enables concurrent execution options for the top-level model.
1-29
1 Modeling Environment for Embedded Coder
Simulink creates a default mapping for each partition (Model block) by assigning each
partition to a separate task. Simulink designates that each partition executes
concurrently and simulates latency effects that data communication between processor
cores imposes. This dialog box displays a mapping consisting of partitions spread across
two independent periodic triggers: SS1, SS2, and Sum mapped to periodic trigger 1 and
Integrator mapped to periodic trigger 2.
Scheduling
Simulink® simulates the model based on the model configuration. Code generated from
the model implements the same execution semantics. Simulink propagates and uses the
1-30
Model Concurrent Execution for Symmetric Multicore CPU Platforms
Inport block sample times to order block execution based on a multicore, multitasking
execution platform.
For this model, the sample time legend shows an implicit rate grouping. Red represents
the fastest discrete rate. Green represents the second fastest discrete rate.
The generated code schedules subrates in the model. In this example, the rate for Inport
block In2_2s, the green rate, is a subrate. The generated code properly transfers data
between the rates.
• Simulink does not impose architectural constraints on the model. Create a model
without imposing software architecture constraints within it.
• Your execution framework does not require details about underlying function
scheduling and data transfers between rates. Therefore, model interface requirements
are simplified. The execution framework uses generated interface code to write input,
call the model step function, and read output.
• The code generator optimizes code across rates, based on multitasking execution
semantics.
• Data transfers occur between a single read task and a single write task.
• Tasks run on a single processor.
• Processes do not stop or restart, especially during data transfers between tasks.
• Read and write operations on byte-sized variables are atomic.
Your execution framework can communicate with external devices for reading and writing
model input. For example, model external devices by using Simulink S-Function blocks.
Generate code for those blocks with the rest of the algorithm.
Generate code and a code generation report. The example model generates a report.
1-31
1 Modeling Environment for Embedded Coder
• ert_main.c is an example main program (execution framework) for the model. This
code controls model code execution by indirectly calling entry-point functions
PeriodicTrigger1_OneSecond_step, PeriodicTrigger1_TwoSecond_step,
and PeriodicTrigger2_OneSecond_step with the function
rtwdemo_concurrent_execution_step. Use this file as a starting point for coding
your execution framework.
• rtwdemo_concurrent_execution.c contains entry points for the code that
implements the model algorithm. This file includes the rate and task scheduling code.
• rtwdemo_concurrent_execution.h declares model data structures and a public
interface to the model entry points and data structures.
• model_reference_types.h contains type definitions for timing bridges. These type
definitions are generated for a model reference target or a model containing Model
blocks.
• rtw_windows.h declares mutex and semaphore function prototypes that the
generated code uses for concurrent execution on Microsoft® Windows® platforms.
• 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
rtwdemo_concurrent_execution.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 model Outport blocks.
Input ports:
Entry-point functions:
1-32
Model Concurrent Execution for Symmetric Multicore CPU Platforms
To achieve real-time execution, define a task or thread for each entry-point step function.
Trigger execution of each function based on a timer that has the same rate as the given
function. The operating system schedules the tasks across cores dynamically or based on
your mapping of tasks to cores.
Output ports:
More About
1-33
1 Modeling Environment for Embedded Coder
1-34
Model Explicit Function Invocation with Atomic Subsystems
This model partitions an algorithm into two atomic subsystems: Rate1s and Rate2s.
Subsystem Rate1s is configured with a sample time of 1 second. Subsystem Rate2s is
configured with a sample time of 2 seconds.
1-35
1 Modeling Environment for Embedded Coder
Scheduling
Simulink® simulates the model based on the model configuration. Simulink propagates
and uses the Inport block sample times to order block execution based on a single-core,
single-tasking execution platform.
For this example, the sample time legend shows implicit rate grouping. Red represents
the fastest discrete rate. Green represents the second fastest discrete rate.
Your execution framework must schedule the generated function code and handle the
data transfers between them. This is an advantage for multirate models because the
generated code assumes no scheduling or data transfer semantics. However, the
execution framework must handle data transfers explicitly.
Generate a single callable function for each subsystem without connections between
them. Multiple ways are available to generate code for a subsystem, including from the
subsystem context menu. For example, right-click a subsystem block and click C/C++
Code > Build This Subsystem. In the Build code for Subsystem dialog box, click Build.
1-36
Model Explicit Function Invocation with Atomic Subsystems
• Rate1s.h and Rate2s.h declare model data structures and a public interface to
subsystem 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-37
1 Modeling Environment for Embedded Coder
More About
1-38
Model Explicit Function Invocation with Function-Call Subsystems
1-39
1 Modeling Environment for Embedded Coder
This model partitions an algorithm into three function-call subsystems: Rate1s, Rate2s,
and DataBuffer. Use function-call subsystems to model multirate systems explicitly.
Subsystems Rate1s and DataBuffer use a sample time of 1 second. Subsystem Rate2s
usea a sample time of 2 seconds.
This model design is referred to as export function modeling. Simulink constrains the
model to function-call subsystems at the root level. The driving Inport block specifies the
function name.
1-40
Model Explicit Function Invocation with Function-Call Subsystems
Scheduling
Simulink® simulates the model based on the model configuration. Simulink propagates
and uses the Inport block sample times to order block execution based on a single-core,
multitasking execution platform.
In the sample time legend, red identifies the fastest discrete rate. Magenta identifies
rates inherited from exported functions, indicating their execution is outside the context
of Simulink scheduling.
Your execution framework must schedule the generated function code and transfer data
between functions.
Your execution framework needs to schedule the generated function code and handle data
transfers between functions. The generated code is simple and you control the order of
execution.
Generate code and a code generation report. The example model generates a report.
• ert_main.c is an example main program (execution framework) for the model. This
code shows how to call the exported functions. The code also shows how to initialize,
execute, and terminate the generated code.
• rtwdemo_explicitinvocation_funccallsubsys.c calls the initialization
function and exported functions for subsystems Rate1s, Rate2s, and DataBuffer.
• rtwdemo_explicitinvocation_funccallsubsys.h declares model data
structures and a public interface to the exported entry point functions and data
structures.
1-41
1 Modeling Environment for Embedded Coder
• 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:
Input ports:
Entry-point functions:
Output ports:
More About
• “Generate Component Source Code for Export to External Code Base” on page 42-52
• “Deploy Generated Standalone Executable Programs To Target Hardware” on page 52-
2
1-42
Model Explicit Function Invocation with Function-Call Subsystems
1-43
1 Modeling Environment for Embedded Coder
Prerequisites
The Embedded Coder Support Package for AUTOSAR Standard is required for generating
C code and arxml descriptions for AUTOSAR software components.
Open the example model rtwdemo_autosar_swc. The model shows the implementation
of an AUTOSAR atomic software component (ASWC). Two periodic runnables,
Runnable_1s and Runnable_2s, are modeled with multiple sample rates: 1 second
(In1_1s) and 2 seconds (In2_2s). To maximize execution efficiency, the model is
configured for multitasking.
The model includes an Initialize Function block, which initializes the integrator in
Runnable_2s to a value of 1.
To display color-coded sample rates with annotations and a legend, select Display >
Sample Time > Colors.
1-44
Modeling Patterns for AUTOSAR Runnables
Scheduling
In the model window, enable sample time color-coding by selecting Display > Sample
Time > Colors. The sample time legend shows the implicit rate grouping. Red represents
the fastest discrete rate. Green represents the second fastest discrete rate. Yellow
represents the mixture of the two rates.
1-45
1 Modeling Environment for Embedded Coder
Because the model has multiple rates and the Solver parameter Treat each discrete
rate as a separate task is selected, the model simulates in multitasking mode. The
model handles the rate transition for In2_2s explicitly with the Rate Transition block.
The Rate Transition block parameter Ensure deterministic data transfer is cleared to
facilitate integration into an AUTOSAR Runtime Environment (RTE).
The generated code for the model schedules subrates in the model. In this example, the
rate for Inport block In2_2s, the green rate, is a subrate. The generated code properly
transfers data between tasks that run at the different rates.
Generate code and a code generation report. The example model generates a report.
Generated code complies with AUTOSAR so that you can schedule the code with the
AUTOSAR RTE.
• rtwdemo_autosar_swc.c contains entry points for the code that implements the
model algorithm. This file includes the rate scheduling code.
• rtwdemo_autosar_swc.h declares model data structures and a public interface to
the model entry points and data structures.
• rtwdemo_autosar_swc_private.h contains local define constants and local data
required by the model and subsystems.
• rtwdemo_autosar_swc_types.h provides forward declarations for the real-time
model data structure and the parameters data structure.
• rtwtypes.h defines data types, structures, and macros that the generated code
requires.
• rtwdemo_autosar_swc_component.arxml,
rtwdemo_autosar_swc_datatype.arxml,
rtwdemo_autosar_swc_implementation.arxml, and
rtwdemo_autosar_swc_interface.arxml contain elements and objects that
represent AUTOSAR software components, ports, interfaces, data types, and
packages. You integrate arxml files into an AUTOSAR RTE. You can import arxml
files into the Simulink environment by using the AUTOSAR arxml importer tool.
1-46
Modeling Patterns for AUTOSAR Runnables
Code Interface
Open and review the Code Interface Report. This information is captured in the arxml
files. The RTE generator uses the arxml descriptions to interface the code into an
AUTOSAR RTE.
Input ports:
Entry-point functions:
Output ports:
1-47
1 Modeling Environment for Embedded Coder
Use this approach to model the JMAAB complex control model type beta architecture. In
JMAAB type beta modeling, at the top level of a control model, you place function layers
above scheduling layers.
The model includes an Initialize Function block, which initializes the unit delay in
Runnable_1s to a value of 0.
To display color-coded sample rates with annotations and a legend, select Display >
Sample Time > Colors.
1-48
Modeling Patterns for AUTOSAR Runnables
Scheduling
In the model window, enable sample time color-coding by selecting Display > Sample
Time > Colors. The sample time legend shows the implicit rate grouping. Red represents
the discrete rate. Magenta represents the asynchronous function trigger. Yellow
represents the mixture of two rates.
The asynchronous trigger runnable runs at asynchronous rates (the Sample time type
parameter of the function-call subsystem Trigger block is set to |triggered]) while the
periodic rate runnable runs at the specified discrete rate. The generated code manages
the rates by using single-tasking assumptions. For models with one discrete rate, the code
generator does not produce scheduling code because there is only a single rate to
execute. Use this technique for a single-rate application when you have one periodic
runnable.
The model handles transitions between the asynchronous and discrete rates of the
connected runnables with the two Rate Transition blocks. The Rate Transition block
parameter Ensure deterministic data transfer is cleared to facilitate integration into
an AUTOSAR Runtime Environment (RTE).
Generate code and a code generation report. The example model generates a report.
Generated code complies with AUTOSAR so that you can schedule the code with the
AUTOSAR RTE.
1-49
1 Modeling Environment for Embedded Coder
Code Interface
Open and review the Code Interface Report. This information is captured in the arxml
files. The RTE generator uses the arxml descriptions to interface the code into an
AUTOSAR RTE.
Input port:
Entry-point functions:
Output port:
1-50
Modeling Patterns for AUTOSAR Runnables
The model includes an Initialize Function block, which initializes the unit delay in
subsystem RollingCounter to a value of 0.
To display color-coded sample rates with annotations and a legend, select Display >
Sample Time > Colors.
1-51
1 Modeling Environment for Embedded Coder
1-52
Modeling Patterns for AUTOSAR Runnables
Scheduling
In the model window, enable sample time color-coding by clicking Display > Sample
Time > Colors. The sample time legend shows the implicit rate grouping. Red identifies
the discrete rate. Magenta identifies rates inherited from exported functions, indicating
their execution is outside the context of Simulink scheduling.
Your execution framework must schedule the generated function code and handle data
transfers between functions.
Generate code and a code generation report. The example model generates a report.
• Produces an AUTOSAR runnable for the function-call subsystem at the root level of the
model.
• Implements signal connections between runnables as AUTOSAR inter-runnable
variables (IRVs).
Generated code complies with AUTOSAR so that you can schedule the code with the
AUTOSAR Runtime Environment (RTE).
1-53
1 Modeling Environment for Embedded Coder
Code Interface
Open and review the Code Interface Report. This information is captured in the arxml
files. The RTE generator uses the arxml descriptions to interface the code into an
AUTOSAR RTE.
Input ports:
Entry-point functions:
1-54
Modeling Patterns for AUTOSAR Runnables
Output ports:
Related Links
1-55
2
3 Open the Code Generation pane and make sure that System target file is set to
grt.tlc.
2-2
Configure a Model for Code Generation
Note The GRT (Generic Real-Time Target) configuration requires a fixed-step solver.
However, the rsim.tlc system target file supports variable step code generation.
The system target file (STF) defines a target, which is an environment for generating
and building code for execution on a certain hardware or operating system platform.
For example, one property of a target is code format. The grt configuration requires a
fixed step solver and the rsim.tlc supports variable step code generation.
4 Open the Code Generation > Custom Code pane, and under Include list of
additional, select Include directories. In the Include directories text field, enter:
"$matlabroot$\toolbox\rtw\rtwdemos\EmbeddedCoderOverview\"
This directory includes files that are required to build an executable for the model.
5 Apply your changes and close the dialog box.
2-3
2 Modeling in Simulink Coder
In this section...
“Related Products” on page 2-4
“Simulink Built-In Blocks That Support Code Generation” on page 2-7
“Simulink Block Data Type Support Table” on page 2-30
“Block Set Support for Code Generation” on page 2-30
As you construct a model, to prevent issues later in the development process, determine
whether the Simulink Coder and Embedded Coder code generators support the products
and blocks that you want to use.
Related Products
The following table summarizes MathWorks products that extend and complement
Simulink Coder software. For information about these products and how code generation
supports them, refer to their product documentation at www.mathworks.com.
2-4
Blocks and Products Supported for C Code Generation
2-5
2 Modeling in Simulink Coder
2-6
Blocks and Products Supported for C Code Generation
2-7
2 Modeling in Simulink Coder
2-8
Blocks and Products Supported for C Code Generation
Continuous
2-9
2 Modeling in Simulink Coder
Discontinuities
2-10
Blocks and Products Supported for C Code Generation
2-11
2 Modeling in Simulink Coder
Discrete
2-12
Blocks and Products Supported for C Code Generation
2-13
2 Modeling in Simulink Coder
2-14
Blocks and Products Supported for C Code Generation
Lookup Tables
2-15
2 Modeling in Simulink Coder
Math Operations
2-16
Blocks and Products Supported for C Code Generation
2-17
2 Modeling in Simulink Coder
2-18
Blocks and Products Supported for C Code Generation
Model Verification
2-19
2 Modeling in Simulink Coder
Model-Wide Utilities
2-20
Blocks and Products Supported for C Code Generation
2-21
2 Modeling in Simulink Coder
Signal Attributes
2-22
Blocks and Products Supported for C Code Generation
Signal Routing
2-23
2 Modeling in Simulink Coder
2-24
Blocks and Products Supported for C Code Generation
Sinks
2-25
2 Modeling in Simulink Coder
Sources
2-26
Blocks and Products Supported for C Code Generation
2-27
2 Modeling in Simulink Coder
2-28
Blocks and Products Supported for C Code Generation
2-29
2 Modeling in Simulink Coder
User-Defined
2-30
Modeling Semantic Considerations
Data Propagation
The first stage of code generation is compilation of the block diagram. This stage is
analogous to that of a C or C++ program. The compiler carries out type checking and
preprocessing. Similarly, the Simulink engine verifies that input/output data types of
block ports are consistent, line widths between blocks are of expected thickness, and the
sample times of connecting blocks are consistent.
The Simulink engine propagates data from one block to the next along signal lines. The
data propagated consists of
• Data type
• Line widths
• Sample times
You can verify what data types a Simulink block supports by typing
showblockdatatypetable
at the MATLAB prompt, or (from the Help browser) clicking the command above.
The Simulink engine typically derives signal attributes from a source block. For example,
the Inport block's parameters dialog box specifies the signal attributes for the block.
2-31
2 Modeling in Simulink Coder
In this example, the Inport block has a port width of 3, a sample time of .01 seconds, the
data type is double, and the signal is complex.
This figure shows the propagation of the signal attributes associated with the Inport block
through a simple block diagram.
2-32
Modeling Semantic Considerations
In this example, the Gain and Outport blocks inherit the attributes specified for the Inport
block.
In such cases, the Simulink engine propagates the known or assigned sample times to
those blocks that have inherited sample times but that have not yet been assigned a
sample time. Thus, the engine continues to fill in the blanks (the unknown sample times)
until sample times have been assigned to as many blocks as possible. Blocks that still do
not have a sample time are assigned a default sample time.
For a completely deterministic model (one where no sample times are set using the above
rules), you should explicitly specify the sample times of your source blocks. Source blocks
include root inport blocks and blocks without input ports. You do not have to set
subsystem input port sample times. You might want to do so, however, when creating
modular systems.
An unconnected input implicitly connects to ground. For ground blocks and ground
connections, the sample time is always constant (inf).
All blocks have an inherited sample time (Ts = -1). They are assigned a sample time of (Tf
- Ti)/50.
When you display sample time colors, by default, Constant blocks appear magenta in
color to indicate that the block outputs have constant values during simulation.
Downstream blocks whose output values are also constant during simulation, such as
Gain blocks, similarly appear magenta if they use an inherited sample time. The code
generated for these blocks depends in part on the tunability of the block parameters.
If you set Configuration Parameters > Optimization > Default parameter behavior
to Inlined, the block parameters are not tunable in the generated code. Because the
block outputs are constant, the code generator eliminates the block code due to constant
folding. If the code generator cannot fold the code, or if you select settings to disable
constant folding, the block code appears in the model initialization function. The
2-33
2 Modeling in Simulink Coder
generated code is more efficient because it does not compute the outputs of these blocks
during execution.
However, if you configure a block or model so that the block parameters appear in the
generated code as tunable variables, the code generator represents the blocks in a
different way. Block parameters are tunable if, for example:
If a block parameter is tunable, the generated code must compute the block outputs
during execution. Therefore, the block code appears in the model step function. If the
model uses multiple discrete rates, the block code appears in the output function for the
fastest downstream rate that uses the block outputs.
For Use
Triggered subsystems Latch input by delaying outside signal
Function-call Latch input for feedback signals of function-call subsystem
subsystems outputs
When you use Latch input for feedback signals of function-call subsystem outputs
for a function-call subsystem, the code generator
For more information on these options, see the block description of Inport.
2-34
Modeling Semantic Considerations
You cannot override this execution order by directly calling a block (in handwritten code)
in a model. For example, in the next figure the disconnected_trigger model on the
left has its trigger port connected to ground, which can lead to the blocks inheriting a
constant sample time. Calling the trigger function, f(), directly from user code does not
work. Instead, you should use a function-call generator to specify the rate at which f()
should be executed, as shown in the connected_trigger model on the right.
f0
Connected
Disconnected Function-call Trigger
Trigger Generator
f0 f0
1 In1 Out1 1 1 In1 Out1 1
In1 Out1 In1 Out1
Triggered Triggered
Subsystem Subsystem
Instead of the function-call generator, you could use another block that can drive the
trigger port. Then, you should call the model's main entry point to execute the trigger
function.
For multirate models, a common use of the code generator is to generate code for
individual models separately and then manually code the I/O between the generated code
modules. This approach places the burden of data consistency between models on the
developer of the models. Another approach is to let Simulink and the code generator
maintain data consistency between rates and generate multirate code for use in a
multitasking environment. The Rate Transition block is able to interface periodic and
asynchronous signals. For a description of the Simulink Coder block libraries, see
2-35
2 Modeling in Simulink Coder
Algebraic Loops
Algebraic loops are circular dependencies between variables. This prevents the
straightforward direct computation of their values. For example, in the case of a system of
equations
• x = y + 2
• y = -x
To solve this, either repeatedly try potential solutions for x and y (in an intelligent
manner, for example, using gradient based search) or “solve” the system of equations. In
the previous example, solving the system into an explicit form leads to
• 2x = 2
• y = -x
• x = 1
• y = -1
An algebraic loop exists whenever the output of a block having direct feedthrough (such
as Gain, Sum, Product, and Transfer Fcn) is fed back as an input to the same block. The
Simulink engine is often able to solve models that contain algebraic loops, such as the
next diagram.
2-36
Modeling Semantic Considerations
The code generator does not produce code that solves algebraic loops. This restriction
includes models that use Algebraic Constraint blocks in feedback paths. However, the
Simulink engine can often eliminate algebraic loops that arise, by grouping equations in
certain ways in models that contain them. It does this by separating the update and
output functions to avoid circular dependencies. For details, see “Algebraic Loops”
(Simulink).
While the Simulink engine can minimize algebraic loops involving atomic and enabled
subsystems, a special consideration applies to some triggered subsystems. An example for
which code can be generated is shown in the following model and triggered subsystem.
The default Simulink behavior is to combine output and update methods for the
subsystem, which creates an apparent algebraic loop, even though the Unit Delay block in
the subsystem has no direct feedthrough.
You can allow the Simulink engine to solve the problem by splitting the output and update
methods of triggered and enabled-triggered subsystems when feasible. If you want the
code generator to take advantage of this feature, select the Minimize algebraic loop
occurrences check box in the Subsystem Parameters dialog box. Select this option to
avoid algebraic loop warnings in triggered subsystems involved in loops.
Note If you check this box, the generated code for the subsystem might contain split
output and update methods, even if the subsystem is not actually involved in a loop. Also,
if a direct feedthrough block (such as a Gain block) is connected to the inport in the above
2-37
2 Modeling in Simulink Coder
triggered subsystem, the Simulink engine cannot solve the problem, and the code
generator is unable to generate code.
2-38
Modeling Guidelines for Blocks
See Also
“Modeling Guidelines for Subsystems” on page 2-40 | “Modeling Guidelines for Charts”
on page 2-43 | “Modeling Guidelines for MATLAB Functions” on page 2-45 | “Modeling
Guidelines for Model Configuration” on page 2-46
2-39
2 Modeling in Simulink Coder
Code Generation “cgsl_0204: Vector and bus signals crossing into atomic subsystems or
Modeling Model blocks” (Simulink)
Guidelines
High-Integrity “hisl_0009: Usage of For Iterator Subsystem blocks” (Simulink)
Systems
Modeling “hisl_0010: Usage of If blocks and If Action Subsystem blocks”
Guidelines (Simulink)
2-40
Modeling Guidelines for Subsystems
2-41
2 Modeling in Simulink Coder
See Also
“Modeling Guidelines for Blocks” on page 2-39 | “Modeling Guidelines for Charts” on
page 2-43 | “Modeling Guidelines for MATLAB Functions” on page 2-45 | “Modeling
Guidelines for Model Configuration” on page 2-46
2-42
Modeling Guidelines for Charts
2-43
2 Modeling in Simulink Coder
See Also
“Modeling Guidelines for Blocks” on page 2-39 | “Modeling Guidelines for Subsystems” on
page 2-40 | “Modeling Guidelines for MATLAB Functions” on page 2-45 | “Modeling
Guidelines for Model Configuration” on page 2-46
2-44
Modeling Guidelines for MATLAB Functions
See Also
“Modeling Guidelines for Blocks” on page 2-39 | “Modeling Guidelines for Subsystems” on
page 2-40 | “Modeling Guidelines for Charts” on page 2-43 | “Modeling Guidelines for
Model Configuration” on page 2-46
2-45
2 Modeling in Simulink Coder
2-46
Modeling Guidelines for Model Configuration
2-47
2 Modeling in Simulink Coder
See Also
“Modeling Guidelines for Blocks” on page 2-39 | “Modeling Guidelines for Subsystems” on
page 2-40 | “Modeling Guidelines for Charts” on page 2-43 | “Modeling Guidelines for
MATLAB Functions” on page 2-45
2-48
3
To See
Generate inlined code from a selected “Inline Subsystem Code” on page 3-8
subsystem.
Generate code for only a subsystem. “Generate Code and Executables for
Individual Subsystems” on page 3-4
Generate separate functions without “Generate Subsystem Code as Separate
arguments, and optionally place the Function and Files” on page 3-11
subsystem code in a separate file.
Generate a single reentrant function for a “Generate Reentrant Code from
subsystem that is included in multiple Subsystems” on page 6-42
places within a model.
Generate a single reentrant function for a “Generate Reusable Code from Library
subsystem that is included in multiple Subsystems Shared Across Models” on
places in a model reference hierarchy. page 6-53
3-2
See Also
subsystem code file contains include directives and comments describing the
dependencies. The code generator checks for cyclic file dependencies and warns about
them at build time. For descriptions of how the code generator packages code, see
“Manage Build Process File Dependencies” (Simulink Coder).
To generate subsystem function code that is independent of the code generated for the
parent model, place the subsystem in a library and configure it as a reusable subsystem,
as explained in “Generate Reusable Code from Library Subsystems Shared Across
Models” on page 6-53.
See Also
Related Examples
• “Modeling Guidelines for Subsystems” on page 2-40
3-3
3 Subsystems in Simulink Coder
1 In the Configuration Parameters dialog box, set up the code generation and build
parameters, similar to setting up the code generation for a model.
2 Right-click the Subsystem block. From the context menu, select C/C++ Code >
Build This Subsystem from the context menu.
Alternatively, in the current model, click a subsystem and then from the Code menu,
select C/C++ Code > Build Selected Subsystem.
Note When you select Build This Subsystem, if the model is operating in external
mode, the build process automatically turns off external mode for the duration of the
build. The code generator restores external mode upon completion of the build
process.
3 The Build code for Subsystem 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 the blocks that reference the
parameter and the parent system of each block.
The Storage Class column contains a menu for each row. The menu options set the
storage class or inline the parameter. To declare a parameter to be tunable, set the
Storage Class to a value other than Inlined.
3-4
Generate Code and Executables for Individual Subsystems
For more information on tunable and inlined parameters and storage classes, see
“Create Tunable Calibration Parameter in the Generated Code” on page 22-121.
4 After selecting tunable parameters, Build to initiate the code generation and build
process.
5 The build process displays status messages in the MATLAB Command Window. When
the build is complete, 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). subsystem is the name of the source subsystem
block.
When you generate code for a subsystem, you can generate an S-function by selecting
Code > C/C++ Code> Generate S-Function, or you right-click the subsystem block
and select C/C++ Code > Build This Subsystem from the context menu. For more
information on S-functions, see “Generate S-Function from Subsystem” (Simulink Coder).
3-5
3 Subsystems in Simulink Coder
• Subsystem build does not support a subsystem that has a function-call trigger input or
a function-call output.
• When you right-click a subsystem block and select C/C++ Code > Build This
Subsystem from the context menu to build a subsystem that includes an Outport
block for which the Data type parameter specifies a bus object, you must address
errors that result from setting signal labels. To configure the software to display these
errors, in the Configuration Parameters dialog box for the parent model, on the
Diagnostics > Connectivity pane, set the Signal label mismatch parameter to
error.
• When a subsystem is in a triggered or function-call subsystem, the right-click build
process might fail if the subsystem code is not sample-time independent. To find out
whether a subsystem is sample-time independent:
a Type to Fixed-step.
b Periodic sample time constraint to Ensure sample time
independent.
c Click Apply.
3 Update the model. If the model is sample-time dependent, Simulink generates an
error in the process of updating the diagram.
• When you use the right-click build process for a subsystem, the code generator
attempts to use the subsystem name for generated code files. In some cases, there can
be a conflict with the name that you specify when you set, for example, File name
options to Use function name or Function name options to Use subsystem
name. You see an error:
To resolve the error, modify one of the conflicting file names so that the names are
unique.
3-6
Generate Code and Executables for Individual Subsystems
• In a subsystem build warning, the subsystem block path hyperlink that is created
references a temporary model block path instead of the actual model block path. In
the Diagnostic Viewer, clicking the subsystem hyperlink does not take you to the block.
In the Command Window, you see a message:
...
No system or file called 'subsystemName' found.
...
3-7
3 Subsystems in Simulink Coder
The Auto option is the default. When there is only one instance of a subsystem in the
model, the Auto option inlines the subsystem code. When multiple instances of a
subsystem exist, the Auto option results in a single copy of the function (as a reusable
function). For function-call subsystems with multiple callers, the subsystem code is
generated as if you specified Nonreusable function.
To inline subsystem code, select Inline. The Inline option explicitly directs the code
generator to inline the subsystem unconditionally.
1 Right-click the Subsystem block. From the context menu, select Block Parameters
(Subsystem).
2 In the Subsystem Parameters dialog box, if the subsystem is virtual, select Treat as
atomic unit. This option makes the subsystem nonvirtual. On the Code Generation
tab, the Function packaging option is now available.
3-8
Inline Subsystem Code
When you generate code from your model, the code generator inlines subsystem code
within model.c or model.cpp (or in its parent system's source file). You can identify this
code by system/block identification tags, such as:
/* Atomic SubSystem Block: <Root>/AtomicSubsys1 */
Exceptions to Inlining
There are certain cases in which the code generator does not inline a nonvirtual
subsystem, even though the Inline option is selected.
3-9
3 Subsystems in Simulink Coder
• In a feedback loop involving function-call subsystems, the code generator forces one of
the subsystems to be generated as a function instead of inlining it. Based on the order
in which the subsystems are sorted internally, the software selects the subsystem to be
generated as a function.
• If a subsystem is called from an S-function block that sets the option
SS_OPTION_FORCE_NONINLINED_FCNCALL to TRUE, it is not inlined. When user-
defined Async Interrupt blocks or Task Sync blocks are present, this result might
occur. Such blocks must be generated as functions. These blocks are located in the
vxlib1 block library and use the SS_OPTION_FORCE_NONINLINED_FCNCALL option.
This library demonstrates integration with an example RTOS (VxWorks®).1
Note You can use the blocks in the vxlib1 (Simulink Coder) library (Async Interrupt and
Task Sync) for simulation and code generation. These blocks provide starting point
examples to help you develop custom blocks for your target environment.
3-10
Generate Subsystem Code as Separate Function and Files
1 Right-click a Subsystem block. From the context menu, select Block Parameters
(Subsystem).
2 In the Subsystem Parameters dialog box, if the subsystem is virtual, select Treat as
atomic unit. On the Code Generation tab, the Function packaging parameter is
now available.
3 Click the Code Generation tab and select Nonreusable function from the
Function packaging parameter. The Nonreusable function option enables two
parameters:
• The “Function name options” (Simulink) parameter controls the naming of the
generated function.
• The “File name options” (Simulink) parameter controls the naming of the
generated file.
4 Set the Function name options parameter.
5 Set the File name options parameter to a value other than Auto. If you are
generating a reusable function for your subsystem, see “Generate Reentrant Code
from Subsystems” on page 6-42 or “Generate Reusable Code from Library
Subsystems Shared Across Models” on page 6-53.
6 Click Apply and close the dialog box.
3-11
3 Subsystems in Simulink Coder
3-12
Code Generation of Constant Parameters
/* Expression: [7 6 5 4 3 2 1]
* Referenced by: '<Root>/Gain'
*/
real_T Gain_Gain[7];
} ConstParam_model;
/* Expression: [7 6 5 4 3 2 1]
* Referenced by: '<Root>/Gain'
*/
{ 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 }
};
3-13
3 Subsystems in Simulink Coder
See Also
Related Examples
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
3-14
4
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 other
types of targets:
• Target hardware — A platform for which the Simulink Coder software generates code
• System target — A file that tells the Simulink Coder software how to generate code for
particular purpose
• Rapid Simulation target (RSim) — A system target file supplied with the Simulink
Coder product
• Simulation target — A MEX-file that implements a referenced model that executes
with Simulink Accelerator™ software
The code generator places the code for the top model of a hierarchy in the code
generation folder (Simulink) and places the code for referenced models in an slprj
folder in the code generation folder (Simulink). Subfolders in slprj provide separate
places for different types of files. For folder information, see “Manage Build Process
Folders” (Simulink Coder).
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 to regenerate model reference targets. To control when rebuilds
occur, use the configuration parameter Model Referencing > Rebuild. For details, see
“Rebuild” (Simulink).
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
4-2
Code Generation of Referenced Models
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
referenced models: the 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.
If you have a Embedded Coder license, custom targets must declare themselves to be
model reference compliant if they need to support Model blocks. For more information,
see “Support Model Referencing” on page 74-84.
4-3
4 Referenced Models in Simulink Coder
You can accomplish some of these tasks automatically with a function called
Simulink.Subsystem.convertToModelReference.
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 example model by typing:
4-4
Generate Code for Referenced Models
vdp
3 Drag a box around the three blocks outlined in blue below:
4 Choose Create Subsystem from Selection from the Diagram > Subsystem &
Model Reference menu.
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.
4-5
4 Referenced Models in Simulink Coder
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 selection 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 Diagnostics. In the right pane, select the Data Validity
tab. In the Signals area, set Signal resolution to Explicit only. Alternatively, if
you do not want to use Simulink.Signal objects, set Signal resolution to None.
7 Click Apply.
The model now has the properties that model referencing requires.
4-6
Generate Code for Referenced Models
8 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 code regeneration when it is not required.
9 In the vdp model window, choose File > Save as. Save the model as vdptop in your
working folder. Leave the model open.
help Simulink.SubSystem.convertToModelReference
doc Simulink.SubSystem.convertToModelReference
sldemo_mdlref_conversion
Simulink also provides a menu command, Subsystem & Model Reference > Convert
Subsystem to > Referenced Model, that you can use to convert a subsystem to a
referenced model. The command calls
Simulink.SubSystem.convertToModelReference with default arguments. For more
information, see “Convert a Subsystem to a Referenced Model” (Simulink).
Simulink.SubSystem.convertToModelReference...
('vdptop/vdpmult', 'vdpmultRM',...
'ReplaceSubsystem', true, 'BuildTarget', 'Sim')
This command:
4-7
4 Referenced Models in Simulink Coder
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.
ans =
1
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 does not have
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 to open the referenced model.
The model looks like this:
4-8
Generate Code for Referenced Models
The files in your working folder now consist of the following (not in this order).
File Description
vdptop model file Top model that contains a Model block where the
vdpmult subsystem was
vdpmultRM model file Referenced model created for the vdpmult
subsystem
vdpmultRM_msf.mexw64 Static library file (Microsoft® Windows platforms
only). The file extension is 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 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 code generation folders, see “Work with Code
Generation Folders” on page 4-12.
Open the Scope block in vdptop if it is not visible. In the vdptop window, click the Run
tool or choose Run from the Simulation menu. The model calls the vdpmultRM_msf
simulation target to simulate. The output looks like this:
4-9
4 Referenced Models in Simulink Coder
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. For example, in the model, press Ctrl+B.
4-10
Generate Code for Referenced Models
The Simulink Coder build process generates and compiles code. The current folder now
contains a new file and a new folder:
File Description
vdptop.exe The executable created by the build process
vdptop_grt_rtw/ The build folder, containing generated code
for the top model
The 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 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.
4-11
4 Referenced Models in Simulink Coder
To view the generated code in the HTML code generation report, see “Generate a
Code Generation Report” (Simulink Coder).
The models referenced by Model blocks can be stored anywhere on the MATLAB path. 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 and generated code derived from these
models. Under most circumstances, to allow code reuse, models referenced by a given top
model must be set up to simulate and generate model reference target code in a single
code generation folder.
This means that, if you reference the same model from several top models, each stored in
a different folder, you must choose one of these approaches:
• Always work with the same code generation folder and be sure that the models are on
your path.
4-12
See Also
• Allow separate code generation folders, simulation targets, and Simulink Coder
targets to be generated in each folder in which you work.
The second approach requires maintenance of several instances of the model reference
code and it is possible for generated code to become redundant. For example, when you
make changes to the referenced model. Therefore, to minimize code regeneration of
referenced models, choose a specific code generation folder for all sessions.
See Also
Related Examples
• “Specify Instance-Specific Parameter Values for Reusable Referenced Model” on
page 22-142
• “Establish Data Ownership in a System of Components” on page 23-15
4-13
4 Referenced Models in Simulink Coder
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
“Precision” (Fixed-Point Designer).
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 “Model Configuration Parameters: Model Referencing” (Simulink) and “Set
Configuration Parameters for Model Referencing” (Simulink).
Note There are some configuration parameter setting limitations for code generation.
See “Simulink Coder Model Referencing Limitations” (Simulink Coder).
4-14
Build Model Reference Targets
The Simulink Coder software generates a model reference target directly from the
Simulink model. The product automatically generates or regenerates model reference
targets, for example, when they require an update.
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 a
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 “Generate Reentrant Code from Subsystems” (Simulink
Coder) for details.
• In the top model, consider setting the model configuration parameter Model
Referencing > Rebuild to If any changes in known dependencies
detected. (See “Rebuild” (Simulink).)
• In all referenced models throughout the hierarchy, set the configuration parameter
Diagnostics > Data Validity > Signal resolution to Explicit only or None. (See
“Signal resolution” (Simulink).)
These parameter values exist in a referenced model's configuration set, not in the
individual Model block. Setting either value for an instance of a referenced model, sets it
for all instances of that model.
4-15
4 Referenced Models in Simulink Coder
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 referenced models that have
incompatible parameter values, or a changed parameter value must propagate to many
referenced models, 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” (Simulink) for details.
4-16
Simulink Coder Model Referencing Requirements
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.
4-17
4 Referenced Models in Simulink Coder
4-18
Simulink Coder Model Referencing Requirements
You can use the Model Advisor to identify models in a model referencing hierarchy for
which code generation changes configuration parameter settings.
1 In the Simulink Editor, select Analysis > Model Advisor.
2 Select By Task.
3 Run the Check code generation identifier formats used for model reference
check.
If a script that operates on generated code uses identifier formats that code generation
changes, then update the script to use the updated identifier format (which includes an
appended $R token).
For more information about identifiers, see “Identifier Format Control” on page 39-22.
4-19
4 Referenced Models in Simulink Coder
Naming Requirements
Within a model that uses model referencing, names of the constituent models cannot
collide. 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 text. 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.
The Embedded Coder product 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 “Model Configuration Parameters: Code Generation Symbols” (Simulink Coder) for
more information.
4-20
Storage Classes for Signals Used with Model Blocks
• ExportedGlobal
• ImportedExtern
• ImportedExternPointer
• Custom
The above are distinct from signals that use the storage class Model default when you
set the default storage class of the corresponding data category to Default in the Code
Mapping Editor, which are treated as test points with Auto storage class.
• An extern declaration is generated by all models that use a given global signal.
As a result, if a signal crosses a Model block boundary, the top model and the
referenced model both generate extern declarations for the signal.
• For an exported signal, the top model is responsible for defining (allocating memory
for) the signal, whether or not the top model itself uses the signal.
• Global signals used by a referenced model are accessed directly (as global memory).
They are not passed as arguments to the functions that are generated for the
referenced models.
Custom storage classes also follow the above rules. However, certain custom storage
classes are not currently supported for use with model reference. For details, see
“Storage Class Limitations” (Simulink Coder).
• Model default
4-21
4 Referenced Models in Simulink Coder
• ExportedGlobal
• ImportedExtern
• ImportedExternPointer
• Custom
Note the following considerations concerning how global tunable parameters are
declared, defined, and used in code generated for targets:
• A global tunable parameter is a parameter in the base workspace with a storage class
other than Auto.
• An extern declaration is generated by all models that use a given parameter.
• If a parameter is exported, the top model is responsible for defining (allocating
memory for) the parameter (whether it uses the parameter or not).
• Global parameters are accessed directly (as global memory). They are not passed as
arguments to the functions that are generated for the referenced models.
• In a referenced model that sets the default storage class for a category of parameter
data to Default in the Code Mapping Editor, symbols for Model default
parameters are generated using unstructured variables (rtP_xxx) instead of being
written into the model_P structure. This is so that each referenced model can be
compiled independently.
Certain custom storage classes for parameters are not currently supported for model
reference. For details, see “Storage Class Limitations” (Simulink Coder).
Parameters used as Model block arguments must be defined in the referenced model's
workspace. For details, see “Parameterize Instances of a Reusable Referenced Model”
(Simulink).
4-22
Storage Classes for Signals Used with Model Blocks
within that referenced model. Because referenced models are compiled independently
without regard to a parent model, they cannot adapt to the 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:
• If the storage class of a root input or output signal in a referenced model is Auto (or is
Model default when you set the storage class of the corresponding data category to
Default in the Code Mapping Editor), the signal is passed as a function argument.
4-23
4 Referenced Models in Simulink Coder
• If the corresponding signal in the parent model is also global, the names and
storage classes must match exactly.
• If the corresponding signal in the parent model is not global, the Signal label
mismatch diagnostic is applied.
You can set the Signal label mismatch diagnostic to error, warning, or none in the
Diagnostics > Connectivity pane of the Configuration Parameters dialog box.
See Also
Related Examples
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements”
(Simulink Coder)
• “Establish Data Ownership in a System of Components” on page 23-15
4-24
Inherited Sample Time for Referenced Models
• An S-function that precludes inheritance: If the sample time is used in the S-function's
run-time algorithm, then the S-function precludes a model from inheriting a sample
time. For example, consider the following mdlOutputs code:
This mdlOutputs code uses the sample time in its algorithm, and the S-function
therefore should specify
ssSetModelReferenceSampleTimeInheritanceRule
(S, DISALLOW_SAMPLE_TIME_INHERITANCE);
• An S-function that does not preclude Inheritance: If the sample time is only used for
determining whether the S-function has a sample hit, then it does not preclude the
model from inheriting a sample time. For example, consider the mdlOutputs code
from the S-function example sfun_multirate.c:
if (ssGetInputPortSampleTime
(S,ENABLE_IPORT)==CONTINUOUS_SAMPLE_TIME &&
ssGetInputPortOffsetTime(S,ENABLE_IPORT)==0.0) {
if (ssIsMajorTimeStep(S) &&
ssIsContinuousTask(S,tid)) {
enablePtrs =
ssGetInputPortRealSignalPtrs(S,ENABLE_IPORT);
*enabled = (*enablePtrs[0] > 0.0);
}
} else {
4-25
4 Referenced Models in Simulink Coder
int enableTid =
ssGetInputPortSampleTimeIndex(S,ENABLE_IPORT);
if (ssIsSampleHit(S, enableTid, tid)) {
enablePtrs =
ssGetInputPortRealSignalPtrs(S,ENABLE_IPORT);
*enabled = (*enablePtrs[0] > 0.0);
}
}
if (*enabled) {
InputRealPtrsType uPtrs =
ssGetInputPortRealSignalPtrs(S,SIGNAL_IPORT);
real_T signal = *uPtrs[0];
int i;
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);
4-26
Customize Library File Suffix and File Type
The TargetLibSuffix parameter does not apply for model builds that use the toolchain
approach. For more information, see “Identify Library File Type for Toolchain Approach”
(Simulink Coder).
4-27
4 Referenced Models in Simulink Coder
Customization Limitations
• The code generator ignores custom code settings in the Configuration Parameters
dialog box and custom code blocks when generating code for a referenced model.
• Data type replacement is not supported for simulation target code generation of
referenced models.
• Simulation targets do not include Stateflow target custom code.
• If you have an Embedded Coder license, some restrictions exist on grouped custom
storage classes in referenced models. For details, see “Storage Class Limitations”
(Simulink Coder).
4-28
Simulink Coder Model Referencing Limitations
Reusability Limitations
If a referenced model used for code generation has any of the following properties, the
model must specify the configuration parameter 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 you do not set the parameter to One, or more than one instance of the
model exists in the hierarchy, an error occurs. The properties are:
• The model references another model which has been set to single instance
• The model contains a state or signal with non-auto storage class
• The model uses any of the following Stateflow constructs:
• Machine-parented data
• Machine-parented events
• Stateflow graphical functions
• The model contains a subsystem that is marked as function
• The model contains an S-function that is:
For more information about Total number of instances allowed per top model, see
“Total number of instances allowed per top model” (Simulink).
4-29
4 Referenced Models in Simulink Coder
S-Function Limitations
• If a referenced model contains an S-function that should be inlined using a Target
Language Compiler file, the S-function must use the ssSetOptions macro to set the
SS_OPTION_USE_TLC_WITH_ACCELERATOR option in its mdlInitializeSizes
method. The simulation target will not inline the S-function unless this flag is set.
• A referenced model cannot use noninlined S-functions generated by the Simulink
Coder software.
• The Simulink Coder S-function target does not support model referencing.
For additional information, see “Use S-Functions with Referenced Models” (Simulink).
Subsystem Limitations
• If a subsystem contains Model blocks, you cannot build a subsystem module by right-
clicking the subsystem (or by using Code > C/C++ Code > Build Selected
Subsystem) unless the model is configured to use an ERT target.
• If you generate code for an atomic subsystem as a reusable function, inputs or outputs
that connect the subsystem to a referenced model might prevent code reuse, as
described in “Generate Reentrant Code from Subsystems” (Simulink Coder).
Target Limitations
• The Simulink Coder S-function target does not support model referencing.
4-30
Simulink Coder Model Referencing Limitations
Other Limitations
• Errors or unexpected behavior can occur if a Model block is part of a cycle, the Model
block is a direct feedthrough block, and an algebraic loop results. For details, see
“Algebraic Loops” (Simulink).
• The External mode option is not supported. If it is enabled, it is ignored during code
generation.
• When a model contains a trigger or enable port, you cannot generate standalone
Simulink Coder code or PIL code.
If the Configuration Parameters > Code Generation > Symbols parameters hold
identifier information about the name of a referenced model and do not use a $R token,
code generation prepends the $R token to the name of the model. You can use the Model
Advisor to check for changed model names. See “Configuration Parameters Changed
During Code Generation” (Simulink Coder).
4-31
5
Techniques
Techniques that you can use to combine code, which the code generator produces for
multiple models or multiple instances of a model, into one executable program include:
The S-function system target (rtwsfcn.tlc) does not support combining code generated
for multiple models.
Consider using model referencing to combine models for simulation and code generation.
Model referencing helps with:
If you combine code generated for different models (that is, without using referenced
models), consider:
5-2
Combine Code Generated for Multiple Models
• For plant models that use continuous time and state, the continuous time signals
connecting models are not handled by a single solver like continuous time signals
within a model. This can lead to subtle numeric differences.
If you use model referencing, you can modularize the generated code and establish clear
ownership of data when you work in a team.
If you do not use model referencing, you can prevent generation of duplicate definitions
for a data item. For example, suppose you store a Simulink.Parameter object in the
base workspace and apply the storage class ExportedGlobal. If you generate code from
two separate models that use the object, each model generates a definition for the
corresponding global variable. Instead, you can specify an owner for the object so that
only the owner generates a definition.
1 Apply a custom storage class to the data item. See “Apply Custom Storage Classes to
Individual Signal, State, and Parameter Data Elements” on page 26-19.
2 Configure the owner of the data item by specifying the Owner custom attribute.
3 Select the model configuration parameter Use owner from data object for data
definition placement.
For more information about controlling ownership and file placement of data definitions
and declarations, see “Control Placement of Global Data Definitions and Declarations in
Generated Files” on page 23-2.
5-3
5 Combined Models in Simulink Coder
1 Set the system target file to a GRT- or ERT-based system target file. The system target
file for the models you combine, must be the same.
2 If you intend to have multiple instances of that model in the application, set the
model configuration parameter Code Generation > Interface > Code interface
packaging to Reusable function. If you specified an ERT-based system target
file, optionally, you can set the model configuration parameter Use dynamic
memory allocation for model initialization, depending on whether you want to
statically or dynamically allocate the memory for each instance of the model.
3 Generate source code. The code generator includes an allocation function in the
generated file model.c. The allocation function dynamically allocates model data for
each instance of the model.
1 Compile the code for each model that you are combining.
2 Combine the makefiles generated for the models into one makefile.
3 Create a combined simulation engine by modifying a main program, such as
rt_malloc_main.c. The main program initializes and calls the code generated for
each model.
4 Run the makefile. The makefile links the object files and the main program into an
executable program.
Use unidirectional signal connections between models. This affects the order in which
models are called. For example, if you use an output signal from modelA as input to
modelB, the modelA output computation should be called first.
Timing Issues
When combining code generated for multiple models or multiple instances of a model:
• Configure the models with the same solver mode (single-tasking or multitasking).
• If the models use continuous states, configure the models with the same solver.
If the base rates for the models differ, the main program (such as rt_malloc_main.c)
must set up the timer interrupt to occur at the greatest common divisor rate of the
models. The main program calls each model at a time interval.
5-4
Combine Code Generated for Multiple Models
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.
5-5
6
A software library is an example of code reuse. A library can contain code for several
functions, each having specific behavior. To use a library, you need to know only the
interface, which is the specification for calling the library functions.
Reusable code can be reentrant. You can invoke, interrupt, and reinvoke reentrant code.
Reentrant code resides in shared memory. Instances of data associated with each use of
the code are unique and preserved. Multiple calls to a reusable, reentrant function, for
example, can access the function code with each call maintaining a unique data set.
• Team-based development.
• Switching between implementations of a function.
• Intellectual property protection.
• Overriding library behavior with a custom implementation.
• Implementing a library that is based on standard library functions.
• Unit testing.
• Performance improvement.
The code generator supports code reuse and reentrancy. You can use key Simulink
componentization techniques to partition a model into design components that you
simulate, generate code for, and verify independently. You can save individual components
as subsystems, libraries, referenced models, or combinations of these elements from
which you can generate code. For example, the code generator produces reusable
function code from library subsystems and export-function models.
6-2
See Also
See Also
More About
• “What Is Reentrant Code?” on page 6-4
• “Choose a Componentization Technique for Code Reuse” on page 6-6
6-3
6 Code Reuse for Simulink Coder
To make generated code for a model component reentrant, you configure the component
such that model entry-point functions receive root-level input and output data as
arguments. How you configure the component depends on the modeling style or
technique that you apply.
See Also
More About
• “What Is Code Reuse?” on page 6-2
6-4
See Also
6-5
6 Code Reuse for Simulink Coder
• Reference models
• Subsystems
• Library subsystems
• Combinations of models, subsystems, and library subsystems
6-6
See Also
See Also
More About
• “Componentization Guidelines” (Simulink)
• “Generate Reentrant Code from Top Models” on page 6-24
• “Generate Reentrant Code from Subsystems” on page 6-42
• “Generate Reentrant Code from Simulink Function Blocks” on page 6-30
• “Generate Reusable Code from Library Subsystems Shared Across Models” on page
6-53
6-7
6 Code Reuse for Simulink Coder
Reusable functions that the code generator produces from subsystems do not share
states. The code generator produces one function for multiple instances of the subsystem
as an optimization. If that subsystem contains blocks that have states, the code generator
produces one function, but passes a different state variable to each instance. The
instances do not share states.
Implementation Options
Choose how to implement Simulink functions and function callers based on your code
generation requirements. Considerations include:
6-8
Simulink Function Blocks and Code Generation
#include "timestwo_sf.h"
#include "ex_slfunc_comp_sf.h"
#include "ex_slfunc_comp_sf_private.h"
A Simulink function caller invokes a function defined with a Simulink Function block.
From anywhere in a model or chart hierarchy, you can call a function defined with a
Simulink Function block by using one of these modeling elements:
6-9
6 Code Reuse for Simulink Coder
void ex_slfunc_comp_sf_step(void)
{
real_T rtb_FunctionCaller1;
timestwo_sf(ex_slfunc_comp_sf_U.In1, &rtb_FunctionCaller1);
ex_slfunc_comp_sf_Y.Out1 = rtb_FunctionCaller1;
.
.
.
codegen-folder/model.c Stateflow chart transition
void ex_slfunc_comp_gf_step(void)
{
real_T rtb_y1_l;
timestwo_gf(ex_slfunc_comp_gf_U.In4, &rtb_y1_l);
ex_slfunc_comp_gf_Y.Out4 = rtb_y1_l;
.
.
.
codegen-folder/model.c MATLAB Function block
void ex_slfunc_comp_mf_step(void)
{
real_T rtb_y;
timestwo_mf(ex_slfunc_comp_mf_U.In3, &rtb_y);
ex_slfunc_comp_mf_Y.Out3 = rtb_y;
.
.
.
For more information about modeling choices, see “Simulink Functions” (Simulink).
6-10
Simulink Function Blocks and Code Generation
• Global---The code generator places code for a global function in source and header
files that are separate from model code files (for example, function.c and
function.h) . The separate files make the function code available for sharing
between function callers.
• Scoped---The code generator places code for a scoped function in model code files
(model.c and model.h). To call a scoped function in the context of a model, the
function caller must be at the same level as the function in the model hierarchy, or one
or more levels below.
To create a library of functions that are accessible from anywhere in the generated
model code, set up each function as a scoped Simulink Function block. Place each
scoped function within a virtual subsystem at the root level of a model.
For more information, see and “Scoped and Global Simulink Function Blocks” (Simulink).
For information, see “Generate Component Source Code for Export to External Code
Base” on page 42-52 and “Export-Function Models” (Simulink).
For more information, see “Customize Generated Function Interfaces for Simulink
Function and Function Caller Blocks” on page 29-24.
6-11
6 Code Reuse for Simulink Coder
Requirements
• Within a model hierarchy, function names are unique. If the code generator finds
multiple functions with the same name, it issues an error. Change the name of one of
the functions and delete the slprj folder.
• The signature (for example, the arguments and argument data types) for a function
and function callers must match.
• If the code generator finds the function first and the signature of a function caller
does not match, the code generator issues an error. Change the function caller
signature to match the signature of the Simulink Function block or delete the
slprj folder.
• If the code generator finds a function caller first and the signature of the function
does not match, the code generator issues a warning message. Change the
signature of the function or function caller so that the signatures match.
• In a Simulink Function block definition, do not define input and output signals for
Argument Inport and Argument Outport blocks with a storage class.
• Do not specify Argument Inport and Argument Outport blocks as test points.
• If you specify the data type of input and output signals for Argument Inport and
Argument Outport blocks as a Simulink.IntEnumType, Simulink.AliasType, or
Simulink.Bus, set the DataScope property to Imported or Exported.
• A function interface and function callers must agree in data type, complexity,
dimension, and number of arguments.
Limitations
• To generate code from a model that includes scoped Simulink functions, the model
must be an export-function model. The code generator does not support rate-based
models that include scoped Simulink functions.
• You can use a Simulink Function block to define a scoped function in a referenced
model. However, you cannot generate code for an export-function model that uses a
Function Caller block in an atomic subsystem to invoke that function.
• You can invoke a C++ function that the code generator produces from a Simulink
Function block with code generated from a Stateflow chart. Due to current scope
limitations for generated C++ functions, you must invoke those functions with code
generated from a Function Caller block.
• Simulink functions and function callers do not honor the MaxStackSize parameter.
6-12
Simulink Function Blocks and Code Generation
• Code generation for a C++ class interface supports scoped Simulink functions only.
You create a function that calls the generated reusable function code. Then, you construct
and configure a model to match the code requirements.
Some of the features used in this example, such as data type aliasing and replacement,
require Embedded Coder software.
In your code generation root folder, create the files call_times2.h and
call_times2.c. If you prefer, you can copy the files from matlabroot\help\toolbox
\ecoder\examples.
call_times2.h
call_times2.c
#include "call_times2.h"
void call_times2(void)
{
int times2result;
6-13
6 Code Reuse for Simulink Coder
func_times2(x1, &y1);
This C code calls reusable function func_times2. The function multiplies an integer
input value x1 by 2 and returns the result as y1.
Create Model
Open the example model ex_slfunc_comp, which is available in the folder matlabroot
\help\toolbox\ecoder\examples. The model includes twoSimulink functions
modeled as Simulink Function blocks, func_times2 and func_times3, and a call to
each function. As indicated in the model, the visibility of the Simulink Function block for
func_times2 is set to global. That visibility setting makes the function code accessible
to other code, including external code that you want to integrate with the generated code.
The visibility for func_times3 is set to scoped.
If you configure the model with the GRT system target file or the ERT system target file
with File packaging format set to Modular, the code generator produces function code
for the model.
For more information, see “Generate Code for a Simulink Function and Function Caller”
on page 6-20.
6-14
Simulink Function Blocks and Code Generation
The example assumes that the generated code runs on target hardware with a native
integer size of 32 bits. The external code represents integers with data type my_int,
which is an alias of int. Configure the code generator to use my_int in place of the data
type that the code generator uses by default, which is int32_T.
my_int = Simulink.AliasType
my_int =
Description: ''
DataScope: 'Auto'
HeaderFile: ''
BaseType: 'double'
2 Set the alias type properties. Enter a description, set the scope to Imported, specify
the header file that includes the type definition, and associate the alias type with the
Simulink base type int32.
my_int
AliasType with properties:
6-15
6 Code Reuse for Simulink Coder
For external code to call a global function, configure the corresponding Simulink Function
block to have global visibility and an interface that matches what is expected by the
external callers.
2 Configure the function name and visibility by setting Trigger Port block parameters.
For example, the code requirements specify that the function name start with the
prefix func_.
6-16
Simulink Function Blocks and Code Generation
If the dialog box lists output argument y1 before input argument x1, reorder the
arguments by dragging the row for x1 above the row for y1.
Configure a Simulink Function block that represents a local function with scoped
visibility. Based on code requirements, you might also have to configure the function
name, input and output argument names and types, and the function interface.
You can set C/C++ return argument to the argument name that you specify for the
Argument Outport block or void. For this example, set it to void.
For arguments, the code generator prepends rtu_ (input) or rty_ (output) to the
argument name that you specify for the Argument Inport block.
6-17
6 Code Reuse for Simulink Coder
If the dialog box lists output argument y1 before input argument x1, reorder the
arguments by dragging the row for x1 above the row for y1.
Source code for the global, reusable function func_times2 is in the build folder in
subsystem file, func_times2.c.
#include "func_times2.h"
The code generator places the definition for the local (scoped) function func_times3
in file build folder in file ex_slfunc_comp.c.
void ex_slfunc_comp_func_times3(my_int rtu_x1, my_int *rty_y1)
{
*rty_y1 = 3 * rtu_x1;
}
• Calls to generated functions
The model execution (step) function, in model file ex_slfunc_comp.c, calls the two
Simulink functions: global function func_times2 and local function
6-18
Simulink Function Blocks and Code Generation
func_times2(ex_slfunc_comp_U.In1, &rtb_FunctionCaller2);
ex_slfunc_comp_Y.Out1 = rtb_FunctionCaller2;
ex_slfunc_comp_func_times3(ex_slfunc_comp_U.In2, &rtb_FunctionCaller2);
ex_slfunc_comp_Y.Out2 = rtb_functionCaller2;
.
.
.
The model header file ex_slfunc_comp.h lists include statements for the global
functionfunc_times2.
#include "func_times2_private.h"
#include "func_times2.h"
• Local macros and data for global function
#ifndef RTW_HEADER_func_times2_private_h_
#define RTW_HEADER_func_times2_private_h_
#ifndef ex_slfunc_comp_COMMON_INCLUDES_
#define ex_slfunc_comp_COMMON_INCLUDES_
#include "rtwtypes.h"
#endif
#endif
• Entry-point declaration for global function
6-19
6 Code Reuse for Simulink Coder
The shared header file func_times2.h, in the shared utilities folder slprj/stf/
_sharedutils, lists shared type includes for rtwtypes.h. The file also includes an
extern declaration for the global function, func_times2. That statement declares
the function entry point.
#ifndef RTW_HEADER_func_times2_
#define RTW_HEADER_func_times2_
#include "rtwtypes.h"
#endif
6-20
Simulink Function Blocks and Code Generation
2 Generate code.
The code generator creates rtwdemo_functions.c. This file contains the function
definition and function initialization code.
void f3_Init(void)
{
rtDWork.Delay_DSTATE = 1;
}
• Code for function f3:
6-21
6 Code Reuse for Simulink Coder
rtY.TicToc10 = rtDWork.Delay_DSTATE;
rtDWork.Delay_DSTATE = (int8_T)(int32_T)-(int32_T)rtY.TicToc10;
*rty_y = rtB.FunctionCaller;
}
#include "rtwtypes.h"
The code generator creates the files rtwdemo_caller.h and rtwdemo_caller.c in the
folder rtwdemo_caller_ert_rtw.
rtwdemo_caller.h includes the shared header file, f3.h, which contains the function
entry-point declaration.
6-22
See Also
See Also
More About
• “Generate Reentrant Code from Simulink Function Blocks” (Simulink Coder)
• “Simulink Functions” (Simulink)
• “Simulink Functions in Simulink Models” (Simulink)
• “Using Simulink Function Blocks” (Simulink)
• “Simulink Functions in Referenced Models” (Simulink)
6-23
6 Code Reuse for Simulink Coder
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” (Simulink Coder) to Reusable function. If you
are using Embedded Coder and generating C++ code, alternatively, you can set the
parameter to C++ class. In both cases, 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” (Simulink Coder) to None, Warning, orError.
• 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” (Simulink Coder) to Individual arguments, Structure
reference, or Part of model data structure.
• To reduce memory usage by omitting the error status field from the real-time model
data structure (requires Embedded Coder), set parameter Remove error status field
in real-time model data structure to On.
• To include a function in the generated file model.c that uses malloc to dynamically
allocate memory for model data structures (requires Embedded Coder), set parameter
Use dynamic memory allocation for model initialization to On
6-24
Generate Reentrant Code from Top Models
Open the model rtwdemo_reusable. The model contains two root Inport blocks and a
root Outport block.
model='rtwdemo_reusable';
open_system(model);
In your working folder, create a temporary folder for generating and reviewing the code.
currentDir=pwd;
[~,cgDir] = rtwdemodir();
2. System target file is set to ert.tlc. Although you can generate reentrant code for a
model configured with the 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.
3. Open the Code Generation > Interface pane and explore relevant parameter
settings.
6-25
6 Code Reuse for Simulink Coder
rtwbuild(model);
• ert_main.c is an example main program (execution framework) for the model. This
code controls model code execution by calling the entry-point function
rtwdemo_reusable_step. Use this file as a starting point for coding your execution
framework.
• rtwdemo_reusable.c contains entry points for the code that implements the model
algorithm. This file includes the rate scheduling code.
• rtwdemo_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.
Open and review the Code Interface Report. Use the information in that report to write
the interface code for your execution framework.
2. Write input data to the generated code for model Inport blocks.
6-26
Generate Reentrant Code from Top Models
4. Read data from the generated code for the model Outport block.
Input ports:
Entry-point functions:
Output port:
cfile = fullfile(cgDir,'rtwdemo_reusable_ert_rtw','rtwdemo_reusable.c');
rtwdemodbtype(cfile,'/* Model step function', '/* Model initialize function ', 1, 0);
6-27
6 Code Reuse for Simulink Coder
* Inport: '<Root>/In2'
* Sum: '<Root>/Sum'
* UnitDelay: '<Root>/Delay'
*/
rtDWork->Delay_DSTATE = (rtU->In1 + rtU->In2) * rtP->k1;
}
The code generator passes model data to the rtwdemo_reusable_step function as part
of the real-time model data structure. Try different settings for the Code interface
packaging and Pass root-level I/O parameters and regenerate code. Observe how the
function signature for the rtwdemo_reusable_step function changes.
bdclose(model)
rtwdemoclean;
cd(currentDir)
• 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, and apply a storage class other than Auto or, if you set the
default storage class for the corresponding category of parameter data to Default
(the default setting) in the Code Mapping Editor, Model 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 “Apply Storage Classes to
Individual Signal, State, and Parameter Data Elements” (Simulink Coder).
• 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 the Share across model instances
parameter. For more information, see “Model Global Data by Creating Data Stores”
(Simulink) and Data Store Memory.
6-28
See Also
See Also
More About
• “What Is Reentrant Code?” on page 6-4
• “Design Models for Generated Embedded Code Deployment” on page 1-2
• “Use Storage Classes in Reentrant, Multi-Instance Models and Components”
(Simulink Coder)
6-29
6 Code Reuse for Simulink Coder
The code generator produces reentrant function code when you configure a:
• Top model with model configuration parameter “Code interface packaging” (Simulink
Coder) set to Reusable function or C++ class (C++ only).
• Referenced model with “Total number of instances allowed per top model” (Simulink)
set to Multiple.
Call a function represented by a scoped Simulink Function block from one level above, at
the same level, or from a level below the level of the function definition. You can scope a
function in an atomic or nonvirtual subsystem, but function call accessibility is limited to
the same level or below of the hierarchy. The function name does not have to be unique.
Identify Requirements
Before and while you design your model, consider:
6-30
Generate Reentrant Code from Simulink Function Blocks
Create Model
Use the example model component rtwdemo_comp to see how to use Simulink Function
blocks to generate reentrant C code. Use example model rtwdemo_comp_cpp if you
prefer to generate C++ code. Open the model and examine the model hierarchy.
The top level of the model includes a function-call subsystem and two instances of a
referenced model.
The subsystem consists of a Simulink Function block. This use of a Simulink Function
block shows how you can limit the scope of the function that the block defines to the
model that contains the subsystem. The code generator produces function code for
6-31
6 Code Reuse for Simulink Coder
func_calc and associates each call to the function with instance-specific data. The data
includes states, such as data stored in memory.
The Simulink Function block that defines function multiinstfunc uses a Function
Caller block to invoke function func_calc. That Simulink Function block also shows that
it can interface to signals in the local environment of the block through Inport and
Outport blocks (see “Simulink Functions in a Simulink Model” (Simulink)).
At the top level of model rtwdemo_comp, the function-call subsystem uses Function
Caller blocks to invoke the two instances of function multiinstfunc. The code
generator produces function code and associates each call with instance-specific data.
6-32
Generate Reentrant Code from Simulink Function Blocks
Configure the Simulink Function blocks by setting parameters for the function Trigger
Port block. For the code generator to produce reentrant code from Simulink Function
blocks:
In the example, the function name for the Simulink Function blocks in the two instances
of the referenced model rtwdemo_func_dinteg is specified as multiinstfunc.
Configure the Function Caller blocks. For each of the blocks, set the Function prototype
block parameter. Start typing a prototype. For example, type y. Prototype options, based
on function definitions in the model, appear in a selection list. Select the prototype that is
appropriate for each function call.
6-33
6 Code Reuse for Simulink Coder
• In the function-call subsystem, the prototypes for the function callers are configured
as y = Instance1.multiinstfunc(u) and y =
Instance2.multiinstfunc(u). The Instancen prefix identifies each function
invocation uniquely and associates the invocation with its own data set.
• The function caller in function multiinstfunc is configured with the prototype y =
subsys_calc.func_calc(u). The prefix subsys_calc identifies the subsystem
that contains the function definition.
For the example, the input and output argument specifications and sample time retain
default settings.
Subsystem Configuration
No configuration changes are required for the subsystem in the example model. When
you include a Simulink Function block in a subsystem, the code generator
• In the Block Parameters dialog box, set Model name to the referenced model file
name. For this example, the model name is rtwdemo_func_dinteg.slx.
• Set Number of model instances allowed to Multiple.
• To generate a C++ class interface for the reference model, set Language to C++ and
Code interface packaging to C++ class.
Optionally, you can configure custom prototypes for the initialize and execution (step)
model-entry point functions. Custom prototypes can minimize changes to existing
external code that you integrate with the generated code. The example uses the default
function prototypes. See “Customize Generated Function Interfaces for Simulink Function
and Function Caller Blocks” on page 29-24.
Configure the top model for a model component. If you want the model component (that
is, the top model) to be reusable, set Code interface packaging to Reusable
6-34
Generate Reentrant Code from Simulink Function Blocks
function. If you are generating C++ code, you can set this parameter to C++ class. In
either case, also:
Optionally, you can configure custom prototypes for the initialize and execution (step)
model-entry point functions. Custom prototypes can minimize changes to existing
external code that you integrate with the generated code. Also see “Customize Generated
Function Interfaces for Simulink Function and Function Caller Blocks” on page 29-24.
When you place a scoped Simulink Function block in a referenced model that you use
multiple times in another model, the code generator places the function code in the
model.c file for the referenced model. For this example, the code generator places
function code for multiinstfunc in slprj/ert/rtwdemo_func_dinteg/
rtwdemo_func_dinteg.c.
real_T rtwdemo_func_dinteg_multiinstfunc(RT_MODEL_rtwdemo_func_dinteg_T * const
rtwdemo_func_dinteg_M, const real_T rtu_u)
{
real_T rtb_TmpLatchAtInOutport1;
real_T rtb_TmpLatchAtIn2Outport1;
real_T rty_y_0;
rtb_TmpLatchAtInOutport1 =
*rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextInport.rtu_In1;
rtb_TmpLatchAtIn2Outport1 =
*rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextInport.rtu_In2;
*rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextOutport.rty_Out2 = 2.0 *
rtb_TmpLatchAtInOutport1;
rtwdemo_func_dinteg_func_calc(rtwdemo_func_dinteg_M, rtb_TmpLatchAtIn2Outport1,
rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextOutport.rty_Out1);
rty_y_0 = rtwdemo_func_dinteg_M->dwork.DiscreteIntegrator_DSTATE;
6-35
6 Code Reuse for Simulink Coder
The code generator places the function code for a Simulink Function block that you
define in a subsystem in the model.c file for the model that contains the subsystem.
For this example, the code generator places the function code for func_calc in
slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg.c.
void rtwdemo_func_dinteg_func_calc(RT_MODEL_rtwdemo_func_dinteg_T * const
rtwdemo_func_dinteg_M, real_T rtu_u, real_T *rty_y)
{
rtwdemo_func_dinteg_M->dwork.calcMem =
rtwdemo_func_dinteg_M->dwork.UnitDelay_DSTATE;
*rty_y = rtwdemo_func_dinteg_M->dwork.UnitDelay_DSTATE;
The code generator uses the real-time model (RT_MODEL) data structure as a self-
referential structure to store the multi-instance data associated with a reusable
function. The code generator defines the structure in slprj/ert/
rtwdemo_func_dinteg/rtwdemo_func_dinteg.h.
typedef struct rtwdemo_func_dinteg_tag_RTM RT_MODEL_rtwdemo_func_dinteg_T;
For each instance of a referenced model that includes the same scoped Simulink
Function block, the code generator produces initialization and startup function code. A
single copy of the initialization code is defined in slprj/ert/
rtwdemo_func_dinteg/rtwdemo_func_dinteg.c.
void rtwdemo_func_dinteg_Start(RT_MODEL_rtwdemo_func_dinteg_T *const
rtwdemo_func_dinteg_M, const real_T *rtu_In1, const real_T *rtu_In2, real_T
*rty_Out2, real_T *rty_Out1)
{
rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextInport.rtu_In1 = rtu_In1;
rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextInport.rtu_In2 = rtu_In2;
rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextOutport.rty_Out2 = rty_Out2;
rtwdemo_func_dinteg_M->rtwdemo_func_dintegrtextOutport.rty_Out1 = rty_Out1;
}
6-36
Generate Reentrant Code from Simulink Function Blocks
The initialization code is called for each instance of a referenced model that contains
the same Simulink Function block. That code is in file rtwdemo_comp.c in the build
folder.
.
.
.
rtwdemo_func_dinteg_initialize(rtmGetErrorStatusPointer(rtwdemo_comp_M),
(&(rtwdemo_comp_M->Instance1)));
rtwdemo_func_dinteg_initialize(rtmGetErrorStatusPointer(rtwdemo_comp_M),
(&(rtwdemo_comp_M->Instance2)));
The model header file rtwdemo_comp.h includes extern declarations for top model
initialize, terminate, and execution (run) entry-point functions.
extern void rtwdemo_comp_initialize(RT_MODEL_rtwdemo_comp_T *const
rtwdemo_comp_M);
When you place a scoped Simulink Function block in a referenced model that you use
multiple times in another model, the code generator places the function code in the
6-37
6 Code Reuse for Simulink Coder
model.cpp file for the referenced model. For this example, the code generator places
function code for multiinstfunc in slprj/ert/rtwdemo_func_dinteg/
rtwdemo_func_dinteg_cpp.cpp.
real_T rtwdemo_func_dintegModelClass::multiinstfunc(const real_T rtu_u)
{
real_T rtb_TmpLatchAtInOutport1;
real_T rtb_TmpLatchAtIn2Outport1;
real_T rty_y_0;
rtb_TmpLatchAtInOutport1 = *rtwdemo_func_dinteg_cprtrtu_In1;
rtb_TmpLatchAtIn2Outport1 = *rtwdemo_func_dinteg_cprtrtu_In2;
rtwdemo_func_dinteg_c_func_calc(rtb_TmpLatchAtIn2Outport1,
rtwdemo_func_dinteg_crtrty_Out1);
rty_y_0 = rtwdemo_func_dinteg_cpprtDW.DiscreteIntegrator_DSTATE;
The code generator places the function code for a Simulink Function block that you
define in a subsystem in model.cpp for the model that contains the subsystem. For
this example, the code generator places the function code for func_calc in
slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg_cpp.cpp.
void rtwdemo_func_dintegModelClass::rtwdemo_func_dinteg_c_func_calc(real_T rtu_u,
real_T *rty_y)
{
rtwdemo_func_dinteg_cpprtDW.calcMem =
rtwdemo_func_dinteg_cpprtDW.UnitDelay_DSTATE;
*rty_y = rtwdemo_func_dinteg_cpprtDW.UnitDelay_DSTATE;
The code generator uses the real-time model (RT_MODEL) data structure as a self-
referential structure to store the multi-instance data associated with a Reusable
function. The code generator defines the structure in slprj/ert/
rtwdemo_func_dinteg/rtwdemo_func_dinteg_cpp.h.
typedef struct rtwdemo_func_dinteg_cpp_tag_RTM rtwdemo_func_dinteg_cp_RT_MODEL;
6-38
Generate Reentrant Code from Simulink Function Blocks
For each instance of a referenced model that includes the same scoped Simulink
Function block, the code generator produces initialization and startup function code. A
single copy of the initialization code is defined in slprj/ert/
rtwdemo_func_dinteg/rtwdemo_func_dinteg_cpp.cpp.
void rtwdemo_func_dintegModelClass::start(real_T *rtu_In1, real_T *rtu_In2,
real_T *rty_Out2, real_T *rty_Out1)
{
rtwdemo_func_dinteg_cprtrtu_In1 = rtu_In1;
rtwdemo_func_dinteg_cprtrtu_In2 = rtu_In2;
rtwdemo_func_dinteg_crtrty_Out2 = rty_Out2;
rtwdemo_func_dinteg_crtrty_Out1 = rty_Out1;
}
.
.
.
void rtwdemo_func_dintegModelClass::initializeRTM()
{
(void) memset((void *)((&rtwdemo_func_dinteg_cpprtM)), 0,
sizeof(rtwdemo_func_dinteg_cp_RT_MODEL));
}
The initialization code is called for each instance of a referenced model that contains
the same Simulink Function block. That code is in file rtwdemo_comp_cpp.cpp in the
build folder.
.
.
.
Instance1MDLOBJ0.initializeRTM();
Instance1MDLOBJ0.setErrorStatusPointer(rtmGetErrorStatusPointer((&rtM)));
Instance1MDLOBJ0.initialize();
Instance2MDLOBJ1.initializeRTM();
Instance2MDLOBJ1.setErrorStatusPointer(rtmGetErrorStatusPointer((&rtM)));
The model header file rtwdemo_comp_cpp.h includes the class declaration for the
top model.
class rtwdemo_compModelClass {
public:
6-39
6 Code Reuse for Simulink Coder
ExtU rtU;
ExtY rtY;
void initialize();
void Run();
rtwdemo_compModelClass();
~rtwdemo_compModelClass();
RT_MODEL * getRTM();
private:
RT_MODEL rtM;
rtwdemo_func_dintegModelClass Instance1MDLOBJ0;
rtwdemo_func_dintegModelClass Instance2MDLOBJ1;
};
rtwdemo_func_dintegModelClass();
~rtwdemo_func_dintegModelClass();
rtwdemo_func_dinteg_cp_RT_MODEL * getRTM();
void initializeRTM();
private:
rtwdemo_func_dinteg_cpp_DW rtwdemo_func_dinteg_cpprtDW;
rtwdemo_func_dinteg_cp_RT_MODEL rtwdemo_func_dinteg_cpprtM;
6-40
See Also
Limitations
These code generation limitations apply to export-function models that include multiple
instances of a Simulink Function block.
• You must set the model configuration parameter Pass root-level I/O as to Part of
model data structure.
• Generated code is compatible with single-threaded execution only. To avoid race
conditions for shared signal data, invoke instances of the function code from the same
execution thread.
• You cannot:
See Also
More About
• “Simulink Functions” (Simulink)
• “Simulink Functions in Simulink Models” (Simulink)
• “Using Simulink Function Blocks” (Simulink)
• “Simulink Functions in Referenced Models” (Simulink)
• “Use Storage Classes in Reentrant, Multi-Instance Models and Components”
(Simulink Coder)
6-41
6 Code Reuse for Simulink Coder
To configure subsystems for reusability and reentrancy, configure mask and block
parameters of the identical subsystems the same way. The code generator performs a
checksum 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.
• 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 display the “Function name” (Simulink) parameter and enter a unique, valid
C/C++ function name, select User specified.
If you are using Embedded Coder, you can use identifier format controls. See
“Identifier Format Control” on page 39-22.
6-42
Generate Reentrant Code from Subsystems
4 Set “File name options” (Simulink). To generate reusable, reentrant code, specify the
same setting for identical subsystems.
Other considerations:
If subsystem A has mask parameter b and K and subsystem B has mask parameters c and
K, code reuse is not possible. The code generator produces separate functions for
subsystems A and B. If you set block parameters for subsystems A and B differently, code
reuse is not possible.
Limitations
• The code generator uses a checksum to determine whether subsystems are identical
and reusable. Subsystem code is not reused if:
6-43
6 Code Reuse for Simulink Coder
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 K with value 15.23 and the tunable variable P with
value [5;7;9]. The expression K+P' is a partially tunable expression because the
expression P' is not tunable. For more information about tunable expression
limitations, see “Tunable Expression Limitations” (Simulink Coder).
• For subsystems that contain S-function blocks that are reusable, the blocks must meet
the requirements listed in “S-Functions That Support Code Reuse” on page 11-105.
• 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” (Simulink) to Auto.
• 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.
6-44
Generate Reentrant Code from Subsystems
If the code generator does not generate code for a subsystem as reusable code, and you
configured the subsystem as reusable, examine the Subsystems section of the code
generation report (see “Generate a Code Generation Report” (Simulink Coder)). The
Subsystems section contains:
The Subsystems section also maps noninlined subsystems in the model to functions or
reused functions in the generated code. For an example, open and build the
rtwdemo_atomic model.
You can determine why subsystem code is not reused by comparing subsystem checksum
data. The code generator determines whether subsystems are identical by comparing
subsystem checksums, as noted in “Limitations” (Simulink Coder). For subsystem reuse
across referenced models, this procedure might not flag every difference.
Consider the model, rtwdemo_ssreuse. SS1 and SS2 are instances of the same
subsystem. In both instances the subsystem parameter Function packaging is set to
Reusable function.
6-45
6 Code Reuse for Simulink Coder
1 Open the model rtwdemo_ssreuse. Save a copy of the model in a folder where you
have write access.
2 Associate the subsystems SS1 and SS2 with gcb. For each of the subsystems , in the
model window, select the subsystem. While the subsystem is selected, in the
Command Window, enter:
SS1 = gcb;
SS2 = gcb;
3 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.
isequal(chksum1, chksum2)
ans =
1
5 To 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.
6-46
Generate Reentrant Code from Subsystems
a Look under the mask of SS1. Right-click the subsystem. In the context menu,
select MaskLook Under Mask.
b In the block diagram of the subsystem, double-click the Lookup Table block to
open the Subsystem Parameters dialog box.
c Click Data Types.
d Select Saturate on integer overflow and click OK.
6 Get the checksum for SS1. Compare the checksums for the two subsystems. This
time, the checksums are not equal.
[chksum1, chksum1_details] = ...
Simulink.SubSystem.getChecksum(SS1);
isequal(chksum1, chksum2)
ans =
0
7 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, compare the data that computes 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.
chksum1_details =
ContentsChecksum: [1x1 struct]
InterfaceChecksum: [1x1 struct]
ContentsChecksumItems: [287x1 struct]
InterfaceChecksumItems: [53x1 struct]
6-47
6 Code Reuse for Simulink Coder
isequal(chksum1_details.InterfaceChecksum.Value,...
chksum2_details.InterfaceChecksum.Value)
ans =
1
10 Run the script. The example assumes that you named the script check_details.
check_details
Character vector values different for contents item 202
The results indicate that differences exist for index item 202 in the subsystem
contents.
11 Use the returned index values to get the handle, identifier, and value details for each
difference found.
chksum1_details.ContentsChecksumItems(202)
ans =
The details identify the Lookup Table block parameter Saturate on integer
overflow as the focus for debugging a subsystem reuse issue.
6-48
See Also
See Also
More About
• “What Is Reentrant Code?” on page 6-4
• “Design Models for Generated Embedded Code Deployment” on page 1-2
• “Generate Reusable Code from Library Subsystems Shared Across Models” on page
6-53
• “Control Generation of Subsystem Functions” on page 3-2
• “Use Storage Classes in Reentrant, Multi-Instance Models and Components”
(Simulink Coder)
6-49
6 Code Reuse for Simulink Coder
• A top model that uses single-tasking mode and includes a referenced model that uses
multi-tasking mode executes for blocks with different rates that are not connected.
however, you get an error if the blocks with different rates are connected by a Rate
Transition block (inserted manually or by Simulink).
• S-functions that you generate with the Embedded Coder Code > C/C++ Code >
Generate S-function menu option do not support subsystems that contain a
continuous sample time.
• The S-function system target file is not supported.
• The code generator ignores tunable parameters settings that you configure from the
Model Parameter Configuration dialog box. To configure parameters to be tunable,
define them as Simulink parameter objects in the base workspace.
• The code generator inlines parameters that are not tunable in the generated code and
S-function.
Note If you select the S-function system target file, the subsystem block menu options
C/C++ Code > Build This System and Code > C/C++ Code > Build Selected
Subsystem behave like Code > C/C++ Code > Generate S-Function (see “Generate S-
Function from Subsystem” on page 11-62).
6-50
Generate Reusable Code From Referenced Models
Suppose that you make the following changes to the subsystem block parameters:
Then, suppose you create this model, which includes three instances of the preceding
subsystem.
With the model configuration parameter “Default parameter behavior” (Simulink Coder)
set to Inlined, the code generator optimizes the code by generating one copy of the
function for the reused subsystem.
If you move the three subsystems into a Model block, you must modify your model and
model configuration.
1 Add a Signal Conversion block or a Bias block between Subsystem3 and the Outport
block. If the subsystem has a Merge block with initial conditions, do not add a Signal
Conversion block. Instead, add a Bias block to obtain a reusable function.
2 Select the model configuration parameter “Pass fixed-size scalar root inputs by value
for code generation” (Simulink).
6-51
6 Code Reuse for Simulink Coder
See Also
Related Examples
• “Generate Reusable Code from Library Subsystems Shared Across Models”
(Simulink Coder)
6-52
Generate Reusable Code from Library Subsystems Shared Across Models
• Within a single model, which is a top model or part of model reference hierarchy
• Across multiple referenced models in a model reference hierarchy
• Across multiple top models that contain Model blocks
• Across multiple top models that do not include Model blocks
The code generator uses checksums to determine reusability. There are cases when the
code generator cannot reuse subsystem code.
For incremental code generation, if the reusable library subsystem changes, a rebuild of
itself and its parents occurs. During the build, if a matching function is not found, a new
instance of the reusable function is generated into the shared utilities folder. If a different
matching function is found from previous builds, that function is used, and a new reusable
function is not emitted.
For subsequent builds, unused files are not replaced or deleted from your folder. During
development of a model, when many obsolete shared functions exist in the shared utilities
folder, you can delete the folder and regenerate the code. If all instances of a reusable
library subsystem are removed from a model reference hierarchy and you regenerate the
code, the obsolete shared functions remain in the shared utilities folder until you delete
them.
If a model changes such that the change might cause different generated code for the
subsystem, a new reusable function is generated. For example, model configuration
parameters that modify code comments might cause different generated code for the
subsystem even if the reusable library subsystem did not change.
6-53
6 Code Reuse for Simulink Coder
For unique naming, reusable function names have a checksum appended to the reusable
library subsystem name. For example, the code and files for a subsystem, SS1, which links
to a reusable library subsystem, RLS, might be:
and File name options to Auto, Use subsystem name, or User specified.
If a reusable library subsystem is connected to the root outport, reuse does not happen
with identical subsystems that are not connected to the root outport. However, you can
set Pass reusable system outputs as to Individual arguments on the
Optimizations pane to make sure that reuse occurs between these subsystems. This
parameter requires an Embedded Coder license.
6-54
Generate Reusable Code from Library Subsystems Shared Across Models
For more information on creating a library, see “Libraries” (Simulink). For an example of
creating a reusable library subsystem, see “Generate Reusable Code for Subsystems
Shared Across Models” (Simulink Coder).
If a reusable library 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.
1 In the Simulink Editor, select File > New > Library. Open rtwdemo_ssreuse to
copy and paste subsystem SS1 into the Library Editor. This action loads the variables
for SS1 into the base workspace. Rename the subsystem block to RLS.
6-55
6 Code Reuse for Simulink Coder
2 Click the Subsystem block and press Ctrl+U to view the contents of subsystem RLS.
6-56
Generate Reusable Code from Library Subsystems Shared Across Models
3 To configure the subsystem, in the Library editor, right-click RLS. In the context
menu, select Block Parameters(Subsystem). In the Subsystem Parameters dialog
box, choose the following options:
6-57
6 Code Reuse for Simulink Coder
1 Create a model which includes one instance of RLS from ssreuselib. Name this
subsystem SS1. Add another subsystem and name it SS2. Name the model
ex_model1.
2 Create another model which includes one instance of RLS from ssreuselib. Name
this subsystem SS1. Add another subsystem and name it SS3. Name the model
ex_model2.
6-58
Generate Reusable Code from Library Subsystems Shared Across Models
3 Create a top model with two model blocks that reference ex_model1 and
ex_model2. Save the top model as ex_mdlref_ssreuse.
6-59
6 Code Reuse for Simulink Coder
1 With model ex_mdlref_ssreuse open in the Simulink Editor, select Simulation >
Model Configuration Parameters to open the Configuration Parameters dialog box.
2 On the Solver pane, specify the Type as Fixed-step.
3 On the Model Referencing pane, select Pass fixed-size scalar root inputs by
value for code generation.
4 On the Code Generation > Report pane, select Create code generation report
and Open report automatically.
5 On the Code Generation > Interface pane, set the “Shared code placement”
(Simulink Coder) to Shared location.
6 On the Code Generation > Symbols pane, set the Maximum identifier length to
256. This step is optional.
7 Click Apply and OK.
1 In the Simulink Editor, select View > Model Explorer to open the Model Explorer. In
the left navigation column of the Model Explorer, expand the ex_mdlref_ssreuse
node.
6-60
Generate Reusable Code from Library Subsystems Shared Across Models
Now, the top model and referenced models use the same configuration reference,
Reference (Active), which points to a model configuration reference object,
configSetObj, in the base workspace. When you save your model, you also need to
export the configSetObj to a MAT-file.
1 To generate code, in the Simulink Editor, press Ctrl+B. After the code is generated,
the code generation report opens.
2 To view the code generation report for a referenced model, in the left navigation
pane, in the Referenced Models section, select ex_model1. The code generation
report displays the generated files for ex_model1.
3 In the left navigation pane, expand the Shared files. The code generator uses the
reusable library subsystem name. The code for subsystem SS1 is in myfun.c and
myfun.h.
6-61
6 Code Reuse for Simulink Coder
4 Click Back and navigate to the ex_model2 code generation report. ex_model2 uses
the same source code, myfun.c and myfun.h, as the code for ex_model1. Your
subsystem function and file names will be different.
6-62
See Also
See Also
More About
• “Libraries” (Simulink)
• “Generate Reentrant Code from Subsystems” on page 6-42
• “Control Generation of Subsystem Functions” on page 3-2
6-63
6 Code Reuse for Simulink Coder
When you generate code for your model, a separate file stores the code for linked atomic
subcharts from the same library.
6-64
Generate Reusable Code from Stateflow Atomic Subcharts
When you generate code for your model, a separate file stores the code for the atomic
subchart. For more information, see “Generate Reusable Code for Unit Testing” on page
10-8.
To convert state A to an atomic subchart, right-click the state and select Group &
Subchart > Atomic Subchart. State A changes to an atomic subchart:
6-65
6 Code Reuse for Simulink Coder
6-66
Generate Reusable Code from Stateflow Atomic Subcharts
1 In the Model Configuration Parameters dialog box, go to the Code Generation >
Symbols pane.
2 Set Subsystem methods to the format scheme $R$N$M$F, where:
To generate code for your model, press Ctrl+B. In the code generation report that
appears, you see a separate file that contains the generated code for the atomic subchart.
To inspect the code for saturator.c, click the hyperlink in the report to see the
following code:
6-67
6 Code Reuse for Simulink Coder
6-68
See Also
Line 28 shows that the during function generated for the atomic subchart has the name
ex_reuse_states_A_during. This name follows the format scheme $R$N$M$F
specified for Subsystem methods:
Note The line numbers shown can differ from the numbers that appear in your code
generation report.
See Also
More About
• “Basic Approach for Modeling Event-Driven Systems” (Stateflow)
• “Encapsulate Modal Logic Using Subcharts” (Stateflow)
6-69
6 Code Reuse for Simulink Coder
• Packaging functions that can have multiple callers into a library when the functions
are defined statically. That is, before you use the code generator to produce code for
your model, the function source code exists in a file.
• Packaging functions that can have multiple callers as shared utilities (produced during
code generation) when the functions cannot be defined statically. For example, several
model- and block-specific properties specify which functions are used and their
behavior. Also, these properties determine type definitions (for example, typedef) in
shared utility header files. The number of possible combinations of properties that
determine unique behavior make it impractical to define statically the possible
function files before code generation.
Configuration Action
A new model or an existing model for which In the Embedded Coder Dictionary,
you have mapped default customization define a function customization template
settings by using the Code Mapping that specifies a custom function naming
Editor or code default mapping rule. Then, in the Code Mapping Editor or
programming interface by using the code default mapping
programming interface, map the Shared
utility function category to that template.
For more information, see “Configure
Default Code Generation for Categories of
Model Data and Functions” on page 21-7.
6-70
Generate Shared Utility Code
Configuration Action
A model created in a release earlier than Set the model configuration parameter
R2018a and that has not been configured Shared utilities identifier format
with the Code Mapping Editor or default (CustomSymbolsStrUtil) to a custom
mapping programming interface function naming rule. For more information,
see “Identifier Format Control” on page 39-
22.
Once you use the Code Mapping Editor or default mapping programming interface to
configure a model, setting the Shared utilities identifier format parameter has no
effect.
The naming rule for shared utility functions must include the conditional checksum token
$C. To customize the length of the checksum that the code generator produces, use the
Shared checksum length (SharedChecksumLength) parameter. Increasing the length
of the checksum reduces the probability of clashes.
• Model blocks
6-71
6 Code Reuse for Simulink Coder
If a model contains one or more of the preceding blocks, the code generator creates and
uses a shared utilities folder within slprj. The naming convention for shared utility
folders is slprj/target/_sharedutils. target is sim for simulations with Model
blocks or the name of the system target file for code generation.
slprj/sim/_sharedutils % folder used with simulation
slprj/grt/_sharedutils % folder used with grt.tlc STF
slprj/ert/_sharedutils % folder used with ert.tlc STF
slprj/mytarget/_sharedutils % folder used with mytarget.tlc STF
To force a model build to use the slprj folder for shared utility generation, even when
the current model does not contain existing shared utility code or one of the preceding
blocks, set parameter Shared code placement to Shared location. The code
generator places utilities under the slprj folder rather than in the normal build folder.
This setting is useful when you are manually combining code from several models,
because it prevents symbol collisions between the models.
Control placement of rtwtypes.h file by selecting whether the build process uses the
shared utilities folder. If the model build uses a shared utilities folder, the build process
places rtwtypes.h in slprj/target/_sharedutils. Otherwise, the software places
rtwtypes.h in model_target_rtw.
Adding a model to a model hierarchy or changing an existing model in the hierarchy can
result in updates to the shared rtwtypes.h file during code generation. If updates occur,
recompile and, depending on your development process, reverify previously generated
code. To minimize updates to the rtwtypes.h file, make the following changes in the
Configuration Parameters dialog box:
• Select Support: complex numbers even if the model does not currently use complex
data types. Selecting this parameter protects against a future requirement to add
support for complex data types when integrating code.
6-72
Generate Shared Utility Code
• You control the file placement of declarations for signals, parameters, and states by
defining and applying storage classes.
• The code generator places utility code in a shared location.
For example, you can specify a header file for a piece of data through:
• A storage class that you define in the Embedded Coder Dictionary and map to
categories of model data in the Code Mapping Editor.
• The Code Generation tab in a Signal Properties dialog box.
• The HeaderFile property of a data object. Data objects are objects of the classes
Simulink.Signal and Simulink.Parameter.
If you want the declaration to appear in the file model.h, it is a best practice to leave the
header file name unspecified. By default, the code generator places data declarations in
model.h.
If you specify model.h as the header file name, and if the code generator places utility
code in a shared location, you cannot generate code from the model. The code generator
cannot create the file model.h in both the model build folder and the shared utility
folder.
Blocks within the same model and blocks in different models can use a shared function
when you use model reference or when you build multiple standalone models from the
6-73
6 Code Reuse for Simulink Coder
same start build folder. The code generator produces the code for a given function only
once for the block that first triggers code generation. As the product determines the
requirement to generate function code for subsequent blocks, it performs a file existence
check. If the file exists, the model build does not regenerate the function. The shared
utility code mechanism requires that a given function and file name represent the same
functional behavior regardless of which block or model generates the function. To satisfy
this requirement:
• Model properties that determine function behavior contribute to the shared utility
checksum or determine the function and file name.
• Block properties that determine the function behavior also determine the function and
file name.
During compilation, makefile rules for the shared utilities folder select compilation of only
new C files and incrementally archive the object file into the shared utility library,
rtwshared.lib, or rtwshared.a. Incremental compilation also occurs.
For more information, see “Reduce Shared Utility Code Generation with Incremental
Builds” (Simulink Coder).
6-74
Generate Shared Utility Code
It is helpful to view the property values that contribute to the checksum. This example
uses the rtwdemo_lct_start_term.slx model. To load the checksum.mat file into
MATLAB and view the targetInfoStruct that defines the checksum-related properties:
For this example, the Command Window displays hashTbl.targetInfoStruct for the
shared utilities that you generated from the model:
ShiftRightIntArith: 'on'
ProdShiftRightIntArith: 'on'
Endianess: 'LittleEndian'
ProdEndianess: 'LittleEndian'
wordlengths: '8,16,32,32,64,32,64,64,64,64'
Prodwordlengths: '8,16,32,32,64,32,64,64,64,64'
TargetWordSize: '64'
ProdWordSize: '64'
TargetHWDeviceType: 'Custom Processor->MATLAB Host Computer'
ProdHWDeviceType: 'Intel->x86-64 (Windows64)'
TargetIntDivRoundTo: 'Zero'
ProdIntDivRoundTo: 'Zero'
tmfName: ''
toolchainName: ''
computer: 'PCWIN64'
UseDivisionForNetSlopeComputation: 'off'
PurelyIntegerCode: 'off'
PortableWordSizes: 'off'
SupportNonInlinedSFcns: ''
6-75
6 Code Reuse for Simulink Coder
RTWReplacementTypes: ''
MaxIdInt8: 'MAX_int8_T'
MinIdInt8: 'MIN_int8_T'
MaxIdUint8: 'MAX_uint8_T'
MaxIdInt16: 'MAX_int16_T'
MinIdInt16: 'MIN_int16_T'
MaxIdUint16: 'MAX_uint16_T'
MaxIdInt32: 'MAX_int32_T'
MinIdInt32: 'MIN_int32_T'
MaxIdUint32: 'MAX_uint32_T'
BooleanTrueId: 'true'
BooleanFalseId: 'false'
TypeLimitIdReplacementHeaderFile: ''
SharedCodeRepository: ''
TargetLang: 'C'
PreserveExternInFcnDecls: 'on'
EnableSignedRightShifts: 'on'
EnableSignedLeftShifts: 'on'
TflName: 'None'
TflCheckSum: [315163228 3.1138e+09 1.4321e+09 952408419]
UtilMemSecName: 'Default'
CodeCoverageChecksum: [3.6498e+09 78774415 2.5508e+09 2.1183e+09]
TargetLargestAtomicInteger: 'Char'
TargetLargestAtomicFloat: 'None'
ProdLargestAtomicInteger: 'Char'
ProdLargestAtomicFloat: 'Float'
LongLongMode: 'on'
ProdLongLongMode: 'off'
CollapseNonTrivialExpressions: 'false'
Examine the targetInfoStruct hash table from the shared utility model. Some key-
value pairs relate directly to a model property. Other pairs relate to groups of properties.
6-76
Generate Shared Utility Code
6-77
6 Code Reuse for Simulink Coder
6-78
See Also
See Also
More About
• “Generate Shared Utility Code for Fixed-Point Functions” (Simulink Coder)
• “Generate Shared Utility Code for Custom Data Types” (Simulink Coder)
• “Cross-Release Shared Utility Code Reuse” (Simulink Coder)
• “Customize Generated C Function Interfaces” on page 29-2
6-79
6 Code Reuse for Simulink Coder
The shared utility checksum mechanism makes sure that several critical properties are
identical for models that use the shared utilities. For the fixed-point functions, there are
additional properties that determine function behavior. The mechanism codes these
properties into the functions and file names to maintain requirements. The additional
properties include:
Category Function/Property
Block properties • Fixed-point operation that the block performs
• Fixed-point data type and scaling (Slope, Bias) of function
inputs and outputs
• Overflow handling mode (Saturation, Wrap)
• Rounding Mode (Floor, Ceil, Zero)
Model properties get_param(bdroot, 'NoFixptDivByZeroProtection')
The file names shown are examples of generated fixed-point utility files. The function or
macro names in the file are identical to the file name without the extension.
FIX2FIX_U12_U16.c
FIX2FIX_S9_S9_SR99.c
ACCUM_POS_S30_S30.h
MUL_S30_S30_S16.h
div_nzp_s16s32_floor.c
div_s32_sat_floor.c
For these examples, the table shows how the respective fields correspond.
The ACCUM_POS example uses the output variable as one of the input variables. So, the
file and macro name only contain the output and second input.
6-80
See Also
The second div example has identical data type and bits for both inputs and the output.
So, the file and function name only include the output.
See Also
More About
• “Generate Shared Utility Code” (Simulink Coder)
• “Generate Shared Utility Code for Custom Data Types” (Simulink Coder)
• “Cross-Release Shared Utility Code Reuse” (Simulink Coder)
6-81
6 Code Reuse for Simulink Coder
However, you can configure the code generator to place a single type definition in a
header file in the _sharedutils folder. Then, when you generate code from a model, if
the type definition already exists in the _sharedutils folder, the code generator does
not duplicate the definition, but instead reuses it through inclusion (#include).
• Simulink data type objects that you instantiate from the classes
Simulink.AliasType, Simulink.Bus, and Simulink.NumericType. For basic
information about creating and using these objects, see “Control Data Type Names in
Generated Code” on page 24-2 and Simulink.Bus.
• Enumerations that you define, for example, by authoring an enum class in a script file
or by using the function Simulink.defineIntEnumType. For basic information
about defining enumerations in Simulink, see “Use Enumerated Data in Simulink
Models” (Simulink).
1 Define the data type. For example, create the Simulink.AliasType object.
2 Set data scope and header file properties to specific values that enable sharing.
For a data type object, set the DataScope property to 'Exported' and, optionally,
specify the header file name through the HeaderFile property.
For an enumeration that you define as an enum class in a script file, implement the
getDataScope method (with return value 'Exported') and, optionally, implement
the getHeaderFile method.
6-82
See Also
4 Before generating code from each model, set the model configuration parameter
Shared code placement to Shared location.
5 Generate code from the models.
Note You can configure the definition of the custom data type to appear in a header
file in the _sharedutils folder. The shared utility functions that the model build
generates into the _sharedutils folder do not use the custom data type name. Only
model code located in code folders for each model uses the custom data type name.
See Also
More About
• “Generate Shared Utility Code” (Simulink Coder)
• “Generate Shared Utility Code for Fixed-Point Functions” (Simulink Coder)
• “Cross-Release Shared Utility Code Reuse” (Simulink Coder)
• “Control File Placement of Custom Data Types” on page 24-23
6-83
6 Code Reuse for Simulink Coder
If you do not want to generate shared constants, and Shared code placement is set to
Shared location, set the parameter GenerateSharedConstants to off. For
example, to turn off shared constants for the current model, in the Command Window,
type the following.
set_param(gcs,'GenerateSharedConstants','off');
The code generator produces shared constant parameters individually and places them in
the file const_params.c. The code generator places that file in the shared utilities
folder slprj/target/_sharedutils.
For example, if a constant has multiple uses within a model reference hierarchy where
the top model is named topmod, the code for the shared constant is as follows:
6-84
Shared Constant Parameters for Code Reuse
In the Configuration parameters dialog box, on the Code Generation > Interface pane,
verify that “Shared code placement” (Simulink Coder) is set to Shared location. If
6-85
6 Code Reuse for Simulink Coder
You see the shared constant definitions in the folder slprj/grt/_sharedutils, in the
file const_params.c:
extern const real_T rtCP_pooled_H4eTKtECwveN[9];
const real_T rtCP_pooled_H4eTKtECwveN[9] = { 1.0, 0.75, 0.6, 0.0, 0.0, 0.0, 0.6,
0.75, 1.0 } ;
6-86
See Also
• The model has a code replacement library (CRL) that is specified for data alignment.
• The model is specified to replace data type names in the generated code.
• The Memory Section for constants is MemVolatile or MemConstVolatile.
• The parameter GenerateSharedConstants is set to off.
See Also
More About
• “Generate Reentrant Code from Subsystems” on page 6-42
• “Generate Reusable Code from Library Subsystems Shared Across Models”
(Simulink Coder)
6-87
7
One run-time environment can serve in multiple capacities, but the run-time
environments remain conceptually distinct. Often, the MATLAB development computer is
the test hardware. Typically, the production hardware is different from, and less powerful
than, the MATLAB development or the test hardware. Many types of production hardware
can do little more than run a downloaded executable file.
Provide information about the production hardware board and the compiler that you use
with it when:
• You use Simulink software to simulate a model for which you later generate code
• You use the code generator to produce code for deployment on production hardware
The software uses the board and compiler information to get bit-true agreement for the
results of integer and fixed-point operations performed in simulation and in code
generated for the production hardware. The code generator uses the information to
create code that executes with maximum efficiency.
When you generate code for testing on test hardware, provide information about the test
hardware board and the compiler that you use. The code generator uses this information
to create code that provides bit-true agreement between results from:
7-2
Configure Run-Time Environment Options
You can achieve bit-true agreement for results even if the production and test hardware
are different. Where the C standard does not completely define behavior, the compilers
for the two types of hardware can use different defaults.
• The production hardware and the compiler that you use with it. This information
affects simulation and code generation. See “Example Production Hardware Setting
That Affects Normal Mode Simulation” on page 7-14.
• The test hardware and the compiler that you use with it. This information affects only
code generation.
Default values and properties appear as initial values in the Hardware Implementation
pane when:
7-3
7 Configure Model Parameters for Simulink Coder
You cannot change parameters that have only one possible value. Parameters that have
more than one possible value provide a list of valid values. If you specify hardware
properties manually in Hardware Implementation pane, verify that these values are
consistent with the system target file. Otherwise, the generated code can fail to compile
or execute, or can execute but produce incorrect results.
For details about specific parameters, see “Hardware Implementation Pane” (Simulink).
To see an example of Hardware Implementation pane capabilities, see the
rtwdemo_targetsettings example model. For details related to configuring a
hardware implementation, see:
Specify the hardware board that runs the code generated from your model. Select a value
for Configuration Parameters > Hardware Implementation > Hardware board.
The Hardware Implementation pane identifies the system target file selected on
Configuration Parameters > Code Generation.
To enable parameters for configuring test hardware details, set ProdEqTarget to off.
7-4
Configure Run-Time Environment Options
To specify the vendor of the microprocessor of the hardware device, use the Device
vendor parameter. Your selection determines the available microprocessors in the Device
type menu. If the vendor name does not appear, select Custom Processor. Then, use
the Device type parameter to specify the microprocessor.
• For complete lists of Device vendor and Device type values, see “Device vendor”
(Simulink) and “Device type” (Simulink).
• To add Device vendor and Device type values to the default set that is displayed on
the Hardware Implementation pane, see “Register More Device Vendor and Device
Type Values” on page 7-6.
To specify the microprocessor name from the supported devices listed for your Device
vendor selection, use the Device type parameter. If the microprocessor does not appear
7-5
7 Configure Model Parameters for Simulink Coder
in the menu, change Device vendor to Custom Processor. Then, specify device details
for your custom device.
If you select a device type for which the system target file specifies default hardware
properties, the properties appear as initial values. You cannot change the value of
parameters with only one possible selection. Parameters that have more than one possible
value provide a menu. Select values for your hardware.
To add Device vendor and Device type values to the default set that is displayed on the
Hardware Implementation pane, you can use a hardware device registration API
provided by the code generator.
To use this API, you create an sl_customization.m file, on your MATLAB path, that
invokes the registerTargetInfo function and fills in a hardware device registry entry
with device information. The device information is registered with Simulink software for
each subsequent Simulink session. (To register your device information without restarting
MATLAB, issue the MATLAB command sl_refresh_customizations.)
For example, the following sl_customization.m file adds device vendor MyDevVendor
and device type MyDevType to the Simulink device lists.
function sl_customization(cm)
cm.registerTargetInfo(@loc_register_device);
end
After device registration, you can select the device in the Hardware Implementation
pane.
7-6
Configure Run-Time Environment Options
function sl_customization(cm)
cm.registerTargetInfo(@loc_register_device);
end
thisDev(1) = RTW.HWDeviceRegistry;
thisDev(1).Vendor = 'MyDevVendor';
thisDev(1).Type = 'MyDevType1';
...
thisDev(4) = RTW.HWDeviceRegistry;
thisDev(4).Vendor = 'MyDevVendor';
thisDev(4).Type = 'MyDevType4';
...
end
7-7
7 Configure Model Parameters for Simulink Coder
Property Description
Vendor Character vector specifying the Device vendor value for your
hardware device.
Type Character vector specifying the Device type value for your
hardware device.
Alias Cell array of character vectors specifying aliases or legacy
names that can resolve to this device. Specify each alias or
legacy name in the format 'Vendor->Type'.
7-8
Configure Run-Time Environment Options
Property Description
ShiftRightIntArith Boolean value specifying whether your compiler implements a
signed integer right shift as an arithmetic right shift (true)
or not (false).
setEnabled Cell array of character vectors specifying which device
properties you can modify in the Hardware Implementation
pane when you select this device type.
The Number of bits parameters describe the native word size of the microprocessor
and the bit lengths of char, short, int, and long data. For code generation to succeed:
• The bit lengths must be such that char <= short <= int <= long.
• Bit lengths must be multiples of 8, with a maximum of 32.
• The bit length for long data must not be less than 32.
The rtwtypes.h file defines integer type names. The values that you provide must be
consistent with the word sizes as defined in the compiler limits.h header file. The code
generator maps its integer type names to the corresponding Simulink integer type names.
If no ANSI® C type with a matching word size is available, but a larger ANSI C type is
available, the code generator uses the larger type for int8_T, uint8_T, int16_T,
uint16_T, int32_T, and uint32_T. When the code generator uses a larger type, the
resulting logged values (for example, MAT-file logging) can have different data types than
logged values for simulation.
An application can use an integer data of length from 1 (unsigned) or 2 (signed) bits up
32 bits. If the integer length matches the length of an available type, the code generator
uses that type. If a matching type is not available, the code generator uses the smallest
available type that can hold the data, generating code that does not use unnecessary
higher-order bits. For example, on hardware that supports 8-bit, 16-bit, and 32-bit
7-9
7 Configure Model Parameters for Simulink Coder
integers, for a signal specified as 24 bits, the code generator implements the data as an
int32_T or uint32_T.
Code that uses emulated integer data is not maximally efficient. This code can be useful
during application development for emulating integer lengths that are available only on
production hardware. Emulation does not affect the results of execution.
During code generation, the software checks the compatibility of model data types with
the data types that you specify for production hardware.
• If none of the lengths that you specify for production hardware integers is 32 bits, the
software generates an error.
• If the lengths of data types that the model uses are smaller than the available
production hardware integer lengths, the software generates a warning.
The Byte ordering parameter specifies whether the hardware uses Big Endian (most
significant byte first) or Little Endian (least significant byte first) byte ordering. If left
as Unspecified, the code generator produces code that determines the endianness of
the hardware. This setting is the least efficient.
ANSI C does not completely define the quotient rounding technique for compilers to use
when dividing one signed integer by another. So, the behavior is implementation-
dependent. If both integers are positive, or both are negative, the quotient must round
7-10
Configure Run-Time Environment Options
down. If either integer is positive and the other is negative, the quotient can round up or
down.
The Signed integer division rounds to parameter instructs the code generator about
how the compiler rounds the result of signed integer division. Providing this information
does not change the operation of the compiler. It only describes that behavior to the code
generator, which uses the information to optimize code generated for signed integer
division. The parameter values are:
• Zero — If the quotient is between two integers, the compiler chooses the integer that
is closer to zero as the result.
• Floor — If the quotient is between two integers, the compiler chooses the integer
that is closer to negative infinity.
• Undefined — If Zero or Floor do not describe the compiler behavior or if that
behavior is unknown, choose this value.
Avoid selecting Undefined. When the code generator does not know the signed integer
division rounding behavior of the compiler, the model build generates extra code.
You can obtain the compiler implementation for signed integer division rounding from the
compiler documentation. If documentation is not available, you can determine this
behavior by experiment.
ANSI C does not define the behavior of right shifts on negative integers for compilers. So,
the behavior is implementation-dependent. The Shift right on a signed integer as
arithmetic shift option instructs the code generator about how the compiler implements
right shifts on negative integers. Providing this information does not change the operation
7-11
7 Configure Model Parameters for Simulink Coder
of the compiler. It only describes that behavior to the code generator, which uses the
information to optimize the code generated for arithmetic right shifts.
If the C compiler implements a signed integer right shift as an arithmetic right shift,
select the option. Otherwise, clear the option. An arithmetic right shift fills bits vacated
by the right shift with the value of the most significant bit, which indicates the sign of the
number in two’s-complement notation. The option is selected by default. If your compiler
handles right shifts as arithmetic shifts, this setting is preferred.
• When you select the option, the code generator produces efficient code whenever the
Simulink model performs arithmetic shifts on signed integers.
• When the option is cleared, the code generator produces fully portable but less
efficient code to implement right arithmetic shifts.
You can obtain the compiler implementation for arithmetic right shifts from the compiler
documentation. If documentation is not available, you can determine this behavior by
experiment.
If your model was created before Release 14 and you have not updated the model, the
Configure current execution hardware device parameter (TargetUnknown) value is
'on' by default.
To update your model, clear the box for Configuration Parameters > Hardware
Implementation > Advanced parameters > Test hardware > Configure test
hardware.Or in the Command Window, type:
cs = getActiveConfigSet('your_model_name');
set_param(cs,'TargetUnknown','off');
1 Clear the box for Configuration Parameters > Hardware Implementation >
Advanced parameters > Test hardware > Test Hardware is the same as
7-12
Configure Run-Time Environment Options
production hardware. Apply this step only if your production and test hardware are
different.
2 Set the parameters in Configuration Parameters > Hardware implementation >
Advanced parameters to match your production and test systems.
3 Save the model.
• Production hardware can have word sizes and other hardware characteristics that
differ from the MATLAB development computer. You can prototype code on hardware
that is different from the production hardware or the MATLAB development computer.
When producing code, the code generator accounts for these differences.
• The Simulink product uses some of the information in the production hardware
configuration. That information enables simulations without code generation to give
the same results as executing generated code. For example, the results can detect
error conditions that arise on the production hardware, such as hardware overflow.
• The code generator produces code that provides bit-true agreement with Simulink
results for integer and fixed-point operations. Generated code that emulates
unavailable data lengths runs less efficiently than without emulation. The emulation
does not affect bit-true agreement with Simulink for integer and fixed-point results.
• If you change run-time environments during application development, before
generating or regenerating code, reconfigure the hardware implementation
parameters for the new run-time environment. When code executes on hardware for
which it was not generated, bit-true agreement is not always achieved for results of
integer and fixed-point operations in simulation, production code, and test code.
• To compile code generated from the model, use the Integer rounding mode
parameter on model blocks to simulate the rounding behavior of the C compiler that
you intend. This setting appears on the Signal Attributes pane in 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
“Precision” (Fixed-Point Designer).
• When models contain Model blocks, configure models that they reference to use
identical hardware settings.
7-13
7 Configure Model Parameters for Simulink Coder
If the test and production environments differ, you can generate code that runs on test
hardware as if it were running on production hardware:
1 To enable test hardware parameters, clear the box for Configuration Parameters >
Hardware Implementation > Advanced parameters > Test hardware > Test
hardware is the same as production hardware. Or, in the Command Window type:
cs = getActiveConfigSet('your_model_name');
set_param(cs,'ProdEqTarget','off');
2 Specify device type details through the test hardware (Target*) parameters.
If you select a system target file that specifies a default microprocessor and its hardware
properties, these default values and properties appear as initial values.
Parameters with only one possible value cannot be changed. If you modify hardware
properties, check that their values are consistent with the system target file. Otherwise,
the generated code can fail to compile or execute, or can execute but produce incorrect
results.
% Create adder
pos = [140 140 200 340];
add_block('simulink/Math Operations/Add', ...
[model '/sum_int32'], ...
7-14
Configure Run-Time Environment Options
'Inputs','++++', ...
'SaturateOnIntegerOverflow', ...
'on', ...
'Position', ...
pos)
7-15
7 Configure Model Parameters for Simulink Coder
plot([y1 y2]);
figure(gcf);
The difference in behavior is due to the accumulator data type in the Sum block. The
Accumulator data type block parameter is set to Inherit: Inherit via internal
rule. For this example, the resulting accumulator data type is 64 bits wide if the use of
the C long long data type is enabled. Otherwise, it is 32 bits wide. Depending on the
input values for the sum block, the 32-bit accumulator can saturate when the 64-bit
accumulator does not. Therefore, normal mode behavior can depend on the
ProdLongLongMode setting. In both cases, the normal mode behavior and production
hardware behavior matches bitwise.
See Also
More About
• “Hardware Implementation Pane” (Simulink)
• “Device vendor” (Simulink)
• “Device type” (Simulink)
• “Precision” (Fixed-Point Designer)
7-16
8
• By default, Simulink creates and stores a protected version of the model in the current
working folder. The protected model has the same name as the source model, with
an .slxp extension.
• To share a protected model, share only the protected model file.
• The original Model block does not change. If the Model block parameter Model name
does not specify an extension, a protected model, .slxp, takes precedence over a
model file, .slx.
• You can optionally create a harness model which includes the protected model. A
badge icon appears in the lower-left corner of the protected model block in the
harness model. For more information, see “Harness Model” on page 8-4.
• You can optionally include generated code with the protected model so that a third
party can generate code for a model that contains the protected model. For more
information, see “Code Generation Support in Protected Models” on page 8-6.
• If the Model block uses variants, only the active variant is protected. For more
information, see “Set up Model Variants Using a Model Block” (Simulink).
• If the model defines callbacks, the model protection process does not preserve these
callbacks. For more information on creating callbacks for use with a protected model,
see “Define Callbacks for Protected Models” (Simulink Coder).
• If you rename a protected model, or change its suffix, the model is unusable until you
restore its original name and suffix. You cannot change a protected model file
internally because such changes make the file unusable.
• The Model block context menu. For more information, see “Create a Protected Model”
on page 8-11.
• The Simulink.ModelReference.protect function.
8-2
Protect Models for Third-Party Use
• The Simulink Editor menu bar. To create a protected model from the current model,
select File > Export Model To > Protected Model.
To use a protected model that requires passwords across platforms, before you create the
protected model, set the MATLAB character set encoding to 'US-ASCII'. For more
information, see slCharacterEncoding.
8-3
8 Model Protection in Simulink Coder
Harness Model
You can create a harness model for the generated protected model. The harness model
opens as a new, untitled model that contains only a Model block that references the
protected model. This Model block:
• Specifies the Model block parameter, Model name, as the name of the protected
model.
• Has a badge icon in the lower-left corner.
• Has the same number of input and output ports as the protected model.
• Defines model reference arguments that the protected model uses, but does not
provide values.
To create a harness model, see “Create a Protected Model” on page 8-11. You can use a
harness model to test your protected model. For more information, see “Test the
Protected Model” on page 8-22. You can also copy the Model block in your harness
model to another model, where it is an interface to the protected model.
8-4
Protected Model Report
• Environment, providing the Simulink version and platform used to create the
protected model.
• Supported functionality, reporting On, Off, or On with password
protection for each possible functionality that the protected model supports.
• Licenses, listing licenses required to run the protected model.
• An Interface Report, including model interface information such as input and output
specifications, exported function information, interface parameters, and data stores.
When you create the protected model from the Simulink Editor, the protected model
report is generated. To generate a report when using the
Simulink.ModelReference.protect function, set the ‘Report’ option to true.
If you configure your protected model for multiple targets, the Summary includes a list
of supported targets in the Supported functionality table. When you build a model that
references a protected model with multiple targets, the protected model code generation
report represents the currently configured target.
To view the protected model report, right-click the protected-model badge icon and select
Display Report. Or, call the Simulink.ProtectedModel.open function with the
report option.
8-5
8 Model Protection in Simulink Coder
In the Create Protected Model dialog box, select the Use generated code check box. The
Content type determines the appearance of the generated code. If you select Readable
source code or Obfuscated source code, the header files match the appearance of
the generated code. If you select Binaries, the header files can appear readable or
obfuscated based on the 'ObfuscateCode' argument. By default, the header files
appear obfuscated.
• Simulink ignores source code comments in the Code Generation > Comments pane.
Obfuscation of the generated code removes comments because comments can reveal
intellectual property.
• Simulink obfuscates custom code specified in the Code Generation > Custom Code
pane, but does not obfuscate identifiers.
For an example on including code generation support, see “Create a Protected Model” on
page 8-11.
To create a protected model that supports code generation, your model must meet all
requirements as described in “Requirements for Protecting a Model” (Simulink Coder)
and these requirements:
8-6
Code Generation Support in Protected Models
• To avoid an error during code generation of a model that includes a protected model:
• The protected model name must be unique from other model names in the same
model reference hierarchy.
• The interfaces must match.
• The parameters must be compatible.
• You must not select the Code Generation > Verification > Measure function
execution time check box. If you have this option selected when you protect your
model, the software turns off the parameter and displays a warning.
• The protected model Existing shared code (ExistingSharedCode) parameter must
not specify a value.
• All protected referenced models must support code generation without password
protection.
• The protected model must be compatible with the Content type of each protected
referenced model. This table provides compatibility information.
When the Content type of the protected parent model and protected referenced
models do not match, code generation applies the more secure Content type. For
example, a protected parent model set for Binaries generates Binaries for
protected referenced models that are set to Obfuscated source code. A protected
8-7
8 Model Protection in Simulink Coder
parent model set for Readable source code generates Obfuscated source
code for protected referenced models that are set to Obfuscated source code.
8-8
Protected Model File
If you created a protected model for simulation only and the referencing model is in
Normal mode, after simulation, the model.mexext file is placed in the build folder.
If you created a protected model for simulation only and the referencing model is in
Accelerator or Rapid Accelerator mode, after simulation, the following files are
unpacked:
• slprj/sim/model/*.h
• slprj/sim/model/modellib.a (or modellib.lib)
• slprj/sim/model/tmwinternal/*
• slprj/sim/_sharedutils/*
For the protected model report, these additional files are unpacked (but not in the build
folder):
• slprj/sim/model/html/*
• slprj/sim/model/buildinfo.mat
If you included code generation support when you created the protected model, after
building your model the following files are unpacked (in addition to the preceding files):
• slprj/sim/model/*.h
• slprj/sim/model/modellib.a (or modellib.lib)
• slprj/sim/model/tmwinternal/*
• slprj/sim/_sharedutils/*
• slprj/target/model/*.h
• slprj/target/model/model_rtwlib.a (or model_rtwlib.lib)
• slprj/target/model/buildinfo.mat
• slprj/target/model/codeinfo.mat
• slprj/target/_sharedutils/*
• slprj/target/model/tmwinternal/*
8-9
8 Model Protection in Simulink Coder
With an Embedded Coder license, you can specify a Top model code interface. In this
case, if you opted to include code generation support when you created the protected
model, after building your model the following files are unpacked:
• slprj/sim/model/*.h
• slprj/sim/model/modellib.a (or modellib.lib)
• slprj/sim/model/tmwinternal/*
• slprj/sim/_sharedutils/*
• model_target_rtw/*.h
• model_target_rtw/*.objExt
• model_target_rtw/buildinfo.mat
• model_target_rtw/codeinfo.mat
• slprj/target/_sharedutils/*
• slprj/target/model/tmwinternal/*
For the protected model report, after building your model these files are unpacked (in
addition to the preceding files):
• slprj/target/model/html/*
• slprj/target/model/buildinfo.mat
• slprj/target/_sharedutils/html/*
Note The slprj/sim/model/* files are deleted after they are used.
8-10
Create a Protected Model
8-11
8 Model Protection in Simulink Coder
7 In the Create Protected Model dialog box, select the Simulate and Use generated
code check boxes. If you want to password-protect the functionality of the protected
model, enter a password with a minimum of four characters. Each functionality can
have a unique password.
8 If you have an Embedded Coder license and specify an ERT-based system target file
(for example, ert.tlc) for the model, the Code interface field is visible. From the
Code interface drop-down list, select one of the following options:
• Model reference — Specifies code access through the model reference code
interface, which allows use of the protected model within a model reference
hierarchy. Users of the protected model can generate code from a parent model
that contains the protected model. In addition, users can run Model block SIL/PIL
simulations with the protected model.
• Top model — Specifies code access through the standalone interface. Users of
the protected model can run Model block SIL/PIL simulations with the protected
model.
8-12
Create a Protected Model
13 To view the protected model report, right-click the protected-model badge icon on the
CounterA block and select Display Report.
8-13
8 Model Protection in Simulink Coder
8-14
See Also
See Also
Related Examples
• “Test the Protected Model” on page 8-22
• “Package a Protected Model” on page 8-25
• “Configure and Run SIL Simulation” on page 67-16
More About
• “Code Generation Support in Protected Models” on page 8-6
• “Protected Model Creation Settings” on page 8-16
• “Code Interfaces for SIL and PIL” on page 67-6
8-15
8 Model Protection in Simulink Coder
• Read-only viewing
• Simulation
• Code Generation
8-16
Protected Model Creation Settings
Simulate
The Simulate check box allows someone to simulate a protected model. When you select
this check box, the Web view is not inherited. To enable the Web view with simulation
functionality, select the Open Read-Only View of Model check box. The Simulate
functionality:
• Model reference — Specifies the model reference code interface, which allows
use of the protected model within a model reference hierarchy. Users of the
protected model can generate code from a parent model that contains the
protected model. In addition, users can run Model block SIL/PIL simulations with
the protected model.
8-17
8 Model Protection in Simulink Coder
• Top model — Specifies code access through the standalone interface. Users of the
protected model can run Model block SIL/PIL simulations with the protected
model.
• Determines the appearance of the generated code by the Content type list. The
options are:
• Binaries
• Obfuscated source code (default)
• Readable source code, which also includes readable code comments
8-18
Create a Protected Model with Multiple Targets
1 Load a model and save a local copy. This model is configured for a GRT target.
sldemo_mdlref_counter
save_system('sldemo_mdlref_counter','mdlref_counter.slx');
2 Add a required password for modifying a protected model. If you do not add a
password, you are prompted to set a password when you create a modifiable,
protected model.
Simulink.ModelReference.ProtectedModel.setPasswordForModify(...
'mdlref_counter','password');
3 Create a modifiable, protected model with support for code generation.
Simulink.ModelReference.protect('mdlref_counter','Mode',...
'CodeGeneration', 'Modifiable',true, 'Report',true);
4 Get a list of targets that the protected model supports.
st = Simulink.ProtectedModel.getSupportedTargets('mdlref_counter')
st =
'grt' 'sim'
5 Configure the unprotected model to support an ERT target.
Simulink.ProtectedModel.addTarget('mdlref_counter');
7 Verify that the list of supported targets now includes the ERT target.
st = Simulink.ProtectedModel.getSupportedTargets('mdlref_counter')
8-19
8 Model Protection in Simulink Coder
st =
8-20
Use a Protected Model with Multiple Targets
1 Get a list of the targets that the protected model supports using the
Simulink.ProtectedModel.getSupportedTargets function.
You can also get this information from the protected model report. To view the report,
on the protected model block, right-click the badge icon. Select Display Report. The
Summary lists the supported targets.
2 Get the configuration set for your chosen target using the
Simulink.ProtectedModel.getConfigSet function. You can use the
configuration set to verify that the protected model interface is compatible with the
parent model.
3 Generate code. The build process selects the corresponding target.
8-21
8 Model Protection in Simulink Coder
You can also compare the output of the protected model to the output of the original
model. Because you are the supplier, both the original and the protected model might
exist on the MATLAB path. In the original model, if the Model block Model name
parameter names the model without providing a suffix, the protected model takes
precedence over the unprotected model. To override this default when testing the output,
in the Model block Model name parameter, specify the file name with the extension of
the unprotected model, .slx.
To compare the unprotected and protected versions of a Model block, use the Simulation
Data Inspector. This example uses sldemo_mdlref_basic and the protected model,
sldemo_mdlref_counter.slxp, which is created in “Create a Protected Model” on
page 8-11.
8-22
Test the Protected Model
box, specify the Model name parameter with the name of the protected model,
sldemo_mdlref_counter.slxp. A badge icon appears on the Model block. Repeat
this step for CounterB block and CounterC block.
9 Simulate the model, which now refers to the protected model. When the simulation is
complete, a new run appears in the Simulation Data Inspector.
10 In the Simulation Data Inspector, rename the new run to indicate that it is for the
protected model.
11 In the Simulation Data Inspector, click the Compare tab. From the Baseline and
Compare To lists, select the runs from the unprotected and protected model,
respectively. To compare the runs, click Compare Runs. For more information about
comparing runs, see “Compare Simulation Data” (Simulink).
8-23
8 Model Protection in Simulink Coder
• Simulink.Signal
• Simulink.Bus
• Simulink.Alias
• Simulink.NumericType that is an alias
For more information, see “Edit and Manage Workspace Variables by Using Model
Explorer” (Simulink).
Before executing the protected model as a part of a third-party model, the receiver of the
protected model must load the MAT-file.
8-24
Package a Protected Model
• Provide the .slxp file and other supporting files as separate files.
• Combine the files into a ZIP or other container file.
• Combine the files using a manifest. For more information, see “Export Files in a
Manifest” (Simulink).
• Provide the files in some other standard or proprietary format specified by the
receiver.
Whichever approach you use to deliver a protected model, include information on how to
retrieve the original files. One approach to consider is to use the Simulink Manifest Tools,
as described in “Analyze Model Dependencies” (Simulink).
8-25
8 Model Protection in Simulink Coder
1 Create your postprocessing function. Use this function to call your custom obfuscator.
The function must be on the MATLAB path and accept a
Simulink.ModelReference.ProtectedModel.HookInfo object as an input
variable.
2 In your function, get the files and exported symbol information that your custom
obfuscator requires to process the protected model files. To get the files and
information, access the properties of your function input variable. The variable is a
Simulink.ModelReference.ProtectedModel.HookInfo object with the
following properties:
• SourceFiles
• NonSourceFiles
• ExportedSymbols
3 Pass the protected model file information to your custom obfuscator. The following is
an example of a postprocessing function for custom obfuscation:
function myHook(protectedModelInfo)
Simulink.ModelReference.protect('myModel, ...
'Mode', ...
'CodeGeneration', ...
8-26
Specify Custom Obfuscator for Protected Model
'CustomPostProcessingHook', ...
@(protectedModelInfo)myHook(protectedModelInfo))
The protected model creator can also enable obfuscation of simulation target code and
generated code through the ‘ObfuscateCode’ option of the
Simulink.ModelReference.protect function. Your custom obfuscator runs only on
the generated code and not on the simulation target code. If both obfuscators are in use,
the custom obfuscator is the last to run on the generated code before the files are
packaged.
8-27
8 Model Protection in Simulink Coder
Creating Callbacks
To create and define a protected model callback, create a
Simulink.ProtectedModel.Callback object. Callback objects specify:
• The code to execute for the callback. The code can be a character vector of MATLAB
commands or a script on the MATLAB path.
• The event that triggers the callback. The event can be 'PreAccess' or 'Build'.
• The protected model functionality that the event applies to. The functionality can be
'CODEGEN', 'SIM', 'VIEW', or 'AUTO'. If you select 'AUTO', and the event is
'PreAccess', the callback applies to each functionality. If you select 'AUTO', and the
event is 'Build', the callback applies only to 'CODEGEN' functionality. If you do not
select any functionality, the default behavior is 'AUTO'.
• The option to override the protected model build process. This option applies only to
'CODEGEN' functionality.
You can create only one callback per event and per functionality.
8-28
Define Callbacks for Protected Models
pmCallback = Simulink.ProtectedModel.Callback('Build',...
'CODEGEN', 'pm_callback.m');
pmCallback.setOverrideBuild(true);
3 Create the protected model and specify the code generation callback.
Simulink.ModelReference.protect('sldemo_mdlref_counter',...
'Mode', 'CodeGeneration','Callbacks',{pmCallback})
4 Build the protected model. In place of the build, the callback displays the code
interface.
rtwbuild('sldemo_mdlref_basic')
8-29
8 Model Protection in Simulink Coder
See Also
Simulink.ModelReference.protect | Simulink.ProtectedModel.Callback |
Simulink.ProtectedModel.getCallbackInfo
More About
• “Protect Models for Third-Party Use” (Simulink Coder)
• “Code Generation Support in Protected Models” (Simulink Coder)
8-30
9
Examples of when to generate code that responds to initialize, reset, or terminate events
include:
Each nonvirtual subsystem and referenced model can have its own set of initialize, reset,
and terminate functions.
The code generator produces initialization and termination code differently than reset
code. For initialization and termination code, the code generator includes your component
initialization and termination code in the default entry-point functions,
model_initialize and model_terminate. The code generator produces reset code
only if you model reset behavior.
• Includes initialize event code with default initialize code in entry-point function
model_initialize.
• Includes terminate event code with default terminate code in entry-point function
model_terminate.
9-2
Generate Code That Responds to Initialize, Reset, and Terminate Events
For this model, the code generator produces initialize and terminate entry-point functions
that other code can interface with.
void rtwdemo_irt_base_initialize(void)
void rtwdemo_irt_base_terminate(void)
This code appears in the generated file rtwdemo_irt_base.c. The initialize function,
rtwdemo_irt_base_initialize:
This code assumes that support for nonfinite numbers and MAT-file logging is disabled.
void rtwdemo_irt_base_initialize(void)
{
rtmSetErrorStatus(rtwdemo_irt_base_M, (NULL));
rtwdemo_irt_base_Y.Out1 = 0.0;
rtwdemo_irt_base_DW.DiscreteIntegrator_DSTATE = 0.0;
}
void rtwdemo_irt_base_terminate(void)
{
/* (no terminate code required) */
}
9-3
9 Component Initialization, Reset, and Termination in Simulink Coder
Add Initialize Function and Terminate Function blocks to the model (see
rtwdemo_irt_initterm). The Initialize Function block uses the State Writer block to
set the initial condition of a Discrete Integrator block. The Terminate Function block
includes a State Reader block, which reads the state of the Discrete Integrator block.
The Event type parameter of the Event Listener block for the initialize and terminate
functions is set to Initialize and Terminate, respectively. The initialize function uses
the State Writer block to initialize the input value for the Discrete Integrator block to 10.
The terminate function uses the State Reader block to read the state of the Discrete
Integrator block.
9-4
Generate Code That Responds to Initialize, Reset, and Terminate Events
9-5
9 Component Initialization, Reset, and Termination in Simulink Coder
The code generator includes the event code that it produces for the Initialize Function
and Terminate Function blocks with standard initialize and terminate code in entry-point
functions rtwdemo_irt_initterm_initialize and
rtwdemo_irt_initterm_terminate. This code assumes that support for nonfinite
numbers and MAT-file logging is disabled.
void rtwdemo_irt_initterm_initialize(void)
{
rtmSetErrorStatus(rtwdemo_irt_initterm_M, (NULL));
rtwdemo_irt_initterm_Y.Out1 = 0.0;
9-6
Generate Code That Responds to Initialize, Reset, and Terminate Events
rtwdemo_irt_initterm_DW.DiscreteIntegrator_DSTATE = 10.0;
}
void rtwdemo_irt__initterm_terminate(void)
{
/* (no terminate code required) */
}
The code generator produces a reset entry-point function only if you model reset
behavior. If a component contains multiple reset specifications, the code that the code
generator produces depends on whether reset functions share an event name. For a given
component hierarchy:
• For reset functions with unique event names, the code generator produces a separate
entry-point function for each named event. The name of each function is the name of
the corresponding event.
• For reset functions that share an event name, the code generator aggregates the reset
code into one entry-point function. The code for the reset functions appears in order,
starting with the lowest level (innermost) of the component hierarchy and ending with
the root (outermost). The name of the function is model_reset. For more
information, see “Event Names and Code Aggregation” (Simulink Coder).
Consider the model rtwdemo_irt_reset, which includes a Reset Function block derived
from an Initialize Function block.
9-7
9 Component Initialization, Reset, and Termination in Simulink Coder
The Event type and Event name parameters of the Event Listener block are set to
Reset and reset, respectively. The function uses the State Writer block to reset the
input value for the Discrete Integrator block to 5.
9-8
Generate Code That Responds to Initialize, Reset, and Terminate Events
void rtwdemo_irt_reset_reset(void)
{
rtwdemo_irt_reset_DW.DiscreteIntegrator_DSTATE = 5.0;
}
9-9
9 Component Initialization, Reset, and Termination in Simulink Coder
When producing code, the code generator aggregates code for functions that have a given
event name across the entire component hierarchy into one entry-point function. The
code for reset functions appears in order, starting with the lowest level (innermost) of the
component hierarchy and ending with the root (outermost). The code generator uses the
event name to name the function.
For example, the model rtwdemo_irt_shared includes a subsystem that replicates the
initialize, reset, and terminate functions that are in the parent model.
Although the model includes multiple copies of the initialize, reset, and terminate
functions, the code generator produces one entry-point function for reset
9-10
Generate Code That Responds to Initialize, Reset, and Terminate Events
.
.
.
void rtwdemo_irt_shared_reset(void)
{
rtwdemo_irt_shared_DW.SubIntegrator2_DSTATE = 5.0;
rtwdemo_irt_shared_DW.Integrator2_DSTATE = 5.0;
}
.
.
.
void rtwdemo_irt_shared_initialize(void)
{
rtmSetErrorStatus(rtwdemo_irt_shared_M, (NULL));
rtwdemo_irt_shared_Y.Out1 = 0.0;
rtwdemo_irt_shared_DW.Integrator1_DSTATE = 0.0;
rtwdemo_irt_shared_DW.SubIntegrator2_DSTATE = 2.0;
rtwdemo_irt_shared_DW.Integrator2_DSTATE = 10.0;
.
.
.
void rtwdemo_irt_shared_terminate(void)
{
/* (no terminate code required) */
}
9-11
9 Component Initialization, Reset, and Termination in Simulink Coder
If you rename the event configured for the subsystem reset function to reset_02, the
code generator produces two reset entry-point functions, rtwdemo_irt_shared_reset
and rtwdemo_irt_shared_reset_02.
void rtwdemo_irt_shared_reset(void)
{
rtwdemo_irt_shared_DW.SubIntegrator2_DSTATE = 5.0;
}
void rtwdemo_irt_shared_reset_02(void)
{
rtwdemo_irt_shared_DW.Integrator2_DSTATE = 5.0;
}
Limitation
You cannot generate code from a harness model—a root model that contains a Model
block, which exposes initialize, reset, or terminate function ports.
See Also
Related Examples
• “Customize Initialize, Reset, and Terminate Functions” (Simulink)
• “Configure Code Generation for Model Entry-Point Functions” (Simulink Coder)
• “Initialization of Signal, State, and Parameter Data in the Generated Code” on page
22-228
9-12
10
You generate code for the entire model in one file and look through that entire file to find
code for a specific part of the chart.
10-2
Code Generation of Stateflow Blocks
You specify code generation parameters so that code for an atomic subchart appears in a
separate file. This method of code generation enables unit testing for a specific part of a
chart. You can avoid searching through unrelated code and focus only on the part that
interests you.
10-3
10 Stateflow Blocks in Simulink Coder
10-4
Code Generation of Stateflow Blocks
Note Unreachable Stateflow states are optimized out and are not included in the
generated code.
For more information, see “Generate Reusable Code for Unit Testing” on page 10-8.
10-5
10 Stateflow Blocks in Simulink Coder
10-6
Generate Reusable Code for Atomic Subcharts
When you generate code for your model, a separate file stores the code for linked atomic
subcharts from the same library.
When you generate code for your model, a separate file stores the code for the atomic
subchart. For more information, see “Generate Reusable Code for Unit Testing” on page
10-8.
10-7
10 Stateflow Blocks in Simulink Coder
10-8
Generate Reusable Code for Unit Testing
Suppose that you want to generate reusable code so that you can perform unit testing on
state A. You can convert that part of the chart to an atomic subchart and then specify a
separate file to store the generated code.
10-9
10 Stateflow Blocks in Simulink Coder
10-10
Generate Reusable Code for Unit Testing
4 Select Model-to-code.
5 Click Apply.
1 In the Model Configuration Parameters dialog box, go to the Code Generation >
Symbols pane.
2 Set Subsystem methods to the format scheme $R$N$M$F, where:
To inspect the code for saturator.c, click the hyperlink in the report to see the
following code:
10-11
10 Stateflow Blocks in Simulink Coder
10-12
Generate Reusable Code for Unit Testing
Line 28 shows that the during function generated for the atomic subchart has the name
ex_reuse_states_A_during. This name follows the format scheme $R$N$M$F
specified for Subsystem methods:
Note The line numbers shown can differ from the numbers that appear in your code
generation report.
10-13
10 Stateflow Blocks in Simulink Coder
In this section...
“Inlined Generated Code for State Functions” on page 10-14
“How to Set the State Function Inline Option” on page 10-16
“Best Practices for Controlling State Function Inlining” on page 10-16
If your model includes Stateflow objects and you have rigorous requirements for
traceability between generated code and the corresponding state functions, you can
override the default behavior. Use the state property Function Inline Option to
explicitly force or prevent inlining of state functions.
If you force inlining for a state, the code generator inlines code for state actions into the
parent function. The parent function contains code for executing the state actions, outer
transitions, and flow charts. It does not include code for empty state actions.
If you prevent inlining for a state, the code generator produces these static functions for
state foo.
Function Description
enter_atomic_foo Marks foo active and performs entry
actions.
enter_internal_foo Calls default paths.
10-14
Inline State Functions in Generated Code
Function Description
inner_default_foo Executes flow charts that originate when an
inner transition and default transition reach
the same junction inside a state.
If you prevent inlining for state A, the code generator produces this code.
10-15
10 Stateflow Blocks in Simulink Coder
1 Right-click inside the state and, from the context menu, select Properties.
Option Behavior
Inline Forces inlining of state functions into the parent function, as long
as the function is not part of a recursion. See “What Happens
When You Force Inlining” on page 10-14.
Function Prevents inlining of state functions. Generates up to six static
functions for the state. See “What Happens When You Prevent
Inlining” on page 10-14.
Auto Uses internal heuristics to determine whether or not to inline the
state functions.
3 Click Apply.
10-16
Air-Fuel Ratio Control System with Stateflow Charts
Open sldemo_fuelsys via rtwdemo_fuelsys and compile the diagram to see the signal data
types.
rtwdemo_fuelsys
sldemo_fuelsys([],[],[],'compile');
sldemo_fuelsys([],[],[],'term');
10-17
10 Stateflow Blocks in Simulink Coder
The air-fuel ratio control system is comprised of Simulink® and Stateflow®. The control
system is the portion of the model for which you generate code.
open_system('sldemo_fuelsys/fuel_rate_control');
The control logic is a Stateflow® chart that specifies the different modes of operation.
open_system('sldemo_fuelsys/fuel_rate_control/control_logic');
10-18
Air-Fuel Ratio Control System with Stateflow Charts
close_system('sldemo_fuelsys/fuel_rate_control/airflow_calc');
close_system('sldemo_fuelsys/fuel_rate_control/fuel_calc');
close_system('sldemo_fuelsys/fuel_rate_control/control_logic');
hDemo.rt=sfroot;hDemo.m=hDemo.rt.find('-isa','Simulink.BlockDiagram');
hDemo.c=hDemo.m.find('-isa','Stateflow.Chart','-and','Name','control_logic');
hDemo.c.visible=false;
close_system('sldemo_fuelsys/fuel_rate_control');
10-19
10 Stateflow Blocks in Simulink Coder
Simulink® Coder™ generates generic ANSI® C code for Simulink® and Stateflow®
models via the Generic Real-Time (GRT) target. You can configure a model for code
generation programmatically.
rtwconfiguredemo('sldemo_fuelsys','GRT');
For this example, build only the air-fuel ratio control system. Once the code generation
process is complete, an HTML report detailing the generated code is displayed. The main
body of the code is located in fuel_rate_control.c.
rtwbuild('sldemo_fuelsys/fuel_rate_control');
Embedded Coder® generates production ANSI® C/C++ code via the Embedded Real-
Time (ERT) target. You can configure a model for code generation programmatically.
rtwconfiguredemo('sldemo_fuelsys','ERT');
Repeat the build process and inspect the generated code. In the Simulink® Coder™
Report, you can navigate to the relevant code segments interactively by using the
Previous and Next buttons. From the chart context menu (right-click the Stateflow®
block), select Code Generation > Navigate to Code. Programmatically, use the
rtwtrace utility.
rtwbuild('sldemo_fuelsys/fuel_rate_control');
rtwtrace('sldemo_fuelsys/fuel_rate_control/control_logic')
10-20
Air-Fuel Ratio Control System with Stateflow Charts
switch (rtDW.bitsForTID0.is_Fueling_Mode) {
case IN_Fuel_Disabled:
rtDW.fuel_mode = DISABLED;
switch (rtDW.bitsForTID0.was_Low_Emissions) {
case IN_Normal:
rtDW.bitsForTID0.is_Low_Emissions = IN_Normal;
rtDW.bitsForTID0.was_Low_Emissions = IN_Normal;
break;
clear hDemo;
rtwdemoclean;
close_system('sldemo_fuelsys',0);
Related Examples
10-21
11
In this section...
“Types of S-Functions” on page 11-3
“Files Required for Implementing Noninlined and Inlined S-Functions” on page 11-5
“Guidelines for Writing S-Functions that Support Code Generation” on page 11-6
You use S-functions to extend Simulink support for simulation and code generation. For
example, you can use them to:
The application program interface (API) for writing S-functions allows you to implement
generic algorithms in the Simulink environment with a great deal of flexibility. If you
intend to use S-functions in a model for code generation, the level of flexibility can vary.
For example, it is not possible to access the MATLAB workspace from an S-function that
you use with the code generator. This topic explains conditions to be aware of for using S-
functions However, using the techniques presented in this topic, you can create S-
functions for most applications that work with the generated code.
Although S-functions provide a generic and flexible solution for implementing complex
algorithms in a model, the underlying API incurs overhead in terms of memory and
computation resources. Most often the additional resources are acceptable for real-time
rapid prototyping systems. In many cases, though, additional resources are unavailable in
real-time embedded applications. You can minimize memory and computational
requirements by using the Target Language Compiler technology provided with the code
generator to inline your S-functions. If you are producing an S-function for existing
external code, consider using the Legacy Code Tool to generate your S-function and
relevant TLC file.
• Level 2 S-functions
11-2
S-Functions and Code Generation
Notes This information is for code generator users. Even if you do not currently use the
code generator, follow these practices when writing S-functions, especially if you are
creating general-purpose S-functions.
Types of S-Functions
Examples for which you might choose to implement an S-function for simulation and code
generation include:
1 “I'm not concerned with efficiency. I just want to write one version of my algorithm
and have it work in the Simulink and code generator products automatically.”
2 “I want to implement a highly optimized algorithm in the Simulink and code
generator products that looks like a built-in block and generates very efficient code.”
3 “I have a lot of hand-written code that I need to interface. I want to call my function
from the Simulink and code generator products in an efficient manner.”
1 Noninlined S-function
2 Inlined S-function
3 Autogenerated S-function for external code
Noninlined S-Functions
Additional memory and computation resources are required for each instance of a
noninlined S-Function block. However, this routine of incorporating algorithms into
models and code generation applications is typical during the prototyping phase of a
project where efficiency is not important. The advantage gained by forgoing efficiency is
the ability to change model parameters and structures rapidly.
11-3
11 Block Authoring and Code Generation for Simulink Coder
Writing a noninlined S-function does not involve TLC coding. Noninlined S-functions are
the default case for the build process in the sense that once you build a MEX S-function in
your model, there is no additional preparation prior to pressing Ctrl+B to build your
model.
Some restrictions exist concerning the names and locations of noninlined S-function files
when generating makefiles. See “Write Noninlined S-Function and TLC Files” on page 11-
67.
Inlined S-Functions
For S-functions to work in the Simulink environment, some overhead code is generated.
When the code generator produces code from models that contain S-functions (without
sfunction.tlc files), it embeds some of this overhead code in the generated code. If
you want to optimize your real-time code and eliminate some of the overhead code, you
must inline (or embed) your S-functions. This involves writing a TLC (sfunction.tlc)
file that eliminates overhead code from the generated code. The Target Language
Compiler processes sfunction.tlc files to define how to inline your S-function
algorithm in the generated code.
Note The term inline should not be confused with the C++ inline keyword. Inline means
to specify text in place of the call to the general S-function API routines (for example,
mdlOutputs). For example, when a TLC file is used to inline an S-function, the generated
code contains the C/ C++ code that would normally appear within the S-function routines
and the S-function itself has been removed from the build process.
A fully inlined S-function builds your algorithm (block) into generated code in a manner
that is indistinguishable from a built-in block. Typically, a fully inlined S-function requires
you to implement your algorithm twice: once for the Simulink model (C/C++ MEX S-
function) and once for code generation (TLC file). The complexity of the TLC file depends
on the complexity of your algorithm and the level of efficiency you're trying to achieve in
the generated code. TLC files vary from simple to complex in structure. See “Inlining S-
Functions” (Simulink Coder)
If you need to invoke hand-written C/C++ code in your model, consider using the
Simulink Legacy Code Tool. The Legacy Code Tool can automate the generation of a fully
inlined S-function and a corresponding TLC file based on information that you register in
a Legacy Code Tool data structure.
11-4
S-Functions and Code Generation
For more information, see “Integrate C Functions Using Legacy Code Tool” (Simulink)
and see “Import Calls to External Code into Generated Code with Legacy Code Tool” on
page 11-7.
Note Fully-inlined S-functions that are generated to invoke legacy or custom C/C++
code also require an sfunction.tlc file, which is generated by Legacy Code Tool.
Fully inlined S-functions might require the placement of the mdlRTW routine in your S-
function MEX-file sfunction.c or sfunction.cpp. The mdlRTW routine lets you place
information in model.rtw, the record file that specifies a model, and which the code
generator invokes the Target Language Compiler to process prior to executing
sfunction.tlc when generating code.
Including a mdlRTW routine is useful when you want to introduce nontunable parameters
into your TLC file. Such parameters are generally used to determine which operating
mode is active in a given instance of the S-function. Based on this information, the TLC
file for the S-function can generate highly efficient, optimal code for that operating mode.
11-5
11 Block Authoring and Code Generation for Simulink Coder
See Also
More About
• “Import Calls to External Code into Generated Code with Legacy Code Tool” on page
11-7
• “Generate S-Function from Subsystem” on page 11-62
• “Write S-Function and TLC Files By Hand” on page 11-67
11-6
Import Calls to External Code into Generated Code with Legacy Code Tool
Note The Legacy Code Tool can interface with C++ functions, but not C++ objects. To
work around this issue so that the tool can interface with C++ objects, see “Legacy Code
Tool Limitations” (Simulink).
If you want to include these types of S-functions in models for which you intend to
generate code, use the tool to generate a TLC block file. The TLC block file specifies how
the generated code for a model calls the existing C or C++ function.
If the S-function depends on files in folders other than the folder containing the S-
function dynamically loadable executable file, use the tool to generate an
11-7
11 Block Authoring and Code Generation for Simulink Coder
For more information, see “Integrate C Functions Using Legacy Code Tool” (Simulink).
• Generate one .cpp file for the inlined S-function. In the Legacy Code Tool data
structure, set the value of the Options.singleCPPMexFile field to true before
generating the S-function source file from your existing C function. For example:
def.Options.singleCPPMexFile = true;
legacy_code('sfcn_cmex_generate', def);
• Generate a source file and a TLC block file for the inlined S-function. For example:
def.Options.singleCPPMexFile = false;
legacy_code('sfcn_cmex_generate', def);
legacy_code('sfcn_tlc_generate', def);
singleCPPMexFile Limitations
• Options.language='C++'
• You use one of the following Simulink objects with the IsAlias property set to true:
• Simulink.Bus
• Simulink.AliasType
• Simulink.NumericType
• The Legacy Code Tool function specification includes a void* or void** to represent
scalar work data for a state argument
• HeaderFiles field of the Legacy Code Tool structure specifies multiple header files
11-8
Import Calls to External Code into Generated Code with Legacy Code Tool
singleCPPMexFile Limitations
• Options.language='C++'
• You use one of the following Simulink objects with the IsAlias property set to true:
• Simulink.Bus
• Simulink.AliasType
• Simulink.NumericType
• The Legacy Code Tool function specification includes a void* or void** to represent
scalar work data for a state argument
• HeaderFiles field of the Legacy Code Tool structure specifies multiple header files
11-9
11 Block Authoring and Code Generation for Simulink Coder
argument, and the name of the Legacy Code Tool data structure as the second argument.
For example:
legacy_code('sfcn_makecfg_generate', lct_spec);
If you use multiple registration files in the same folder and generate an S-function for
each file with a single call to legacy_code, the call to legacy_code that specifies
'sfcn_makecfg_generate' or 'rtwmakecfg_generate' must be common to all
registration files. For more information, see “Handling Multiple Registration Files”
(Simulink).
For example, if you define defs as an array of Legacy Code Tool structures, you call
legacy_code with 'sfcn_makecfg_generate' once.
defs = [defs1(:);defs2(:);defs3(:)];
legacy_code('sfcn_makecfg_generate', defs);
For more information, see “Build Support for S-Functions” (Simulink Coder).
• Registration file
• Compiled dynamically loadable executable
• TLC block file
• sFunction_makecfg.m or rtwmakecfg.m file
• Header, source, and include files on which the generated S-function depends
• Before using the deployed files in a Simulink model, add the folder that contains the S-
function files to the MATLAB path.
• If the Legacy Code Tool data structure registers required files as absolute paths and
the location of the files changes, regenerate the sFunction_makecfg.m or
rtwmakecfg.m file.
11-10
Import Calls to External Code into Generated Code with Legacy Code Tool
Functions provided with the Legacy Code Tool take a specific data structure or array of
structures as the argument. The data structure is initialized by calling the function
legacy_code() using 'initialize' as the first input. After initializing the structure, assign its
properties to values corresponding to the legacy code being integrated. For detailed help
on the properties, call legacy_code('help'). The definition of the legacy C++ class in this
example is:
class adder {
private:
int int_state;
public:
adder();
int add_one(int increment);
int get_val();
};
% rtwdemo_sfun_adder_cpp
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_adder_cpp';
def.StartFcnSpec = 'createAdder()';
def.OutputFcnSpec = 'int32 y1 = adderOutput(int32 u1)';
def.TerminateFcnSpec = 'deleteAdder()';
def.HeaderFiles = {'adder_cpp.h'};
def.SourceFiles = {'adder_cpp.cpp'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
11-11
11 Block Authoring and Code Generation for Simulink Coder
def.Options.language = 'C++';
def.Options.useTlcWithAccel = false;
After you generate the C-MEX S-function source file, to compile the S-function for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', def);
After you compile the S-function and use it in simulation, you can call the function
legacy_code() again. Set the first input to 'sfcn_tlc_generate' to generate a TLC block file
that supports code generation through Simulink® Coder™. If the TLC block file is not
created and you try to generate code for a model that includes the S-function, code
generation fails. The TLC block file for the S-function is: rtwdemo_sfun_adder_cpp.tlc.
legacy_code('sfcn_tlc_generate', def);
After you create the TLC block file, you can call the function legacy_code() again. Set the
first input to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file that supports code
11-12
Import Calls to External Code into Generated Code with Legacy Code Tool
generation through Simulink® Coder™. If the required source and header files for the S-
function are not in the same folder as the S-function, and you want to add these
dependencies in the makefile produced during code generation, generate the
rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', def);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again. Set the first input to 'slblock_generate' to generate a masked S-function block that
is configured to call that S-function. The software places the block in a new model. You
can copy the block to an existing model.
% legacy_code('slblock_generate', def);
open_system('rtwdemo_lct_cpp')
sim('rtwdemo_lct_cpp')
11-13
11 Block Authoring and Code Generation for Simulink Coder
• Modify the class definition for adder in a new file adder_cpp.hpp. Add three new
macros that dynamically allocate a new adder object, invoke the method add_one(),
and free the memory allocated. Each macro takes a pointer to an adder object.
Because each function called by the Legacy Code Tool must have a C-like signature,
11-14
Import Calls to External Code into Generated Code with Legacy Code Tool
the pointer is cached and passed as a void*. Then you must explicitly cast to adder*
in the macro. The new class definition for adder:
#ifndef _ADDER_CPP_
#define _ADDER_CPP_
class adder {
private:
int int_state;
public:
adder(): int_state(0) {};
int add_one(int increment);
int get_val() {return int_state;};
};
#define deleteAdder(work1) \
delete(static_cast<adder*>(*(work1)))
#endif /* _ADDER_CPP_ */
• Update adder_cpp.cpp. With the class modification, instead of one global instance,
each generated S-function manages its own adder object.
#include "adder_cpp.hpp"
• StartFcnSpec calls the macro that allocates a new adder object and caches the
pointer.
def.StartFcnSpec = 'createAdder(void **work1)';
• OutputFcnSpec calls the macro that invokes the method add_one() and provides
the S-function specific adder pointer object.
11-15
11 Block Authoring and Code Generation for Simulink Coder
This example shows how to use the Legacy Code Tool to integrate legacy C functions that
pass their input arguments by value versus address.
Legacy Code Tool functions take a specific data structure or array of structures as the
argument. You can initialize the data structure by calling the function legacy_code() using
'initialize' as the first input. After initializing the structure, assign its properties to values
corresponding to the legacy code being integrated. For detailed help on the properties,
call legacy_code('help'). The prototypes of the legacy functions being called in this
example are:
• FLT filterV1(const FLT signal, const FLT prevSignal, const FLT gain)
• FLT filterV2(const FLT* signal, const FLT prevSignal, const FLT gain)
FLT is a typedef to float. The legacy source code is in the files your_types.h, myfilter.h,
filterV1.c, and filterV2.c.
Note the difference in the OutputFcnSpec defined in the two structures; the first case
specifies that the first input argument is passed by value, while the second case specifies
pass by pointer.
11-16
Import Calls to External Code into Generated Code with Legacy Code Tool
defs = [];
% rtwdemo_sfun_filterV1
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_filterV1';
def.OutputFcnSpec = 'single y1 = filterV1(single u1, single u2, single p1)';
def.HeaderFiles = {'myfilter.h'};
def.SourceFiles = {'filterV1.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
defs = [defs; def];
% rtwdemo_sfun_filterV2
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_filterV2';
def.OutputFcnSpec = 'single y1 = filterV2(single u1[1], single u2, single p1)';
def.HeaderFiles = {'myfilter.h'};
def.SourceFiles = {'filterV2.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
defs = [defs; def];
After you generate the C-MEX S-function source files, to compile the S-functions for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', defs);
11-17
11 Block Authoring and Code Generation for Simulink Coder
mex('rtwdemo_sfun_filterV1.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src',
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_filterV1
### Exit
After you compile the S-functions and use them in simulation, you can call the function
legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate TLC block
files. Block files specify how the generated code for a model calls the legacy code. If you
do not generate TLC block files and you try to generate code for a model that includes the
S-functions, code generation fails. The TLC block files for the S-functions are
rtwdemo_sfun_filterV1.tlc and rtwdemo_sfun_filterV2.tlc.
legacy_code('sfcn_tlc_generate', defs);
After you create the TLC block files, you can call the function legacy_code() again with
the first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support
code generation. If the required source and header files for the S-functions are not in the
same folder as the S-functions, and you want to add these dependencies in the makefile
produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', defs);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to 'slblock_generate' to generate masked S-function blocks
that call the S-functions. The software places the blocks in a new model. From there you
can copy them to an existing model.
11-18
Import Calls to External Code into Generated Code with Legacy Code Tool
legacy_code('slblock_generate', defs);
The model rtwdemo_lct_filter shows integration of the model with the legacy code. The
subsystem TestFilter serves as a harness for the calls to the legacy C functions via the
generate S-functions, with unit delays serving to store the previous output values.
open_system('rtwdemo_lct_filter')
open_system('rtwdemo_lct_filter/TestFilter')
sim('rtwdemo_lct_filter')
11-19
11 Block Authoring and Code Generation for Simulink Coder
This example shows how to use the Legacy Code Tool to integrate legacy C functions that
pass their output as a return argument.
11-20
Import Calls to External Code into Generated Code with Legacy Code Tool
Legacy Code Tool functions take a specific data structure or array of structures as the
argument. You can initialize the data structure by calling the function legacy_code() using
'initialize' as the first input. After initializing the structure, assign its properties to values
corresponding to the legacy code being integrated. For detailed help on the properties,
call legacy_code('help'). The prototype of the legacy functions being called in this example
is:
FLT is a typedef to float. The legacy source code is in the files your_types.h, gain.h, and
gainScalar.c.
% rtwdemo_sfun_gain_scalar
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_gain_scalar';
def.OutputFcnSpec = 'single y1 = gainScalar(single u1, single p1)';
def.HeaderFiles = {'gain.h'};
def.SourceFiles = {'gainScalar.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
legacy_code('sfcn_cmex_generate', def);
After you generate the C-MEX S-function source file, to compile the S-function for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', def);
11-21
11 Block Authoring and Code Generation for Simulink Coder
After you compile the S-function and use it in simulation, you can call the function
legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate a TLC block
file. The block file specifies how the generated code for a model calls the legacy code. If
you do not generate a TLC block file and you try to generate code for a model that
includes the S-function, code generation fails. The TLC block file for the S-function is:
rtwdemo_sfun_gain_scalar.tlc.
legacy_code('sfcn_tlc_generate', def);
After you create the TLC block file, you can call the function legacy_code() again with the
first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support code
generation. If the required source and header files for the S-function are not in the same
folder as the S-function, and you want to add these dependencies in the makefile
produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', def);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to 'slblock_generate' to generate a masked S-function block
that calls that S-function. The software places the block in a new model. From there you
can copy it to an existing model.
legacy_code('slblock_generate', def);
11-22
Import Calls to External Code into Generated Code with Legacy Code Tool
The model rtwdemo_lct_gain shows integration of the model with the legacy code. The
subsystem TestGain serves as a harness for the call to the legacy C function via the
generate S-function.
open_system('rtwdemo_lct_gain')
open_system('rtwdemo_lct_gain/TestGain')
sim('rtwdemo_lct_gain')
Integrate External C Functions That Pass Input and Output Arguments as Signals
with a Fixed-Point Data Type
This example shows how to use the Legacy Code Tool to integrate legacy C functions that
pass their inputs and outputs by using parameters of fixed-point data type.
Legacy Code Tool functions take a specific data structure or array of structures as the
argument. You can initialize the data structure by calling the function legacy_code() using
'initialize' as the first input. After initializing the structure, assign its properties to values
corresponding to the legacy code being integrated. For detailed help on the properties,
call legacy_code('help'). The prototype of the legacy functions being called in this example
is:
myFixpt timesS16(const myFixpt in1, const myFixpt in2, const uint8_T fracLength)
11-23
11 Block Authoring and Code Generation for Simulink Coder
After you generate the C-MEX S-function source file, to compile the S-function for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', def);
11-24
Import Calls to External Code into Generated Code with Legacy Code Tool
After you compile the S-function and use it in simulation, you can call the function
legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate a TLC block
file. The block file specifies how the generated code for a model calls the legacy code. If
you do not generate a TLC block file and you try to generate code for a model that
includes the S-function, code generation fails. The TLC block file for the S-function is:
rtwdemo_sfun_times_s16.tlc.
legacy_code('sfcn_tlc_generate', def);
After you create the TLC block file, you can call the function legacy_code() again with the
first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support code
generation. If the required source and header files for the S-function are not in the same
folder as the S-function, and you want to add these dependencies in the makefile
produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', def);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to 'slblock_generate' to generate a masked S-function block
that calls that S-function. The software places the block in a new model. From there you
can copy it to an existing model.
legacy_code('slblock_generate', def);
11-25
11 Block Authoring and Code Generation for Simulink Coder
The model rtwdemo_lct_fixpt_signals shows integration of the model with the legacy code.
The subsystem TestFixpt serves as a harness for the call to the legacy C function via the
generated S-function.
open_system('rtwdemo_lct_fixpt_signals')
open_system('rtwdemo_lct_fixpt_signals/TestFixpt')
sim('rtwdemo_lct_fixpt_signals')
Integrate legacy C functions that use instance-specific persistent memory by using the
Legacy Code Tool.
Legacy Code Tool functions take a specific data structure or array of structures as the
argument. You can initialize the data structure by calling the function legacy_code() using
'initialize' as the first input. After initializing the structure, assign its properties to values
corresponding to the legacy code being integrated. For detailed help on the properties,
call legacy_code('help'). The prototypes of the legacy functions being called in this
example are:
11-26
Import Calls to External Code into Generated Code with Legacy Code Tool
mem is an instance-specific persistent memory for applying a one integration step delay.
COUNTERBUS is a struct typedef defined in counterbus.h and implemented with a
Simulink.Bus object in the base workspace. The legacy source code is in the files
memory_bus.h, and memory_bus.c.
evalin('base','load rtwdemo_lct_data.mat')
% rtwdemo_sfun_work
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_work';
def.InitializeConditionsFcnSpec = ...
'void memory_bus_init(COUNTERBUS work1[1], int32 p1, int32 p2)';
def.OutputFcnSpec = ...
'void memory_bus_step(COUNTERBUS u1[1], COUNTERBUS work1[1], COUNTERBUS y1[1])';
def.HeaderFiles = {'memory_bus.h'};
def.SourceFiles = {'memory_bus.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
legacy_code('sfcn_cmex_generate', def);
After you generate the C-MEX S-function source file, to compile the S-function for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', def);
11-27
11 Block Authoring and Code Generation for Simulink Coder
After you compile the S-function and use it in simulation, you can call the function
legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate a TLC block
file. The block file specifies how the generated code for a model calls the legacy code. If
you do not generate a TLC block file and you try to generate code for a model that
includes the S-function, code generation fails. The TLC block file for the S-function is:
rtwdemo_sfun_work.tlc.
legacy_code('sfcn_tlc_generate', def);
After you create the TLC block file, you can call the function legacy_code() again with the
first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support code
generation. If the required source and header files for the S-function are not in the same
folder as the S-function, and you want to add these dependencies in the makefile
produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', def);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to 'slblock_generate' to generate a masked S-function block
that calls that S-function. The software places the block in a new model. From there you
can copy it to an existing model.
legacy_code('slblock_generate', def);
11-28
Import Calls to External Code into Generated Code with Legacy Code Tool
The model rtwdemo_lct_work shows integration of the model with the legacy code. The
subsystem memory_bus serves as a harness for the call to the legacy C function.
open_system('rtwdemo_lct_work')
open_system('rtwdemo_lct_work/memory_bus')
sim('rtwdemo_lct_work')
Integrate legacy C functions with structure arguments that use Simulink® buses with the
Legacy Code Tool.
Legacy Code Tool functions take a specific data structure or array of structures as the
argument. You can initialize the data structure by calling the function legacy_code() using
'initialize' as the first input. After initializing the structure, assign its properties to values
corresponding to the legacy code being integrated. For detailed help on the properties,
call legacy_code('help'). The prototype of the legacy functions being called in this example
is:
11-29
11 Block Authoring and Code Generation for Simulink Coder
evalin('base','load rtwdemo_lct_data.mat')
% rtwdemo_sfun_counterbus
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_counterbus';
def.OutputFcnSpec = ...
'void counterbusFcn(COUNTERBUS u1[1], int32 u2, COUNTERBUS y1[1], int32 y2[1])';
def.HeaderFiles = {'counterbus.h'};
def.SourceFiles = {'counterbus.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
legacy_code('sfcn_cmex_generate', def);
After you generate the C-MEX S-function source file, to compile the S-function for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', def);
11-30
Import Calls to External Code into Generated Code with Legacy Code Tool
After you compile the S-function and use it in simulation, you can call the function
legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate a TLC block
file. The block file specifies how the generated code for a model calls the legacy code. If
you do not generate a TLC block file and you try to generate code for a model that
includes the S-function, code generation fails. The TLC block file for the S-function is:
rtwdemo_sfun_counterbus.tlc.
legacy_code('sfcn_tlc_generate', def);
After you create the TLC block file, you can call the function legacy_code() again with the
first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support code
generation. If the required source and header files for the S-function are not in the same
folder as the S-function, and you want to add these dependencies in the makefile
produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', def);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to 'slblock_generate' to generate a masked S-function block
that calls that S-function. The software places the block in a new model. From there you
can copy it to an existing model.
legacy_code('slblock_generate', def);
The model rtwdemo_lct_bus shows integration of the model with the legacy code. The
subsystem TestCounter serves as a harness for the call to the legacy C function.
open_system('rtwdemo_lct_bus')
open_system('rtwdemo_lct_bus/TestCounter')
sim('rtwdemo_lct_bus')
11-31
11 Block Authoring and Code Generation for Simulink Coder
Integrate External C Functions That Pass Input and Output Arguments as Signals
with Complex Data
Integrate legacy C functions using complex signals with the Legacy Code Tool.
Legacy Code Tool functions take a specific data structure or array of structures as the
argument. You can initialize the data structure by calling the function legacy_code() using
'initialize' as the first input. After initializing the structure, assign its properties to values
corresponding to the legacy code being integrated. For detailed help on the properties,
call legacy_code('help'). The prototype of the legacy functions being called in this example
is:
creal_T is the complex representation of a double. The legacy source code is in the files
cplxgain.h, and cplxgain.c.
% rtwdemo_sfun_gain_scalar
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_cplx_gain';
def.OutputFcnSpec = ...
['void cplx_gain(complex<double> u1[1], '...
11-32
Import Calls to External Code into Generated Code with Legacy Code Tool
legacy_code('sfcn_cmex_generate', def);
After you generate the C-MEX S-function source file, to compile the S-function for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', def);
After you compile the S-function and use it in simulation, you can call the function
legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate a TLC block
file. The block file specifies how the generated code for a model calls the legacy code. If
you do not generate a TLC block file and you try to generate code for a model that
includes the S-function, code generation fails. The TLC block file for the S-function is:
rtwdemo_sfun_cplx_gain.tlc.
legacy_code('sfcn_tlc_generate', def);
11-33
11 Block Authoring and Code Generation for Simulink Coder
After you create the TLC block file, you can call the function legacy_code() again with the
first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support code
generation. If the required source and header files for the S-function are not in the same
folder as the S-function, and you want to add these dependencies in the makefile
produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', def);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to 'slblock_generate' to generate a masked S-function block
that calls that S-function. The software places the block in a new model. From there you
can copy it to an existing model.
legacy_code('slblock_generate', def);
The model rtwdemo_lct_cplxgain shows integration of the model with the legacy code.
The subsystem complex_gain serves as a harness for the call to the legacy C function via
the generate S-function.
if isempty(find_system('SearchDepth',0,'Name','rtwdemo_lct_cplxgain'))
open_system('rtwdemo_lct_cplxgain')
open_system('rtwdemo_lct_cplxgain/complex_gain')
sim('rtwdemo_lct_cplxgain')
end
11-34
Import Calls to External Code into Generated Code with Legacy Code Tool
This example shows how to use the Legacy Code Tool to integrate legacy C functions
whose arguments have inherited dimensions.
Legacy Code Tool functions take a specific data structure or array of structures as the
argument. You can initialize the data structure by calling the function legacy_code() using
'initialize' as the first input. After initializing the structure, assign its properties to values
corresponding to the legacy code being integrated. For detailed help on the properties,
call legacy_code('help'). The prototypes of the legacy functions being called in this
example are:
• void mat_add(real_T *u1, real_T *u2, int32_T nbRows, int32_T nbCols, real_T *y1)
• void mat_mult(real_T *u1, real_T *u2, int32_T nbRows1, int32_T nbCols1, int32_T
nbCols2, real_T *y1)
real_T is a typedef to double, and int32_T is a typedef to a 32-bit integer. The legacy
source code is in the files mat_ops.h, and mat_ops.c.
defs = [];
% rtwdemo_sfun_mat_add
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_mat_add';
11-35
11 Block Authoring and Code Generation for Simulink Coder
% rtwdemo_sfun_mat_mult
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_mat_mult';
def.OutputFcnSpec = ['void mat_mult(double u1[p1][p2], double u2[p2][p3], '...
'int32 p1, int32 p2, int32 p3, double y1[p1][p3])'];
def.HeaderFiles = {'mat_ops.h'};
def.SourceFiles = {'mat_ops.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
defs = [defs; def];
After you generate the C-MEX S-function source files, to compile the S-functions for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', defs);
11-36
Import Calls to External Code into Generated Code with Legacy Code Tool
After you compile the S-functions and use them in simulation, you can call the function
legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate TLC block
files. Block files specify how the generated code for a model calls the legacy code. If you
do not generate TLC block files and you try to generate code for a model that includes the
S-functions, code generation fails. The TLC block files for the S-functions are
rtwdemo_sfun_mat_add.tlc and rtwdemo_sfun_mat_mult.tlc.
legacy_code('sfcn_tlc_generate', defs);
After you create the TLC block files, you can call the function legacy_code() again with
the first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support
code generation. If the required source and header files for the S-functions are not in the
same folder as the S-functions, and you want to add these dependencies in the makefile
produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', defs);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to 'slblock_generate' to generate masked S-function blocks
that call the S-functions. The software places the blocks in a new model. From there you
can copy them to an existing model
legacy_code('slblock_generate', defs);
11-37
11 Block Authoring and Code Generation for Simulink Coder
The model rtwdemo_lct_inherit_dims shows integration of the model with the legacy code.
The subsystem TestMatOps serves as a harness for the calls to the legacy C functions,
with unit delays serving to store the previous output values.
open_system('rtwdemo_lct_inherit_dims')
open_system('rtwdemo_lct_inherit_dims/TestMatOps')
sim('rtwdemo_lct_inherit_dims')
11-38
Import Calls to External Code into Generated Code with Legacy Code Tool
Integrate legacy C functions that have start and terminate actions by using the Legacy
Code Tool.
Legacy Code Tool functions take a specific data structure or array of structures as the
argument. You can initialize the data structure by calling the function legacy_code() using
'initialize' as the first input. After initializing the structure, assign its properties to values
corresponding to the legacy code being integrated. For detailed help on the properties,
11-39
11 Block Authoring and Code Generation for Simulink Coder
call legacy_code('help'). The prototypes of the legacy functions being called in this
example are:
The legacy source code is in the files your_types.h, fault.h, and fault.c.
% rtwdemo_sfun_fault
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_fault';
def.InitializeConditionsFcnSpec = 'initFaultCounter(uint32 work2[1])';
def.StartFcnSpec = 'openLogFile(void **work1)';
def.OutputFcnSpec = ...
'incAndLogFaultCounter(void *work1, uint32 work2[1], double u1)';
def.TerminateFcnSpec = 'closeLogFile(void **work1)';
def.HeaderFiles = {'fault.h'};
def.SourceFiles = {'fault.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
def.Options.useTlcWithAccel = false;
legacy_code('sfcn_cmex_generate', def);
After you generate the C-MEX S-function source file, to compile the S-function for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', def);
11-40
Import Calls to External Code into Generated Code with Legacy Code Tool
mex('-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src', '-IC:\TEMP\Bdoc18a_815039_1
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
mex('rtwdemo_sfun_fault.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src', '-I
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_fault
### Exit
After you compile the S-function and use it in simulation, you can call the function
legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate a TLC block
file. The block file specifies how the generated code for a model calls the legacy code. If
you do not generate a TLC block file and you try to generate code for a model that
includes the S-function, code generation fails. The TLC block file for the S-function is:
rtwdemo_sfun_fault.tlc.
legacy_code('sfcn_tlc_generate', def);
After you create the TLC block file, you can call the function legacy_code() again with the
first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support code
generation. If the required source and header files for the S-function are not in the same
folder as the S-function, and you want to add these dependencies in the makefile
produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', def);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to 'slblock_generate' to generate a masked S-function block
that calls that S-function. The software places the block in a new model. From there you
can copy it to an existing model.
legacy_code('slblock_generate', def);
11-41
11 Block Authoring and Code Generation for Simulink Coder
The model rtwdemo_lct_start_term shows integration of the model with the legacy code.
The subsystem TestFixpt serves as a harness for the call to the legacy C function, and the
scope compares the output of the function with the output of the built-in Simulink®
product block; the results should be identical.
open_system('rtwdemo_lct_start_term')
open_system('rtwdemo_lct_start_term/TestFault')
sim('rtwdemo_lct_start_term')
This example shows how to use the Legacy Code Tool to integrate legacy C functions with
multi-dimensional Signals.
Legacy Code Tool functions take a specific data structure or array of structures as the
argument. You can initialize the data structure by calling the function legacy_code() using
'initialize' as the first input. After initializing the structure, assign its properties to values
corresponding to the legacy code being integrated. For detailed help on the properties,
call legacy_code('help'). The prototype of the legacy functions being called in this example
is:
11-42
Import Calls to External Code into Generated Code with Legacy Code Tool
void array3d_add(real_T *y1, real_T *u1, real_T *u2, int32_T nbRows, int32_T nbCols,
int32_T nbPages);
real_T is a typedef to double, and int32_T is a typedef to a 32-bit integer. The legacy
source code is in the files ndarray_ops.h, and ndarray_ops.c.
% rtwdemo_sfun_ndarray_add
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_ndarray_add';
def.OutputFcnSpec =...
['void array3d_add(double y1[size(u1,1)][size(u1,2)][size(u1,3)], ',...
'double u1[][][], double u2[][][], ' ...
'int32 size(u1,1), int32 size(u1,2), int32 size(u1,3))'];
def.HeaderFiles = {'ndarray_ops.h'};
def.SourceFiles = {'ndarray_ops.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
y1 is a 3-D output signal of same dimensions as the 3-D input signal u1. Note that the last
3 arguments passed to the legacy function correspond to the number of element in each
dimension of the 3-D input signal u1.
legacy_code('sfcn_cmex_generate', def);
After you generate the C-MEX S-function source file, to compile the S-function for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', def);
11-43
11 Block Authoring and Code Generation for Simulink Coder
mex('rtwdemo_sfun_ndarray_add.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_ndarray_add
### Exit
After you compile the S-function and use it in simulation, you can call the function
legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate a TLC block
file. The block file specifies how the generated code for a model calls the legacy code. If
you do not generate a TLC block file and you try to generate code for a model that
includes the S-function, code generation fails. The TLC block file for the S-function is:
rtwdemo_sfun_ndarray_add.tlc.
legacy_code('sfcn_tlc_generate', def);
After you create the TLC block file, you can call the function legacy_code() again with the
first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support code
generation. If the required source and header files for the S-function are not in the same
folder as the S-function, and you want to add these dependencies in the makefile
produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', def);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to 'slblock_generate' to generate a masked S-function block
that calls that S-function. The software places the block in a new model. From there you
can copy it to an existing model.
legacy_code('slblock_generate', def);
11-44
Import Calls to External Code into Generated Code with Legacy Code Tool
The model rtwdemo_lct_ndarray shows integration of the model with the legacy code. The
subsystem ndarray_add serves as a harness for the call to the legacy C function.
open_system('rtwdemo_lct_ndarray')
open_system('rtwdemo_lct_ndarray/ndarray_add')
sim('rtwdemo_lct_ndarray')
This example shows how to use the Legacy Code Tool to integrate legacy C functions with
the block's sample time specified, inherited and parameterized.
Legacy Code Tool functions take a specific data structure or array of structures as the
argument. You can initialize the data structure by calling the function legacy_code() using
'initialize' as the first input. After initializing the structure, assign its properties to values
11-45
11 Block Authoring and Code Generation for Simulink Coder
corresponding to the legacy code being integrated. For detailed help on the properties,
call legacy_code('help'). The prototype of the legacy functions being called in this example
is:
FLT is a typedef to float. The legacy source code is in the files your_types.h, gain.h, and
gainScalar.c.
defs = [];
% rtwdemo_sfun_st_inherited
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_st_inherited';
def.OutputFcnSpec = 'single y1 = gainScalar(single u1, single p1)';
def.HeaderFiles = {'gain.h'};
def.SourceFiles = {'gainScalar.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
defs = [defs; def];
% rtwdemo_sfun_st_fixed
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_st_fixed';
def.OutputFcnSpec = 'single y1 = gainScalar(single u1, single p1)';
def.HeaderFiles = {'gain.h'};
def.SourceFiles = {'gainScalar.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
def.SampleTime = [2 1];
defs = [defs; def];
% rtwdemo_sfun_st_parameterized
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_st_parameterized';
def.OutputFcnSpec = 'single y1 = gainScalar(single u1, single p1)';
def.HeaderFiles = {'gain.h'};
def.SourceFiles = {'gainScalar.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
def.SampleTime = 'parameterized';
defs = [defs; def];
11-46
Import Calls to External Code into Generated Code with Legacy Code Tool
legacy_code('sfcn_cmex_generate', defs);
After you generate the C-MEX S-function source files, to compile the S-functions for
simulation with Simulink®, call the function legacy_code() again with the first input set to
'compile'.
legacy_code('compile', defs);
11-47
11 Block Authoring and Code Generation for Simulink Coder
After you compile the S-functions and use them in simulation, you can call the function
legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate TLC block
files. Block files specify how the generated code for a model calls the legacy code. If you
do not generate TLC block files and you try to generate code for a model that includes the
S-functions, code generation fails. The TLC block files for the S-functions are
rtwdemo_sfun_st_inherited.tlc and rtwdemo_sfun_st_fixed.tlc.
rtwdemo_sfun_st_parameterized.tlc.
legacy_code('sfcn_tlc_generate', defs);
After you create the TLC block files, you can call the function legacy_code() again with
the first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support
code generation. If the required source and header files for the S-functions are not in the
same folder as the S-functions, and you want to add these dependencies in the makefile
produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', defs);
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to 'slblock_generate' to generate masked S-function blocks
that call the S-functions. The software places the blocks in a new model. From there you
can copy them to an existing model.
legacy_code('slblock_generate', defs);
11-48
Import Calls to External Code into Generated Code with Legacy Code Tool
The model rtwdemo_lct_sampletime shows integration of the model with the legacy code.
The subsystem sample_time serves as a harness for the calls to the legacy C functions,
with unit delays serving to store the previous output values.
open_system('rtwdemo_lct_sampletime')
open_system('rtwdemo_lct_sampletime/sample_time')
sim('rtwdemo_lct_sampletime')
11-49
11 Block Authoring and Code Generation for Simulink Coder
See Also
legacy_code
Related Examples
• “Integrate C Functions Using Legacy Code Tool” (Simulink)
• “Call External C Code from Model and Generated Code”
11-50
External Code Integration Examples
Insert External C and C++ Code Into Stateflow Charts for Code
Generation
This example shows how to use Stateflow® to integrate external code into a model.
Open Model
model='rtwdemo_sfcustom';
open_system(model);
11-51
11 Block Authoring and Code Generation for Simulink Coder
Integrate Code
1. The example includes the custom header file my_header.c and the custom source file
my_function.c.
2. On the Configuration Parameters dialog box Simulation Target pane, enter the
custom source file and header file. Also enter additional include directories and source
files.
In this example, the custom header file my_header.c and source file my_function.c
are entered on the Simulation Target pane.
3. If you generate code with Simulink Coder®, on the Configuration Parameters dialog
box Code Generation > Custom Code pane, enter the same custom source file and
header file. Also enter the same additional include directories and source files.
In this example, the custom header file my_header.c and source file my_function.c
are entered on the Code Generation > Custom Code pane.
Generate Code
rtwbuild('rtwdemo_sfcustom')
To call custom C code functions from Stateflow, use the same syntax as graphical function
calls: result = my_custom_function(in_args);
To call variables of structure type, use the dot notation: result = my_var.my_field;
11-52
External Code Integration Examples
See Also
Close Model
rtwdemoclean;
close_system('rtwdemo_sfcustom',0);
open_system('rtwdemo_slcustcode')
11-53
11 Block Authoring and Code Generation for Simulink Coder
2. Open the Model Configuration Parameters dialog box and navigate to the Custom
Code pane.
3. Examine the settings for parameters Source file and Initialize function.
11-54
External Code Integration Examples
• Source file specifies a comment and sets the variable GLOBAL_INT2 to -1.
• Initialize function initializes the variable GLOBAL_INT2 to 1.
5. Double-click the Model Source block. The Top of Model Source field specifies that the
code generator declare the variable GLOBAL_INT1 and set it to 0 at the top of the
generated file rtwdemo_slcustcode.c.
6. Open the triggered subsystem Amplifier. The subsystem includes the System
Outputs block. The code generator places code that you specify in that block in the
generated code for the nearest parent atomic subsystem. In this case, the code generator
places the external code in the generated code for the Amplifier subsystem. The
external code:
• Declares the pointer variable *intPtr and initializes it with the value of variable
GLOBAL_INT1.
• Sets the pointer variable to -1 during execution.
• Resets the pointer variable to 0 before exiting.
8. Examine the code in the generated source file rtwdemo_slcustcode.c. At the top of
the file, after the #include statements, you find the following declaration code. The
example specifies the first declaration with the Source file configuration parameter and
the second declaration with the Model Source block.
int_T GLOBAL_INT1 = 0;
The Output function for the Amplifier subsystem includes the following code, which
shows the external code integrated with generated code that applies the gain. The
example specifies the three lines of code for the pointer variable with the System Outputs
block in the Amplifier subsystem.
*intPtr = -1;
11-55
11 Block Authoring and Code Generation for Simulink Coder
*intPtr = 0;
The following assignment appears in the model initialize entry-point function. The
example specifies this assignment with the Initialize function configuration parameter.
GLOBAL_INT2 = 1;
open_system('rtwdemo_slcustcode')
11-56
External Code Integration Examples
2. Open the Model Configuration Parameters dialog box and navigate to the Custom
Code pane.
3. Examine the settings for parameters Source file and Initialize function.
11-57
11 Block Authoring and Code Generation for Simulink Coder
• Source file specifies a comment and sets the variable GLOBAL_INT2 to -1.
• Initialize function initializes the variable GLOBAL_INT2 to 1.
5. Double-click the Model Source block. The Top of Model Source field specifies that the
code generator declare the variable GLOBAL_INT1 and set it to 0 at the top of the
generated file rtwdemo_slcustcode.c.
6. Open the triggered subsystem Amplifier. The subsystem includes the System
Outputs block. The code generator places code that you specify in that block in the
generated code for the nearest parent atomic subsystem. In this case, the code generator
places the external code in the generated code for the Amplifier subsystem. The
external code:
• Declares the pointer variable *intPtr and initializes it with the value of variable
GLOBAL_INT1.
• Sets the pointer variable to -1 during execution.
• Resets the pointer variable to 0 before exiting.
8. Examine the code in the generated source file rtwdemo_slcustcode.c. At the top of
the file, after the #include statements, you find the following declaration code. The
example specifies the first declaration with the Source file configuration parameter and
the second declaration with the Model Source block.
int_T GLOBAL_INT1 = 0;
The Output function for the Amplifier subsystem includes the following code, which
shows the external code integrated with generated code that applies the gain. The
example specifies the three lines of code for the pointer variable with the System Outputs
block in the Amplifier subsystem.
*intPtr = -1;
11-58
External Code Integration Examples
*intPtr = 0;
The following assignment appears in the model initialize entry-point function. The
example specifies this assignment with the Initialize function configuration parameter.
GLOBAL_INT2 = 1;
Insert External C and C++ Code Into Stateflow Charts for Code
Generation
This example shows how to use Stateflow® to integrate external code into a model.
Open Model
model='rtwdemo_sfcustom';
open_system(model);
11-59
11 Block Authoring and Code Generation for Simulink Coder
Integrate Code
1. The example includes the custom header file my_header.c and the custom source file
my_function.c.
2. On the Configuration Parameters dialog box Simulation Target pane, enter the
custom source file and header file. Also enter additional include directories and source
files.
In this example, the custom header file my_header.c and source file my_function.c
are entered on the Simulation Target pane.
3. If you generate code with Simulink Coder®, on the Configuration Parameters dialog
box Code Generation > Custom Code pane, enter the same custom source file and
header file. Also enter the same additional include directories and source files.
In this example, the custom header file my_header.c and source file my_function.c
are entered on the Code Generation > Custom Code pane.
Generate Code
rtwbuild('rtwdemo_sfcustom')
To call custom C code functions from Stateflow, use the same syntax as graphical function
calls: result = my_custom_function(in_args);
To call variables of structure type, use the dot notation: result = my_var.my_field;
11-60
External Code Integration Examples
See Also
Close Model
rtwdemoclean;
close_system('rtwdemo_sfcustom',0);
11-61
11 Block Authoring and Code Generation for Simulink Coder
Alternatively, you can right-click the subsystem and select C/C++ Code > Generate
S-Function from the subsystem block's context menu.
3 The Generate S-Function window is displayed (see the next figure). This window
shows variables (or data objects) that are referenced as block parameters in the
subsystem, and lets you declare them as tunable.
11-62
Generate S-Function from Subsystem
When you select a parameter in the upper pane, the lower pane shows the blocks that
reference the parameter, and the parent system of each such block.
11-63
11 Block Authoring and Code Generation for Simulink Coder
6 The model window contains an S-Function block with the same name as the
subsystem from which the block was generated (in this example, SourceSubsys).
Optionally, you can save the generated model containing the generated block.
7 The generated code for the S-Function block is stored in the current working folder.
The following files are written to the top level folder:
The source code for the S-function is written to the subfolder subsys_sfcn_rtw.
The top-level .c or .cpp file is a stub file that simply contains an include directive
that you can use to interface other C/C++ code to the generated code.
Note For a list of files required to deploy your S-Function block for simulation or
code generation, see “Required Files for S-Function Deployment” on page 49-60.
8 The generated S-Function block has inports and outports whose widths and sample
times correspond to those of the original model.
The following code, from the mdlOutputs routine of the generated S-function code (in
SourceSubsys_sf.c), shows how the tunable variable K is referenced by using calls to
the MEX API.
static void mdlOutputs(SimStruct *S, int_T tid)
...
11-64
Generate S-Function from Subsystem
• In automatic S-function generation, the Use Value for Tunable Parameters option is
cleared or at the command line is set to 'off'.
• Use a MEX S-function wrapper only in the MATLAB version in which the wrapper is
created.
Macro Parameters
Suppose that you apply a custom storage class such as Define to a
Simulink.Parameter object so that the parameter appears as a macro in the generated
code. If you use the parameter object inside a subsystem from which you generate an ERT
S-function, you cannot select the parameter object as a tunable parameter. Instead, the S-
function code generator applies the custom storage class to the parameter object. This
generation of macros in the S-function code allows you to generate S-functions from
subsystems that contain variant elements, such as Variant Subsystem blocks, that you
configure to produce preprocessor conditionals in the generated code. However, you
cannot change the value of the parameter during simulation of the S-function.
To select the parameter object as a tunable parameter, apply a different storage class or
custom storage class. Custom storage classes that treat parameters as macros include
Define, ImportedDefine, CompilerFlag, and custom storage classes that you create
by setting Data initialization to Macro in the Custom Storage Class Designer. If you use
a non-macro storage class or custom storage class, you cannot use the parameter object
as a variant control variable and generate preprocessor conditionals.
If you apply a custom storage class that treats the parameter object as an imported
macro, provide the macro definition before you generate the ERT S-function. For
example, suppose you apply the custom storage class ImportedDefine to a
Simulink.Parameter object, and use the parameter object as a variant control variable
in the subsystem. If you set the custom attribute HeaderFile to 'myHdr.h', when you
generate the S-function, place the custom header file myHdr.h in the current folder. The
11-65
11 Block Authoring and Code Generation for Simulink Coder
generated S-function uses the macro value from your header file instead of the value from
the Value property of the parameter object.
To use a macro that you define through a compiler option, for example by applying the
custom storage class CompilerFlag, use the model configuration parameter
Configuration Parameters > Code Generation > Custom Code > Additional build
information > Defines to specify the compiler option. For more information, see Code
Generation Pane: Custom Code: Additional Build Information: Defines (Simulink Coder).
See Also
legacy_code
More About
• “S-Functions and Code Generation” on page 11-2
• “Import Calls to External Code into Generated Code with Legacy Code Tool” on page
11-7
• “Build S-Functions Automatically” (Simulink)
11-66
Write S-Function and TLC Files By Hand
Noninlined S-functions are identified by the absence of an sfunction.tlc file for your
S-function. The filename varies depending on your platform. For example, on a 64–bit
Microsoft Windows system, the file name would be sfunction.mexw64. Type mexext in
the MATLAB Command Window to see which extension your system uses.
• Use only MATLAB API function that the code generator supports, which include:
mxGetEps
mxGetInf
mxGetM
mxGetN
mxGetNaN
mxGetPr
mxGetScalar
mxGetString
mxIsEmpty
mxIsFinite
11-67
11 Block Authoring and Code Generation for Simulink Coder
mxIsInf
• MEX library calls are not supported in generated code. To use such calls in MEX-file
and not in the generated code, conditionalize the code as follows:
#ifdef MATLAB_MEX_FILE
#endif
You can then use the following call to set_param to include the required modules:
set_param(sfun_block, "SFunctionModules","sfun_module1 sfun_module2")
When you are ready to generate code, force the code generator to rebuild the top
model, as explained in “Control Regeneration of Top Model Code” (Simulink Coder).
• Double precision
• Characters in scalars, vectors, or 2-D matrices
For more flexibility in the type of parameters you can supply to S-functions or the
operations in the S-function, inline your S-function and consider using an mdlRTW S-
function routine.
Use of other functions from the MATLAB matrix.h API or other MATLAB APIs, such as
mex.h and mat.h, is not supported. If you call unsupported APIs from an S-function
11-68
Write S-Function and TLC Files By Hand
If you use mxGetPr on an empty matrix, the function does not return NULL; rather, it
returns a random value. Therefore, you should protect calls to mxGetPr with mxIsEmpty.
Creating S-functions using an S-function wrapper allows you to insert C/C++ code
algorithms in Simulink models and the generated code with little or no change to your
original C/C++ function. A MEX S-function wrapper is an S-function that calls code that
resides in another module. A TLC S-function wrapper is a TLC file that specifies how the
code generator should call your code (the same code that was called from the C MEX S-
function wrapper).
Note A MEX S-function wrapper must only be used in the MATLAB version in which the
wrapper is created.
Suppose you have an algorithm (that is, a C function) called my_alg that resides in the
file my_alg.c. You can integrate my_alg into a Simulink model by creating a MEX S-
function wrapper (for example, wrapsfcn.c). Once this is done, a Simulink model can
call my_alg from an S-Function block. However, the Simulink S-function contains a set of
11-69
11 Block Authoring and Code Generation for Simulink Coder
empty functions that the Simulink engine requires for various API-related purposes. For
example, although only mdlOutputs calls my_alg, the engine calls mdlTerminate as
well, even though this S-function routine performs no action.
You can integrate my_alg into generated code (that is, embed the call to my_alg in the
generated code) by creating a TLC S-function wrapper (for example, wrapsfcn.tlc).
The advantage of creating a TLC S-function wrapper is that the empty function calls can
be eliminated and the overhead of executing the mdlOutputs function and then the
my_alg function can be eliminated.
Wrapper S-functions are useful when you are creating new algorithms that are procedural
in nature or when you are integrating legacy code into a Simulink model. However, if you
want to create code that is
then you must create a fully inlined TLC file for your S-function.
11-70
Write S-Function and TLC Files By Hand
wrapsfcn.c
...
mdlOutputs(...) In the TLC wrapper
{ version of the S-function,
... mdlOutputs in
my_alg(); wrapper.exe calls my_alg.
}
mdlOutputs in
my_alg.c
wrapsfcn.mex ...
calls external
function my_alg. real_T my_alg(real_T u)
{
...
y=f(u);
}
*The dotted line is the path taken if the S-function does not have a TLC wrapper
file. If there is no TLC wrapper file, the generated code calls mdlOutputs.
Using an S-function wrapper to import algorithms in your Simulink model means that the
S-function serves as an interface that calls your C/C++ algorithms from mdlOutputs. S-
function wrappers have the advantage that you can quickly integrate large standalone
C /C++ programs into your model without having to make changes to the code.
11-71
11 Block Authoring and Code Generation for Simulink Coder
There are two files associated with the wrapsfcn block, the S-function wrapper and the
C/C++ code that contains the algorithm. The S-function wrapper code for wrapsfcn.c
appears below. The first three statements do the following:
1 Defines the name of the S-function (what you enter in the Simulink S-Function block
dialog).
2 Specifies that the S-function is using the level 2 format.
3 Provides access to the SimStruct data structure, which contains pointers to data
used during simulation and code generation and defines macros that store data in
and retrieve data from the SimStruct.
/*
* mdlInitializeSizes - initialize the sizes array
*/
static void mdlInitializeSizes(SimStruct *S)
{
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetNumSampleTimes( S, 1);
}
/*
11-72
Write S-Function and TLC Files By Hand
/*
* mdlOutputs - compute the outputs by calling my_alg, which
* resides in another module, my_alg.c
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
real_T *y = ssGetOutputPortRealSignal(S,0);
*y = my_alg(*uPtrs[0]); /* Call my_alg in mdlOutputs */
}
/*
* mdlTerminate - called when the simulation is terminated.
*/
static void mdlTerminate(SimStruct *S)
{
}
The S-function routine mdlOutputs contains a function call to my_alg, which is the C
function containing the algorithm that the S-function performs. This is the code for
my_alg.c:
#ifdef MATLAB_MEX_FILE
#include "tmwtypes.h"
#else
#include "rtwtypes.h"
#endif
real_T my_alg(real_T u)
{
return(u * 2.0);
}
For more information, see “Manage Build Process File Dependencies” (Simulink Coder).
The wrapper S-function wrapsfcn calls my_alg, which computes u * 2.0. To build
wrapsfcn.mex, use the following command:
mex wrapsfcn.c my_alg.c
11-73
11 Block Authoring and Code Generation for Simulink Coder
This topic describes how to inline the call to my_alg in the mdlOutputs section of the
generated code. In the above example, the call to my_alg is embedded in the
mdlOutputs section as
*y = my_alg(*uPtrs[0]);
When you are creating a TLC S-function wrapper, the goal is to embed the same type of
call in the generated code.
It is instructive to look at how the code generator executes S-functions that are not
inlined. A noninlined S-function is identified by the absence of the file sfunction.tlc
and the existence of sfunction.mex. When generating code for a noninlined S-function,
the code generator produces a call to mdlOutputs through a function pointer that, in this
example, then calls my_alg.
The wrapper example contains one S-function, wrapsfcn.mex. You must compile and
link an additional module, my_alg, with the generated code. To do this, specify
set_param('wrapper/S-Function','SFunctionModules','my_alg')
The code generated when using grt.tlc as the system target file without
wrapsfcn.tlc is
<Generated code comments for wrapper model with noninlined wrapsfcn S-function>
#include <math.h>
#include <string.h>
#include "wrapper.h"
#include "wrapper.prm"
11-74
Write S-Function and TLC Files By Hand
/* Terminate function */
void mdlTerminate(void)
{
/* Level2 S-Function Block: <Root>/S-Function (wrapsfcn) */
{
/* Noninlined S-functions require a SimStruct object and
* the call to S-function routine mdlTerminate
*/
SimStruct *rts = ssGetSFunction(rtS, 0);
sfcnTerminate(rts);
}
}
#include "wrapper.reg"
/* [EOF] wrapper.c */
In addition to the overhead outlined above, the wrapper.reg generated file contains the
initialization of the SimStruct for the wrapper S-Function block. There is one child
SimStruct for each S-Function block in your model. You can significantly reduce this
overhead by creating a TLC wrapper for the S-function.
How to Inline
The generated code makes the call to your S-function, wrapsfcn.c, in mdlOutputs by
using this code:
SimStruct *rts = ssGetSFunction(rtS, 0);
sfcnOutputs(rts, tid);
This call has computational overhead associated with it. First, the Simulink engine
creates a SimStruct data structure for the S-Function block. Second, the code generator
constructs a call through a function pointer to execute mdlOutputs, then mdlOutputs
calls my_alg. By inlining the call to your C/C++ algorithm, my_alg, you can eliminate
11-75
11 Block Authoring and Code Generation for Simulink Coder
both the SimStruct and the extra function call, thereby improving the efficiency and
reducing the size of the generated code.
Inlining a wrapper S-function requires an sfunction.tlc file for the S-function (see the
“Target Language Compiler” (Simulink Coder) for details). The TLC file must contain the
function call to my_alg. The following figure shows the relationships between the
algorithm, the wrapper S-function, and the sfunction.tlc file.
To inline this call, you have to place your function call in an sfunction.tlc file with the
same name as the S-function (in this example, wrapsfcn.tlc). This causes the Target
Language Compiler to override the default method of placing calls to your S-function in
the generated code.
11-76
Write S-Function and TLC Files By Hand
%endfunction %% Outputs
The first section of this code inlines the wrapsfcn S-Function block and generates the
code in C:
%implements "wrapsfcn" "C"
The next task is to tell the code generator that the routine my_alg needs to be declared
external in the generated wrapper.h file for any wrapsfcn S-Function blocks in the
model. You only need to do this once for all wrapsfcn S-Function blocks, so use the
BlockTypeSetup function. In this function, you tell the Target Language Compiler to
create a buffer and cache the my_alg as extern in the wrapper.h generated header
file.
The final step is the inlining of the call to the function my_alg. This is done by the
Outputs function. In this function, you access the block's input and output and place a
direct call to my_alg. The call is embedded in wrapper.c.
The code generated when you inline your wrapper S-function is similar to the default
generated code. The mdlTerminate function does not contain a call to an empty function
and the mdlOutputs function now directly calls my_alg.
void mdlOutputs(int_T tid)
{
/* Sin Block: <Root>/Sin */
rtB.Sin = rtP.Sin.Amplitude *
sin(rtP.Sin.Frequency * ssGetT(rtS) + rtP.Sin.Phase);
11-77
11 Block Authoring and Code Generation for Simulink Coder
In addition, wrapper.reg does not create a child SimStruct for the S-function because
the generated code is calling my_alg directly. This eliminates over 1 KB of memory
usage.
use
%<y> = 2.0 * %<u>;
The Target Language Compiler has replaced the call to my_alg with the algorithm itself.
Multiport S-Function
11-78
Write S-Function and TLC Files By Hand
As an example of how to use the mdlRTW function, this topic discusses the steps you must
take to create a direct-index lookup S-function. Lookup tables are collections of ordered
data points of a function. Typically, these tables use some interpolation scheme to
approximate values of the associated function between known data points. To incorporate
the example lookup table algorithm into a Simulink model, the first step is to write an S-
function that executes the algorithm in mdlOutputs. To produce the most efficient code,
the next step is to create a corresponding TLC file to eliminate computational overhead
and improve the speed of the lookup computations.
For your convenience, the Simulink product provides support for two general-purpose
lookup 1-D and 2-D algorithms. You can use these algorithms as they are or create a
custom lookup table S-function to fit your requirements. This topic illustrates how to
create a 1-D lookup S-function, sfun_directlook.c, and its corresponding inlined
sfun_directlook.tlc file (see “Target Language Compiler” (Simulink Coder) for more
details). This 1-D direct-index lookup table example illustrates the following concepts that
you need to know to create your own custom lookup tables:
11-79
11 Block Authoring and Code Generation for Simulink Coder
S-Function RTWdata
There is a property of blocks called RTWdata, which can be used by the Target Language
Compiler when inlining an S-function. RTWdata is a structure of character vectors that
you can attach to a block. It is saved with the model and placed in the model.rtw file
when generating code. For example, this set of MATLAB commands,
mydata.field1 = 'information for field1';
mydata.field2 = 'information for field2';
set_param(gcb,'RTWdata',mydata)
get_param(gcb,'RTWdata')
Inside the model.rtw file for the associated S-Function block is this information.
Block {
Type "S-Function"
RTWdata {
field1 "information for field1"
field2 "information for field2"
}
Note RTWdata is saved in the model file for S-functions that are not linked to a library.
However, RTWdata is not persistent for S-Function blocks that are linked to a library.
The 1-D lookup table block provided in the Simulink library uses interpolation or
extrapolation when computing outputs. This extra accuracy might not be required. In this
example, you create a lookup table that directly indexes the output vector (y-data vector)
based on the current input (x-data) point.
This direct 1-D lookup example computes an approximate solution p(x) to a partially
known function f(x) at x=x0, given data point pairs (x,y) in the form of an x-data vector
and a y-data vector. For a given data pair (for example, the i'th pair), y_i = f(x_i). It is
assumed that the x-data values are monotonically increasing. If x0 is outside the range of
the x-data vector, the first or last point is returned.
11-80
Write S-Function and TLC Files By Hand
XData and YData are double vectors of equal length representing the values of the
unknown function. XDataEvenlySpaced is a scalar, 0.0 for false and 1.0 for true. If the
XData vector is evenly spaced, XDataEvenlySpaced is 1.0 and more efficient code is
generated.
11-81
11 Block Authoring and Code Generation for Simulink Coder
This topic shows how to improve the lookup table by inlining a direct-index S-function
with a TLC file. This direct-index lookup table S-function does not require a TLC file. Here
the example uses a TLC file for the direct-index lookup table S-function to reduce the
code size and increase efficiency of the generated code.
Implementation of the direct-index algorithm with inlined TLC file requires the S-function
main module, sfun_directlook.c, and a corresponding lookup_index.c module. The
lookup_index.c module contains the GetDirectLookupIndex function that is used to
locate the index in the XData for the current x input value when the XData is unevenly
11-82
Write S-Function and TLC Files By Hand
spaced. The GetDirectLookupIndex routine is called from both the S-function and the
generated code. Here the example uses the wrapper concept for sharing C/C++ code
between Simulink MEX-files and the generated code.
If the XData is evenly spaced, then both the S-function main module and the generated
code contain the lookup algorithm (not a call to the algorithm) to compute the y-value of a
given x-value, because the algorithm is short. This illustrates the use of a fully inlined S-
function for generating optimal code.
Error Handling
11-83
11 Block Authoring and Code Generation for Simulink Coder
mdlRTW Usage
The code generator calls the mdlRTW routine while generating the model.rtw file. To
produce optimal code for your Simulink model, you can add information to the
model.rtw file about the mode in which your S-Function block is operating.
The following example adds parameter settings to the model.rtw file. The parameter
settings do not change during execution. In this case, the XDataEvenlySpaced S-
function parameter cannot change during execution (ssSetSFcnParamTunable was
specified as false (0) for it in mdlInitializeSizes). The example writes it out as a
parameter setting (XSpacing) using the function ssWriteRTWParamSettings.
Before examining the S-function and the inlined TLC file, consider the generated code for
the following model.
The model uses evenly spaced XData in the top S-Function block and unevenly spaced
XData in the bottom S-Function block. When creating this model, you need to specify the
following for each S-Function block.
set_param('sfun_directlook_ex/S-Function','SFunctionModules','lookup_index')
set_param('sfun_directlook_ex/S-Function1','SFunctionModules','lookup_index')
11-84
Write S-Function and TLC Files By Hand
This informs the build process to use the module lookup_index.c when creating the
executable.
When generating code for this model, the code generator uses the S-function mdlRTW
method to generate a model.rtw file with the value EvenlySpaced for the XSpacing
parameter for the top S-Function block, and the value UnEvenlySpaced for the
XSpacing parameter for the bottom S-Function block. The TLC-file uses the value of
XSpacing to determine what algorithm to include in the generated code. The generated
code contains the lookup algorithm when the XData is evenly spaced, but calls the
GetDirectLookupIndex routine when the XData is unevenly spaced. The generated
model.c or model.cpp code for the lookup table example model is similar to the
following:
/*
* sfun_directlook_ex.c
*
* Code generation for Simulink model
* "sfun_directlook_ex.slx".
*
...
*/
#include "sfun_directlook_ex.h"
#include "sfun_directlook_ex_private.h"
/* Real-time model */
RT_MODEL_sfun_directlook_ex_T sfun_directlook_ex_M_;
RT_MODEL_sfun_directlook_ex_T *const sfun_directlook_ex_M =
&sfun_directlook_ex_M_;
11-85
11 Block Authoring and Code Generation for Simulink Coder
/* Outport: '<Root>/Out1' */
sfun_directlook_ex_Y.Out1 = rtb_SFunction;
/* Outport: '<Root>/Out2' */
sfun_directlook_ex_Y.Out2 = rtb_SFunction1;
}
sfun_directlook_ex_M->Timing.t[0] = sfun_directlook_ex_M->Timing.clockTick0 *
11-86
Write S-Function and TLC Files By Hand
sfun_directlook_ex_M->Timing.stepSize0 +
sfun_directlook_ex_M->Timing.clockTickH0 *
sfun_directlook_ex_M->Timing.stepSize0 * 4294967296.0;
}
...
The .rtw file that the code generator produces for the block includes the comments
specified in the structure mydata.
• Consider using the mdlRTW function to inline your C MEX S-function in the generated
code. This is useful when you want to
This topic describes how you can take advantage of expression folding to increase the
efficiency of code generated by your own inlined S-Function blocks, by calling macros
provided in the S-Function API. This topic assumes that you are familiar with:
11-87
11 Block Authoring and Code Generation for Simulink Coder
The S-Function API lets you specify whether a given S-Function block should nominally
accept expressions at a given input port. A block should not always accept expressions.
For example, if the address of the signal at the input is used, expressions should not be
accepted at that input, because it is not possible to take the address of an expression.
The S-Function API also lets you specify whether an expression can represent the
computations associated with a given output port. When you request an expression at a
block's input or output port, the Simulink engine determines whether or not it can honor
that request, given the block's context. For example, the engine might deny a block's
request to output an expression if the destination block does not accept expressions at its
input, if the destination block has an update function, or if multiple output destinations
exist.
The decision to honor or deny a request to output an expression can also depend on the
category of output expression the block uses (see “Categories of Output Expressions” on
page 11-88).
• When and how you can request that a block accept expressions at an input port
• When and how you can request that a block generate expressions at an outport
• The conditions under which the Simulink engine will honor or deny such requests
To take advantage of expression folding in your S-functions, you should understand when
to request acceptance and generation of expressions for specific blocks. You do not have
to understand the algorithm by which the Simulink engine chooses to accept or deny
these requests. However, if you want to trace between the model and the generated code,
it is helpful to understand some of the more common situations that lead to denial of a
request.
When you implement a C MEX S-function, you can specify whether the code
corresponding to a block's output is to be generated as an expression. If the block
generates an expression, you must specify that the expression is constant, trivial, or
generic.
A constant output expression is a direct access to one of the block's parameters. For
example, the output of a Constant block is defined as a constant expression because the
output expression is simply a direct access to the block's Value parameter.
11-88
Write S-Function and TLC Files By Hand
Consider the following block diagram. The Delay block has multiple destinations, yet its
output is designated as a trivial output expression, so that it can be used more than once
without degrading the efficiency of the code.
The following code excerpt shows code generated from the Unit Delay block in this block
diagram. The three root outputs are directly assigned from the state of the Unit Delay
block, which is stored in a field of the global data structure rtDWork. Since the
assignment is direct, without expressions, there is no performance penalty associated
with using the trivial expression for multiple destinations.
void MdlOutputs(int_T tid)
{
...
/* Outport: <Root>/Out1 incorporates:
11-89
11 Block Authoring and Code Generation for Simulink Coder
...
}
On the other hand, consider the Sum blocks in the following model:
The upper Sum block in the preceding model generates the signal labeled non_triv.
Computation of this output signal involves two multiplications and an addition. If the Sum
block's output were permitted to generate an expression even when the block had
multiple destinations, the block's operations would be duplicated in the generated code.
In the case illustrated, the generated expressions would proliferate to four multiplications
and two additions. This would degrade the efficiency of the program. Accordingly the
output of the Sum block is not allowed to be an expression because it has multiple
destinations
The code generated for the previous block diagram shows how code is generated for Sum
blocks with single and multiple destinations.
The Simulink engine does not permit the output of the upper Sum block to be an
expression because the signal non_triv is routed to two output destinations. Instead,
the result of the multiplication and addition operations is stored in a temporary variable
(rtb_non_triv) that is referenced twice in the statements that follow, as seen in the
code excerpt below.
11-90
Write S-Function and TLC Files By Hand
In contrast, the lower Sum block, which has only a single output destination (Out2), does
generate an expression.
void MdlOutputs(int_T tid)
{
/* local block i/o variables */
real_T rtb_non_triv;
real_T rtb_Sine_Wave;
/* Outport: <Root>/Out1 */
rtY.Out1 = rtb_non_triv;
rtb_Sine_Wave = rtP.Sine_Wave_Amp *
sin(rtP.Sine_Wave_Freq * rtmGetT(rtM_model) +
rtP.Sine_Wave_Phase) + rtP.Sine_Wave_Bias;
The S-Function API provides macros that let you declare whether an output of a block
should be an expression, and if so, to specify the category of the expression. The following
table specifies when to declare a block output to be a constant, trivial, or generic output
expression.
11-91
11 Block Authoring and Code Generation for Simulink Coder
The following macros are available for setting an output to be a constant, trivial, or
generic expression:
The following macros are available for querying the status set by prior calls to the macros
above:
The set of generic expressions is a superset of the set of trivial expressions, and the set of
trivial expressions is a superset of the set of constant expressions.
Therefore, when you query an output that has been set to be a constant expression with
ssGetOutputPortTrivialOutputExprInRTW, it returns True. A constant expression
11-92
Write S-Function and TLC Files By Hand
Similarly, an output that has been configured to be a constant or trivial expression returns
True when queried for its status as a generic expression.
A block can request that its output be represented in code as an expression. Such a
request can be denied if the destination block cannot accept expressions at its input port.
Furthermore, conditions independent of the requesting block and its destination blocks
can prevent acceptance of expressions.
This topic discusses block-specific conditions under which requests for input expressions
are denied. For information on other conditions that prevent acceptance of expressions,
see “Denial of Block Requests to Output Expressions” on page 11-94.
A block should not be configured to accept expressions at its input port under the
following conditions:
• The block must take the address of its input data. It is not possible to take the address
of most types of input expressions.
• The code generated for the block references the input more than once (for example,
the Abs or Max blocks). This would lead to duplication of a potentially complex
expression and a subsequent degradation of code efficiency.
If a block refuses to accept expressions at an input port, then a block that is connected to
that input port is not permitted to output a generic or trivial expression.
• Specify whether a block input should accept nonconstant expressions (that is, trivial or
generic expressions)
• Query whether a block input accepts nonconstant expressions
11-93
11 Block Authoring and Code Generation for Simulink Coder
You should call the macros in your mdlSetWorkWidths function. The macros have the
following arguments:
The macro available for specifying whether or not a block input should accept a
nonconstant expression is as follows:
void ssSetInputPortAcceptExprInRTW(SimStruct *S, int portIdx, bool value)
The corresponding macro available for querying the status set by any prior calls to
ssSetInputPortAcceptExprInRTW is as follows:
bool ssGetInputPortAcceptExprInRTW(SimStruct *S, int portIdx)
Even after a specific block requests that it be allowed to generate an output expression,
that request can be denied for generic reasons. These reasons include, but are not limited
to
• The output expression is nontrivial, and the output has multiple destinations.
• The output expression is nonconstant, and the output is connected to at least one
destination that does not accept expressions at its input port.
• The output is a test point.
• The output has been assigned an external storage class.
• The output must be stored using global data (for example is an input to a merge block
or a block with states).
• The output signal is complex.
You do not need to consider these generic factors when deciding whether or not to utilize
expression folding for a particular block. However, these rules can be helpful when you
are examining generated code and analyzing cases where the expression folding
optimization is suppressed.
11-94
Write S-Function and TLC Files By Hand
To take advantage of expression folding, you must modify the TLC block implementation
of an inlined S-Function such that it informs the Simulink engine whether it generates or
accepts expressions at its
You can conditionally disable expression folding at the inputs and outputs of a block by
making the call to this function conditionally.
If you override one of the TLC block implementations provided by the code generator with
your own implementation, you should not make the preceding call until you have updated
your implementation, as described by the guidelines for expression folding in the
following topics.
Output Expressions
11-95
11 Block Authoring and Code Generation for Simulink Coder
• block: the record for the block for which an output expression is being generated
• system: the record for the system containing the block
• portIdx: zero-based index of the output port for which an expression is being
generated
• ucv: user control variable defining the output element for which code is being
generated
• lcv: loop control variable defining the output element for which code is being
generated
• idx: signal index defining the output element for which code is being generated
• retType: character vector defining the type of signal access desired:
The BlockOutputSignal function returns a character vector for the output signal or
address. The character vector should enforce the precedence of the expression by using
opening and terminating parentheses, unless the expression consists of a function call.
The address of an expression can only be returned for a constant expression; it is the
address of the parameter whose memory is being accessed. The code implementing the
BlockOutputSignal function for the Constant block is shown below.
%% Function: BlockOutputSignal =================================================
%% Abstract:
%% Return the reference to the parameter. This function *may*
%% be used by Simulink when optimizing the Block IO data structure.
%%
%function BlockOutputSignal(block,system,portIdx,ucv,lcv,idx,retType) void
%switch retType
%case "Signal"
%return LibBlockParameter(Value,ucv,lcv,idx)
%case "SignalAddr"
%return LibBlockParameterAddr(Value,ucv,lcv,idx)
%default
%assign errTxt = "Unsupported return type: %<retType>"
%<LibBlockReportError(block,errTxt)>
%endswitch
%endfunction
The code implementing the BlockOutputSignal function for the Relational Operator
block is shown below.
%% Function: BlockOutputSignal =================================================
%% Abstract:
11-96
Write S-Function and TLC Files By Hand
When a block has a single output, the Outputs function in the block's TLC file is called
only if the output port is not an expression. Otherwise, the BlockOutputSignal function
is called.
If a block has multiple outputs, the Outputs function is called if any output port is not an
expression. The Outputs function should guard against generating code for output ports
that are expressions. This is achieved by guarding sections of code corresponding to
individual output ports with calls to LibBlockOutputSignalIsExpr().
For example, consider an S-Function with two inputs and two outputs, where
• The first output, y0, is equal to two times the first input.
• The second output, y1, is equal to four times the second input.
The Outputs and BlockOutputSignal functions for the S-function are shown in the
following code excerpt.
%% Function: BlockOutputSignal =================================================
%% Abstract:
%% Return an output expression. This function *may*
%% be used by Simulink when optimizing the Block IO data structure.
%%
%function BlockOutputSignal(block,system,portIdx,ucv,lcv,idx,retType) void
%switch retType
%case "Signal"
%assign u = LibBlockInputSignal(portIdx, ucv, lcv, idx)
11-97
11 Block Authoring and Code Generation for Simulink Coder
%case "Signal"
%if portIdx == 0
%return "(2 * %<u>)"
%elseif portIdx == 1
%return "(4 * %<u>)"
%endif
%default
%assign errTxt = "Unsupported return type: %<retType>"
%<LibBlockReportError(block,errTxt)>
%endswitch
%endfunction
%%
%% Function: Outputs =================================================
%% Abstract:
%% Compute output signals of block
%%
%function Outputs(block,system) Output
%assign rollVars = ["U", "Y"]
%roll sigIdx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
%assign u0 = LibBlockInputSignal(0, "", lcv, sigIdx)
%assign u1 = LibBlockInputSignal(1, "", lcv, sigIdx)
%assign y0 = LibBlockOutputSignal(0, "", lcv, sigIdx)
%assign y1 = LibBlockOutputSignal(1, "", lcv, sigIdx)
%if !LibBlockOutputSignalIsExpr(0)
%<y0> = 2 * %<u0>;
%endif
%if !LibBlockOutputSignalIsExpr(1)
%<y1> = 4 * %<u1>;
%endif
%endroll
%endfunction
In the past, blocks preceded their outputs code with comments of the form
/* %<Type> Block: %<Name> */
The following TLC code illustrates registering a block comment. Note the use of the
function LibBlockParameterForComment, which returns a character vector, suitable
for a block comment, specifying the value of the block parameter.
11-98
Write S-Function and TLC Files By Hand
%openfile commentBuf
$c(*) Gain value: %<LibBlockParameterForComment(Gain)>
%closefile commentBuf
%<LibCacheBlockComment(block, commentBuf)>
You declare an input or output as local or global, and indicate its reusability, by passing
one of the following four options to the ssSetInputPortOptimOpts and
ssSetOutputPortOptimOpts macros:
• SS_NOT_REUSABLE_AND_GLOBAL: Indicates that the input and output ports are stored
in separate memory locations in the global block input and output structure
• SS_NOT_REUSABLE_AND_LOCAL: Indicates that the code generator can declare
individual local variables for the input and output ports
• SS_REUSABLE_AND_LOCAL: Indicates that the code generator can reuse a single local
variable for these input and output ports
• SS_REUSABLE_AND_GLOBAL: Indicates that these input and output ports are stored in
a single element in the global block input and output structure
Note Marking an input or output port as a local variable does not imply that the code
generator uses a local variable in the generated code. If your S-function accesses the
inputs and outputs only in its mdlOutputs routine, the code generator declares the
inputs and outputs as local variables. However, if the inputs and outputs are used
elsewhere in the S-function, the code generator includes them in the global block input
and output structure.
11-99
11 Block Authoring and Code Generation for Simulink Coder
The reusability setting indicates if the memory associated with an input or output port
can be overwritten. To reuse input and output port memory:
The following example shows how different scope and reusability settings affect the
generated code. The following model contains an S-function block pointing to the C MEX
S-function matlabroot/toolbox/simulink/simdemos/simfeatures/src/
sfun_directlook.c, which models a direct 1-D lookup table.
/* snip */
ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL);
/* snip */
}
The generated code for this model stores the input and output signals in a single local
variable rtb_SFunction, as shown in the following output function:
static void sl_directlook_output(int_T tid)
{
/* local block i/o variables */
real_T rtb_SFunction[2];
11-100
Write S-Function and TLC Files By Hand
/* Outport: '<Root>/Out1' */
sl_directlook_Y.Out1[0] = rtb_SFunction[0];
sl_directlook_Y.Out1[1] = rtb_SFunction[1];
UNUSED_PARAMETER(tid);
}
The following table shows variations of the code generated for this model when using the
generic real-time target (GRT). Each row explains a different setting for the scope and
reusability of the S-function's input and output ports.
11-101
11 Block Authoring and Code Generation for Simulink Coder
11-102
Write S-Function and TLC Files By Hand
• ssGetSampleTime
• ssGetInputPortSampleTime
• ssGetOutputPortSampleTime
• ssGetInputPortOffsetTime
• ssGetOutputPortOffsetTime
• ssGetSampleTimePtr
11-103
11 Block Authoring and Code Generation for Simulink Coder
• ssGetInputPortSampleTimeIndex
• ssGetOutputPortSampleTimeIndex
• ssGetSampleTimeTaskID
• ssGetSampleTimeTaskIDPtr
2 Check for the following in your S-function TLC code:
• LibBlockSampleTime
• CompiledModel.SampleTime
• LibBlockInputSignalSampleTime
• LibBlockInputSignalOffsetTime
• LibBlockOutputSignalSampleTime
• LibBlockOutputSignalOffsetTime
3 Depending on your search results, use
ssSetModelReferenceSampleTimeInheritanceRule as indicated in the
following table.
If... Use...
None of the macros or functions ssSetModelReferenceSampleTimeInheritanceRule
are present, the S-function does (S, USE_DEFAULT_FOR_DISCRETE_INHERITANCE)
not preclude the model from
inheriting a sample time.
Any of the macros or functions are ssSetModelReferenceSampleTimeInheritanceRule...
used for (S,USE_DEFAULT_FOR_DISCRETE_INHERITANCE)
11-104
Write S-Function and TLC Files By Hand
If... Use...
The S-function uses its sample ssSetModelReferenceSampleTimeInheritanceRule
time for computing parameters, (S, DISALLOW_SAMPLE_TIME_INHERITANCE)
outputs, and so on
You can use settings on Configuration Parameters > Diagnostics > Advanced
parameters to control how the Simulink engine responds when it encounters S-functions
that have unspecified sample time inheritance rules. Toggle the Configuration
Parameters > Diagnostics > Sample Time > Unspecified inheritability of sample
time diagnostic to none, warning, or error. The default is warning.
In addition to meeting the preceding requirements, your S-function must set the
SS_OPTION_WORKS_WITH_CODE_REUSE flag (see the description of ssSetOptions in
11-105
11 Block Authoring and Code Generation for Simulink Coder
the Simulink Writing S-Function documentation). This flag indicates that your S-function
meets the requirements for subsystem code reuse.
S-functions can be used in models with multiple sample rates and deployed in
multitasking target environments. Likewise, S-functions themselves can have multiple
rates at which they operate. The code generator produces code for multirate multitasking
models using an approach called rate grouping. In code generated for ERT-based targets,
rate grouping generates separate model_step functions for the base rate task and each
subrate task in the model. Although rate grouping is a code generation feature found in
ERT targets only, your S-functions can use it in other contexts when you code them as
explained below.
To take advantage of rate grouping, you must inline your multirate S-functions if you have
not done so. You need to follow certain Target Language Compiler protocols to exploit
rate grouping. Coding TLC to exploit rate grouping does not prevent your inlined S-
functions from functioning properly in GRT. Likewise, your inlined S-functions will still
generate valid ERT code even if you do not make them rate-grouping-compliant. If you do
so, however, they will generate more efficient code for multirate models.
For instructions and examples of Target Language Compiler code illustrating how to
create and upgrade S-functions to generate rate-grouping-compliant code, see “Rate
Grouping Compliance and Compatibility Issues” on page 52-17.
For each multirate S-function that is not rate grouping-compliant, the code generator
issues the following warning when you build:
Warning: Simulink Coder: Code of output function for multirate block
'<Root>/S-Function' is guarded by sample hit checks rather than being rate
grouped. This will generate the same code for all rates used by the block,
possibly generating dead code. To avoid dead code, you must update the TLC
file for the block.
11-106
Write S-Function and TLC Files By Hand
You will also find a comment such as the following in code generated for each
noncompliant S-function:
/* Because the output function of multirate block
<Root>/S-Function is not rate grouped,
the following code might contain unreachable blocks of code.
To avoid this, you must update your block TLC file. */
The words “update function” are substituted for “output function” in these warnings.
The following instructions show how to support both data determinism and data integrity
in multirate S-functions. They do not cover cases where there is no determinism nor
integrity. Support for frame-based processing does not affect the requirements.
Note The slow rates must be multiples of the fastest rate. The instructions do not apply
when two rates being interfaced are not multiples or when the rates are not periodic.
The rules that multirate S-functions should observe for inputs are
• The input should only be read at the rate that is associated with the input port sample
time.
• Generally, the input data is written to DWork, and the DWork can then be accessed at
the slower (downstream) rate.
The input can be read at every sample hit of the input rate and written into DWork
memory, but this DWork memory cannot then be directly accessed by the slower rate.
DWork memory that will be read by the slow rate must only be written by the fast rate
when there is a special sample hit. A special sample hit occurs when both this input port
rate and rate to which it is interfacing have a hit. Depending on their requirements and
design, algorithms can process the data in several locations.
The rules that multirate S-functions should observe for outputs are
• The output should not be written by a rate other than the rate assigned to the output
port, except in the optimized case described below.
• The output should always be written when the sample rate of the output port has a hit.
11-107
11 Block Authoring and Code Generation for Simulink Coder
If these conditions are met, the S-Function block can specify that the input port and
output port can both be made local and reusable.
You can include an optimization when little or no processing needs to be done on the data.
In such cases, the input rate code can directly write to the output (instead of by using
DWork) when there is a special sample hit. If you do this, however, you must declare the
outport port to be global and not reusable. This optimization results in one less memcpy
but does introduce nonuniform processing requirements on the faster rate.
Whether you use this optimization or not, the most recent input data, as seen by the
slower rate, is the value when both the faster and slower rate had their hits (and possible
earlier input data as well, depending on the algorithm). Subsequent steps by the faster
rate and the associated input data updates are not seen by the slower rate until the next
hit for the slow rate occurs.
Pseudocode Examples of Fast-to-Slow Rate Transition
The pseudocode below abstracts how you should write your C MEX code to handle fast-to-
slow transitions, illustrating with an input rate of 0.1 second driving an output rate of one
second. A similar approach can be taken when inlining the code. The block has following
characteristics:
11-108
Write S-Function and TLC Files By Hand
OutputFcn
if (ssIsSampleHit(".1")) {
if (ssIsSpecialSampleHit("1")) {
y = u;
}
}
When output rates are faster than input rates, input should only be read at the rate that is
associated with the input port sample time, observing the following rules:
11-109
11 Block Authoring and Code Generation for Simulink Coder
• Write the second DWork to the output at every hit of the output sample rate.
The block can request that the input port be made local but it cannot be set to reusable.
The output port can be set to local and reusable.
As in the fast-to-slow transition case, the input should not be read by a rate other than the
one assigned to the input port. Similarly, the output should not be written to at a rate
other than the rate assigned to the output port.
An optimization can be made when the algorithm being implemented is only required to
run at the slow rate. In such cases, you use only one DWork. The input still writes to the
DWork in the update function. When there is a special sample hit between the rates, the
output function copies the same DWork directly to the output. You must set the output
port to be global and not reusable in this case. This optimization results in one less
memcpy operation per special sample hit.
In either case, the data that the fast rate computations operate on is always delayed, that
is, the data is from the previous step of the slow rate code.
Pseudocode Examples of Slow-to-Fast Rate Transition
The pseudocode below abstracts what your S-function needs to do to handle slow-to-fast
transitions, illustrating with an input rate of one second driving an output rate of 0.1
second. The block has following characteristics:
11-110
Write S-Function and TLC Files By Hand
• Input: Set to local, will be local if output/update are combined (ERT) otherwise will be
global. Set to not reusable because input needs to be preserved until the update
function runs.
• Output: global and not reusable because it needs to persist between special sample
hits.
• DirectFeedthrough: no
OutputFcn
if (ssIsSampleHit(".1") {
if (ssIsSpecialSampleHit("1") {
y = DWork;
}
}
UpdateFcn
if (ssIsSampleHit("1")) {
DWork = u;
}
11-111
11 Block Authoring and Code Generation for Simulink Coder
See Also
legacy_code
Related Examples
• “Introduction to the Target Language Compiler” (Simulink Coder)
• “Inlining S-Functions” (Simulink Coder)
• “Import Calls to External Code into Generated Code with Legacy Code Tool” on page
11-7
11-112
12
12-2
Support for Standards and Guidelines
12-3
12 Guidelines and Standards for Embedded Coder
12-4
MAAB Guidelines
MAAB Guidelines
The MathWorks Automotive Advisory Board (MAAB) involves major automotive OEMs and
suppliers in the process of evolving MathWorks controls, simulation, and code generation
products, including Simulink, Stateflow, and Simulink Coder. An important result of the
MAAB has been the “MAAB Control Algorithm Modeling” (Simulink) guidelines.
If you have a Simulink Check product license, you can check that your Simulink model or
subsystem, and the code that you generate from it, complies with MAAB guidelines. To
check your model or subsystem, open the Simulink Model Advisor (Simulink). Navigate to
By Product > Simulink Check > Modeling Standards > MathWorks Automotive
Advisory Board Checks and run the MathWorks Automotive Advisory Board checks
(Simulink Check).
For more information on using the Model Advisor, see “Run Model Checks” (Simulink).
12-5
12 Guidelines and Standards for Embedded Coder
MISRA C Guidelines
The Motor Industry Software Reliability Association (MISRA2) has established “Guidelines
for the Use of the C Language in Critical Systems” (MISRA C).
In 1998, MIRA Ltd. published MISRA C (MISRA C:1998) to provide a restricted subset of
a standardized, structured language that met Safety Integrity Level (SIL) 2 and higher. A
major update based on feedback was published in 2004 (MISRA C:2004), followed by a
minor update in 2007 known as Technical Corrigendum (TC1).
In 2007, MIRA Ltd. published the MISRA AC AGC standard, “MISRA AC AGC: Guidelines
for the Application of MISRA-C:2004 in the Context of Automatic Code Generation.”
MISRA AC AGC does not change MISRA C:2004 rules, rather it modifies the adherence
recommendation.
In 2013, MIRA Ltd. published the MISRA C:2012 standard, “Guidelines for the use of the
C language in critical systems.” MISRA C:2012 provides improvements based on user
feedback and includes guidance on automatic code generation.
Embedded Coder and Simulink offer capabilities to minimize the potential for MISRA C
rule violations.
To configure a model or subsystem so that the code generator is most likely to produce
MISRA C:2012 compliant code, use the Code Generation Advisor. For more information,
see “Configure Model for Code Generation Objectives by Using Code Generation Advisor”
on page 32-2.
The Model Advisor (Simulink) also checks that you developed your model or subsystem to
increase the likelihood of generating MISRA C:2012 compliant code. To check your model
or subsystem:
For more information about using the Model Advisor, see “Run Model Checks” (Simulink).
2. MISRA and MISRA C are registered trademarks of MIRA Ltd., held on behalf of the MISRA Consortium.
12-6
MISRA C Guidelines
For information about using Embedded Coder software within MISRA C guidelines, see
Technical Solution 1-1IFP0W on the MathWorks website.
12-7
12 Guidelines and Standards for Embedded Coder
If you have an Embedded Coder or Simulink Check product license, you can check that
your Simulink model or subsystem, and the code that you generate from it, conforms to
these secure coding standards. To check your model or subsystem:
For more information about using the Model Advisor, see “Run Model Checks” (Simulink).
If you have a Polyspace Bug Finder product license, you can evaluate your code against
these secure coding standards. For more information, see “Check C/C++ Code for
Security Standards” (Polyspace Bug Finder)
12-8
IEC 61508 Standard
MathWorks provides an IEC Certification Kit product that you can use to certify
MathWorks code generation and verification tools for projects based on the IEC 61508
standard. For more information, see https://www.mathworks.com/products/iec-61508/.
For more information on using the Model Advisor, see “Run Model Checks” (Simulink).
Validate Traceability
Typically, applications that require certification require some level of traceability between
requirements, models, and corresponding code.
12-9
12 Guidelines and Standards for Embedded Coder
To... Use...
Associate requirements documents The “Requirements Management Interface
with objects in Simulink models Setup” (Simulink Requirements) that is available
if you have a Simulink Requirements license.
Trace model blocks and subsystems to The “Model-to-Code Traceability” on page 64-10
generated code option when generating an HTML report during
the code generation or build process.
Trace generated code to model blocks The “Code-to-Model Traceability” on page 64-8
and subsystems option when generating an HTML report during
the code generation or build process.
12-10
Develop a Model that Complies with the IEC 61508 Standard
The IEC 61508 checks identify issues with a model that impede deployment in safety-
related applications or limit traceability.
According to the functional requirements, a model shall be created that checks whether
the 1-norm distance between points (x1,x2) and (y1,y2) is less than or equal to a
given threshold thr. For two points (x1,x2) and (y1,y2), the 1-norm distance is given
as:
The rtwdemo_iec61508 model implements the preceding requirement. Open and get
familiar with the model.
model='rtwdemo_iec61508';
open_system(model)
12-11
12 Guidelines and Standards for Embedded Coder
To deploy the model in a safety-related software component that must comply with the
IEC 61508 safety standard, check the model for issues that might impede deployment in
such an environment or limit traceability between the model and generated source code.
12-12
Develop a Model that Complies with the IEC 61508 Standard
1 Start the Model Advisor by selecting Analysis > Model Advisor or by entering
modeladvisor('rtwdemo_IEC61508') at the MATLAB command line.
2 In the Task Hierarchy, expand By Task > Modeling Standards for IEC 61508.
3 Select the checks within the group.
4 Select Show report after run to generate an HTML report that shows the check
results.
5 Click Run Selected Checks. Model Advisor processes the IEC 61508 checks and
displays the results.
See Also
• For descriptions of the IEC 61508 checks, see IEC 61508, IEC 62304, ISO 26262, and
EN 50128 Checks in the Simulink Check documentation.
• For more information on using Model Advisor, see Run Model Checks in the Simulink
documentation.
12-13
12 Guidelines and Standards for Embedded Coder
MathWorks provides an IEC Certification Kit product that you can use to certify
MathWorks code generation and verification tools for projects based on the IEC 62304
standard. For more information, see https://www.mathworks.com/products/iec-61508/.
For more information on using the Model Advisor, see “Run Model Checks” (Simulink).
12-14
ISO 26262 Standard
In this section...
“Apply Simulink and Embedded Coder to the ISO 26262 Standard” on page 12-15
“Check for ISO 26262 Standard Compliance Using the Model Advisor” on page 12-15
“Validate Traceability” on page 12-15
MathWorks provides an IEC Certification Kit product that you can use to qualify
MathWorks code generation and verification tools for projects based on the ISO 26262
standard. For more information, see https://www.mathworks.com/products/iso–26262/.
For more information on using the Model Advisor, see “Run Model Checks” (Simulink).
Validate Traceability
Typically, applications that require certification require some level of traceability between
requirements, models, and corresponding code.
12-15
12 Guidelines and Standards for Embedded Coder
To... Use...
Associate requirements documents The “Requirements Management Interface
with objects in Simulink models Setup” (Simulink Requirements) that is available
if you have a Simulink Requirements license.
Trace model blocks and subsystems to The “Model-to-Code Traceability” on page 64-10
generated code option when generating an HTML report during
the code generation or build process.
Trace generated code to model blocks The “Code-to-Model Traceability” on page 64-8
and subsystems option when generating an HTML report during
the code generation or build process.
12-16
EN 50128 Standard
EN 50128 Standard
In this section...
“Apply Simulink and Embedded Coder to the EN 50128 Standard” on page 12-17
“Check for EN 50128 Standard Compliance Using the Model Advisor” on page 12-17
“Validate Traceability” on page 12-17
MathWorks provides an IEC Certification Kit product that you can use to certify
MathWorks code generation and verification tools for projects based on the EN 50128
standard. For more information, see https://www.mathworks.com/products/iec-61508/.
For more information on using the Model Advisor, see “Run Model Checks” (Simulink).
Validate Traceability
Typically, applications that require certification require some level of traceability between
requirements, models, and corresponding code.
12-17
12 Guidelines and Standards for Embedded Coder
To... Use...
Associate requirements documents The “Requirements Management Interface
with objects in Simulink models Setup” (Simulink Requirements) that is available
if you have a Simulink Requirements license.
Trace model blocks and subsystems to The “Model-to-Code Traceability” on page 64-10
generated code option when generating an HTML report during
the code generation or build process.
Trace generated code to model blocks The “Code-to-Model Traceability” on page 64-8
and subsystems option when generating an HTML report during
the code generation or build process.
12-18
DO-178C Standard
DO-178C Standard
In this section...
“Apply Simulink and Embedded Coder to the DO-178C Standard” on page 12-19
“Check for Standard Compliance Using the Model Advisor” on page 12-19
“Validate Traceability” on page 12-19
For information about Model-Based Design and MathWorks support of aerospace and
defense industry standards, see https://www.mathworks.com/aerospace-defense/ .
For more information on using the Model Advisor, see “Run Model Checks” (Simulink).
Validate Traceability
Typically, applications that require certification require some level of traceability between
requirements, models, and corresponding code.
12-19
12 Guidelines and Standards for Embedded Coder
To... Use...
Associate requirements documents The “Requirements Management Interface
with objects in Simulink models Setup” (Simulink Requirements) that is available
if you have a Simulink Requirements license.
Trace model blocks and subsystems to The “Model-to-Code Traceability” on page 64-10
generated code option when generating an HTML report during
the code generation or build process.
Trace generated code to model blocks The “Code-to-Model Traceability” on page 64-8
and subsystems option when generating an HTML report during
the code generation or build process.
12-20
13
When using MISRA C:2012 coding guidelines to evaluate the quality of your generated C
code, you are required per section 5.3 of the MISRA C:2012 Guidelines for the Use of C
Language in Critical Systems document to prepare a compliance statement for the project
being evaluated. To assist you in the development of this compliance statement,
MathWorks evaluates the MISRA C:2012 guidelines against C code generated by using
Embedded Coder and provides the following information:
• Compliance Summary Tables on page 13-7, which identify the method used to
obtain compliance for each rule and directive.
• Deviations on page 13-30, which identify rules or directives that are not compliant.
For information about the process MathWorks uses to evaluate generated C code against
MISRA C:2012 guidelines, see “MathWorks Process for Identifying Violations of MISRA C:
2012 Guidelines in Generated C Code” on page 13-2.
For additional information about the MISRA organization, their coding guidelines, and the
MISRA publication timeline, see www.misra.org.uk .
13-2
Using This Documentation When Developing a MISRA C:2012 Compliance Statement
Product Purpose
Simulink Create/maintain models.
Stateflow Create/maintain models.
Fixed-Point Designer Create/maintain models.
Embedded Coder Generate C code.
Simulink Check Execute MISRA C:2012 Model Advisor
checks.a
Polyspace Bug Finder Identify bug/coding defects.
Note The compliance analysis performed by the Polyspace MISRA C:2012 Checker
assesses C code generated by Embedded Coder. No assessment is made of the Embedded
Coder tool chain. Handwritten C code and third-party libraries that are used with code
generated by Embedded Coder are not considered. Other MISRA C code analysis tools
can yield different results.
13-3
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
3 If necessary, modify the model to adhere to the “Modeling Guidelines for MISRA C:
2012 Compliance” on page 13-21.
4 After all MISRA C:2012 checks pass successfully, generate code by using Embedded
Coder.
To avoid possible name clashes, multiple functions definitions, and multiple data
definitions, use one of these code generation approaches:
• Single model: Generate code from a single model, including submodels, by using
Model blocks.
• Multiple models: Generate code from multiple models, including:
13-4
Evaluate Your Generated Code for MISRA C:2012 Compliance
For more information about running a Polyspace analysis on your generated code,
including analysis options and results, see:
• Analysis of Generated Code using Polyspace Bug Finder (Polyspace Bug Finder)
• Analysis of Generated Code using Polyspace Code Prover (Polyspace Code Prover)
6 Justify violations to the MISRA C:2012 coding standards using Polyspace annotations
(Polyspace Bug Finder).
13-5
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
13-6
Compliance Information Summary Tables
In this section...
“Compliance Summary Tables” on page 13-7
“Explanatory Notes” on page 13-17
You can use these tables when preparing the MISRA C:2012 compliance statement for
your project as required per section 5.3 of the MISRA C:2012 Guidelines for the Use of C
Language in Critical Systems document. These tables align with the published MISRA C:
2012 rule and directives tables.
13-7
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
13-8
Compliance Information Summary Tables
• hisl_0001
• hisl_0002,
• hisl_0004
• hisl_0005
• hisl_0006
• hisl_0053
• hisl_0054
• “Explanatory Note for Directive 4.1” on page
13-18
4.3 Required Compliant: No
Deviation:
13-9
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
• hisl_0060
a. The Polyspace MISRA C:2012 Checker might flag Directive 4.7 as a Rule 17.7 violation for user-defined
functions if there is no knowledge about whether the return value contains error information.
• hisl_0053
• hisl_0101
2.2 Required Compliant Yes
13-10
Compliance Information Summary Tables
• hisl_0063
• “Explanatory Note for Rules 5.1, 5.2, 5.4, 5.5,
5.6, 5.7, and 5.8” on page 13-19
5.2 Required Compliant: Yes
• hisl_0063
• “Explanatory Note for Rules 5.1, 5.2, 5.4, 5.5,
5.6, 5.7, and 5.8” on page 13-19
5.4 Required Compliant: Yes
• hisl_0063
• “Explanatory Note for Rules 5.1, 5.2, 5.4, 5.5,
5.6, 5.7, and 5.8” on page 13-19
5.5 Required Compliant: Yes
• hisl_0063
• “Explanatory Note for Rules 5.1, 5.2, 5.4, 5.5,
5.6, 5.7, and 5.8” on page 13-19
5.6 Required Compliant: Yes
13-11
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
• hisl_0060
6.2 Required Compliant: Yes
• hisl_0060
13-12
Compliance Information Summary Tables
• hisl_0029
• Check usage of Assignment blocks
9.4 Required Compliant Yes
• hisl_0020
11.6 Required Compliant Yes
11.7 Required Compliant Yes
11.8 Required Compliant: Yes
• hisl_0020
13-13
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
• hisl_0062
13.5 Required Compliant: Yes
• hisl_0062
Deviation:
• hisl_0101
13-14
Compliance Information Summary Tables
• hisf_0004
17.3 Mandatory Compliant Yes
17.4 Mandatory Compliant Yes
17.6 Mandatory Compliant Yes
13-15
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
• hisl_0201
21.3 Required Compliant: Yes
• hisl_0060
21.4 Required Compliant Yes
21.6 Required Compliant Yes
21.7 Required Compliant Yes
21.8 Required Compliant Yes
21.9 Required Compliant Yes
21.10 Required Compliant Yes
21.11 Required Compliant Yes
13-16
Compliance Information Summary Tables
Explanatory Notes
These explanatory notes are referenced from the “Compliance Information Summary
Tables” on page 13-7.
Configure the integer division method in the Model Configuration Parameters dialog box,
on the Hardware Implementation pane. For additional information, see “Configure
Run-Time Environment Options” on page 7-2
In both instances, you are responsible for documenting the intended use of the #pragma.
For more information, see “Control Data and Function Placement in Memory by Inserting
Pragmas” on page 30-2.
13-17
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
• Pack Boolean data into bitfields. This parameter is available only for ERT-based
system target files on page 33-2.
• Use bitsets for storing state configuration.
• Use bitsets for storing Boolean data.
2 Create a custom storage class with defined bitfields. See “Create Custom Storage
Classes by Using the Custom Storage Class Designer” on page 26-26 for more
information.
You can link requirements model elements. These links are included in the generated C
code to provide traceability from a requirements document, to the model elements, and to
the generated code. For additional information, see “View Linked Requirements in Models
and Blocks” (Simulink) and “Link Blocks and Requirements” (Simulink Requirements).
You can use Polyspace Bug Finder to identify run-time errors and Polyspace Code Prover
to prove the absence of run-time errors.
Embedded Coder does not directly call assembly language code. You can add calls to
assembly language functions through S-functions, code replacement libraries, Stateflow,
and in MATLAB blocks. These calls are documented as calls to “External C Functions” on
page 14-65. In these cases, you are responsible for encapsulation.
13-18
Compliance Information Summary Tables
• “Control Data and Function Placement in Memory by Inserting Pragmas” on page 30-
2
Embedded Coder replaces basic data types with typedefs types, which are compatible
with Directive 4.6. A guideline is not required because this behavior is default behavior in
Embedded Coder. For additional information, see “Replace and Rename Data Types to
Conform to Coding Standards” on page 24-27 and Typedefs on page 14-75.
“Demonstrate statically that the input parameters can never take invalid values”.
You can use Polyspace Code Prover to analyze parameter ranges and prove the absence of
run-time errors caused by out-of-range values. For additional information, see “Run
Polyspace Analysis on Code Generated with Embedded Coder” (Polyspace Code Prover).
Explanatory Note for Rules 5.1, 5.2, 5.4, 5.5, 5.6, 5.7, and 5.8
To ensure unique names for different types of variables (local scope variables, global
scope variables, macros, and so on), implement a naming convention. For additional
information, see Model Configuration Parameters: Code Generation Symbols.
Embedded Coder supports the use of enumerated data. The file used to define the
enumeration can be either manually or automatically generated. Files defining
enumerations generated by Embedded Coder are compliant with MISRA C:2012 Rule
8.12 by design. If you manually create the definition file, you are responsible for ensuring
compliance. For additional information, see “Use Enumerated Data in Simulink Models”
(Simulink).
Embedded Coder does not directly create data of type char. Data of char type can be
introduced by user-defined S-functions, code replacement libraries, and custom storage
classes. In this case, limit the usage of plain char to:
13-19
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
13-20
Modeling Guidelines for MISRA C:2012 Compliance
Many high-integrity modeling guidelines have Model Advisor checks that you can use to
verify adherence of your model to the guideline. This table identifies the high-integrity
modeling guidelines for Simulink and provides the corresponding Model Advisor check.
Not all modeling guidelines have a corresponding Model Advisor check.
13-21
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
13-22
Modeling Guidelines for MISRA C:2012 Compliance
This table identifies the high-integrity modeling guidelines for Stateflow and indicates
whether the guideline has a corresponding Model Advisor check.
13-23
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
13-24
Modeling Guidelines for MISRA C:2012 Compliance
13-25
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
13-26
Modeling Guidelines for MISRA C:2012 Compliance
13-27
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
13-28
Modeling Guidelines for MISRA C:2012 Compliance
13-29
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
Deviations Rationale
Instances in which the generated code does not comply with the MISRA C:2012
guidelines are marked as deviations in the “Compliance Information Summary Tables” on
page 13-7. In accordance with Section 5.4 of the MISRA C:2012 guidelines,information
about the deviations includes:
If a function returns error information, then that error information shall be tested.
Rationale
Note This directive is violated only when an AUTOSAR-based code generation target is
used.
When a function call provides information that indicates an unsuccessful operation, the
calling program has to check for the indication of an error when the function is returned.
The function calls are not limited to calls in the standard library.
Description
AUTOSAR sender interface function calls, such as Rte_Write_..., have return type
Std_ReturnType that indicates if writing the value was successful. The matching
13-30
Deviations Rationale
Model Example
AUTOSAR Configuration
13-31
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
In the sample code, note the use of AUTOSAR function call Rte_Write_... in
Rte_Write_OUT_DE1_OUT_DE1(rtb_TmpSignalConversionAtIN_DE1);.
13-32
Deviations Rationale
void Runnable_Step(void)
{
/* local block i/o variables */
real_T rtb_TmpSignalConversionAtIN_DE1;
…
rtb_TmpSignalConversionAtIN_D_l = Rte_Read_IN_DE1_IN_DE1
(&rtb_TmpSignalConversionAtIN_DE1);
…
if (rtb_TmpSignalConversionAtIN_D_l > 0) {
…
Rte_Write_OUT_DE1_OUT_DE1(rtb_TmpSignalConversionAtIN_DE1);
}
…
}
Justification
Failures of Rte_Write_... function calls are typically handled on the receiver side
because function call returns do not always include all potential errors.
Consequences of Noncompliance
The calling program cannot react when the sender operation is unsuccessful.
When a Polyspace analysis of your code finds known or acceptable coding rule violations,
you can suppress the violations in subsequent analyses by adding code annotations
(Polyspace Bug Finder) to the Outport block. In future analyses, Polyspace hides results
justified through annotations in the Results List pane. To review the coding rule
violations, see “Filter and Group Results” (Polyspace Bug Finder).
If you have already provided annotations for MISRA C:2004 violations, Polyspace imports
these justifications when you check your code for MISRA C:2012 violations. For additional
information, see “Import Existing MISRA C: 2004 Justifications to MISRA C: 2012
Results” (Polyspace Bug Finder).
13-33
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
The right hand operand of a logical && or || operator shall not contain persistent side
effects.
Rationale
Persistent side effects of the right hand side operand of the && and || operators can
occur depending on the left hand side operand, which is contrary to the expectations of
the programmer.
Note The term persistent side effect is defined in "Appendix J: Glossary" of the MISRA C:
2012 Guidelines for the Use of C Language in Critical Systems document.
Description
Using math operations as second input to Logical Operator blocks configured as AND or
OR operation.
Model Example
13-34
Deviations Rationale
In the sample code, note the use of operand && in Y1 = (U1 && (sqrt(U2) <=
3.0));.
Justification
Some standard math functions have at least one persistent side effect of modifying the
global errno variable, as defined in the C90 or C99 standard. Since the errno variable is
not used by Embedded Coder, the second operand can be treated as not having persistent
side effects.
Note Polyspace Bug Finder treats every function with no available source code as
potentially having side effects.
This deviation is requested for all calls to standard math functions used as right hand side
argument of && and || operators.
Consequences of Noncompliance
13-35
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder
There are no consequences associated with noncompliance with MISRA C:2012 Rule 13.5
in the circumstances described in this deviation record. There are no additional
verification and validation requirements resulting from this deviation.
When a Polyspace analysis of your code finds known or acceptable coding rule violations,
you can suppress the violations in subsequent analyses by adding code annotations
(Polyspace Bug Finder) to the Logical Operator block. In future analyses, Polyspace hides
results justified through annotations in the Results List pane. To review the coding rule
violations, see “Filter and Group Results” (Polyspace Bug Finder).
If you have already provided annotations for MISRA C:2004 violations, Polyspace imports
these justifications when you check your code for MISRA C:2012 violations. For additional
information, see “Import Existing MISRA C: 2004 Justifications to MISRA C: 2012
Results” (Polyspace Bug Finder).
For additional information, see “Compliance Information Summary Tables” on page 13-7.
#define and #undef shall not be used on a reserved identifier or reserved macro name.
Rationale
Identifiers that begin with an underscore (_) are treated as reserved identifiers and apply
to MISRA C:2012 Rule 21.1. Reserved identifiers are intended to be used for
implementation only.
Description
Depending on modeling patterns and used features, identifiers with leading underscores
might be present in generated and static code files. For example, the generated
rtwtypes.h file might redefine the following macros with leading underscores:
• __RTWTYPES_H__
• __TMWTYPES_H__
• __ZERO_CROSSING_TYPES__
13-36
Deviations Rationale
Justification
A symbol with a leading underscore is not defined by the compiler implementation: Code
behaves as expected because the compiler-provided headers are included before headers
provided by Embedded Coder.
The deviation is requested for all instances of identifiers starting with an underscore in
the generated code.
Consequences of Noncompliance
A reserved identifier that is redefined in the generated code can result in undefined or
unexpected behavior.
Review violations caused by leading underscores to check whether there is a conflict with
compiler implementation.
13-37
14
14-2
Prepare a Model for Code Generation
In this section...
“Configure Input Ports, Output Ports, and Arbitrary Signals” on page 14-3
“Initialize and Configure States” on page 14-4
“Set Up Configuration Parameters for Code Generation” on page 14-4
“Set Up an Example Model With a Stateflow Chart” on page 14-5
“Set Up an Example Model With a MATLAB Function Block” on page 14-6
Several standard methods are available for setting up a model to generate specific C
constructs in your code. For preparing your model for code generation, some of these
methods include: configuring signals and ports, initializing states, and setting up
configuration parameters for code generation. Depending on the components of your
model, some of these methods are optional. Methods for configuring a model to generate
specific C constructs are organized by category, for example, the Control Flow category
includes constructs if-else, switch, for, and while. Refer to the name of a construct
to see how you should configure blocks and parameters in your model. Different modeling
methodologies are available, such as Simulink blocks, Stateflow charts, and MATLAB
Function blocks, to implement a C construct.
Model examples in “Modeling Patterns for C Code” have the following naming
conventions:
Input ports are named to reflect the signal names that they propagate.
14-3
14 Patterns for C Code in Embedded Coder
For example, apply the storage class ExportedGlobal, which makes the signal
appear in the generated code as a separate global variable. The variable has the
same name as the signal in the model.
14-4
Prepare a Model for Code Generation
Follow this general procedure to create a simple model containing a Stateflow chart.
1 From the Stateflow > Chart library, add a Stateflow chart to your model .
2 Add Inport blocks and Outport blocks according to the example model.
3 Open the Stateflow Editor by performing one of the following:
14-5
14 Patterns for C Code in Embedded Coder
1 Add the number of Inport and Outport blocks according to a C construct example
included in this chapter.
2 From the Simulink User-defined Functions library drag a MATLAB Function block
into the model.
3 Double-click the block. The MATLAB Function Block Editor opens. Edit the function
to implement your application.
4 Click File > Save and close the MATLAB Function Block Editor.
5 Connect the Inport and Outport blocks to the MATLAB Function block. See
“Configure Input Ports, Output Ports, and Arbitrary Signals” on page 14-3.
6 Save your model.
14-6
Definition, Initialization, and Declaration of Parameter Data
C Construct
int32 myParam = 3;
Procedure
1 Create the ex_defn_decl model by using a Gain block.
14-7
14 Patterns for C Code in Embedded Coder
Results
The generated header file myDecls.h declares the global variable myParam by using the
extern keyword.
See Also
Related Examples
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Control Placement of Global Data Definitions and Declarations in Generated Files”
on page 23-2
14-8
Definition and Declaration of Signal Data
C Construct
float mySig;
Procedure
1 Create the ex_defn_decl model by using a Gain block.
Results
The generated header file myDecls.h declares the global variable mySig by using the
extern keyword.
14-9
14 Patterns for C Code in Embedded Coder
See Also
Related Examples
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements” on
page 22-81
14-10
Data Type Conversion
C Construct
y1 = (double)u1;
Modeling Patterns
• “Modeling Pattern for Data Type Conversion — Simulink Block” on page 14-11
• “Modeling Pattern for Data Type Conversion — Stateflow Chart” on page 14-12
• “Modeling Pattern for Data Type Conversion — MATLAB Function Block” on page 14-
13
ex_data_type_SL
1 From the Commonly Used Blocks library, drag a Data Type Conversion block into
your model and connect to the Inport and Outport blocks.
2 Double-click on the Data Type Conversion block to open the Block Parameters dialog
box.
3 Select the Output data type parameter as double.
4 Press Ctrl+B to build the model and generate code.
int32_T u1;
real_T y1;
14-11
14 Patterns for C Code in Embedded Coder
void ex_data_type_SL_step(void)
{
y1 = (real_T)u1;
}
Procedure
1 Follow the steps for “Set Up an Example Model With a Stateflow Chart” on page 14-
5 . This example contains one Inport block and one Outport block.
2 Name the example model ex_data_type_SF.
3 Double-click the Inport block and select the Signal Attributes tab. Specify the Data
Type as int32 from the drop down menu.
4 Double-click the Outport block and select the Signal Attributes tab. Specify the
Data Type as Inherit: auto from the drop down menu.
5 Press Ctrl+B to build the model and generate code.
Results
14-12
See Also
1 Follow the steps for “Set Up an Example Model With a MATLAB Function Block” on
page 14-6 . This example model contains one Inport block and one Outport block.
2 Name the model ex_data_type_ML_Func.
3 In the MATLAB Function Block Editor enter the function, as follows:
function y1 = typeconv(u1)
y1 = double(u1);
end
4 Press Ctrl+B to build the model and generate code.
Results
void ex_data_type_ML_func_step(void)
{
y1 = u1;
}
See Also
Data Type Conversion
14-13
14 Patterns for C Code in Embedded Coder
Type Qualifiers
This example shows how to apply the const and volatile keywords to a global variable
that represents parameter data.
C Construct
const volatile double myParam = 9.8;
Procedure
1 Create the ex_const_volatile model by using a Gain block.
Alternatively, to apply only one of the keywords, you can use the storage classes
Const or Volatile.
7 Generate code from the model.
14-14
See Also
Results
The generated source file ex_const_volatile.c defines myParam by using the const
and volatile keywords.
See Also
Related Examples
• “Create Tunable Calibration Parameter in the Generated Code” on page 22-121
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
14-15
14 Patterns for C Code in Embedded Coder
ex_logical_SL
Procedure
1 From the Logic and Bit Operations library, drag a Logical Operator block into your
model.
2 Double-click the block to configure the logical operation. Set the Operator field to
OR.
3 Name the blocks, as shown in the model ex_logical_SL.
4 Connect the blocks and name the signals, as shown in the model ex_logical_SL.
5 Press Ctrl+B to build the model and generate code.
Note You can use the above procedure to implement relational operators by replacing
the Logical Operator block with a Relational Operator block.
14-16
Relational and Logical Operators
Results
Procedure
1 Follow the steps for “Set Up an Example Model With a Stateflow Chart” on page 14-5.
This example model contains two Inport blocks and one Outport block.
2 Name the example model ex_logical_SF.
3 In the Stateflow Editor, specify the Data Type for y1 as Boolean.
4 In the Stateflow Editor, create the Stateflow diagram as shown. The relational or
logical operation actions are on the transition from one junction to another.
Relational statements specify conditions to conditionally allow a transition. In that
case, the statement would be within square brackets.
14-17
14 Patterns for C Code in Embedded Coder
Results
void ex_logical_SF_step(void)
{
y1 = (u1 || u2);
}
Procedure
1 Follow the steps for “Set Up an Example Model With a MATLAB Function Block” on
page 14-6 . This example model contains two Inport blocks and one Outport block.
2 Name the example model ex_rel_operator_ML.
3 In the MATLAB Function Block Editor enter the function, as follows:
function y1 = fcn(u1, u2)
y1 = u1 > u2;
end
4 Press Ctrl+B to build the model and generate code.
Results
14-18
Relational and Logical Operators
void ex_rel_operator_ML_step(void)
{
y = (u1 > u2);
}
14-19
14 Patterns for C Code in Embedded Coder
Bitwise Operations
ex_bit_logic_SL
Procedure
1 Drag a Bitwise Operator block from the Logic and Bit Operations library into your
model.
2 Double-click the block to open the Block Parameters dialog.
3 Select the type of Operator. In this example, select AND.
4 In order to perform Bitwise operations with a bit-mask, select Use bit mask.
Note If another input uses Bitwise operations, clear the Use bit mask parameter
and enter the number of input ports.
5 In the Bit Mask field, enter a decimal number. Use bin2dec or hex2dec to convert
from binary or hexadecimal. In this example, enter hex2dec('D9').
6 Name the blocks, as shown in, model ex_bit_logic_SL.
7 Connect the blocks and name the signals, as shown in, model ex_bit_logic_SL.
8 Press Ctrl+B to build the model and generate code.
Results
14-20
Bitwise Operations
uint8_T u1;
uint8_T y1;
void ex_bit_logic_SL_step(void)
{
y1 = (uint8_T)(u1 & 217);
}
Stateflow Chart
Procedure
1 Follow the steps for “Set Up an Example Model With a Stateflow Chart” on page 14-5.
This example contains one Inport block and one Outport block.
2 Name the example model ex_bit_logic_SF.
3 From the Stateflow Editor, select Tools > Explore to open the Model Explorer.
4 In the Model Explorer, on the right pane, select Enable C-bit operations.
5 In the Stateflow Editor, create the Stateflow diagram, ex_bit_logic_SF/
Bit_Logic.
6 Press Ctrl+B to build the model and generate code.
Results
uint8_T u1;
uint8_T y1;
void bit_logic_SF_step(void)
14-21
14 Patterns for C Code in Embedded Coder
{
y1 = (uint8_T)(u1 & 0xD9);
}
Procedure
1 Follow the steps for “Set Up an Example Model With a MATLAB Function Block” on
page 14-6. This example model contains two Inport blocks and one Outport block.
2 Name your model ex_bit_logic_ML.
3 In the MATLAB Function Block Editor enter the function, as follows:
y1 = bitor(u1, u2);
end
4 Press Ctrl+B to build the model and generate code.
Results
uint8_T u1;
uint8_T u2;
uint8_T y1;
void ex_bit_logic_ML_step(void)
{
y1 = (uint8_T)(u1 | u2);
}
14-22
Enumeration
Enumeration
To generate an enumerated data type, define an enumeration class in a MATLAB file.
Then, use the enumeration class as the data type of signals, block parameters, and states
in a model.
C Construct
typedef enum {
Choice1 = 0,
Choice2
} myEnumType;
Procedure
In your current folder, create the MATLAB file ex_myEnumType.m. The file defines an
enumeration class ex_myEnumType.
enumeration
Choice1(0)
Choice2(1)
end %enumeration
methods (Static)
function retVal = getHeaderFile()
retVal = 'myEnumHdr.h';
end %function
end %classdef
open_system('ex_pattern_enum')
14-23
14 Patterns for C Code in Embedded Coder
In the Model Data Editor, use the Value column to set the constant value to myChoice.
Next to myChoice, click the action button (with three vertical dots) and select Create.
In the property dialog box for myChoice, set Storage Class to ExportedGlobal. With
this setting, the object appears in the generated code as a global variable.
Alternatively, at the command prompt, use these commands to create the object:
myChoice = Simulink.Parameter(ex_myEnumType.Choice1);
myChoice.CoderInfo.StorageClass = 'ExportedGlobal';
In the model, select the output signal of the Enumerated Constant block.
In the Model Data Editor, use the Data Type column to set the signal data type to Enum:
ex_myEnumType.
14-24
Enumeration
Set Configuration Parameters > File packaging format to Modular. With this
setting, in the generated code, the definition of ex_myEnumType can appear in the
specified header file, myEnumHdr.h.
rtwbuild('ex_pattern_enum');
Results
View the generated header file myEnumHdr.h. The file defines the enumerated data type.
file = fullfile('ex_pattern_enum_ert_rtw','myEnumHdr.h');
rtwdemodbtype(file,'typedef enum {','} ex_myEnumType;',1,1)
typedef enum {
Choice1 = 0, /* Default value */
Choice2
} ex_myEnumType;
View the source file ex_pattern_enum.c. The file defines the variable myChoice. The
algorithm in the step function uses myChoice to route one of the input signals to the
output signal.
file = fullfile('ex_pattern_enum_ert_rtw','ex_pattern_enum.c');
rtwdemodbtype(file,'ex_myEnumType myChoice = Choice1;','/* Variable: myChoice',1,1)
rtwdemodbtype(file,'/* Model step function */','/* Model initialize function */',1,0)
14-25
14 Patterns for C Code in Embedded Coder
void ex_pattern_enum_step(void)
{
/* MultiPortSwitch: '<Root>/Multiport Switch' incorporates:
* Constant: '<S1>/Constant'
*/
if (myChoice == Choice1) {
/* Outport: '<Root>/Data Out' incorporates:
* Inport: '<Root>/Data In 1'
*/
rtY.DataOut = rtU.DataIn1;
} else {
/* Outport: '<Root>/Data Out' incorporates:
* Inport: '<Root>/Data In 2'
*/
rtY.DataOut = rtU.DataIn2;
}
See Also
enumeration
Related Examples
• “Use Enumerated Data in Simulink Models” (Simulink)
• “Use Enumerated Data in Generated Code” on page 22-90
• “Define Enumerated Data Types” (Stateflow)
• “Define Enumerations for MATLAB Function Blocks” (Simulink)
14-26
If-Else
If-Else
C Construct
if (u1 > u2)
{
y1 = u1;
}
else
{
y1 = u2;
}
Modeling Patterns
• “Modeling Pattern for If-Else: Switch block” on page 14-27
• “Modeling Pattern for If-Else: Stateflow Chart” on page 14-29
• “Modeling Pattern for If-Else: MATLAB Function Block” on page 14-30
14-27
14 Patterns for C Code in Embedded Coder
Model ex_if_else_SL
Procedure
1 Drag the Switch block from the Simulink>Signal Routing library into your model.
2 Connect the data inputs and outputs to the block.
3 Drag a Relational Operator block from the Logic & Bit Operations library into your
model.
4 Connect the signals that are used in the if-expression to the Relational Operator
block. The order of connection determines the placement of each signal in the if-
expression.
5 Configure the Relational Operator block to be a greater than operator.
6 Connect the controlling input to the middle input port of the Switch block.
7 Double-click the Switch block and set Criteria for passing first input to u2~=0.
The software selects u1 if u2 is TRUE; otherwise u2 passes.
8 Enter Ctrl+B to build the model and generate code.
Results
The generated code includes the following ex_if_else_SL_step function in the file
ex_if_else_SL.c:
/* External inputs (root inport signals with auto storage) */
ExternalInputs U;
14-28
If-Else
ex_if_else_SF/Chart
Procedure
1 Follow the steps for “Set Up an Example Model With a Stateflow Chart” on page 14-5.
This example model contains two Inport blocks and one Outport block.
2 Name your model ex_if_else_SF.
3 When configuring your Stateflow chart, select Chart > Add Patterns > Decision >
If-Else. The Stateflow Pattern dialog opens. Fill in the fields as follows:
14-29
14 Patterns for C Code in Embedded Coder
If condition u1 > u2
If action y1 = u1
Else action y1 = u2
4 Press Ctrl+B to build the model and generate code.
Results
The generated code includes the following ex_if_else_SF_step function in the file
If_Else_SF.c:
/* External inputs (root inport signals with auto storage) */
ExternalInputs U;
/* Transition: '<S1>:19' */
} else {
/* Outport: '<Root>/y1' */
/* Transition: '<S1>:17' */
Y.y1 = U.u2;
}
1 Follow the steps for “Set Up an Example Model With a MATLAB Function Block” on
page 14-6. This example model contains two Inport blocks and one Outport block.
14-30
If-Else
Results
The generated code includes the following ex_if_else_ML_step function in the file
ex_if_else_ML.c:
/* External inputs (root inport signals with auto storage) */
ExternalInputs U;
14-31
14 Patterns for C Code in Embedded Coder
Switch
C Construct
switch (u1)
{
case 2:
y1 = u2;
break;
case 3:
u3;
break;
default:
y1 = u4;
break;
}
Modeling Patterns
• “Modeling Pattern for Switch: Switch Case block” on page 14-32
• “Modeling Pattern for Switch: MATLAB Function block” on page 14-35
• “Convert If-Elseif-Else to Switch statement” on page 14-36
14-32
Switch
Model ex_switch_SL
Procedure
1 Drag a Switch Case block from the Simulink > Ports and Subsystems library into
your model.
2 Double-click the block. In the Block Parameters dialog box, fill in the Case
Conditions parameter. In this example, the two cases are: {2,3}.
3 Select the Show default case parameter. The default case is optional in a switch
statement.
4 Connect the condition input u1 to the input port of the Switch block.
5 Drag Switch Case Action Subsystem blocks from the Simulink>Ports and
Subsystems library to correspond with the number of cases.
6 Configure the Switch Case Action Subsystem subsystems.
7 Drag a Merge block from the Simulink > Signal Routing library to merge the
outputs.
8 The Switch Case block takes an integer input, therefore, the input signal u1 is type
cast to an int32.
14-33
14 Patterns for C Code in Embedded Coder
Results
The generated code includes the following ex_switch_SL_step function in the file
ex_switch_SL.c:
/* Exported block signals */
int32_T u1; /* '<Root>/u1' */
case 3:
/* Inport: '<S2>/u3' incorporates:
* Inport: '<Root>/u3'
* Outport: '<Root>/y1'
*/
Y.y1 = U.u3;
break;
default:
/* Inport: '<S3>/u4' incorporates:
* Inport: '<Root>/u4'
* Outport: '<Root>/y1'
*/
Y.y1 = U.u4;
break;
}
}
14-34
Switch
1 Follow the steps for “Set Up an Example Model With a MATLAB Function Block” on
page 14-6. This example model contains four Inport blocks and one Outport block.
2 Name your model ex_switch_ML.
3 In the MATLAB Function Block Editor enter the function, as follows:
switch u1
case 2
y1 = u2;
case 3
y1 = u3;
otherwise
y1 = u4;
end
4 Press Ctrl+B to build the model and generate code.
Results
The generated code includes the following ex_switch_ML_step function in the file
ex_switch_ML.c:
/* External inputs (root inport signals with auto storage) */
ExternalInputs U;
14-35
14 Patterns for C Code in Embedded Coder
case 3:
/* '<S1>:1:8' */
Y.y1 = U.u3;
break;
default:
/* '<S1>:1:10' */
Y.y1 = U.u4;
break;
}
}
See Also
Switch Case
Related Examples
• “If-Else” on page 14-27
• “Enumeration” on page 14-23
• “Create Flow Charts with the Pattern Wizard” (Stateflow)
• “What Is a MATLAB Function Block?” (Simulink)
14-36
For Loop
For Loop
C Construct
y1 = 0;
for(inx = 0; inx <10; inx++)
{
y1 = u1[inx] + y1;
}
Modeling Patterns:
• “Modeling Pattern for For Loop: For-Iterator Subsystem block” on page 14-37
• “Modeling Pattern for For Loop: Stateflow Chart” on page 14-40
• “Modeling Pattern for For Loop: MATLAB Function block” on page 14-41
Model ex_for_loop_SL
14-37
14 Patterns for C Code in Embedded Coder
Procedure
1 Drag a For Iterator Subsystem block from the Simulink > Ports and Subsystems
library into your model.
2 Connect the data inputs and outputs to the For Iterator Subsystem block.
3 Open the Inport block.
4 In the Block Parameters dialog box, select the Signal Attributes pane and set the
Port dimensions parameter to 10.
5 Double-click the For Iterator Subsystem block to open the subsystem.
6 Drag an Index Vector block from the Signal-Routing library into the subsystem.
7 Open the For Iterator block. In the Block Parameters dialog box set the Index-mode
parameter to Zero-based and the Iteration limit parameter to 10.
8 Connect the controlling input to the topmost input port of the Index Vector block, and
the other input to the second port.
9 Drag an Add block from the Math Operations library into the subsystem.
10 Drag a Unit Delay block from Commonly Used Blocks library into the subsystem.
11 Double-click the Unit Delay block and set the Initial Conditions parameter to 0.
This parameter initializes the state to zero.
12 Connect the blocks as shown in the model diagram.
14-38
For Loop
Results
The generated code includes the following ex_for_loop_SL_step function in the file
ex_for_loop_SL.c:
/* External inputs (root inport signals with auto storage) */
ExternalInputs U;
/* Outport: '<Root>/y1' */
Y.y1 = rtb_y1;
}
14-39
14 Patterns for C Code in Embedded Coder
Model ex_for_loop_SF
Procedure
1 Follow the steps for “Set Up an Example Model With a Stateflow Chart” on page 14-5.
This example model contains one Inport block and one Outport block.
2 Name the model ex_for_loop_SF.
3 Enter Ctrl+R to open the Model Explorer.
4 In the Model Explorer, select the output variable, u1, and in the right pane, select the
General tab and set the Initial Value to 0.
5 In the Stateflow Editor, select Chart > Add Patterns > Loop > For. The Stateflow
Pattern dialog opens.
6 Fill in the fields in the Stateflow Pattern dialog box as follows:
14-40
For Loop
Results
The generated code includes the following ex_for_loop_SF_step function in the file
ex_for_loop_SF.c:
/* External inputs (root inport signals with auto storage) */
ExternalInputs U;
/* Chart: '<Root>/Chart' */
/* Gateway: Chart */
/* During: Chart */
/* Entry Internal: Chart */
/* Transition: '<S1>:13' */
/* Transition: '<S1>:14' */
for (inx = 0; inx < 10; inx++) {
/* Outport: '<Root>/y1' incorporates:
* Inport: '<Root>/u1'
*/
/* Transition: '<S1>:11' */
/* Transition: '<S1>:12' */
Y.y1 += U.u1[inx];
/* Transition: '<S1>:10' */
}
1 Follow the directions for “Set Up an Example Model With a MATLAB Function Block”
on page 14-6. This example model contains one Inport block and one Outport block.
2 Name your model ex_for_loop_ML.
3 In the MATLAB Function Block Editor enter the function, as follows:
function y1 = fcn(u1)
y1 = 0;
14-41
14 Patterns for C Code in Embedded Coder
for inx=1:10
y1 = u1(inx) + y1 ;
end
4 Press Ctrl+B to build the model and generate code.
Results
The generated code includes the following ex_for_loop_ML_step function in the file
ex_for_loop_ML.c:
/* Exported block signals */
real_T u1[10]; /* '<Root>/u1' */
real_T y1; /* '<Root>/MATLAB Function' */
See Also
For Iterator Subsystem
Related Examples
• “Create Flow Charts with the Pattern Wizard” (Stateflow)
More About
• “What Is a MATLAB Function Block?” (Simulink)
14-42
While Loop
While Loop
C Construct
while(flag && (num_iter <= 100)
{
flag = func ();
num_iter ++;
}
Modeling Patterns
• “Modeling Pattern for While Loop: While Iterator Subsystem block” on page 14-43
• “Modeling Pattern for While Loop: Stateflow Chart” on page 14-46
• “Modeling Pattern for While Loop: MATLAB Function Block” on page 14-49
Model ex_while_loop_SL
14-43
14 Patterns for C Code in Embedded Coder
Procedure
1 Drag a While Iterator Subsystem block from the Simulink > Ports and Subsystems
library into the model.
2 Drag a Constant block from the Simulink > Commonly Used Blocks library into
the model. In this case, set the Initial Condition to 1 and the Data Type to
Boolean. You do not have to set the initial condition to FALSE. The initial condition
can be dependent on the input to the block.
3 Connect the Constant block to the While Iterator Subsystem block.
4 Double-click the While Iterator Subsystem block to open the subsystem.
5 Place a Subsystem block next to the While Iterator block.
6 Right-click the subsystem and select Block Parameters (Subsystem). The Block
Parameters dialog box opens.
7 Select the Treat as atomic unit parameter to configure the subsystem to generate a
function. This enables parameters on the Code Generation tab.
8 Select the Code Generation tab. From the Function packaging list, select the
option, Nonreusable function.
9 From the Function name options list, select the option, User specified. The
Function name parameter is displayed.
10 Specify the name as func.
11 Click Apply.
14-44
While Loop
12 Double-click the func subsystem block. In this example, function func() has an
output flag set to 0 or 1 depending on the result of the algorithm in func( ). Create
the func() algorithm as shown in the following diagram:
func
13 Double-click the While Iterator block to set the Maximum number of iterations to
100.
14 Connect blocks as shown in the model and subsystem diagrams.
Results
The generated code includes the following ex_while_loop_SL_step function in the file
ex_while_loop_SL.c:
/* Model step function */
void ex_while_loop_SL_step(void)
{
int32_T s1_iter;
boolean_T loopCond;
14-45
14 Patterns for C Code in Embedded Coder
Model ex_while_loop_SF
14-46
While Loop
Procedure
1 Add a Stateflow Chart to your model from the Stateflow > Chart library.
2 Double-click the chart.
3 Add the input, flag, and output, func, to the chart and specify their data type.
4 Connect the data input and output to the Stateflow chart as shown in the model
diagram.
5 In the Model Explorer, select the output variable, then, in the right pane, select the
General tab and set the Initial Value to 0.
6 Select Chart > Add Patterns > Loop > While. The Stateflow Pattern dialog opens.
7 Fill in the fields for the Stateflow Pattern dialog box as follows:
14-47
14 Patterns for C Code in Embedded Coder
12 From the Function name options list, select the option, User specified. The
Function name parameter is displayed.
13 Specify the name as func.
14 Click Apply to apply the changes.
15 Double-click the func subsystem block. In this example, function func has an output
flag set to 0 or 1 depending on the result of the algorithm in func( ). The Trigger
block parameter Trigger type is function-call. Create the func() algorithm, as
shown in the following diagram:
Results
The generated code includes the following ex_while_loop_SF_step function in the file
ex_while_loop_SF.c:
14-48
While Loop
/* Chart: '<Root>/Chart' */
/* Gateway: Chart */
/* During: Chart */
/* Entry Internal: Chart */
/* Transition: '<S1>:2' */
num_iter = 1;
while (flag && (num_iter <= 100)) {
/* Outputs for Function Call SubSystem: '<Root>/func' */
/* Transition: '<S1>:3' */
/* Transition: '<S1>:4' */
/* Event: '<S1>:12' */
func();
/* Transition: '<S1>:5' */
}
Model ex_while_loop_ML
14-49
14 Patterns for C Code in Embedded Coder
Procedure
1 In the Simulink Library Browser, click Simulink > User Defined Functions, and
drag a MATLAB Function block into your model.
2 Double-click the MATLAB Function block. The MATLAB Function Block Editor opens.
3 In the MATLAB Function Block Editor enter the function, as follows:
function fcn(func_flag)
flag = true;
num_iter = 1;
14-50
While Loop
Model ex_while_loop_ML_func
14 Save and close the subsystem.
15 Connect the MATLAB Function block to the func() subsystem.
16 Save your model.
Results
The generated code includes the following while_loop_ML_step function in the file
while_loop_ML.c. In some cases an equivalent for loop might be generated instead of
a while loop.
/* '<S1>:1:4' */
num_iter = 1;
while (flag && (num_iter <= 100)) {
/* Outputs for Function Call SubSystem: '<Root>/func' */
/* '<S1>:1:6' */
/* '<S1>:1:7' */
14-51
14 Patterns for C Code in Embedded Coder
func();
/* '<S1>:1:8' */
flag = func_flag_0;
/* '<S1>:1:9' */
num_iter++;
}
See Also
While Iterator Subsystem
Related Examples
• “Create Flow Charts with the Pattern Wizard” (Stateflow)
More About
• “What Is a MATLAB Function Block?” (Simulink)
14-52
Do While Loop
Do While Loop
C Construct
num_iter = 1;
do {
flag = func();
num_iter++;
}
while (flag && num_iter <= 100)
Modeling Patterns
• “Modeling Pattern for Do While Loop: While Iterator Subsystem block” on page 14-53
• “Modeling Pattern for Do While Loop: Stateflow Chart” on page 14-56
ex_do_while_loop_SL
14-53
14 Patterns for C Code in Embedded Coder
Procedure
1 Drag a While Iterator Subsystem block from the Simulink > Ports and Subsystems
library into the model.
2 Double-click the While Iterator Subsystem block to open the subsystem.
3 Place a Subsystem block next to the While Iterator block.
4 Right-click the subsystem and select Block Parameters (Subsystem). The Block
Parameters dialog box opens.
5 Select the Treat as atomic unit parameter to configure the subsystem to generate a
function. This enables parameters on the Code Generation tab.
6 Select the Code Generation tab. From the Function packaging list, select the
option, Nonreusable function.
7 From the Function name options list, select the option, User specified. The
Function name parameter is displayed.
8 Specify the name as func.
9 Click Apply.
10 Double-click the func subsystem block. In this example, function func has an output
flag set to 0 or 1 depending on the result of the algorithm in func. Create the func
algorithm as shown in the following diagram:
14-54
Do While Loop
Results
void func(void)
{
flag = (DWork.NextOutput > (real_T)P.Constant1_Value);
DWork.NextOutput =
rt_NormalRand(&DWork.RandSeed) * P.RandomNumber_StdDev +
P.RandomNumber_Mean;
}
void ex_do_while_loop_SL_step(void)
{
int32_T s1_iter;
s1_iter = 1;
do {
func();
s1_iter++;
} while (flag && (s1_iter <= 100));
14-55
14 Patterns for C Code in Embedded Coder
ex_do_while_loop_SF
ex_do_while_loop_SF/Chart
1 Add a Stateflow Chart to your model from the Stateflow > Chart library.
2 Double-click the chart to open it.
3 Add the inputs and outputs to the chart and specify their data type.
4 Connect the data input and output to the Stateflow chart.
5 In the Model Explorer, select the output variable, then, in the right pane, select the
General tab and set the Initial Value to 0.
14-56
Do While Loop
6 Select Chart > Add Patterns > Loop > While. The Stateflow Pattern dialog opens.
7 Fill in the fields for the Stateflow Pattern dialog box as follows:
14-57
14 Patterns for C Code in Embedded Coder
Results
void ex_do_while_loop_SF_step(void)
{
int32_T sf_num_iter;
num_iter = 1;
do {
func();
num_iter++;
} while (flag && (sf_num_iter <= 100));
See Also
While Iterator Subsystem
Related Examples
• “Create Flow Charts with the Pattern Wizard” (Stateflow)
14-58
Function Call
Function Call
To generate a function call, add a subsystem, which implements the operations that you
want.
C Construct
void add_function(void)
{
y1 = u1 + u2;
}
ex_function_call
Procedure
1 Create a model containing a subsystem. In this example, the subsystem has two
inputs and returns one output.
2 Double-click the subsystem. Create Add_Subsystem, as shown.
ex_function_call/Add_Subsystem
3 Right-click the subsystem and select Block Parameters (Subsystem) to open the
Subsystem Parameters dialog box.
4 Select the Treat as atomic unit parameter. This enables parameters on the Code
Generation tab.
14-59
14 Patterns for C Code in Embedded Coder
Select the Code Generation tab. For the Function packaging parameter, from the
drop-down list, select Nonreusable function.
5 For the Function name options parameter, from the drop-down list, select User
specified.
6 In the Function name field, enter the subsystem name, add_function.
7 In the File name options field, select Use function name.
8 Click Apply and OK.
9 Press Ctrl+B to build and generate code.
Results
In ex_function_call.c, the function is called from ex_function_call_step:
void ex_function_call_step(void)
{
add_function();
}
See Also
Function-Call Subsystem
Related Examples
• “Generate Reentrant Code from Subsystems” (Simulink Coder)
More About
• “Conditionally Executed Subsystems Overview” (Simulink)
14-60
Function Prototyping
Function Prototyping
C Construct
double add_function(double u1, double u2)
{
return u1 + u2;
}
Modeling Patterns
• “Function Call Using Graphical Functions” on page 14-61
• “Control Function Prototype of the model_step Function” on page 14-63
1 Follow the steps in “Set Up an Example Model With a Stateflow Chart” on page 14-5.
This example model contains two Inport blocks and one Outport block.
2 Name the example model ex_func_SF.
3 In the Stateflow Editor, create a graphical function by clicking the fx button and
placing a graphical function into the Stateflow chart.
4 Edit the graphical function signature to: output = add_function(u1, u2).
5 Add the transition action.
14-61
14 Patterns for C Code in Embedded Coder
ex_func_SF/Chart
In the Stateflow chart, there is an example of a simple transition that calls
add_function.
6 Open the Model Explorer. From the Model Hierarchy tree, select ex_func_SF >
Chart > f()add_function. On the right pane, specify the Function Inline Option as
Function.
7 From the Model Hierarchy tree, click Chart and on the right pane select the Export
Chart Level Functions (Make Global) parameter. The function is now available
globally to the entire model.
8 Press Ctrl+B to build the model and generate code.
Results
14-62
Function Prototyping
ex_control_step_function
Procedure
• Switch the order of the two inports. Move the row for Inport below the row for
Inport1.
• For Inport1, set C Type Qualifier to Auto (pass by value) and C Identifier
Name to argIn1.
• For Inport, set C Type Qualifier to Pointer to const and C Identifier
Name to argIn2.
14-63
14 Patterns for C Code in Embedded Coder
For more information about controlling function prototypes, see “Customize Generated C
Function Interfaces” on page 29-2.
Results
See Also
Related Examples
• “Options for Configuring Generated C Function Interfaces” on page 29-2
• “Reuse Logic Patterns Using Graphical Functions” (Stateflow)
14-64
External C Functions
External C Functions
C Construct
#include "add.h"
double add(double u1, double u2)
{
double y1;
y1 = u1 + u2;
return (y1);
}
Modeling Patterns
There are several methods for integrating legacy C functions into the generated code.
These methods either create an S-function or make a call to an external C function. For
more information on S-functions, see “S-Functions and Code Generation” (Simulink
Coder).
Procedure
1 Create a C header file named add.h that contains the function signature:
14-65
14 Patterns for C Code in Embedded Coder
2 Create a C source file named add.c that contains the function body:
14-66
External C Functions
ex_function_call_lct
5 Name and save your model. In this example, the model is named
ex_function_call_lct.
6 Press Ctrl+B to build the model and generate code.
Results
#include "add.h"
1 Create a C header file named add.h that contains the example function signature.
2 Create a C source file named add.c that contains the function body.
3 Follow the steps for “Set Up an Example Model With a Stateflow Chart” on page 14-5.
This example model contains two Inport blocks and one Outport block.
4 Name the example model ex_exfunction_call_SF.
14-67
14 Patterns for C Code in Embedded Coder
5 Double-click the Stateflow chart and edit the chart as shown. Place the call to the
add function within a transition action.
ex_exfunction_call_SF/Chart
6 On the Stateflow Editor, select Simulation > Model Configuration Parameters.
7 On the Configuration Parameters dialog box, select Simulation Target > Custom
Code. In the Include custom C code in generated section, on the left pane, select
Header file and in the Header file field, enter the #include statement:
#include "add.h"
8 In the Include list of additional section, select Source files and in the Source
files field, enter add.c.
9 On the Configuration Parameters dialog box, select Code Generation > Custom
Code.
10 Select Use the same custom code settings as Simulation Target .
11 Press Ctrl+B to build the model and generate code.
Results
void exfunction_call_SF_step(void)
{
y1 = (real_T)add(u1, u2);
}
14-68
External C Functions
1 Create a C header file named add.h that contains the example function signature.
2 Create a C source file named add.c that contains the function body.
3 In the Simulink Library Browser, click Simulink > User Defined Functions, and
drag a MATLAB Function block into your model.
4 Double-click the MATLAB Function block. The MATLAB Function Block Editor opens.
5 Edit the function to include the statement:
end
6 Open the Configuration Parameters dialog box, and select Simulation Target >
Custom Code.
7 In the Include custom C code in generated section, on the left pane, select
Header file and in the Header file field, enter the statement, :
#include "add.h"
8 In the Include list of additional section, select Source files and in the Source
files field, enter add.c.
9 Add two Inport blocks and one Outport block to the model and connect to the
MATLAB Function block.
10 Configure the signals: u1, u2, and y1, as described in “Configure Input Ports, Output
Ports, and Arbitrary Signals” on page 14-3.
11 Save the model as ex_exfunction_call_ML.
12 Press Ctrl+B to build the model and generate code.
Results
14-69
14 Patterns for C Code in Embedded Coder
real_T u1;
real_T u2;
real_T y1;
void ex_exfunction_call_ML_step(void)
{
y1 = add(u1, u2);
}
See Also
Related Examples
• “Call C Functions in C Charts” (Stateflow)
More About
• “When to Generate Code from MATLAB Algorithms” (Simulink)
• “Legacy Code Tool and Code Generation” (Simulink Coder)
14-70
Macro Definitions (#define)
C Construct
#define myParam 9.8;
14-71
14 Patterns for C Code in Embedded Coder
Results
#ifndef _EXTERNAL_PARAMS
#define _EXTERNAL_PARAMS
#endif
/* EOF */
7 Generate code from the model.
Results
The generated header file ex_param_macro.h does not define the macro. Instead, the
file includes (#include) the custom header file external_params.h.
14-72
See Also
The source file ex_param_macro.c contains a guard to check that a definition for
myParam exists.
/*
* Check that imported macros with storage
* class "ImportedDefine" are defined
*/
#ifndef myParam
#error The variable for the parameter "myParam" is not defined
#endif
See Also
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
14-73
14 Patterns for C Code in Embedded Coder
14-74
Typedef
Typedef
C Construct
typedef float float_32;
Procedure
To create a data type alias in Simulink, use a Simulink.AliasType. The code generator
creates a typedef statement.
The built-in Simulink data type single corresponds to the C data type float.
float_32 = Simulink.AliasType('single')
2 Create the ex_typedef model by using a Gain block.
With this setting, the Inport block appears in the generated code as a separate global
variable.
11 Generate code from the model.
14-75
14 Patterns for C Code in Embedded Coder
Results
The generated header file ex_typedef.h defines the data type alias float_32.
#ifndef DEFINED_TYPEDEF_FOR_float_32_
#define DEFINED_TYPEDEF_FOR_float_32_
#endif
By default, the code generator also creates the alias real32_T, which corresponds to the
C data type float. You can see the typedef statement in the generated header file
rtwtypes.h.
The generated source file ex_typedef.c uses float_32 to define the global variable
mySig.
See Also
Simulink.AliasType
Related Examples
• “Control Data Type Names in Generated Code” on page 24-2
• “Structures of Signals” on page 14-81
14-76
Structures of Parameters
Structures of Parameters
Create a structure in the generated code. The structure stores parameter data.
C Construct
typedef struct {
double G1;
double G2;
} myStructType;
myStructType myStruct = {
2.0,
-2.0
} ;
Procedure
rtwdemo_paraminline
14-77
14 Patterns for C Code in Embedded Coder
In the Model Data Editor, use the Value column to set the value of the Gain parameter to
myStruct.G1.
Use the Model Data Editor to set the value of the Gain parameter in the G2 block to
myStruct.G2.
Next to myStruct.G2, click the action button (with three vertical dots) and select
Create.
In the Create New Data dialog box, set Value to Simulink.Parameter(struct) and
click Create. A Simulink.Parameter object named myStruct appears in the base
workspace.
In the Simulink.Parameter property dialog box, next to the Value property, click the
action button and select Open Variable Editor.
In the Variable Editor, right-click the white space under the Field column and select New.
Name the new structure field G1. Use the Value column to set the value of the field to 2.
Use the Variable Editor to add a field G2 whose value is -2 and then close the Variable
Editor.
Alternatively, use these commands to configure the blocks and create myStruct.
rtwdemo_paraminline
set_param('rtwdemo_paraminline/G1','Gain','myStruct.G1')
set_param('rtwdemo_paraminline/G2','Gain','myStruct.G2')
myStruct.G1 = 2;
myStruct.G2 = -2;
myStruct = Simulink.Parameter(myStruct);
myStruct.CoderInfo.StorageClass = 'ExportedGlobal';
14-78
Structures of Parameters
Results
rtwbuild('rtwdemo_paraminline')
file = fullfile('rtwdemo_paraminline_grt_rtw',...
'rtwdemo_paraminline_types.h');
rtwdemodbtype(file,'typedef struct {','} struct_6h72eH5WFuEIyQr5YrdGuB;',...
1,1)
typedef struct {
real_T G1;
real_T G2;
} struct_6h72eH5WFuEIyQr5YrdGuB;
The source file rtwdemo_paraminline.c defines and initializes the structure variable
myStruct.
file = fullfile('rtwdemo_paraminline_grt_rtw','rtwdemo_paraminline.c');
rtwdemodbtype(file,'struct_6h72eH5WFuEIyQr5YrdGuB myStruct',...
'/* Variable: myStruct',1,1)
struct_6h72eH5WFuEIyQr5YrdGuB myStruct = {
2.0,
-2.0
} ; /* Variable: myStruct
Optionally, specify a name to use for the structure type definition (struct).
Simulink.Bus.createObject(myStruct.Value);
14-79
14 Patterns for C Code in Embedded Coder
The default name of the object is slBus1. Change the name by copying the object into a
new MATLAB variable.
myStructType = copy(slBus1);
In the Model Data Editor, click the Show/refresh additional information button.
In the data table, find the row that corresponds to myStruct. Use the Data Type column
to set the data type of myStruct to Bus: myStructType.
Alternatively, at the command prompt, use this command to set the data type of
myStruct.
rtwbuild('rtwdemo_paraminline')
The code generates the definition of the structure type myStructType and uses this type
to define the global variable myStruct.
myStructType myStruct = {
2.0,
-2.0
} ; /* Variable: myStruct
See Also
Related Examples
• “Organize Data into Structures in Generated Code” on page 22-177
14-80
Structures of Signals
Structures of Signals
This example shows how to create a structure of signal data in the generated code.
C Construct
typedef struct {
double signal1;
double signal2;
double signal3;
} my_signals_type;
Procedure
To represent a structure type in a model, create a Simulink.Bus object. Use the object
as the data type of bus signals in your model.
Create the ex_signal_struct model with Gain blocks, a Bus Creator block, and a Unit
Delay block. The Gain and Unit Delay blocks make the structure more identifiable in the
generated code.
To configure the Bus Creator block to accept three inputs, in the block dialog box, set
Number of inputs to 3.
14-81
14 Patterns for C Code in Embedded Coder
Use the Bus Editor to create a Simulink.Bus object named my_signals_type that
contains three signal elements: signal1, signal2, and signal3. To create bus objects
with the Bus Editor, see “Create Bus Objects with the Bus Editor” (Simulink).
This bus object represents the structure type that you want the generated code to use.
In the Bus Creator block dialog box, set Output data type to Bus: my_signals_type.
Select Output as nonvirtual bus. Click OK. A nonvirtual bus appears in the generated
code as a structure.
In the Model Data Editor, on the Signals tab, from the Change view drop-down list,
select Code.
In the model, click the output signal of the Bus Creator block.
In the Model Data Editor, for the output of the Bus Creator block, set Name to
sig_struct_var.
Set Storage Class to ExportedGlobal. With this setting, the output of the Bus Creator
block appears in the generated code as a separate global structure variable named
sig_struct_var.
Results
typedef struct {
real_T signal1;
real_T signal2;
14-82
See Also
real_T signal3;
} my_signals_type;
The source file ex_signal_struct.c allocates memory for the global variable
sig_struct_var, which represents the output of the Bus Creator block.
In the same file, in the model step function, the algorithm accesses sig_struct_var
and the fields of sig_struct_var.
See Also
Simulink.Bus
Related Examples
• “Organize Data into Structures in Generated Code” on page 22-177
• “Combine Buses into an Array of Buses” (Simulink)
14-83
14 Patterns for C Code in Embedded Coder
C Construct
typedef struct {
double signal1;
double signal2;
double signal3;
} B_struct_type;
typedef struct {
double signal1;
double signal2;
} C_struct_type;
typedef struct {
B_struct_type subStruct_B;
C_struct_type subStruct_C;
} A_struct_type;
Procedure
To represent a structure type in a model, create a Simulink.Bus object. Use the object
as the data type of bus signals in your model.
To nest a structure inside another structure, use a bus object as the data type of a signal
element in another bus object.
Create the ex_signal_nested_struct model with Gain blocks, Bus Creator blocks,
and a Unit Delay block. The Gain and Unit Delay blocks make the structure more
identifiable in the generated code.
14-84
Nested Structures of Signals
To configure a Bus Creator block to accept three inputs, in the block dialog box, set
Number of inputs to 3.
Use the Bus Editor to create a Simulink.Bus object named A_struct_type that
contains two signal elements: subStruct_B and subStruct_C. To create bus objects
with the Bus Editor, see “Create Bus Objects with the Bus Editor” (Simulink). This bus
object represents the top-level structure type that you want the generated code to use.
For the subStruct_B element, set DataType to Bus: B_struct_type. Use a similar
type name for subStruct_C.
14-85
14 Patterns for C Code in Embedded Coder
Each signal element in A_struct_type uses another bus object as a data type. Now,
these elements represent substructures.
Use the Bus Editor to create the Simulink.Bus objects B_struct_type (with three
signal elements) and C_struct_type (with two signal elements).
In the dialog box of the Bus Creator block that collects the three Gain signals, set Output
data type to Bus: B_struct_type. Click Apply.
In the dialog box of the other subordinate Bus Creator block, set Output data type to
Bus: C_struct_type and select Output as nonvirtual bus. Click OK.
In the last Bus Creator block dialog box, set Output data type to Bus: A_struct_type
and select Output as nonvirtual bus. Click OK.
In the Model Data Editor, on the Signals tab, from the Change view drop-down list,
select Code.
14-86
Nested Structures of Signals
In the model, click the output signal of the A_struct_type Bus Creator block, which
feeds the Unit Delay block.
In the Model Data Editor, for the output of the Bus Creator block, set Name to
sig_struct_var.
Set Storage Class to ExportedGlobal. With this setting, the output of the Bus Creator
block appears in the generated code as a separate global structure variable named
sig_struct_var.
Results
typedef struct {
real_T signal1;
real_T signal2;
real_T signal3;
} B_struct_type;
typedef struct {
real_T signal1;
real_T signal2;
} C_struct_type;
typedef struct {
B_struct_type subStruct_B;
C_struct_type subStruct_C;
} A_struct_type;
14-87
14 Patterns for C Code in Embedded Coder
In the same file, in the model step function, the algorithm accesses sig_struct_var
and the fields of sig_struct_var.
See Also
Simulink.Bus
Related Examples
• “Organize Data into Structures in Generated Code” on page 22-177
• “Combine Buses into an Array of Buses” (Simulink)
14-88
Bitfields
Bitfields
C Construct
typedef struct {
unsigned int p1 : 1;
unsigned int p2 : 1;
unsigned int p3 : 1;
} my_struct_type
Procedure
1 Create the ex_struct_bitfield_CSC model with three Constant blocks and three
Outport blocks.
14-89
14 Patterns for C Code in Embedded Coder
8 In the Model Data Editor, click the Show/refresh additional information button.
9 Set the Change view drop-down list to Code.
10 Use the Storage Class column to apply the custom storage class BitField to the
parameter objects.
11 Use the Struct Name column to configure each object to use the same structure
type, my_struct.
12 Generate code from the model.
Results
The generated header file ex_struct_bitfield_CSC.h defines the structure type
my_struct_type.
/* p2 */
1,
/* p3 */
0
};
14-90
See Also
See Also
Related Examples
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
• “Pack Boolean data into bitfields” (Simulink Coder)
14-91
14 Patterns for C Code in Embedded Coder
C Construct
float myParams[5]= {1.0F,2.0F,3.0F,4.0F,5.0F};
Procedure
1 Create the ex_param_array model by using a Gain block.
2 In the model, select View > Property Inspector. The Property Inspector opens.
3 In the model, select the Gain block.
4 In the Property Inspector, set the value of the Gain parameter to myParams.
5
Next to the parameter value, click the action button and select Create.
6 In the Create New Data dialog box, set Value to Simulink.Parameter([1 2 3 4
5]). Click Create.
With this setting, myParams appears in the generated code as a separate global
variable.
8 Set Data type to single. Click OK.
9 Generate code from the model.
Results
The generated source file ex_param_array.c defines and initializes the global variable
myParams.
14-92
See Also
See Also
Related Examples
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Code Generation of Matrices and Arrays” on page 36-77
14-93
14 Patterns for C Code in Embedded Coder
C Construct
double myIn[5];
double myOut[5];
Procedure
1 Create the ex_signal_array model by using a Gain block.
With this setting, the blocks appear in the generated code as separate global
variables.
11 Generate code from the model.
Results
The generated source file ex_signal_array.c defines the global variables myIn and
myOut as arrays with 5 elements each.
14-94
See Also
See Also
Related Examples
• “Determine Output Signal Dimensions” (Simulink)
• “Signal Dimensions” (Simulink)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Code Generation of Matrices and Arrays” on page 36-77
14-95
14 Patterns for C Code in Embedded Coder
Pointers
When your handwritten code allocates memory for signal, state, or parameter data, you
can generate code that accesses that data through a pointer. Apply a storage class such
as ImportedExternPointer to a data item in the model. Your handwritten code
provides the pointer definition.
C Construct
extern double *myIn;
Procedure
1 Create the ex_pointer model by using a Gain block.
Results
The generated header file ex_pointer.h declares the pointer.
In the generated source file ex_pointer.c, in the model step function, the algorithm
dereferences the pointer, myIn.
14-96
See Also
See Also
Related Examples
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements”
(Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
14-97
15
• “Implement Dimension Variants for Array Sizes in Generated Code” on page 15-2
• “Code Generation for Variant Blocks” on page 15-18
• “Represent Subsystem and Model Variants in Generated Code” on page 15-23
• “Generate Preprocessor Conditionals for Variant Systems” on page 15-35
• “Represent Variant Source and Sink Blocks in Generated Code” on page 15-42
• “Configure Dimension Variants for S-Function Blocks” on page 15-52
• “Generate Code for Variant Subsystem with Child Subsystems of Different Output
Signal Dimensions” on page 15-57
15 Variant Systems in Embedded Coder
Dimension Variants
Use symbolic dimensions to simulate various sets of dimension choices without
regenerating code for every set. Set up your model with dimensions that you specify as
symbols in blocks and data objects. These symbols propagate throughout the model
during simulation, and then go into the generated code. Modeling constraints for symbols
during simulation (for example, C=A+B) are output as preprocessor conditionals in either
the model.h or the model _types.h file.
You can directly specify dimension information as a symbol or a numeric constant for
these blocks and data objects:
• Inport
• Outport
• Signal Specification
• Data Store Memory
• Interpreted MATLAB Function
• Simulink.Signal
• Simulink.Parameter
• Simulink.BusElement
• AUTOSAR.Parameter
The Data Store Memory and Interpreted MATLAB Function blocks also support variable
dimension signals. For these blocks, the symbolic dimensions control the maximum
allowed size.
You must provide the code for Simulink.Parameter objects that contain symbolic
dimensions. You can provide this code by using the ImportedExtern or
ImportedExternPointer built-in storage classes.
15-2
Implement Dimension Variants for Array Sizes in Generated Code
You must fix symbolic dimension values at compile-time. You can not resolve a symbolic
dimension to another variable and then vary it during run-time because you define the
behavior during simulation.
Note: The dimension variants feature is on by default. You can turn off this feature by
clearing the “Allow symbolic dimension specification” (Simulink) parameter in the
Configuration Parameters dialog box.
1 To show block names, on the Display menu, deselect Hide Automatic Names.
2 Open the Model Explorer. Select the base workspace pane.
15-3
15 Variant Systems in Embedded Coder
3 In the base workspace, there are four Simulink.Parameter objects for specifying
symbolic dimensions. These Simulink.Parameter objects have the names A, B, C,
and D.
4 Select the Simulink.Parameter object A. Review the information in the
Simulink.Parameter dialog box. A has a storage class of CompilerFlag.
5 Repeat Step 4 for each of the Simulink.Parameter objects B, C, and D.
6 For Simulink.Parameter objects with an ImportedDefine custom storage class,
provide a header file on the MATLAB path. Insert the name of the header file in the
HeaderFile field in the Simulink.Parameter dialog box.
You can use MATLAB expressions to specify symbolic dimensions. For a list of supported
MATLAB expressions, see the section Operators and Operands in Variant Condition
Expressions in “Introduction to Variant Controls” (Simulink).
1 Open the Source Block Parameters dialog box of Inport Block In2. In the Signal
Attributes tab, the Port Dimensions field contains the Simulink.Parameter
object A. For Inport blocks, you specify symbolic dimensions in the Port Dimensions
field.
2 Open the Source Block Parameters dialog box of Inport block In3. In the Signal
Attributes tab, the Port Dimensions field contains the Simulink.Parameter
object B.
3 In the base workspace, select the Simulink.Parameter object Data. In the
Simulink.Parameter dialog box for Data, the Dimension field has the character vector
'[1,C]' , which is equivalent to '[1,5]' because C has a value of 5. The Value
field contains an array with 5 values, so the dimensions of C are consistent with the
dimension of the Data object. The dimensions of the Data object must always be
consistent with the value of the Simulink.Parameter object that is in the Data
object Dimensions field. Data has a Storage class of ImportedExtern. A
Simulink.Parameter object that uses a Simulink.Parameter for symbolic
15-4
Implement Dimension Variants for Array Sizes in Generated Code
15-5
15 Variant Systems in Embedded Coder
Though not shown in this example, you can specify an n-D dimension expression with one
or more of the dimensions being a symbol (for example, '[A,B,C]' or '[1,A,3]').
Once you have verified dimension specifications through model simulation, generate code
for rtwdemo_dimension_variants.
15-6
Implement Dimension Variants for Array Sizes in Generated Code
#ifndef A
#error The variable for the parameter "A" is not defined
#endif
#ifndef B
#error The variable for the parameter "B" is not defined
#endif
#ifndef C
#error The variable for the parameter "C" is not defined
#endif
#ifndef D
15-7
15 Variant Systems in Embedded Coder
/*
* Constraints for division operations in dimension variants
*/
#if (1 == 0) || (((A+B) % 1) != 0)
# error "The preprocessor definition '1' must not be equal to zero and the division of
#endif
/*
* Registered constraints for dimension variants
*/
/* Constraint 'C == (A+B)' registered by:
* '<Root>/1-D Lookup Table1'
*/
#if C != (A+B)
# error "The preprocessor definition 'C' must be equal to '(A+B)'"
#endif
#if A <= 1
# error "The preprocessor definition 'A' must be greater than '1'"
#endif
#if B <= 1
# error "The preprocessor definition 'B' must be greater than '1'"
#endif
15-8
Implement Dimension Variants for Array Sizes in Generated Code
15-9
15 Variant Systems in Embedded Coder
/* Sum: '<Root>/Add' */
rtb_VectorConcatenate[ForEach_itr] = rtb_VectorConcatenate_m;
}
15-10
Implement Dimension Variants for Array Sizes in Generated Code
bdclose(model)
rtwdemoclean;
cd(currentDir)
To reduce the effort of maintenance when you change the value of C, you can set the
value of Data to an expression involving C.
rtwdemo_dimension_variants
2 At the command prompt, inspect the initial values of Data and C. The value of Data
is a vector of integers from 1 to C.
Data.Value
ans =
1 2 3 4 5
C.Value
ans =
5
3 In MATLAB code syntax, the value of Data is 1:C. To preserve this relationship
between the parameter objects, set the value of Data by using the slexpr function.
Data.Value = slexpr('1:C');
4 To prevent data type propagation errors, set the data type of Data explicitly to
double, which is the data type that the parameter acquired before you set the
parameter value to an expression.
15-11
15 Variant Systems in Embedded Coder
Data.DataType = 'double';
5 Set the value of C to a different number, such as 6. Due to dimension constraints in
the model, you must set the value of another dimension symbol, A, to 3.
C.Value = 6;
A.Value = 3;
6 Simulate the model. The block diagram shows that the value of Data now has six
elements.
For more complicated applications, you can write your own MATLAB function that returns
parameter values based on dimension symbols. Set the value of the parameter data to an
expression that calls your function.
15-12
Implement Dimension Variants for Array Sizes in Generated Code
Backward Compatibility
If an existing model uses Simulink.Parameter objects to specify dimensions, it can be
incompatible with dimension variants. Here are two common scenarios:
You can address these backward compatibility issues by doing the following:
• Turn off dimension variants feature by clearing the Allow symbolic dimension
specification parameter in the Configuration Parameters dialog box.
• Update Simulink.Parameter objects that define symbolic dimensions or have
symbolic dimension specifications.
• Update the model so that only supported blocks have symbolic dimensions or
propagate symbolic dimensions.
Supported Blocks
For a list of supported blocks, see the Block Support Table. To access the information in
this table, enter showblockdatatypetable at the MATLAB command prompt.
Unsupported blocks (for example, MATLAB Function) can still work in a model containing
symbolic dimensions as long as these blocks do not directly interact with symbolic
dimensions.
• For Unit Delay blocks, you specify a Simulink.Signal object that has symbolic
dimensions for the Block Parameters > State Attributes > State name parameter.
• For Assignment and Selector blocks, you set the Block Parameters > Index Option
parameter to Index vector (dialog). For Selector and Assignment blocks, if you
specify a symbolic dimension for the Index parameter, the code generator does not
honor the symbolic dimension in the generated code.
15-13
15 Variant Systems in Embedded Coder
• For the Sum block, you specify |+ for the Block Parameters > List of signs
parameter, and you set the Block Parameters > Sum over parameter to Specified
dimension.
• For the Product block, you specify a value of 1 for the Block Parameters > Number
of inputs parameter, and you set the Multiply over parameter to Specified
dimensions.
• For the ForEach block, you specify a symbolic dimension for the Partition Width
parameter.
Note that the following modeling patterns are among those modeling patterns that can
cause Simulink to error out:
• For Switch blocks, an input signal or the Threshold parameter has symbolic
dimensions, and you select Allow different data input sizes (Results in variable-
size output signal).
• A Data Store Read block selects elements of a Simulink.Bus signal that has symbolic
dimensions.
• For Lookup Table blocks, on the Block Parameters > Algorithm tab, you select the
parameter Use one input port for all input data.
Limitations
The following products and software capabilities support dimension variants in that they
act on the numeric value of a symbolic dimension. These features do not support the
propagation of symbolic dimensions during model simulation and the preservation of
symbolic dimensions in the generated code.
15-14
Implement Dimension Variants for Array Sizes in Generated Code
• HDL Coder
• System Object
• Stateflow
• Physical modeling
• Discrete-event simulation
• Frame data
• MATLAB functions
The following limitations also apply to models that utilize symbolic dimensions.
• For simulation, the size of a symbolic dimension can equal 1. For code generation, the
size of a symbolic dimension must be greater than 1.
• If a symbolic dimension is a MATLAB expression that contains an arithmetic
expression and either a relational or logical expression, you must add +0 after the
relational or logical part of the MATLAB expression. If you do not add +0, the model
errors out during simulation because you cannot mix a boolean data type with
integer or double data types. Adding +0 converts the data type of the relational or
logical part of the expression from a boolean to a double.
For example, suppose in the Inport block parameters dialog box, the Port dimensions
parameter has the expression [(C==8)*D+E,3]. The Data type parameter is set to
double. Since C==8 is a relational expression, you must change the expression to
[((C==8)+0)*D+E,3] to prevent the model from producing an error during
simulation.
• Simulink propagates symbolic dimensions for an entire structure or matrix, but not for
a part of a structure or matrix. For example, the Simulink.Parameter P is a 2x3
matrix with symbolic dimensions [Dim,Dim1].
15-15
15 Variant Systems in Embedded Coder
Dim.CoderInfo.StorageClass='Custom'
Dim.CoderInfo.CustomStorageClass='Define'
Dim1.CoderInfo.StorageClass='Custom'
Dim1.CoderInfo.CustomStorageClass='Define'
If you specify p.A for a dimensions parameter, Simulink propagates the symbolic
dimensions [Dim,Dim1]. If you specify p.A(1,:), Simulink propagates the numeric
dimension 3 but not the symbolic dimension, Dim1.
• The MATLAB expression A(:) does not maintain symbolic dimension information. Use
A instead.
• The MATLAB expression P(2:A) does not maintain symbolic dimension information.
Use the Selector block instead.
• The MATLAB expression P(2,:) is not a tunable expression, so it does not maintain
symbolic dimension information.
• Suppose that you set the value of a mask parameter, myMaskParam, by using a field of
a structure or by using a subset of the structures in an array of structures. You store
the structure or array of structures in a Simulink.Parameter object so that you can
use a Simulink.Bus object to apply symbolic dimensions to the structure fields.
Under the mask, you configure a block parameter to use one of the fields that have
symbolic dimensions. The table shows some example cases.
In these cases, you cannot generate code from the model. As a workaround, choose
one of these techniques:
15-16
See Also
This limitation also applies when you use a field of a structure or a subset of the
structures in an array of structures as the value of a model argument in a Model block.
See Also
Related Examples
• “Configure Dimension Variants for S-Function Blocks” on page 15-52
15-17
15 Variant Systems in Embedded Coder
Code is generated for different variant choices, the active variant, and the default variant.
To generate code for variants, set the following conditions in the Variant Subsystem,
Variant Source, or Variant Sink block:
• Clear the option Override variant conditions and use the following variant.
• Select the option Analyze all choices during update diagram and generate
preprocessor conditionals.
To construct models with variant sources and sinks and generate preprocessor directives
in the generated code, see the example “Represent Variant Source and Sink Blocks in
Generated Code” on page 15-42.
15-18
Code Generation for Variant Blocks
In the figure below, the code generation process makes the following connections and
adds VariantMerge blocks to the sldemo_variant_subsystems model.
When compared to a generic Merge block the VariantMerge block can have only one
parameter which is the number of Inputs. The VariantMerge block is used for code
generation in variant subsystems internally, and is not available externally to be used in
models. The number of inputs for VariantMerge is determined and wired as shown in
the figure below.
The child subsystems of the Variant Subsystem block must be atomic subsystems. Select
Treat as atomic unit parameter in the Subsystem block parameters dialog, to make the
subsystems atomic. The VariantMerge blocks are inserted at the outport of the
subsystems if more than one child subsystems are present. If the source block of a
VariantMerge block input is nonvirtual, an error message will be displayed during code
generation. You must make the source block contiguous, by inserting Signal Conversion
blocks inside the variant choices. The signals that enter a Variant Subsystem block must
have the same signal properties (for example, signal dimensions, port width, and storage
class). The VariantMerge block does not support different signal properties because the
15-19
15 Variant Systems in Embedded Coder
input ports and output ports share the same memory. You can use symbolic dimensions to
generate code for a variant subsystem with child subsystems of different output signal
dimensions.
For example, the model Varianttoground contains a Variant Source block with one
variant choice. When the Variant Control SYSCONST_A==6 evaluates to true, the input to
Subsystem is a sine wave. When SYSCONST_A==6 evaluates to false, the input to
Subsystem is 0.0.
15-20
Code Generation for Variant Blocks
varianttoground_B.VM_Conditional_Signal_Subsystem_0_r64 = sin
(varianttoground_M->Timing.t[0]);
#endif /* SYSCONST_A == 6 */
/* SignalConversion: '<Root>/VM_SignalConversion_Subsystem_0' */
#if SYSCONST_A != 6
varianttoground_B.VM_Conditional_Signal_Subsystem_0_r64 = 0.0;
#endif /* SYSCONST_A != 6 */
The comments in the generated code indicate the presence of the hidden signal
conversion block. The code does not contain a comment for the Variant Merge block
15-21
15 Variant Systems in Embedded Coder
because this block does not have associated generated code. The Variant Merge block is
used internally and is not in the Simulink library.
15-22
Represent Subsystem and Model Variants in Generated Code
Using Simulink, you can create models that are based on a modular design platform that
comprises a fixed common structure with a finite set of variable components. The
variability helps you develop a single, fixed master design with variable components. For
more information, see “What Are Variants and When to Use Them” (Simulink) (Simulink).
When you implement variants in the generated code, you can:
• Reuse generated code from a set of application models that share functionality with
minor variations.
• Share generated code with a third party that activates one of the variants in the code.
• Validate the supported variants for a model and then choose to activate one variant for
a particular application, without regenerating and re-validating the code.
• Generate code for the default variant that is selected when an active variant does not
exist.
Using Embedded Coder, you can generate code from Simulink models containing one or
more variant choices. The generated code contains preprocessor conditionals that control
the activation of each variant choice.
This example shows how to represent variant choices in a Simulink model and then
prepare the model so that those variant choices are represented in generated code.
15-23
15 Variant Systems in Embedded Coder
variant choices inside Variant Subsystem blocks. For other ways to represent variant
choices, see “Options for Representing Variants in Simulink” (Simulink) (Simulink).
open_system('rtwdemo_preprocessor_subsys')
15-24
Represent Subsystem and Model Variants in Generated Code
Note You can only add Inport, Outport, Subsystem, and Model blocks inside a
Variant Subsystem block.
2 Open the LeftController block.
The LeftController block serves as the container for the variant choices. It contains
two variant choices represented using Subsystem blocks Nonlinear and Linear. The
nonlinear controller subsystems implement hysteresis, whereas the linear controller
subsystems act as simple low-pass filters.
15-25
15 Variant Systems in Embedded Coder
The Subsystem blocks have the same number of inports and outports as the
containing Variant Subsystem block.
Variant choices can have different numbers of inports and outports. See “Mapping
Inports and Outports of Variant Choices” (Simulink) (Simulink).
3 Open the Nonlinear block.
The Nonlinear block represents one variant choice that Simulink activates when a
condition is satisfied. The Linear block represents another variant choice.
15-26
Represent Subsystem and Model Variants in Generated Code
Tip When you are prototyping variant choices, you can create empty Subsystem
blocks with no inputs or outputs inside a Variant Subsystem block. The empty
subsystem recreates the situation in which that subsystem is inactive without the
need for completely modeling the variant choice.
A variant control is a Boolean expression that activates a specific variant choice when it
evaluates to true.
15-27
15 Variant Systems in Embedded Coder
The Condition column displays the Boolean expression that when true activates
each variant choice. In this example, these conditions are specified using
Simulink.Variant objects LINEAR and NONLINEAR.
2 Use these commands to specify a variant control using a Simulink.Variant object.
LINEAR = Simulink.Variant;
LINEAR.Condition = 'VSSMODE==0';
NONLINEAR = Simulink.Variant;
NONLINEAR.Condition = 'VSSMODE==1';
Here, VSSMODE is called a variant control variable that can be specified in one of the
ways listed in “Approaches for Specifying Variant Controls” (Simulink) (Simulink).
3 Define the variant control variable VSSMODE.
15-28
Represent Subsystem and Model Variants in Generated Code
objects allow you to specify other attributes such as data type that are required for
generating code.
VSSMODE = Simulink.Parameter;
VSSMODE.Value = 1;
VSSMODE.DataType = 'int32';
VSSMODE.CoderInfo.StorageClass = 'Custom';
VSSMODE.CoderInfo.CustomStorageClass = 'ImportedDefine';
VSSMODE.CoderInfo.CustomAttributes.HeaderFile = 'rtwdemo_importedmacros.h';
You can also convert a scalar variant control variable into a Simulink.Parameter
object. See “Convert Variant Control Variables into Simulink.Parameter Objects”
(Simulink) (Simulink).
15-29
15 Variant Systems in Embedded Coder
When you select this option, Simulink analyzes all variant choices during an update
diagram or simulation. This analysis provides early validation of the code generation
readiness of all variant choices.
7 Clear the option Override variant conditions and use following variant.
8 Build the model.
1 To open the Code Generation Report click Code > C/C++ Code > Code Generation
Report > Open Model Report.
15-30
Represent Subsystem and Model Variants in Generated Code
15-31
15 Variant Systems in Embedded Coder
15-32
Represent Subsystem and Model Variants in Generated Code
#ifndef LINEAR
#define LINEAR (VSSMODE == 0)
#endif
#ifndef NONLINEAR
#define NONLINEAR (VSSMODE == 1)
#endif
4 Select the rtwdemo_preprocessor_subsys.c file from the left.
In this file, calls to the step and initialization functions of each variant are
conditionally compiled.
Limitations
• When you are generating code for Model Variants blocks and Variant Subsystem
blocks, the blocks cannot have:
• Mass matrices
• Function call ports
• Outports with constant sample time
• Simscape blocks
• The Model Variants block and its referenced models must have the same number of
inports and outports.
• The port numbers and names for each active child subsystem must belong to a subset
of the port numbers and names of the parent Variant Subsystem block.
15-33
15 Variant Systems in Embedded Coder
See Also
Related Examples
• “Define, Configure, and Activate Variants” (Simulink)
• “Variant Subsystems” (Simulink)
• “Model Reference Variants” (Simulink)
More About
• “What Are Variants and When to Use Them” (Simulink)
• “Introduction to Variant Controls” (Simulink)
15-34
Generate Preprocessor Conditionals for Variant Systems
• Define
• ImportedDefine(Custom)
• CompilerFlag(Custom)
• A storage class created using the Custom Storage Class Designer. Your storage
class must have the Data initialization parameter set to Macro and the Data
scope parameter set to Imported. See “Control Data Representation by
Configuring Custom Storage Class Properties” on page 26-31 for more
information.
6 Specify the value of the variant control. If the storage class is
ImportedDefine(Custom), do the following:
15-35
15 Variant Systems in Embedded Coder
a Specify the Header File parameter as an external header file in the Custom
Attributes section of the Simulink.Parameter property dialog box.
b Enter the values of the variant controls in the external header file.
If the variant control is a CompilerFlag custom storage class, the value of the
variant control is set at compile time. Use the Configuration Parameters >
Code Generation > Custom Code > Additional build information > Defines
parameter to add a list of variant controls (macro definitions) to the compiler
command line. For example, for variant control VSSMODE, in the text field for the
Defines parameter, enter:
-DVSSMODE=1
If you want to modify the value of the variant control after generating a makefile,
use a makefile option when compiling your code. For example, at a command line
outside of MATLAB, enter:
makecommand -f model.mk DEFINES_CUSTOM="-DVSSMODE=1"
Note You can define the variant controls using Simulink.Parameter object of
enumerated type. This approach provides meaningful names and improves the readability
of the conditions. The generated code includes preprocessor conditionals to check that
the variant condition contains valid values of the enumerated type.
15-36
Generate Preprocessor Conditionals for Variant Systems
5 In the Model Variants block parameter dialog box, select the Generate
preprocessor conditionals parameter option. In the Variant Subsystem, Variant
Source, or Variant Sink block parameter dialog boxes, select the Analyze all choices
during update diagram and generate preprocessor conditionals option.
6 In both cases, clear the option to Override variant conditions and use following
variant.
7 Generate code.
15-37
15 Variant Systems in Embedded Coder
run(fullfile(matlabroot,'examples','ecoder','main','prepare_rtwdemo_preproc_subsys'));
Navigate inside the variant subsystems. The subsystems each have a linear and a
nonlinear algorithm variant.
15-38
Generate Preprocessor Conditionals for Variant Systems
At the root level of the model, open the block dialog box of the variant subsystem labeled
LeftController. The algorithm variants in the subsystem activate based on the states
of two Simulink.Variant objects, LINEAR and NONLINEAR, in the base workspace.
The state of each object depends on the values of two variant control variables, MODE_A
and MODE_B, which are Simulink.Parameter objects in the base workspace. The
parameter objects use the custom storage class Define and are configured to appear in
the generated code as C-code macros in macros.h.
In this example, change the name of the generated header file from macros.h to
variant_controls.h. You must change the file name in each parameter object.
In the Filter contents box, enter MODE. The Model Data Editor shows two rows that
correspond to the parameter objects.
Select both rows. Then, for one of the rows, use the Header File column to change the
header file name from macros.h to variant_controls.h. The Model Data Editor
applies the change to both rows.
To change the name of the header file, you must change the configuration of each
parameter object. You can use the Model Data Editor to perform batch editing, but when
you add a new variant control variable (parameter object), you must remember to specify
the name of the header file for that object. Also, the Model Data Editor can show the
parameter objects used by only one model at a time.
Instead, you can create a custom storage class and specify the name of the header file
only once: In the definition of the custom storage class.
15-39
15 Variant Systems in Embedded Coder
At the command prompt, copy the built-in SimulinkDemos package into your current
folder as myPackage.
copyfile(fullfile(matlabroot,...
'toolbox','simulink','simdemos','dataclasses','+SimulinkDemos'),...
'+myPackage','f')
Navigate inside the +myPackage folder to the file Parameter.m and open the file.
Uncomment the methods section that defines the method setupCoderInfo. In the call
to the function useLocalCustomStorageClasses, replace 'packageName' with
'myPackage'. When you finish, the section appears as follows:
methods
function setupCoderInfo(h)
% Use custom storage classes from this package
useLocalCustomStorageClasses(h, 'myPackage');
end
end % methods
Set your current folder to the folder that contains the package myPackage.
cscdesigner('myPackage')
Click Copy. A new custom storage class, Define_1, appears. Select this new custom
storage class.
At the command prompt, replace the Simulink.Parameter objects MODE_A and MODE_B
with myPackage.Parameter objects. Apply the new custom storage class
VariantControlVar.
15-40
See Also
MODE_A = myPackage.Parameter;
MODE_A.Value = 1;
MODE_A.DataType = 'int32';
MODE_A.CoderInfo.StorageClass = 'Custom';
MODE_A.CoderInfo.CustomStorageClass = 'VariantControlVar';
MODE_B = myPackage.Parameter;
MODE_B.Value = 1;
MODE_B.DataType = 'int32';
MODE_B.CoderInfo.StorageClass = 'Custom';
MODE_B.CoderInfo.CustomStorageClass = 'VariantControlVar';
Now, to indicate that a parameter object represents a variant control variable, you can
apply the custom storage class VariantControlVar. To change the name of the header
file, use the Custom Storage Class Designer.
See Also
Related Examples
• “Create Variant Controls Programmatically” (Simulink)
• “Working with Variant Choices” (Simulink)
15-41
15 Variant Systems in Embedded Coder
You can use Variant Source and Variant Sink blocks to perceive multiple implementations
of a model in a single, unified block diagram. Each implementation depends on conditions
that you set for Variant Source and Variant Sink blocks. Simulink propagates these
conditions to upstream and downstream blocks including root input and root output ports.
• Code from a Simulink model containing Variant Sink and Variant Source blocks.
• Code that contains preprocessor conditionals that control the activation of each
variant choice.
• Preprocessor conditionals that allow for no active variant choice.
1 From the Simulink Block Library, add 1 Sine Wave Function block, two Add blocks,
three Gain blocks, two Outports, and two Variant Source blocks into a new model.
2 Open the Sine Wave Function block. For the Sine type parameter, select Sample
based. For the Time (t) parameter, select Use simulation time. For the Sample
time parameter, insert a value of 0.2.
3 Make four copies of the Sine Wave Function block.
4 Connect and name the blocks as shown.
15-42
Represent Variant Source and Sink Blocks in Generated Code
5 Insert values of 2, 3, and 4 in the Gain2, Gain3, and Gain4 blocks, respectively.
6 Give the model the name inline_variants_example.
7 Open the Block Parameters dialog box for Variant Source.
15-43
15 Variant Systems in Embedded Coder
8 In the Variant control column, for Port 1, replace Variant_1 with V==1. For Port 2,
replace Variant_2 with V==2.
9 Open the Block Parameters dialog box for Variant Source1.
10 In the Variant control column, replace Variant_1 with W==1. For Port 2, replace
Variant_2 with W==2.
15-44
Represent Variant Source and Sink Blocks in Generated Code
V = Simulink.Parameter;
V.Value = 1;
V.DataType='int32';
V.CoderInfo.StorageClass = 'custom';
V.CoderInfo.CustomStorageClass = 'Define';
V.CoderInfo.CustomAttributes.HeaderFile='inline_importedmacro.h'
W = Simulink.Parameter;
W.Value = 2;
W.DataType='int32';
W.CoderInfo.StorageClass = 'custom';
W.CoderInfo.CustomStorageClass = 'Define';
W.CoderInfo.CustomAttributes.HeaderFile='inline_importedmacro.h'
In this example, the variant control variables are Simulink.Parameter objects. For
code generation, if you use Simulink.Variant objects to specify variant controls,
use Simulink.Parameter objects or MATLAB variables to specify their conditions. .
If you use scalar variant control variables to simulate the model, you can convert
those variables into Simulink.Parameter objects. See “Convert Variant Control
Variables into Simulink.Parameter Objects” (Simulink).
12 Simulate the model.
15-45
15 Variant Systems in Embedded Coder
Input port 1 is the active choice for Variant Source because the value of variant
control variable V is 1. Input port 2 is the active choice for Variant Source1
because the value of variant control variable W is 2. The inactive choices are removed
from execution, and their paths are grayed-out in the diagram.
15-46
Represent Variant Source and Sink Blocks in Generated Code
/* Sin: '<Root>/Sine1' */
15-47
15 Variant Systems in Embedded Coder
#if V == 1
#endif /* V == 1 */
#endif /* V == 2 */
/* Gain: '<Root>/Gain2' */
#if W == 1
#endif /* W == 1 */
rtb_VariantMerge_For_Variant_So = sin((real_T)
15-48
Represent Variant Source and Sink Blocks in Generated Code
#endif /* W == 2 */
When you select Allow zero active variant controls parameter, you can generate code
for a model containing Variant Source and Variant Sink blocks even when you specify a
value for a variant control variable that does not allow for an active variant. Choosing a
value for a variant control variable that does not allow for an active variant and not
selecting the Allow zero active variant controls parameter, produces an error.
15-49
15 Variant Systems in Embedded Coder
#endif /* V == 1 || V == 2 */
...
#if (V == 1 && W == 1) || (V == 2 && W == 1) || W == 2
...
For example, suppose that a model has a Variant Source block with four variant choices.
One of these choices contains blocks with state information. If you simulate the model
with the active variant that is other than the variant choice that contains state
information, there is no logged state data. In the model.h file, the generated code still
15-50
See Also
initializes these global state variables to 0 because #if and #endif guards do not
surround the state variable declarations. If you create a model.mat file from a
model.exe file, and compare it to the simulation output, the results do not match. For
this example, the simulation output is empty because there is no logged state data. The
model.mat file contains multiple values of 0.
If the active variant is the variant choice containing state information, the results do
match.
See Also
Related Examples
• “Define and Configure Variant Sources and Sinks” (Simulink)
• “Variant Condition Propagation with Variant Sources and Sinks” (Simulink)
• “Introduction to Variant Controls” (Simulink)
15-51
15 Variant Systems in Embedded Coder
Note If you are writing an S-function with symbolic dimensions, you cannot use the
%roll directive. You must write an explicit loop.
15-52
Configure Dimension Variants for S-Function Blocks
15-53
15 Variant Systems in Embedded Coder
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_INPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetInputPortSymbolicDimensions(SimStruct* S,
int_T portIndex, SymbDimsId symbDimsId)
{
assert(0 == portIndex);
// Set the compiled input symbolic dimension.
ssSetCompInputPortSymbolicDimsId(S, portIndex, symbDimsId);
// Register "B" and get its symbolic dimensions id.
const SymbDimsId symbolIdForB = ssRegisterSymbolicDimsString(S, "B");
// Subtract "B" from the input symbolic dimension.
const SymbDimsId outputDimsId =
ssRegisterSymbolicDimsMinus(S, symbDimsId, symbolIdForB);
//Set the resulting symbolic dimensions id as the output.
ssSetCompOutputPortSymbolicDimsId(S, portIndex, outputDimsId);
}
#endif
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_OUTPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetOutputPortSymbolicDimensions(SimStruct *S,
int_T portIndex, SymbDimsId symbDimsId)
{
assert(0 == portIndex);
// The input dimensions are not set, so this S-function only
// supports forward propagation.
ssSetCompOutputPortSymbolicDimsId(S, portIndex, symbDimsId);
}
#endif
15-54
Configure Dimension Variants for S-Function Blocks
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_INPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetInputPortSymbolicDimensions(SimStruct* S,
int_T portIndex, SymbDimsId symbDimsId)
{
assert(0 == portIndex);
if (SL_INHERIT ==
ssGetCompOutputPortSymbolicDimsId(S, portIndex)) {
ssSetCompOutputPortSymbolicDimsId(S, portIndex,
outputDimsId);
}
}
#endif
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_OUTPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetOutputPortSymbolicDimensions(SimStruct *S,
15-55
15 Variant Systems in Embedded Coder
if (SL_INHERIT ==
ssGetCompInputPortSymbolicDimsId(S, portIndex)) {
See Also
Related Examples
• “Implement Dimension Variants for Array Sizes in Generated Code” on page 15-2
15-56
Generate Code for Variant Subsystem with Child Subsystems of Different Output Signal Dimensions
This example shows how to use symbolic dimensions to generate code with preprocessor
conditionals for a variant subsystem consisting of child subsystems of different output
signal dimensions. The value of the variant control variable determines the active variant
choice and the output signal dimensions. By changing the value of the variant control
variable, you change the active variant and the output signal dimensions in the generated
code.
Example Model
The model slexVariantSymbolicDims contains a Variant Subsystem consisting of the
child subsystems Subsystem and Subsystem1. When the variant control variable Var
has a value of 1, Subsystem is the active variant. When Var has a value of 2,
Subsystem1 is the active variant.
15-57
15 Variant Systems in Embedded Coder
Simulate Model
To generate code with preprocessor conditionals, the output signal dimensions of the
child subsystems must be the same during simulation. In this example, double-clicking
the subsystem Activate Variant Choice changes the active variant and the output
signal dimension. When Var equals 1, the output signal dimension of each child
subsystem is 5. When Var equals 2, the output signal dimension of each child subsystem
is 6.
1 Open the example model slexVariantSymbolicDims.
2 From the Display > Signals & Ports menu, select Signal Dimensions.
3 Open the Variant Subsystem Block Parameters dialog box. The Analyze all choices
during update diagram and generate preprocessor conditionals parameter is
selected.
4 Open Subsystem. In the Constant Block Parameters dialog box, the Constant value
parameter is P1.
5 Open Subsystem1. In the Constant Block Parameters dialog box, the Constant
value parameter is P2.
15-58
Generate Code for Variant Subsystem with Child Subsystems of Different Output Signal Dimensions
6 Open the base workspace. The Simulink.Parameters P1 and P2 are arrays with
dimensions '[1,A]'. The Simulink.Parameter A has a value of 5. Var has a value
of 1.
7 Simulate the model. Subsystem is the active variant with an output signal dimension
of 5.
8 Double-click the masked subsystem ActivateVariant.
9 In the base workspace, Var has a value of 2. P1 and P2 have a dimension of 6. A has
a value of 6.
10 Simulate the model. Subsystem1 is the active variant with an output signal
dimension of 6.
Generate Code
1 Open the header file slexVariantSymbolicDims_variant_defines.h. The
definition of A is conditional upon the value of Var.
/* Copyright 2016 The MathWorks, Inc. */
// To select variant choice during compile, define Var at compile time,
#ifndef Var
#define Var 1
#endif
#if Var == 1
#define A 5
#elif Var == 2
15-59
15 Variant Systems in Embedded Coder
#define A 6
#else
#error "Variant control variable, Var, must be defined as 1 or 2"
#endif
2 Generate code.
3 Open the slexVariantSymbolicDims.h file. The output dimension size is A.
int32_T P1[] = { 5, 5, 5, 5, 5 };
#elif Var == 2
int32_T P2[] = { 6, 6, 6, 6, 6, 6 };
#endif
Preprocessor conditionals control the size of A and which array, P1 or P2, is active in
the generated code. By changing the value of Var, you can change the size of A and
the active array.
See Also
Related Examples
• “Implement Dimension Variants for Array Sizes in Generated Code” on page 15-2
• “Represent Subsystem and Model Variants in Generated Code” on page 15-23
15-60
16
About Timers
Certain blocks require the value of either absolute time (that is, the time from the start of
program execution to the present time) or elapsed time (for example, the time elapsed
between two trigger events). Targets that support the real-time model (rtModel) data
structure provide efficient time computation services to blocks that request absolute or
elapsed time. Absolute and elapsed timer features include
See “Absolute Time Limitations” (Simulink Coder) for more information about absolute
time and the restrictions that it imposes.
16-2
Absolute and Elapsed Time Computation
The code generator also provides timer support for blocks whose execution is
asynchronous with respect to the periodic timing source of the model. See the following
topics:
Allocation of Timers
If you create or maintain an S-Function block that requires absolute or elapsed time data,
it must register the requirement (see “Access Timers Programmatically” on page 16-5).
In multirate models, timers are allocated on a per-rate basis. For example, consider a
model structured as follows:
In this case, two timers are generated, running at rates A and C respectively. The timing
engine updates the timers as the tasks associated with rates A and C execute. Blocks
executing at rates A and C obtain time data from the timers associated with rates A and
C.
16-3
16 Timers in Simulink Coder
Note If you are using simplified initialization mode, elapsed time is reset on first
execution after becoming enabled, whether or not the subsystem is configured to reset on
enable. For more information, see “Underspecified initialization detection” (Simulink).
See Also
More About
• “Access Timers Programmatically” (Simulink Coder)
• “Generate Code for an Elapsed Time Counter” (Simulink Coder)
• “Optimize Memory Usage for Time Counters” (Simulink Coder)
• “Absolute Time Limitations” (Simulink Coder)
16-4
Access Timers Programmatically
• To generate and use the new timers as described above, your S-functions must
register the need to use an absolute or elapsed timer by calling
ssSetNeedAbsoluteTime or ssSetNeedElapseTime in
mdlInitializeSampleTime.
• Existing S-functions that read absolute time but do not register by using these macros
continue to operate as expected, but generate less efficient code.
In the functions below, the SimStruct *S argument is a pointer to the simstruct of the
calling S-function.
16-5
16 Timers in Simulink Coder
To determine how to access the returned counter value, obtain the data type of the
counter by calling ssGetElapseTimeCounterDtype, as in the following code:
int *y_dtype;
ssGetElapseTimeCounterDtype(S, y_dtype);
switch(*y_dtype) {
case SS_DOUBLE_UINT32:
{
uint32_T dataPtr[2];
ssGetElapseTimeCounter(S, dataPtr);
}
break;
case SS_UINT32:
{
16-6
Access Timers Programmatically
uint32_T dataPtr[1];
ssGetElapseTimeCounter(S, dataPtr);
}
break;
case SS_UINT16:
{
uint16_T dataPtr[1];
ssGetElapseTimeCounter(S, dataPtr);
}
break;
case SS_UINT8:
{
uint8_T dataPtr[1];
ssGetElapseTimeCounter(S, dataPtr);
}
break;
case SS_DOUBLE:
{
real_T dataPtr[1];
ssGetElapseTimeCounter(S, dataPtr);
}
break;
default:
ssSetErrorStatus(S, "Invalid data type for elaspe time
counter");
break;
}
If you want to use the actual elapsed time, issue a call to the ssGetElapseTime
function to access the elapsed time directly. You do not need to get the counter value
and then calculate the elapsed time.
double *y_elapseTime;
.
.
.
ssGetElapseTime(S, elapseTime)
16-7
16 Timers in Simulink Coder
Note Do not use LibGetT for this purpose. LibGetT always reads the base rate (tid
0) timer. If LibGetT is called for a block executing at a subrate, the wrong timer is
read, causing serious errors.
• LibGetElapseTime(system): Generates code to read the elapsed time counter for
system. (system is the parent system of the calling block.) See “Generate Code for an
Elapsed Time Counter” on page 16-9 for an example of code generated by this
function.
• LibGetElapseTimeCounter(system): Generates code to read the integer value of
the elapsed time counter for system. (system is the parent system of the calling
block.) This function should be used in conjunction with
LibGetElapseTimeCounterDtypeId and LibGetElapseTimeResolution. (See
the discussion of ssGetElapseTimeCounter above.)
• LibGetElapseTimeCounterDtypeId(system): Generates code that returns the
data type of the elapsed time counter for system. (system is the parent system of the
calling block.)
• LibGetElapseTimeResolution(system): Generates code that returns the
resolution of the elapsed time counter for system. (system is the parent system of
the calling block.)
See Also
More About
• “Absolute and Elapsed Time Computation” (Simulink Coder)
• “Generate Code for an Elapsed Time Counter” (Simulink Coder)
• “Absolute Time Limitations” (Simulink Coder)
16-8
Generate Code for an Elapsed Time Counter
ex_elapseTime Model
Amplifier Subsystem
Code in the generated header file ex_elapseTime.h for the model uses 64 bits to
implement the timer for the base rate (clockTick0 and clockTickH0).
/*
* Timing:
* The following substructure contains information regarding
* the timing information for the model.
*/
struct {
time_T taskTime0;
uint32_T clockTick0;
16-9
16 Timers in Simulink Coder
uint32_T clockTickH0;
time_T stepSize0;
time_T tFinal;
boolean_T stopRequestedFlag;
} Timing;
The code generator allocates storage for the previous-time value and elapsed-time value
of the Amplifier subsystem (Amplifier_PREV_T) in the D_Work(states) structure in
ex_elapsedTime.h.
/* Block states (auto storage) for system '<Root>' */
typedef struct {
real_T DiscreteTimeIntegrator_DSTATE;
/* '<S1>/Discrete-Time Integrator' */
int32_T clockTickCounter;
/* '<Root>/Pulse Generator' */
uint32_T Amplifier_ELAPS_T[2];
/* '<Root>/Amplifier' */
uint32_T Amplifier_PREV_T[2];
/* '<Root>/Amplifier' */
} DW_ex_elapseTime_T;
ex_elapseTime_DW.Amplifier_ELAPS_T[0] =
ex_elapseTime_M->Timing.clockTick0
- ex_elapseTime_DW.Amplifier_PREV_T[0];
ex_elapseTime_DW.Amplifier_PREV_T[0] =
16-10
See Also
ex_elapseTime_M->Timing.clockTick0;
ex_elapseTime_DW.Amplifier_ELAPS_T[1] =
elapseT_H;
ex_elapseTime_DW.Amplifier_PREV_T[1] =
ex_elapseTime_M->Timing.clockTickH0;
As shown above, the elapsed time is maintained as a state of the triggered subsystem.
The Discrete-Time Integrator block finally performs its output and update computations
using the elapsed time.
/* ---
DiscreteIntegrator: '<S1>/Discrete-Time Integrator'
--- */
OUTPUT = ex_elapseTime_DW.DiscreteTimeIntegrator_DSTATE;
/* ---
Update for DiscreteIntegrator:
'<S1>/Discrete-Time Integrator' incorporates:
Constant: '<Root>/Constant'
--- */
ex_elapseTime_DW.DiscreteTimeIntegrator_DSTATE += 0.3 * (real_T)
ex_elapseTime_DW.Amplifier_ELAPS_T[0] * 1.5;
See Also
More About
• “Absolute and Elapsed Time Computation” (Simulink Coder)
• “Absolute Time Limitations” (Simulink Coder)
16-11
16 Timers in Simulink Coder
When you design an application that is intended to run indefinitely, you must take care
when logging time values, or using charts or blocks that depend on absolute time. If the
value of time reaches the largest value that can be represented by the data type used by
the timer to store time, the timer overflows and the logged time or block output is
incorrect.
If your target uses rtModel, you can avoid timer overflow by specifying a value for the
Application life span parameter. See “Integer Timers in Generated Code” on page 16-3
for more information.
• If you log time values by opening the Configuration Parameters dialog box and
enabling Data Import/Export > Time parameter, your model uses absolute time.
• Every Stateflow chart that uses time is dependent on absolute time. The only way to
eliminate the dependency is to change the Stateflow chart to not use time.
• The following Simulink blocks depend on absolute time:
• Backlash
• Chirp Signal
• Clock
• Derivative
• Digital Clock
• Discrete-Time Integrator (only when used in triggered subsystems)
• From File
• From Workspace
• Pulse Generator
• Ramp
• Rate Limiter
• Repeating Sequence
16-12
See Also
• Signal Generator
• Sine Wave (only when the Sine type parameter is set to Time-based)
• Step
• To File
• To Workspace (only when logging to StructureWithTime format)
• Transport Delay
• Variable Time Delay
• Variable Transport Delay
In addition to the Simulink blocks above, blocks in other blocksets may depend on
absolute time. See the documentation for the blocksets that you use.
See Also
More About
• “Absolute and Elapsed Time Computation” (Simulink Coder)
16-13
17
Tasking Modes
There are two execution modes for a fixed-step Simulink model: single-tasking and
multitasking. These modes are available only for fixed-step solvers. To select an execution
mode, use the Treat each discrete rate as a separate task checkbox on the Solver
pane of the Configuration Parameters dialog box. When this parameter is selected,
multitasking execution is applied for a multirate model. When this option is cleared,
single-tasking execution is applied.
Note A model that is multirate and uses multitasking cannot reference a multirate model
that uses single-tasking.
17-2
Time-Based Scheduling and Code Generation
Execution of models in a real-time system can be done with the aid of a real-time
operating system, or it can be done on bare-metal target hardware, where the model runs
in the context of an interrupt service routine (ISR).
The fact that a system (such as The Open Group UNIX or Microsoft Windows systems) is
multitasking does not imply that your program can execute in real time. This is because
the program might not preempt other processes when required.
In operating systems (such as PC-DOS) where only one process can exist at a given time,
an interrupt service routine (ISR) must perform the steps of saving the processor context,
executing the model code, collecting data, and restoring the processor context.
17-3
17 Time-Based Scheduling in Simulink Coder
17-4
Time-Based Scheduling and Code Generation
To avoid raising rate transition errors, insert Rate Transition blocks between tasks. You
can request that the Simulink engine handle rate transitions automatically by inserting
hidden Rate Transition blocks. See “Automatic Rate Transition” on page 17-26 for an
explanation of this option.
To understand such problems, first consider how Simulink simulations differ from real-
time programs.
The key to this process is the ordering of blocks. A block whose output is directly
dependent on its input (that is, a block with direct feedthrough) cannot execute until the
block driving its input executes.
Some blocks set their outputs based on values acquired in a previous time step or from
initial conditions specified as a block parameter. The output of such a block is determined
by a value stored in memory, which can be updated independently of its input. During
simulation, computations are performed prior to advancing the variable corresponding to
time. This results in computations occurring instantaneously (that is, no computational
delay).
17-5
17 Time-Based Scheduling in Simulink Coder
t0 t1 t2
Time
Note the processing inefficiency in the sample interval t1. That interval cannot be
compressed to increase execution speed because, by definition, sample times are clocked
in real time.
You can circumvent this potential inefficiency by using the multitasking mode. The
multitasking mode defines tasks with different priorities to execute parts of the model
code that have different sample rates.
Multitasking mode can improve the efficiency of your program if the model is large and
has many blocks executing at each rate.
However, if your model is dominated by a single rate, and only a few blocks execute at a
slower rate, multitasking can actually degrade performance. In such a model, the
overhead incurred in task switching can be greater than the time required to execute the
slower blocks. In this case, it is more efficient to execute all blocks at the dominant rate.
If you have a model that can benefit from multitasking execution, you might need to
modify your model by adding Rate Transition blocks (or instruct the Simulink engine to do
so) to generate expected results.
For more information about the two modes of execution and examples, see “Modeling for
Single-Tasking Execution” on page 17-8 and “Modeling for Multitasking Execution” on
page 17-12.
17-6
See Also
See Also
More About
• “What Is Sample Time?” (Simulink)
• “Sample Times in Subsystems” (Simulink)
• “Sample Times in Systems” (Simulink)
• “Configure Time-Based Scheduling” (Simulink Coder)
• “Sample Times in Subsystems” (Simulink)
• “Sample Times in Systems” (Simulink)
• “Resolve Rate Transitions” (Simulink)
• “Handle Rate Transitions” (Simulink Coder)
• “Time-Based Scheduling and Code Generation” (Simulink Coder)
• “Modeling for Single-Tasking Execution” (Simulink Coder)
• “Modeling for Multitasking Execution” (Simulink Coder)
• “Time-Based Scheduling Example Models” (Simulink Coder)
17-7
17 Time-Based Scheduling in Simulink Coder
In single-tasking mode, the base sample rate must define a time interval that is long
enough to allow the execution of all blocks within that interval.
t0 t1 t2 t3 t4
Single-tasking system execution requires a base sample rate that is long enough to
execute one step through the entire model.
Single-Tasking Execution
This example examines how a simple multirate model executes in both real time and
simulation, using a fixed-step solver. It considers operation in both single-tasking and
multitasking modes, as determined by setting of the Treat each discrete rate as a
separate task parameter on the Solver pane.
The example model is shown in the next figure. The discussion refers to the six blocks of
the model as A through F, as labeled in the block diagram.
17-8
Modeling for Single-Tasking Execution
The execution order of the blocks (indicated in the upper right of each block) has been
forced into the order shown by assigning higher priorities to blocks F, E, and D. The
ordering shown is one possible valid execution ordering for this model. For more
information, see “Simulation Phases in Dynamic Systems” (Simulink).
Note The discussion and timing diagrams in this section are based on the assumption
that the Rate Transition blocks are used in the default (protected/deterministic) mode,
with the Ensure data integrity during data transfer and Ensure deterministic data
transfer (maximum delay) options on.
This example considers the execution of the above model when the Treat each discrete
rate as a separate task checkbox is cleared, which indicates the single-tasking mode.
The following table shows, for each block in the model, the execution order, sample time,
and whether the block has an output or update computation. Block A does not have
discrete states, and accordingly does not have an update computation.
17-9
17 Time-Based Scheduling in Simulink Coder
The next figure shows the scheduling of computations when the generated code is
deployed in a real-time system. The generated program is shown running in real time,
under control of interrupts from a 10 Hz timer.
At time 0.0, 1.0, and every second thereafter, both the slow and fast blocks execute their
output computations; this is followed by update computations for blocks that have states.
Within a given time interval, output and update computations are sequenced in block
execution order.
The fast blocks execute on every tick, at intervals of 0.1 second. Output computations are
followed by update computations.
The system spends some portion of each time interval (labeled “wait”) idling. During the
intervals when only the fast blocks execute, a larger portion of the interval is spent idling.
This illustrates an inherent inefficiency of single-tasking mode.
17-10
See Also
The next figure shows the execution of the model during the Simulink simulation loop.
Because time is simulated, the placement of ticks represents the iterations of the
simulation loop. Blocks execute in exactly the same order as in the previous figure, but
without the constraint of a real-time clock. Therefore there is no idle time between
simulated sample periods.
See Also
More About
• “Time-Based Scheduling and Code Generation” (Simulink Coder)
• “Configure Time-Based Scheduling” (Simulink Coder)
• “Time-Based Scheduling Example Models” (Simulink Coder)
17-11
17 Time-Based Scheduling in Simulink Coder
Where tasks are asynchronous rather than periodic, there may not necessarily be a
relationship between sample rates and task priorities; the task with the highest priority
need not have the fastest sample rate. You specify asynchronous task priorities using
Async Interrupt and Task Sync blocks. You can switch the sense of what priority numbers
mean by selecting or deselecting the Solver option Higher priority value indicates
higher task priority.
In multitasking environments (that is, under a real-time operating system), you can define
separate tasks and assign them priorities. For bare-metal target hardware (that is, no
real-time operating system present), you cannot create separate tasks. However,
generated application modules implement what is effectively a multitasking execution
scheme using overlapped interrupts, accompanied by programmatic context switching.
This means an interrupt can occur while another interrupt is currently in progress. When
this happens, the current interrupt is preempted, the floating-point unit (FPU) context is
saved, and the higher priority interrupt executes its higher priority (that is, faster sample
rate) code. Once complete, control is returned to the preempted ISR.
The next figures illustrate how timing of tasks in multirate systems are handled by the
code generator in multitasking, pseudomultitasking, and single-tasking environments.
17-12
Modeling for Multitasking Execution
t0 t1 t2 t3 t4
rate 1
Highest Priority
rate 2
rate 3
Lowest Priority
Dotted lines with downward pointing Dark gray areas indicate task execution.
arrows indicate the release of control
to a lower priority task.
Hashed areas indicate task preemption
by a higher priority task.
Dotted lines with upward pointing
arrows indicate preemption by a
higher priority task. Light gray areas indicate task execution
is pending.
The next figure shows how overlapped interrupts are used to implement
pseudomultitasking. In this case, Interrupt 0 does not return until after Interrupts 1, 2,
and 3.
17-13
17 Time-Based Scheduling in Simulink Coder
Highest Priority
Interrupt 2
Ends
Interrupt 0
Ends
Lowest Priority
17-14
Modeling for Multitasking Execution
You set sample rates and their constraints on the Solver pane of the Configuration
Parameters dialog box. To generate code, select Fixed-step for the solver type. Certain
restrictions apply to the sample rates that you can use:
• The sample rate of a block must be an integer multiple of the base (that is, the fastest)
sample period.
• When Periodic sample time constraint is unconstrained, the base sample period
is determined by the Fixed step size specified on the Solvers pane of the
Configuration parameters dialog box.
• When Periodic sample time constraint is Specified, the base rate fixed-step size
is the first element of the sample time matrix that you specify in the companion option
Sample time properties. The Solver pane from the example model
rtwdemo_mrmtbb shows an example.
17-15
17 Time-Based Scheduling in Simulink Coder
• Continuous blocks execute by using an integration algorithm that runs at the base
sample rate. The base sample period is the greatest common denominator of all rates
in the model only when Periodic sample time constraint is set to Unconstrained
and Fixed step size is Auto.
• The continuous and discrete parts of the model can execute at different rates only if
the discrete part is executed at the same or a slower rate than the continuous part and
is an integer multiple of the base sample rate.
Multitasking Execution
This example examines how a simple multirate model executes in both real time and
simulation, using a fixed-step solver. It considers operation in both single-tasking and
multitasking modes, as determined by setting of the Treat each discrete rate as a
separate task parameter on the Solver pane.
The example model is shown in the next figure. The discussion refers to the six blocks of
the model as A through F, as labeled in the block diagram.
The execution order of the blocks (indicated in the upper right of each block) has been
forced into the order shown by assigning higher priorities to blocks F, E, and D. The
ordering shown is one possible valid execution ordering for this model. For more
information, see “Simulation Phases in Dynamic Systems” (Simulink).
Note The discussion and timing diagrams in this section are based on the assumption
that the Rate Transition blocks are used in the default (protected/deterministic) mode,
17-16
Modeling for Multitasking Execution
with the Ensure data integrity during data transfer and Ensure deterministic data
transfer (maximum delay) options on.
This example considers the execution of the above model when the solver Tasking mode
is MultiTasking. Block computations are executed under two tasks, prioritized by rate:
• The slower task, which gets the lower priority, is scheduled to run every second. This
is called the 1 second task.
• The faster task, which gets higher priority, is scheduled to run 10 times per second.
This is called the 0.1 second task. The 0.1 second task can preempt the 1 second task.
The following table shows, for each block in the model, the execution order, the task
under which the block runs, and whether the block has an output or update computation.
Blocks A and B do not have discrete states, and accordingly do not have an update
computation.
17-17
17 Time-Based Scheduling in Simulink Coder
The next figure shows the scheduling of computations in MultiTasking solver mode
when the generated code is deployed in a real-time system. The generated program is
shown running in real time, as two tasks under control of interrupts from a 10 Hz timer.
17-18
Modeling for Multitasking Execution
The next figure shows the Simulink execution of the same model, in MultiTasking
solver mode. In this case, the Simulink engine runs the blocks in one thread of execution,
simulating multitasking. No preemption occurs.
17-19
17 Time-Based Scheduling in Simulink Coder
See Also
More About
• “Time-Based Scheduling and Code Generation” (Simulink Coder)
• “Sample Times in Subsystems” (Simulink)
• “Sample Times in Systems” (Simulink)
• “Configure Time-Based Scheduling” (Simulink Coder)
• “Resolve Rate Transitions” (Simulink)
• “Handle Rate Transitions” (Simulink Coder)
• “Time-Based Scheduling Example Models” (Simulink Coder)
17-20
Handle Rate Transitions
Rate Transitions
Two periodic sample rate transitions can exist within a model:
The following sections concern models with periodic sample times with zero offset only.
Other considerations apply to multirate models that involve asynchronous tasks. For
details on how to generate code for asynchronous multitasking, see “Asynchronous
Support” (Simulink Coder).
In multitasking and pseudomultitasking systems, differing sample rates can cause blocks
to be executed in the wrong order. To prevent possible errors in calculated data, you must
control model execution at these transitions. When connecting faster and slower blocks,
you or the Simulink engine must add Rate Transition blocks between them. Fast-to-slow
transitions are illustrated in the next figure.
T = 1s T = 2s
Faster Slower
Block Block
becomes
Port-based:
T = 1s Tin = 1s; Tout = 2s T = 2s
17-21
17 Time-Based Scheduling in Simulink Coder
T = 2s T = 1s
Slower Faster
Block Block
becomes
Port-based:
T = 2s Tin = 2s; Tout = 1s T = 1s
Note Although the Rate Transition block offers a superset of the capabilities of the Unit
Delay block (for slow-to-fast transitions) and the Zero-Order Hold block (for fast-to-slow
transitions), you should use the Rate Transition block instead of these blocks.
• Data integrity: A problem of data integrity exists when the input to a block changes
during the execution of that block. Data integrity problems can be caused by
preemption.
17-22
Handle Rate Transitions
Such a data transfer is called unprotected. “Faster to Slower Transitions in Real Time”
on page 17-30 shows an unprotected data transfer.
In a protected data transfer, the output V1 of the faster block is held until the slower
block finishes executing.
• Deterministic versus nondeterministic data transfer: In a deterministic data transfer,
the timing of the data transfer is completely predictable, as determined by the sample
rates of the blocks.
The timing of a nondeterministic data transfer depends on the availability of data, the
sample rates of the blocks, and the time at which the receiving block begins to execute
relative to the driving block.
You can use the Rate Transition block to protect data transfers in your application and
make them deterministic. These characteristics are considered desirable in most
applications. However, the Rate Transition block supports flexible options that allow you
to compromise data integrity and determinism in favor of lower latency. The next section
summarizes these options.
• Data transitions occur between a single reading task and a single writing task.
• A read or write of a byte-sized variable is atomic.
• When two tasks interact through a data transition, only one of them can preempt the
other.
• For periodic tasks, the faster rate task has higher priority than the slower rate task;
the faster rate task preempts the slower rate task.
• All tasks run on a single processor. Time slicing is not allowed.
• Processes do not crash or restart (especially while data is transferred between tasks).
17-23
17 Time-Based Scheduling in Simulink Coder
The Rate Transition block handles periodic (fast to slow and slow to fast) and
asynchronous transitions. When inserted between two blocks of differing sample rates,
the Rate Transition block automatically configures its input and output sample rates for
the type of transition; you do not need to specify whether a transition is slow-to-fast or
fast-to-slow (low-to-high or high-to-low priorities for asynchronous tasks).
The critical decision you must make in configuring a Rate Transition block is the choice of
data transfer mechanism to be used between the two rates. Your choice is dictated by
considerations of safety, memory usage, and performance. As the Rate Transition block
parameter dialog box in the next figure shows, the data transfer mechanism is controlled
by two options.
• Ensure data integrity during data transfer: When this option is on, data
transferred between rates maintains its integrity (the data transfer is protected).
17-24
Handle Rate Transitions
When this option is off, the data might not maintain its integrity (the data transfer is
unprotected). By default, Ensure data integrity during data transfer is on.
• Ensure deterministic data transfer (maximum delay): This option is supported for
periodic tasks with an offset of zero and fast and slow rates that are multiples of each
other. Enable this option for protected data transfers (when Ensure data integrity
during data transfer is on). When this option is on, the Rate Transition block
behaves like a Zero-Order Hold block (for fast to slow transitions) or a Unit Delay
block (for slow to fast transitions). The Rate Transition block controls the timing of
data transfer in a completely predictable way. When this option is off, the data transfer
is nondeterministic. By default, Ensure deterministic data transfer (maximum
delay) is on for transitions between periodic rates with an offset of zero; for
asynchronous transitions, it cannot be selected.
Thus the Rate Transition block offers three modes of operation with respect to data
transfer. In order of level of safety:
The drawbacks of this mode are its nondeterministic timing. The advantage of this
mode is its low latency.
• Unprotected/NonDeterministic: This mode is not recommended for mission-critical
applications. The latency of this mode is the same as for Protected/NonDeterministic
mode, but memory requirements are reduced since neither double-buffering nor
semaphores are required. That is, the Rate Transition block does nothing in this mode
other than to pass signals through; it simply exists to notify you that a rate transition
exists (and can cause generated code to compute incorrect answers). Selecting this
mode, however, generates the least amount of code.
17-25
17 Time-Based Scheduling in Simulink Coder
Note In unprotected mode (Ensure data integrity during data transfer option off),
the Rate Transition block does nothing other than allow the rate transition to exist in
the model.
The sample time at the output port of a Rate Transition block can only be discrete or fixed
in minor time step. This means that when a Rate Transition block inherits continuous
sample time from its destination block, it treats the inherited sample time as Fixed in
Minor Time Step. Therefore, the output function of the Rate Transition block runs only at
major time steps. If the destination block sample time is continuous, Rate Transition block
output sample time is the base rate sample time (if solver is fixed-step), or zero-order-
hold-continuous sample time (if solver is variable-step).
• Simulink handles transitions between periodic sample times and asynchronous tasks.
• Simulink inserts hidden Rate Transition blocks in the block diagram.
• The code generator produces code for the Rate Transition blocks that were
automatically inserted. This code is identical to the code generated for Rate Transition
blocks that were inserted manually.
• Automatically inserted Rate Transition blocks operate in protected mode for periodic
tasks and asynchronous tasks. You cannot alter this behavior. For periodic tasks,
automatically inserted Rate Transition blocks operate with the level of determinism
specified by the Deterministic data transfer parameter in the Solver pane. The
default setting is Whenever possible, which enables determinism for data transfers
between periodic sample-times that are related by an integer multiple. For more
information, see “Deterministic data transfer” (Simulink). To use other modes, you
must insert Rate Transition blocks and set their modes manually.
For example, in this model, SineWave2 has a sample time of 2, and SineWave3 has a
sample time of 3.
17-26
Handle Rate Transitions
When you select Automatically handle rate transition for data transfer, Simulink
inserts a Rate Transition block between each Sine Wave block and the Product block. The
inserted blocks have the parameter values to reconcile the Sine Wave block sample times.
If the input port and output port data sample rates in a model are not multiples of each
other, Simulink inserts a Rate Transition block whose sample rate is the greatest common
divisor (GCD) of the two rates. If no other block in the model contains this new rate, an
error occurs during simulation. In this case, you must insert a Rate Transition block
manually.
17-27
17 Time-Based Scheduling in Simulink Coder
You can show or hide badge labels using the Display > Signals and Ports > Hidden
Rate Transition Block Indicators setting.
To configure the hidden Rate Transition blocks, right click on a badge label and click on
Insert rate transition block to make the block visible.
• You can see the type of Rate Transition block inserted as well as the location in the
model.
17-28
Handle Rate Transitions
To learn more about the types of Rate Transition blocks, see Rate Transition.
In a model where a faster block drives a slower block having direct feedthrough, the
outputs of the faster block are computed first. In simulation intervals where the slower
17-29
17 Time-Based Scheduling in Simulink Coder
block does not execute, the simulation progresses more rapidly because there are fewer
blocks to execute. The next figure illustrates this situation.
t0 t1 t2 t3
T = 1s T = 2s
T = 1s T = 2s T = 1s T = 1s T = 2s T = 1s
Faster Slower
Block Block Time
A Simulink simulation does not execute in real time, which means that it is not bound by
real-time constraints. The simulation waits for, or moves ahead to, whatever tasks are
required to complete simulation flow. The actual time interval between sample time steps
can vary.
In models where a faster block drives a slower block, you must compensate for the fact
that execution of the slower block might span more than one execution period of the
faster block. This means that the outputs of the faster block can change before the slower
block has finished computing its outputs. The next figure shows a situation in which this
problem arises (T = sample time). Note that lower priority tasks are preempted by higher
priority tasks before completion.
Time
1 The faster task (T=1s) completes.
17-30
Handle Rate Transitions
In the above figure, the faster block executes a second time before the slower block has
completed execution. This can cause unpredictable results because the input data to the
slow task is changing. Data might not maintain its integrity in this situation.
To avoid this situation, the Simulink engine must hold the outputs of the 1 second (faster)
block until the 2 second (slower) block finishes executing. The way to accomplish this is
by inserting a Rate Transition block between the 1 second and 2 second blocks. The input
to the slower block does not change during its execution, maintaining data integrity.
It is assumed that the Rate Transition block is used in its default (protected/deterministic)
mode.
The Rate Transition block executes at the sample rate of the slower block, but with the
priority of the faster block.
t0 t2
2 Sec
Task T=2s T=2s
t0 t1 t2 t3
Time
When you add a Rate Transition block, the block executes before the 2 second block (its
priority is higher) and its output value is held constant while the 2 second block executes
(it executes at the slower sample rate).
17-31
17 Time-Based Scheduling in Simulink Coder
In a model where a slower block drives a faster block, the Simulink engine again
computes the output of the driving block first. During sample intervals where only the
faster block executes, the simulation progresses more rapidly.
t0 t1 t2 t3
T = 2s T = 1s
T = 2s T = 1s T = 1s T = 2s T = 1s T = 1s
Slower Faster
Block Block Time
As you can see from the preceding figures, the Simulink engine can simulate models with
multiple sample rates in an efficient manner. However, a Simulink simulation does not
operate in real time.
In models where a slower block drives a faster block, the generated code assigns the
faster block a higher priority than the slower block. This means the faster block is
executed before the slower block, which requires special care to avoid incorrect results.
t0 t2
T = 2s T = 1s t0 1 t1 2 t2 1 t3 2 t4
Block Faster
Block 1 Sec T=1s T=1s T=1s T=1s T=1s
Task
Time
17-32
Handle Rate Transitions
• Execution of the slower block is split over more than one faster block interval. In this
case the faster task executes a second time before the slower task has completed
execution. This means the inputs to the faster task can have incorrect values some of
the time.
• The faster block executes before the slower block (which is backward from the way a
Simulink simulation operates). In this case, the 1 second block executes first; but the
inputs to the faster task have not been computed. This can cause unpredictable
results.
To eliminate these problems, you must insert a Rate Transition block between the slower
and faster blocks.
T = 2s Tin = 2 Tout = 1 T = 1s
It is assumed that the Rate Transition block is used in its default (protected/deterministic)
mode.
The next figure shows the timing sequence that results with the added Rate Transition
block.
17-33
17 Time-Based Scheduling in Simulink Coder
2 Sec RT RT
T=2s update T=2s update
Task
t0 t1 t2 t3
1 1
1 1
1 Sec RT RT
T=1s
Task output T=1s 3 output T=1s T=1s
Time
Three key points about transitions in this diagram (refer to circled numbers):
1 The Rate Transition block output runs in the 1 second task, but at a slower rate (2
seconds). The output of the Rate Transition block feeds the 1 second task blocks.
2 The Rate Transition update uses the output of the 2 second task to update its internal
state.
3 The Rate Transition output in the 1 second task uses the state of the Rate Transition
that was updated in the 2 second task.
The first problem is alleviated because the Rate Transition block is updating at a slower
rate and at the priority of the slower block. The input to the Rate Transition block (which
is the output of the slower block) is read after the slower block completes executing.
The second problem is alleviated because the Rate Transition block executes at a slower
rate and its output does not change during the computation of the faster block it is
driving. The output portion of a Rate Transition block is executed at the sample rate of
the slower block, but with the priority of the faster block. Since the Rate Transition block
drives the faster block and has effectively the same priority, it is executed before the
faster block.
17-34
Handle Rate Transitions
Note This use of the Rate Transition block changes the model. The output of the slower
block is now delayed by one time step compared to the output without a Rate Transition
block.
Particularly for a multitasking application, the tasks (rates) involved in a data transfer can
write to the transferred data, buffers, and semaphores at times that your compiler cannot
anticipate. To prevent your compiler from optimizing the assembly code in a manner that
compromises the integrity of the transferred data, the code generator applies the
keyword volatile to the buffers and semaphores. The code generator does not apply
volatile to the global variable that represents the transferred data because the
volatile buffers and semaphores typically offer enough protection.
If necessary, with Embedded Coder, you can explicitly apply volatile to the transferred
data by applying the built-in custom storage class Volatile to the input of the Rate
Transition block. For example, you can use this technique to help protect the integrity of
data that your external code shares with the generated code.
Alternatively, to protect data that your external code shares with the generated code, you
can write your own C functions that read and write the data in a protected manner. Then,
you can apply the custom storage class GetSet to the data in the model, which causes
the generated code to call your functions instead of directly accessing the data.
For more information about applying volatile, see “Protect Global Data with const and
volatile Keywords” on page 30-17. For more information about GetSet, see “Access Data
Through Functions with Custom Storage Class GetSet” on page 26-42.
17-35
17 Time-Based Scheduling in Simulink Coder
Separating Rate Transition block code and data from algorithm code and data enables
you to analyze, optimize, and test Rate Transition block and algorithm code independently
from each other.
See Also
More About
• “Time-Based Scheduling and Code Generation” (Simulink Coder)
• “Sample Times in Subsystems” (Simulink)
• “Sample Times in Systems” (Simulink)
• “Modeling for Multitasking Execution” (Simulink Coder)
• “Configure Time-Based Scheduling” (Simulink Coder)
• “Resolve Rate Transitions” (Simulink)
• “Time-Based Scheduling Example Models” (Simulink Coder)
17-36
Configure Time-Based Scheduling
When using the GRT or ERT targets, you can override the stop time when running a
generated program from the Microsoft Windows command prompt or UNIX3 command
line. To override the stop time that was set during code generation, use the -tf switch.
model -tf n
The program runs for n seconds. If n = inf, the program runs indefinitely.
Certain blocks have a dependency on absolute time. If you are designing a program that
is intended to run indefinitely (Stop time = inf), and your generated code does not use
the rtModel data structure (that is, it uses simstructs instead), you must not use these
blocks. See “Absolute Time Limitations” on page 16-12 for a list of blocks that can
potentially overflow timers.
If you know how long an application that depends on absolute time needs to run, you can
prevent the timers from overflowing and force the use of optimal word sizes by specifying
the Application lifespan (days) (Simulink) parameter on the Math and Data Types
pane. See “Control Memory Allocation for Time Counters” on page 56-11 for details.
3. UNIX is a registered trademark of The Open Group in the United States and other countries.
17-37
17 Time-Based Scheduling in Simulink Coder
See Also
More About
• “Time-Based Scheduling and Code Generation” (Simulink Coder)
• “Sample Times in Subsystems” (Simulink)
• “Sample Times in Systems” (Simulink)
• “Time-Based Scheduling Example Models” (Simulink Coder)
17-38
Time-Based Scheduling Example Models
The code generator represents time counters as unsigned integers. The word size of time
counters is based on the setting of the model configuration parameter Application
lifespan (days), which specifies the expected maximum duration of time the application
runs. You can use this parameter to prevent time counter overflows. The default size is 64
bits.
The number of bits that a time counter uses depends on the setting of the Application
lifespan (days) parameter. For example, if a time counter increments at a rate of 1 kHz,
to avoid an overflow, the counter has the following number of bits:
A 64-bit time counter does not overflow for 590 million years.
17-39
17 Time-Based Scheduling in Simulink Coder
The model consists of three subsystems SS1, SS2, and SS3. On the Math and Data
Types pane, the Application lifespan (days) parameter is set to the default, which is
inf.
17-40
Time-Based Scheduling Example Models
The three subsystems contain a discrete-time integrator that requires elapsed time as
input to compute its output value. The subsystems vary as follows:
• SS1 - Clocked at 1 kHz. Does not require a time counter. Sample time type
parameter for trigger port is set to periodic. Elapsed time is inlined as 0.001.
• SS2 - Clocked at 100 Hz. Requires a time counter. Based on a lifespan of 1 day, a 32-bit
counter stores the elapsed time.
• SS3 - Clocked at 0.5 Hz. Requires a time counter. Based on a lifespan of 1 day, a 16-bit
counter stores the elapsed time.
Simulate the model. By default, the model is configured to show sample times in different
colors. Discrete sample times for the three subsystems appear red, green, and blue.
Triggered subsystems are blue-green.
2. Configure the model for the code generator to use the GRT system target file and a
lifespan of inf days.
struct tag_RTM_rtwdemo_abstime_T {
const char_T *errorStatus;
/*
* Timing:
* The following substructure contains information regarding
* the timing information for the model.
*/
struct {
uint32_T clockTick1;
17-41
17 Time-Based Scheduling in Simulink Coder
uint32_T clockTickH1;
uint32_T clockTick2;
uint32_T clockTickH2;
struct {
uint16_T TID[3];
uint16_T cLimit[3];
} TaskCounters;
} Timing;
};
/*-
* The generated code includes comments that allow you to trace directly
* back to the appropriate location in the model. The basic format
* is <system>/block_name, where system is the system number (uniquely
* assigned by Simulink) and block_name is the name of the block.
*
* Use the MATLAB hilite_system command to trace the generated code back
* to the model. For example,
*
* hilite_system('<S3>') - opens system 3
* hilite_system('<S3>/Kp') - opens and selects block Kp which resides in S3
*
* Here is the system hierarchy for this model
*
* '<Root>' : 'rtwdemo_abstime'
* '<S1>' : 'rtwdemo_abstime/SS1'
* '<S2>' : 'rtwdemo_abstime/SS2'
17-42
Time-Based Scheduling Example Models
* '<S3>' : 'rtwdemo_abstime/SS3'
*/
#endif /* RTW_HEADER_rtwdemo_abstime_h_ */
struct tag_RTM_rtwdemo_abstime_T {
const char_T *errorStatus;
/*
* Timing:
* The following substructure contains information regarding
* the timing information for the model.
*/
struct {
uint32_T clockTick1;
uint16_T clockTick2;
struct {
uint16_T TID[3];
uint16_T cLimit[3];
} TaskCounters;
} Timing;
};
17-43
17 Time-Based Scheduling in Simulink Coder
/*-
* The generated code includes comments that allow you to trace directly
* back to the appropriate location in the model. The basic format
* is <system>/block_name, where system is the system number (uniquely
* assigned by Simulink) and block_name is the name of the block.
*
* Use the MATLAB hilite_system command to trace the generated code back
* to the model. For example,
*
* hilite_system('<S3>') - opens system 3
* hilite_system('<S3>/Kp') - opens and selects block Kp which resides in S3
*
* Here is the system hierarchy for this model
*
* '<Root>' : 'rtwdemo_abstime'
* '<S1>' : 'rtwdemo_abstime/SS1'
* '<S2>' : 'rtwdemo_abstime/SS2'
* '<S3>' : 'rtwdemo_abstime/SS3'
*/
#endif /* RTW_HEADER_rtwdemo_abstime_h_ */
The new setting for the Application lifespan (days) parameter instructs the code
generator to set aside less memory for the time counters. The regenerated code includes:
• 32-bit unsigned integer, clockTick1, for storing the elapsed time of the task for SS2
• 16-bit unsigned integer, clockTick2, for storing the elapsed time of the task for SS3
Related Information
17-44
Time-Based Scheduling Example Models
open_system('rtwdemo_srbb')
17-45
17 Time-Based Scheduling in Simulink Coder
The model uses one sample time. Inport block 1 and Inport block 2 both specify a 1-
second sample time, which is enforced by the Periodic sample time constraint option
17-46
Time-Based Scheduling Example Models
on the Solver configuration page. To view the solver page, double-click the corresponding
yellow button in the model. To display the sample times in the model, double-click the
corresponding yellow button in the model.
This model is configured to display sample-time colors upon diagram update. Red
represents the fastest discrete sample time in the model, green represents the second
fastest, and yellow represents mixed sample times. Click the yellow button in the model to
update the diagram and show sample-time colors.
open_system('rtwdemo_mrstbb')
17-47
17 Time-Based Scheduling in Simulink Coder
17-48
Time-Based Scheduling Example Models
The model contains two sample times. Inport block 1 and Inport block 2 specify 1-second
and 2-second sample times, respectively, which are enforced by the Periodic sample
time constraint option on the Solver configuration page. The solver is set for single-
tasking operation. Rate transition blocks are, therefore, not necessary between blocks
executing at different sample times because preemption will not occur.
The model is configured to display sample-time colors upon diagram update. Red
represents the fastest discrete sample time in the model, green represents the second
fastest, and yellow represents mixed sample times. Double-click the yellow button in the
model to update the diagram and show sample-time colors.
open_system('rtwdemo_mrmtbb')
17-49
17 Time-Based Scheduling in Simulink Coder
17-50
Time-Based Scheduling Example Models
The model contains two sample times. Inport block 1 and Inport block 2 specify 1-second
and 2-second sample times, respectively, which are enforced by the Periodic sample
time constraint option on the Solver configuration page. The solver is set for
multitasking operation, which means a rate transition block is required to ensure that
data integrity is enforced when the 1-second task preempts the 2-second task. Proper rate
transitions are always enforced by Simulink and Simulink Coder. This model specifies an
explicit rate transition block. Alternatively, this block could be automatically inserted by
Simulink using the model configuration parameter Automatically handle rate
transition for data transfer.
The model is configured to display sample-time colors upon diagram update. Red
represents the fastest discrete sample time in the model, green represents the second
fastest, and yellow represents mixed sample times. Click the yellow button to the right to
update the diagram and show sample-time colors.
1 Data transitions occur between a single reading task and a single writing task.
2 A read or write of a byte sized variable is atomic.
3 When two tasks interact through a data transition, only one of them can preempt the
other.
4 For periodic tasks, the faster rate task has higher priority than the slower rate task;
the faster rate task always preempts the slower rate task.
5 All tasks run on a single processor. Time slicing is not allowed.
6 Processes do not crash/restart (especially while data is being transferred between
tasks)
17-51
17 Time-Based Scheduling in Simulink Coder
Ensure data integrity and determinism (DetAndInteg) : Data is transferred such that
all data bytes for the signal (including all elements of a wide signal) are from the same
time step. Additionally, it is ensured that the relative sample time (delay) from which the
data is transferred from one rate to another is always the same. Only ANSI-C code is
used, no target specific 'critical section' protection is needed.
Ensure integrity (IntegOnly) : Data is transferred such that all data bytes for the signal
(including all elements of a wide signal) are from the same time step. However, from one
transfer of data to the next, the relative sample time (delay) for which the data is
transferred can vary. In this mode, the code to read/write the data is run more often than
in the DetandInt mode. In the worst case, the delay is equivalent to the DetandInt mode,
but the delay can be less which is important is some applications. Also, this mode support
data transfers to/from asynchronous rates which the DetandInt mode cannot support.
Only ANSI-C code is used, no target specific 'critical section' protection is needed.
No data consistency operations are performed (None) : For this case, the Rate
Transition block does not generated code. This mode is acceptable in some application
where atomic access of scalar data types is guaranteed and when the relative temporal
values of the data is not important. This mode does not introduce any delay.
• Data transitions occur between a single reading task and a single writing task.
• A read or write of a byte sized variable is atomic.
• When two tasks interact through a data transition, only one of them can preempt the
other.
• For periodic tasks, the faster rate task has higher priority than the slower rate task;
the faster rate task always preempts the slower rate task.
• All tasks run on a single processor. Time slicing is not allowed.
• Processes do not crash/restart (especially while data is being transferred between
tasks)
Model rtwdemo_ratetrans
open_system('rtwdemo_ratetrans')
17-52
Time-Based Scheduling Example Models
17-53
17 Time-Based Scheduling in Simulink Coder
• Uses two persistent data buffers, an internal buffer and the blocks output.
• The internal buffer is copied to the output at the slower rate but done during the
faster rate context.
• The internal buffer is written at the slower rate and during the slower rate context.
• The data that Fast rate sees is always delayed, i.e. data is from the previous step of the
slow rate code.
17-54
See Also
No code is generated for the Rate Transition block when determinism and data integrity
is waived.
No code is generated for the Rate Transition block when determinism and data integrity
is waived.
bdclose('rtwdemo_ratetrans');
See Also
More About
• “Time-Based Scheduling and Code Generation” (Simulink Coder)
• “Modeling for Single-Tasking Execution” (Simulink Coder)
• “Modeling for Multitasking Execution” (Simulink Coder)
17-55
18
Asynchronous Events
Asynchronous Support
Normally, you time models from which you plan to generate code from a periodic
interrupt source (for example, a hardware timer). Blocks in a periodically clocked single-
rate model run at a timer interrupt rate (the base rate of the model). Blocks in a
periodically clocked multirate model run at the base rate or at multiples of that rate.
Many systems must also support execution of blocks in response to events that are
asynchronous with respect to the periodic timing source of the system. For example, a
peripheral device might signal completion of an input operation by generating an
interrupt. The system must service such interrupts, for example, by acquiring data from
the interrupting device.
This chapter explains how to use blocks to model and generate code for asynchronous
event handling, including servicing of hardware-generated interrupts, maintenance of
timers, asynchronous read and write operations, and spawning of asynchronous tasks
under a real-time operating system (RTOS). This block library demonstrates integration
with an example RTOS (VxWorks). Although the blocks target an example RTOS, this
chapter provides source code analysis and other information you can use to develop
blocks that support asynchronous event handling for an alternative target RTOS.4
18-2
Asynchronous Events
The key blocks in the library are the Async Interrupt and Task Sync blocks. These blocks
are targeted for an example RTOS (VxWorks). You can use them, with modification, to
support your RTOS applications.
Note You can use the blocks in the vxlib1 (Simulink Coder) library (Async Interrupt and
Task Sync) for simulation and code generation. These blocks provide starting point
examples to help you develop custom blocks for your target environment.
To implement asynchronous support for an RTOS other than the example RTOS, use the
guidelines and example code are provided to help you adapt the vxlib1 library blocks to
target your RTOS. This topic is discussed in “Create a Customized Asynchronous Library”
on page 18-49.
The use of protected and unprotected Rate Transition blocks in asynchronous contexts is
discussed in “Rate Transitions and Asynchronous Blocks” on page 18-40. For general
information on rate transitions, see “Time-Based Scheduling and Code Generation” on
page 17-2.
18-3
18 Event-Based Scheduling in Simulink Coder
• Select system target file ert.tlc (requires an Embedded Coder license) from the
browse menu for the Code Generation > System target file parameter
(SystemTargetFile).
• Enable the Configuration Parameters > Code Generation > Generate code only
parameter (GenCodeOnly).
• Enable the Configuration Parameters > Code Generation > Templates > Custom
templates > Generate an example main program parameter
(GenerateSampleERTMain).
• Select VxWorksExample from the menu for the Configuration Parameters > Code
Generation > Templates > Custom templates > Target operating system
parameter (TargetOS).
• The rtwdemo_async model, which uses the tornado.tlc system target file and
vxlib1 block library. To open this example, type rtwdemo_async at the MATLAB
command prompt.
• The rtwdemo_async_mdlreftop model, which uses the tornado.tlc system target
file and vxlib1 block library. To open this example, type
rtwdemo_async_mdlreftop at the MATLAB command prompt.
• “Time-Based Scheduling and Code Generation” (Simulink Coder), discusses general
multitasking and rate transition issues for periodic models.
• The Embedded Coder documentation discusses the ert.tlc system target file,
including task execution and scheduling.
18-4
See Also
• For detailed information about the system calls to the example RTOS (VxWorks)
mentioned in this chapter, see VxWorks system documentation on the Wind River
website.
See Also
More About
• “Time-Based Scheduling and Code Generation” (Simulink Coder)
• “Generate Interrupt Service Routines” (Simulink Coder)
• “Spawn and Synchronize Execution of RTOS Task” (Simulink Coder)
• “Pass Asynchronous Events in RTOS as Input To a Referenced Model” (Simulink
Coder)
• “Timers in Asynchronous Tasks” (Simulink Coder)
• “Import Asynchronous Event Data for Simulation” (Simulink Coder)
• “Rate Transitions and Asynchronous Blocks” (Simulink Coder)
• “Create a Customized Asynchronous Library” (Simulink Coder)
• “Asynchronous Support Limitations” (Simulink Coder)
18-5
18 Event-Based Scheduling in Simulink Coder
You can also use the Async Interrupt block in a simulation. It provides an input port that
can be enabled and connected to a simulated interrupt source.
Note The operating system integration techniques that are demonstrated in this section
use one or more blocks the blocks in the vxlib1 (Simulink Coder) library. These blocks
provide starting point examples to help you develop custom blocks for your target
environment.
The next figure shows an Async Interrupt block configured to service two interrupt
sources. The outputs (signal width 2) are connected to two function call subsystems.
18-6
Generate Interrupt Service Routines
• sysIntEnable
• sysIntDisable
• intConnect
• intLock
• intUnlock
• tickGet
Performance Considerations
Execution of large subsystems at interrupt level can have a significant impact on interrupt
response time for interrupts of equal and lower priority in the system. As a general rule, it
is best to keep ISRs as short as possible. Connect only function call subsystems that
contain a small number of blocks to an Async Interrupt block.
18-7
18 Event-Based Scheduling in Simulink Coder
A better solution for large subsystems is to use the Task Sync block to synchronize the
execution of the function call subsystem to a RTOS task. The Task Sync block is placed
between the Async Interrupt block and the function call subsystem. The Async Interrupt
block then installs the Task Sync block as the ISR. The ISR releases a synchronization
semaphore (performs a semGive) to the task, and returns immediately from interrupt
level. The task is then scheduled and run by the example RTOS (VxWorks). See “Spawn
and Synchronize Execution of RTOS Task” on page 18-15 for more information.
Model
Plant (for simulation)
Plant Controller
Dual-Model Use of Async Interrupt Block for Simulation and Code Generation
A single-model approach is also possible. In this approach, the Plant component of the
model is active only in simulation. During code generation, the Plant components are
effectively switched out of the system and code is generated only for the interrupt block
and controller parts of the model. For an example of this approach, see the
rtwdemo_async model.
18-8
Generate Interrupt Service Routines
The simulated interrupt signals are routed through the Async Interrupt block's input port.
Upon receiving a simulated interrupt, the block calls the connected subsystem.
During simulation, subsystems connected to Async Interrupt block outputs are executed
in order of their priority in the example RTOS (VxWorks). In the event that two or more
interrupt signals occur simultaneously, the Async Interrupt block executes the
downstream systems in the order specified by their interrupt levels (level 7 gets the
highest priority). The first input element maps to the first output element.
You can also use the Async Interrupt block in a simulation without enabling the simulation
input. In such a case, the Async Interrupt block inherits the base rate of the model and
calls the connected subsystems in order of their priorities in the RTOS. (In this case, the
Async Interrupt block behaves as if all inputs received a 1 simultaneously.)
18-9
18 Event-Based Scheduling in Simulink Coder
The Ground blocks drive control input of the Environment Controller block, so code is not
generated for that signal path. The code generator does not produce code for blocks that
drive the simulation control input to the Environment Controller block because that path
is not selected during code generation. However, the sample times of driving blocks for
the simulation input to the Environment Controller block contribute to the sample times
supported in the generated code. To avoid including unnecessary sample times in the
generated code, use the sample times of the blocks driving the simulation input in the
model where generated code is intended.
Standalone functions are installed as ISRs and the interrupt vector table is as follows:
Offset
192 &isr_num1_vec192()
193 &isr_num2_vec193()
Consider the code generated from this model, assuming that the Async Interrupt block
parameters are configured as shown in the next figure.
18-10
Generate Interrupt Service Routines
Initialization Code
In the generated code, the Async Interrupt block installs the code in the Subsystem
blocks as interrupt service routines. The interrupt vectors for IRQ1 and IRQ2 are stored
at locations 192 and 193 relative to the base of the interrupt vector table, as specified by
the VME interrupt vector offset(s) parameter.
18-11
18 Event-Based Scheduling in Simulink Coder
The hardware that generates the interrupt is not configured by the Async Interrupt block.
Typically, the interrupt source is a VME I/O board, which generates interrupts for specific
events (for example, end of A/D conversion). The VME interrupt level and vector are set
up in registers or by using jumpers on the board. You can use the mdlStart routine of a
user-written device driver (S-function) to set up the registers and enable interrupt
generation on the board. You must match the interrupt level and vector specified in the
Async Interrupt block dialog to the level and vector set up on the I/O board.
The actual ISR generated for IRQ1 in the RTOS (VxWorks) is listed below.
void isr_num1_vec192(void)
{
int_T lock;
FP_CONTEXT context;
/* re-enable interrupts */
18-12
See Also
intUnlock(lock);
}
• Because of the setting of the Preemption Flag(s) parameter, this ISR is locked; that
is, it cannot be preempted by a higher priority interrupt. The ISR is locked and
unlocked in the example RTOS (VxWorks) by the int_lock and int_unlock
functions.
• The connected subsystem, Count, is called from within the ISR.
• The Count function executes algorithmic (model) code. Therefore, the floating-point
context is saved and restored across the call to Count.
• The ISR maintains its own absolute time counter, which is distinct from other periodic
base rate or subrate counters in the system. Timing data is maintained for the use of
any blocks executed within the ISR that require absolute or elapsed time.
The model's termination function disables the interrupts in the RTOS (VxWorks):
See Also
More About
• “Spawn and Synchronize Execution of RTOS Task” (Simulink Coder)
18-13
18 Event-Based Scheduling in Simulink Coder
18-14
Spawn and Synchronize Execution of RTOS Task
18-15
18 Event-Based Scheduling in Simulink Coder
The model simulates an interrupt source and includes an Async Interrupt block, a Task
Sync block, function-call subsystems Count and Algorithm, and Rate Transition blocks.
The Async Interrupt block creates two Versa Module Eurocard (VME) interrupt service
routines (ISRs) that pass interrupt signals to subsystem Count and the Task Sync block.
You can place an Async Interrupt block between a simulated interrupt source and one of
the following:
18-16
Spawn and Synchronize Execution of RTOS Task
The Async Interrupt and Task Sync blocks enable the subsystems to execute
asynchronously.
Count represents a simple interrupt service routine (ISR) that executes at interrupt level.
It is best to keep ISRs as simple as possible. This subsystem includes only a Discrete-Time
Integrator block.
Algorithm includes more substance. It includes multiple blocks and produces two output
values. Execution of larger subsystems at interrupt level can significantly impact
response time for interrupts of equal and lower priority in the system. A better solution
for larger subsystems is to use the Task Sync block to represent the ISR for the function-
call subsystem.
The Async Interrupt block generates calls to ISRs. Place the block between a simulated
interrupt source and one of the following:
For each specified interrupt level, the block generates a Versa Module Eurocard (VME)
ISR that executes the connected subsystem, Task Sync block, or chart.
In the example model, the Async Interrupt block is configured for VME interrupts 1 and 2,
by using interrupt vector offsets 192 and 193. Interrupt 1 connects directly to subsystem
Count. Interrupt 2 connects to a Task Sync block, which serves as the ISR for
Algorithm. Place a Task Sync block in one of the following locations:
In the example model, the Task Sync block is between the Async Interrupt block and
function-call subsystem Algorithm. The Task Sync block is configured with the task
18-17
18 Event-Based Scheduling in Simulink Coder
name Task(), a priority of 50, a stack size of 8192, and data transfers of the task
synchronized with the caller task. The spawned task uses a semaphore to synchronize
task execution. The Async Interrupt block triggers a release of the task semaphore.
Four Rate Transition blocks handle data transfers between ports that operate at different
rates. In two instances, Protected Rate Transition blocks protect data transfers (prevent
them from being preempted and corrupted). In the other two instances, Unprotected Rate
Transition blocks introduce no special behavior. Their presence informs Simulink® of a
rate transition.
The code generated for the Async Interrupt and Task Sync blocks is tailored for the
example RTOS (VxWorks®). However, you can modify the blocks to generate code specific
to your run-time environment.
• Data transfers occur between one reading task and one writing task.
• A read or write operation on a byte-size variable is atomic.
• When two tasks interact, only one can preempt the other.
• For periodic tasks, the task with the faster rate has higher priority than the task with
the slower rate. The task with the faster rate preempts the tasks with slower rates.
• Tasks run on a single processor. Time slicing is not allowed.
• Processes do not stop and restart, especially while data is being transferred between
tasks.
Simulate the model. By default, the model is configured to show sample times in different
colors. Discrete sample times for input and output appear red and green, respectively.
Constants are reddish-blue. Asynchronous interrupts and tasks are purple. The Rate
Transition Blocks, which are a hybrid rate (their input and output sample times can
differ), are yellow.
Generate code and a code generation report for the model. Generated code for the Async
Interrupt and Task Sync blocks is for the example RTOS (VxWorks®). However, you can
modify the blocks to generate code for another run-time environment.
18-18
Spawn and Synchronize Execution of RTOS Task
rtwdemo_async_DW.SFunction_IWORK.TaskID = taskSpawn("Task0",
50.0,
VX_FP_TASK,
8192.0,
(FUNCPTR)Task0,
0, 0, 0, 0, 0, 0, 0,0, 0, 0);
if (rtwdemo_async_DW.SFunction_IWORK.TaskID == ERROR) {
printf("taskSpawn call failed for block Task0.\n");
}
18-19
18 Event-Based Scheduling in Simulink Coder
sysIntEnable(1);
sysIntEnable(2);
{
int32_T i;
18-20
Spawn and Synchronize Execution of RTOS Task
18-21
18 Event-Based Scheduling in Simulink Coder
/*========================================================================*
* Start of Classic call interface *
*========================================================================*/
void MdlOutputs(int_T tid)
{
rtwdemo_async_output(tid);
}
void MdlInitializeSizes(void)
{
}
void MdlInitializeSampleTimes(void)
{
}
void MdlInitialize(void)
{
}
18-22
Spawn and Synchronize Execution of RTOS Task
void MdlStart(void)
{
rtwdemo_async_initialize();
}
void MdlTerminate(void)
{
rtwdemo_async_terminate();
}
/* Registration function */
RT_MODEL_rtwdemo_async_T *rtwdemo_async(void)
{
/* Registration code */
/* initialize non-finites */
rt_InitInfAndNaN(sizeof(real_T));
/* task periods */
rtwdemo_async_M->Timing.sampleTimes[0] = (0.016666666666666666);
rtwdemo_async_M->Timing.sampleTimes[1] = (0.05);
/* task offsets */
rtwdemo_async_M->Timing.offsetTimes[0] = (0.0);
rtwdemo_async_M->Timing.offsetTimes[1] = (0.0);
}
rtmSetTPtr(rtwdemo_async_M, &rtwdemo_async_M->Timing.tArray[0]);
18-23
18 Event-Based Scheduling in Simulink Coder
{
int_T *mdlSampleHits = rtwdemo_async_M->Timing.sampleHitArray;
int_T *mdlPerTaskSampleHits = rtwdemo_async_M->Timing.perTaskSampleHitsArray;
rtwdemo_async_M->Timing.perTaskSampleHits = (&mdlPerTaskSampleHits[0]);
mdlSampleHits[0] = 1;
rtwdemo_async_M->Timing.sampleHits = (&mdlSampleHits[0]);
}
rtmSetTFinal(rtwdemo_async_M, 0.5);
rtwdemo_async_M->Timing.stepSize0 = 0.016666666666666666;
rtwdemo_async_M->Timing.stepSize1 = 0.05;
rtwdemo_async_M->solverInfoPtr = (&rtwdemo_async_M->solverInfo);
rtwdemo_async_M->Timing.stepSize = (0.016666666666666666);
rtsiSetFixedStepSize(&rtwdemo_async_M->solverInfo, 0.016666666666666666);
rtsiSetSolverMode(&rtwdemo_async_M->solverInfo, SOLVER_MODE_MULTITASKING);
/* block I/O */
rtwdemo_async_M->blockIO = ((void *) &rtwdemo_async_B);
(void) memset(((void *) &rtwdemo_async_B), 0,
sizeof(B_rtwdemo_async_T));
/* states (dwork) */
rtwdemo_async_M->dwork = ((void *) &rtwdemo_async_DW);
(void) memset((void *)&rtwdemo_async_DW, 0,
sizeof(DW_rtwdemo_async_T));
/* external inputs */
rtwdemo_async_M->inputs = (((void*)&rtwdemo_async_U));
(void)memset((void *)&rtwdemo_async_U, 0, sizeof(ExtU_rtwdemo_async_T));
/* external outputs */
rtwdemo_async_M->outputs = (&rtwdemo_async_Y);
(void) memset((void *)&rtwdemo_async_Y, 0,
sizeof(ExtY_rtwdemo_async_T));
/* Initialize Sizes */
rtwdemo_async_M->Sizes.numContStates = (0);/* Number of continuous states */
rtwdemo_async_M->Sizes.numY = (3); /* Number of model outputs */
rtwdemo_async_M->Sizes.numU = (60); /* Number of model inputs */
rtwdemo_async_M->Sizes.sysDirFeedThru = (0);/* The model is not direct feedthrough */
rtwdemo_async_M->Sizes.numSampTimes = (2);/* Number of sample times */
rtwdemo_async_M->Sizes.numBlocks = (17);/* Number of blocks */
rtwdemo_async_M->Sizes.numBlockIO = (4);/* Number of block outputs */
return rtwdemo_async_M;
18-24
Spawn and Synchronize Execution of RTOS Task
/*========================================================================*
* End of Classic call interface *
*========================================================================*/
The order of these operations is important. Before the code generator enables the
interrupt that activates the task, it must spawn the task.
In the generated source file rtwdemo_async.c, review the task and task synchronization
code.
The code generator produces the code for function Task0 from the Task Sync block. That
function includes a small amount of interrupt-level code and runs as an RTOS task.
The task waits in an infinite for loop until the system releases a synchronization
semaphore. If the system releases the semaphore, the function updates its task timer and
calls the code generated for the Algorithm subsystem.
In the example model, the Synchronize the data transfer of this task with the caller
task parameter for the Task Sync block is set. This parameter setting updates the timer
associated with the Task Sync block (rtM->Timing.clockTick2) with the value of the
timer that the Async Interrupt block (rtM->Timing.clockTick3) maintains. As a result,
code for blocks within the Algorithm subsystem use timer values that are based on the
time of the most recent interrupt, rather than the most recent activation of Task0.
{
/* Wait for semaphore to be released by system: rtwdemo_async/Task Sync */
for (;;) {
if (semTake(*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID,NO_WAIT) !=
ERROR) {
logMsg("Rate for Task Task0() too fast.\n",0,0,0,0,0,0);
#if STOPONOVERRUN
#endif
18-25
18 Event-Based Scheduling in Simulink Coder
} else {
semTake(*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID, WAIT_FOREVER);
}
18-26
Spawn and Synchronize Execution of RTOS Task
* Constant: '<S1>/Offset'
*/
for (i = 0; i < 60; i++) {
rtwdemo_async_B.Sum[i] = rtwdemo_async_B.ProtectedRT1[i] + 1.25;
}
/* Sum: '<S1>/Sum1' */
tmp = -0.0;
for (i = 0; i < 60; i++) {
tmp += rtwdemo_async_B.Sum[i];
}
{
int32_T i;
rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx = (int8_T)
(rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx == 0);
18-27
18 Event-Based Scheduling in Simulink Coder
The code generator produces code for ISRs isr_num1_vec192 and isr_num2_vec293.
ISR isr_num2_vec192:
• Disables interrupts.
• Saves floating-point context.
• Calls the code generated for the subsystem that connects to the referenced model
Inport block, which receives the interrupt.
• Restores floating-point context.
• Reenables interrupts.
void isr_num1_vec192(void)
{
int_T lock;
FP_CONTEXT context;
18-28
Spawn and Synchronize Execution of RTOS Task
* DiscreteIntegrator: '<S2>/Integrator'
*/
rtwdemo_async_Y.Out1 = rtwdemo_async_DW.Integrator_DSTATE_l;
/* re-enable interrupts */
intUnlock(lock);
}
ISR isr_num2_vec293 maintains a timer that stores the tick count at the time that the
interrupt occurs. After updating the timer, the ISR releases the semaphore that activates
Task0.
void isr_num2_vec193(void)
{
/* Use tickGet() as a portable tick
counter example. A much higher resolution can
be achieved with a hardware counter */
rtwdemo_async_M->Timing.clockTick3 = tickGet();
18-29
18 Event-Based Scheduling in Simulink Coder
18-30
See Also
Related Information
• Async Interrupt
• Task Sync
• “Generate Interrupt Service Routines” (Simulink Coder)
• “Timers in Asynchronous Tasks” (Simulink Coder)
• “Create a Customized Asynchronous Library” (Simulink Coder)
• “Import Asynchronous Event Data for Simulation” (Simulink Coder)
• “Load Data to Root-Level Input Ports” (Simulink)
• “Asynchronous Events” (Simulink Coder)
• “Rate Transitions and Asynchronous Blocks” (Simulink Coder)
• “Asynchronous Support Limitations” (Simulink Coder)
See Also
More About
• “Generate Interrupt Service Routines” (Simulink Coder)
• “Pass Asynchronous Events in RTOS as Input To a Referenced Model” (Simulink
Coder)
• “Timers in Asynchronous Tasks” (Simulink Coder)
• “Import Asynchronous Event Data for Simulation” (Simulink Coder)
• “Rate Transitions and Asynchronous Blocks” (Simulink Coder)
18-31
18 Event-Based Scheduling in Simulink Coder
18-32
Pass Asynchronous Events in RTOS as Input To a Referenced Model
The model simulates an interrupt source and includes an Async Interrupt block and
referenced model. The Async Interrupt block creates two Versa Module Eurocard (VME)
interrupt service routines (ISRs) that pass interrupt signals to Inport blocks 1 and 2 of the
referenced model. You can place an Async Interrupt block between a simulated interrupt
source and one of the following:
18-33
18 Event-Based Scheduling in Simulink Coder
In this example model, the Async Interrupt block passes asynchronous events (function-
call trigger signals), Interrupt1 and Interrupt2, to the referenced model through
Inport blocks 1 and 2.
The code generated for the Async Interrupt block is tailored for the example real-time
operating system (VxWorks). However, you can modify the block to generate code specific
to your run-time environment.
The referenced model includes the two Inport blocks that receive the interrupts, each
connected to an Asynchronous Task Specification block, function-call subsystems Count
and Algorithm, and Rate Transition blocks. The Asynchronous Task Specification block,
in combination with a root-level Inport block, allows a reference model to receive
asynchronous function-call input. To use the block:
1 Connect the Asynchronous Task Specification block to the output port of a root-level
Inport block that outputs a function-call trigger.
2 Select the Output function call parameter of the Inport block to specify that it
accepts function-call signals.
3 On the Asynchronous Task Specification parameters dialog box, set the task priority
for the asynchronous task associated with an Inport block. Specify an integer or []. If
you specify an integer, it must match the priority of the interrupt initiated by the
Async Interrupt block in the parent model. If you specify [], the priorities do not have
to match.
The Asynchronous Task Specification block for the higher priority interrupt, interrupt1,
connects to function-call subsystem Count. Count represents a simple interrupt service
routine (ISR). The second Asynchronous Task Specification block connects to the
subsystem Algorithm, which includes more substance. It includes multiple blocks and
produces two output values. Both subsystems execute at interrupt level.
For each interrupt level specified for the Async Interrupt block in the parent model, the
block generates a VME ISR that executes the connected subsystem, Task Sync block, or
chart.
In the example top model, the Async Interrupt block is configured for VME interrupts 1
and 2, using interrupt vector offsets 192 and 193. Interrupt 1 is wired to trigger
subsystem Count. Interrupt 2 is wired to trigger subsystem Algorithm.
18-34
Pass Asynchronous Events in RTOS as Input To a Referenced Model
The Rate Transition blocks handle data transfers between ports that operate at different
rates. In two instances, the blocks protect data transfers (prevent them from being
preempted and corrupted). In the other instance, no special behavior occurs.
• Data transfers occur between one reading task and one writing task.
• A read or write operation on a byte-sized variable is atomic.
• When two tasks interact, only one can preempt the other.
• For periodic tasks, the task with the faster rate has higher priority than the task with
the slower rate. The task with the faster rate preempts the tasks slower rates.
• Tasks run on a single processor. Time slicing is not allowed.
• Processes do not crash and restart, especially while data is being transferred between
tasks.
Simulate the model. By default, the model is configured to show sample times in different
colors. Discrete sample times for input and output appear red and green, respectively.
Constants are magenta. Asynchronous interrupts are purple. The Rate Transition Blocks,
which are hybrid (input and output sample times can differ), appear yellow.
Generate code and a code generation report for the model. Async Interrupt block and
Task Sync block generated code is for the example RTOS (VxWorks). However, you can
modify the blocks to generate code for another run-time environment.
Warning: Simulink Coder: The tornado.tlc target will be removed in a future release.
18-35
18 Event-Based Scheduling in Simulink Coder
sysIntEnable(1);
sysIntEnable(2);
18-36
Pass Asynchronous Events in RTOS as Input To a Referenced Model
In the generated source file rtwdemo_async_mdlreftop.c, review the code for ISRs
isr_num1_vec192 and isr_num2_vec293. Each ISR:
• Disables interrupts.
• Saves floating-point context.
• Calls the code generated for the subsystem connected to the referenced model Inport
block that receives the interrupt.
• Restores floating-point context.
• Reenables interrupts.
void isr_num1_vec192(void)
{
int_T lock;
FP_CONTEXT context;
/* re-enable interrupts */
intUnlock(lock);
18-37
18 Event-Based Scheduling in Simulink Coder
18-38
See Also
Related Information
• Async Interrupt
• Asynchronous Task Specification
• “Generate Interrupt Service Routines” (Simulink Coder)
• “Timers in Asynchronous Tasks” (Simulink Coder)
• “Create a Customized Asynchronous Library” (Simulink Coder)
• “Import Asynchronous Event Data for Simulation” (Simulink Coder)
• “Load Data to Root-Level Input Ports” (Simulink)
• “Asynchronous Events” (Simulink Coder)
• “Rate Transitions and Asynchronous Blocks” (Simulink Coder)
• “Asynchronous Support Limitations” (Simulink Coder)
See Also
More About
• “Generate Interrupt Service Routines” (Simulink Coder)
• “Spawn and Synchronize Execution of RTOS Task” (Simulink Coder)
• “Timers in Asynchronous Tasks” (Simulink Coder)
• “Import Asynchronous Event Data for Simulation” (Simulink Coder)
• “Rate Transitions and Asynchronous Blocks” (Simulink Coder)
18-39
18 Event-Based Scheduling in Simulink Coder
Note The operating system integration techniques that are demonstrated in this section
use one or more blocks the blocks in the vxlib1 (Simulink Coder) library. These blocks
provide starting point examples to help you develop custom blocks for your target
environment.
You can handle rate transition issues automatically by selecting the Automatically
handle rate transition for data transfer parameter on the Solver pane of the
Configuration Parameters dialog box. This saves you from having to manually insert Rate
Transition blocks to avoid invalid rate transitions, including invalid asynchronous-to-
periodic and asynchronous-to-asynchronous rate transitions, in multirate models. For
asynchronous tasks, the Simulink engine configures inserted blocks for data integrity but
not determinism during data transfers.
For asynchronous rate transitions, the Rate Transition block provides data integrity, but
cannot provide determinism. Therefore, when you insert Rate Transition blocks explicitly,
18-40
Rate Transitions and Asynchronous Blocks
you must clear the Ensure data determinism check box in the Block Parameters dialog
box.
When you insert a Rate Transition block between two blocks to maintain data integrity
and priorities are assigned to the tasks associated with the blocks, the code generator
assumes that the higher priority task can preempt the lower priority task and the lower
priority task cannot preempt the higher priority task. If the priority associated with task
for either block is not assigned or the priorities of the tasks for both blocks are the same,
the code generator assumes that either task can preempt the other task.
Priorities of periodic tasks are assigned by the Simulink engine, in accordance with the
options specified in the Solver selection section of the Solver pane of the Configuration
Parameters dialog box. When the Periodic sample time constraint option field of
Solver selection is set to Unconstrained, the model base rate priority is set to 40.
Priorities for subrates then increment or decrement by 1 from the base rate priority,
depending on the setting of the Higher priority value indicates higher task priority
option.
You can assign priorities manually by using the Periodic sample time properties field.
The Simulink engine does not assign a priority to asynchronous blocks. For example, the
priority of a function call subsystem that connects back to an Async Interrupt block is
assigned by the Async Interrupt block.
The Simulink task priority field of the Async Interrupt block specifies a priority level
(required) for every interrupt number entered in the VME interrupt number(s) field.
The priority array sets the priorities of the subsystems connected to each interrupt.
For the Task Sync block, if the example RTOS (VxWorks) is the target, the Higher
priority value indicates higher task priority option should be deselected. The
Simulink task priority field specifies the block priority relative to connected blocks (in
addition to assigning an RTOS priority to the generated task code).
The vxlib1 library provides two types of rate transition blocks as a convenience. These
are simply preconfigured instances of the built-in Simulink Rate Transition block:
• Protected Rate Transition block: Rate Transition block that is configured with the
Ensure data integrity during data transfers on and Ensure deterministic data
transfer off.
• Unprotected Rate Transition block: Rate Transition block that is configured with the
Ensure data integrity during data transfers option off.
18-41
18 Event-Based Scheduling in Simulink Coder
You can use the Rate Transition block in either of the following modes:
Alternatively, you can use target-specific rate transition blocks. The following blocks are
available for the example RTOS (VxWorks):
18-42
Rate Transitions and Asynchronous Blocks
The two tasks must have equal priorities. When priorities are the same, the outcome
depends on whether they are firing periodically or asynchronously, and also on a
diagnostic setting. The following table and notes describe these outcomes:
Supported Sample Time and Priority for Function Call Subsystem with Multiple Triggers
Async Priority = Async Priority = Async Priority Periodic Priority Periodic Priority
1 2 Unspecified =1 =2
Async Priority = Supported (1)
1
Async Priority = Supported (1)
2
Async Priority Supported (2)
Unspecified
Periodic Priority Supported
=1
Periodic Priority Supported
=2
1 Control these outcomes using the Tasks with equal priority option in the
Diagnostics pane of the Configuration Parameters dialog box; set this diagnostic to
none if tasks of equal priority cannot preempt each other in the target system.
2 For this case, the following warning message is issued unconditionally:
18-43
18 Event-Based Scheduling in Simulink Coder
Empty cells in the above table represent multiple triggers with differing priorities, which
are unsupported.
The code generator provides absolute time management for a function call subsystem
connected to multiple interrupts in the case where timer settings for TriggerA and
TriggerB (time source, resolution) are the same.
Assume that all of the following conditions are true for the model shown above:
The asynchronous function call subsystem has one global variable, clockTick# (where #
is the task ID associated with the subsystem). This variable stores absolute time for the
asynchronous task. There are two ways timing can be handled:
The word size of the clock tick variable can be set directly or be established according to
the Application lifespan (days) (Simulink) setting and the timer resolution set by the
TriggerA and TriggerB S-functions (which must be the same). See “Timers in
Asynchronous Tasks” on page 18-46 and “Control Memory Allocation for Time Counters”
on page 56-11 for more information.
18-44
See Also
transferred data. For more information, see “Protect Global Data with const and volatile
Keywords” on page 30-17.
See Also
More About
• “Handle Rate Transitions” (Simulink Coder)
• “Time-Based Scheduling and Code Generation” (Simulink Coder)
• “Asynchronous Support Limitations” (Simulink Coder)
18-45
18 Event-Based Scheduling in Simulink Coder
• SS_TIMESOURCE_SELF: Each generated ISR maintains its own absolute time counter,
which is distinct from a periodic base rate or subrate counters in the system. The
counter value and the timer resolution value (specified in the Timer resolution
(seconds) parameter of the Async Interrupt block) are used by downstream blocks to
determine absolute time values required by block computations.
• SS_TIMESOURCE_CALLER: The ISR reads time from a counter maintained by its caller.
Time resolution is thus the same as its caller's resolution.
• SS_TIMESOURCE_BASERATE: The ISR can read absolute time from the model's
periodic base rate. Time resolution is thus the same as its base rate resolution.
Note The operating system integration techniques that are demonstrated in this section
use one or more blocks the blocks in the vxlib1 (Simulink Coder) library. These blocks
provide starting point examples to help you develop custom blocks for your target
environment.
/*
* Timing:
* The following substructure contains information regarding
* the timing information for the model.
*/
struct {
uint32_T clockTick1;
18-46
Timers in Asynchronous Tasks
uint32_T clockTick2;
} Timing;
};
The example omits unused fields in the Timing data structure (a feature of ERT target
code not found in GRT). For a target that supports the rtModel data structure, the
counter word size is determined by the Application lifespan (days) (Simulink) model
parameter.
By default, the vxlib1 library blocks for the example RTOS (VxWorks) set the timer
source to SS_TIMESOURCE_SELF and update their counters by using the system call
tickGet. tickGet returns a timer value maintained by the RTOS kernel. The maximum
word size for the timer is UINT32. The following example shows a generated call to
tickGet.
The tickGet call is supplied only as an example. It can (and in many instances should) be
replaced by a timing source that has better resolution. If you are implementing a custom
asynchronous block for an RTOS other than the example RTOS (VxWorks), you should
either generate an equivalent call to the target RTOS, or generate code to read a timer
register on the target hardware.
The default Timer resolution (seconds) parameter of your Async Interrupt block
implementation should be changed to match the resolution of your target's timing source.
The counter is updated at interrupt level. Its value represents the tick value of the timing
source at the most recent execution of the ISR. The rate of this timing source is unrelated
to sample rates in the model. In fact, typically it is faster than the model's base rate.
Select the timer source and set its rate and resolution based on the expected rate of
interrupts to be serviced by the Async Interrupt block.
For an example of timer code generation, see “Async Interrupt Block Implementation” on
page 18-50.
18-47
18 Event-Based Scheduling in Simulink Coder
See Also
Related Examples
• “Generate Interrupt Service Routines” on page 18-6
• “Spawn and Synchronize Execution of RTOS Task” on page 18-15
• “Timers in Asynchronous Tasks” on page 18-46
• “Create a Customized Asynchronous Library” on page 18-49
• “Import Asynchronous Event Data for Simulation” on page 18-59
More About
• “Absolute and Elapsed Time Computation” (Simulink Coder)
• “Time-Based Scheduling and Code Generation” (Simulink Coder)
• “Asynchronous Events” (Simulink Coder)
• “Asynchronous Support Limitations” (Simulink Coder)
18-48
Create a Customized Asynchronous Library
In this section...
“About Implementing Asynchronous Blocks” on page 18-49
“Async Interrupt Block Implementation” on page 18-50
“Task Sync Block Implementation” on page 18-54
“asynclib.tlc Support Library” on page 18-56
Note The operating system integration techniques that are demonstrated in this section
use one or more blocks the blocks in the vxlib1 (Simulink Coder) library. These blocks
provide starting point examples to help you develop custom blocks for your target
environment.
In addition, you need to modify the block masks to remove references specific to the
example RTOS (VxWorks) and to incorporate parameters required by your target RTOS.
18-49
18 Event-Based Scheduling in Simulink Coder
The following sections discuss the C/C++ and TLC implementations of the asynchronous
library blocks, including required SimStruct macros and functions in the TLC
asynchronous support library (asynclib.tlc).
Most of the code in vxinterrupt1.c performs ordinary functions that are not related to
asynchronous support (for example, obtaining and validating parameters from the block
mask, marking parameters nontunable, and passing parameter data to the model.rtw
file).
• ssSetTimeSource
• ssSetAsyncTimerAttributes
• ssSetAsyncTimerResolutionEl
• ssSetAsyncTimerDataType
• ssSetAsyncTimerDataTypeEl
• ssSetAsyncTaskPriorities
18-50
Create a Customized Asynchronous Library
• ssSetAsyncTaskPrioritiesEl
If one of the above macros is called before ssSetOutputPortWidth, the following error
message appears:
SL_SfcnMustSpecifyPortWidthBfCallSomeMacro {
S-function '%s' in '%<BLOCKFULLPATH>'
must set output port %d width using
ssSetOutputPortWidth before calling macro %s
}
ssSetAsyncTimerAttributes
ssSetAsyncTimerAttributes declares that the block requires a timer, and sets the
resolution of the timer as specified in the Timer resolution (seconds) parameter.
where
• S is a Simstruct pointer.
• res is the Timer resolution (seconds) parameter value.
ssSetAsyncTaskPriorities
where
• S is a SimStruct pointer.
• numISRs is the number of interrupts specified in the VME interrupt number(s)
parameter.
18-51
18 Event-Based Scheduling in Simulink Coder
SS_OPTION Settings
The code excerpt below shows the SS_OPTION settings for vxinterrupt1.c.
SS_OPTION_ASYNCHRONOUS_INTERRUPT should be used when a function call subsystem
is attached to an interrupt. For more information, see the documentation for SS_OPTION
and SS_OPTION_ASYNCHRONOUS in matlabroot/simulink/include/simstruc.h.
ssSetOptions( S, (SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME |
SS_OPTION_ASYNCHRONOUS_INTERRUPT |
TLC Implementation
18-52
Create a Customized Asynchronous Library
%include "vxlib.tlc"
vxlib.tlc is a target-specific file that generates directives to include header files for the
example RTOS (VxWorks). You should replace this with a file that generates includes for
your target RTOS.
BlockInstanceSetup Function
For each connected output of the Async Interrupt block, BlockInstanceSetup defines a
function name for the corresponding ISR in the generated code. The functions names are
of the form
isr_num_vec_offset
where num is the ISR number defined in the VME interrupt number(s) block parameter,
and offset is an interrupt table offset defined in the VME interrupt vector offset(s)
block parameter.
The function names are cached for use by the Outputs function, which generates the
actual ISR code.
Outputs Function
Outputs iterates over the connected outputs of the Async Interrupt block. An ISR is
generated for each such output.
The ISR code is cached in the "Functions" section of the generated code. Before
generating the ISR, Outputs does the following:
• The preemption flag for the ISR must be set to 1. An error results otherwise.
• The RTOS (VxWorks) calls to save and restore floating-point context are generated,
unless the user has configured the model for integer-only code generation.
18-53
18 Event-Based Scheduling in Simulink Coder
When generating the ISR code, Outputs calls the asynclib function
LibNeedAsyncCounter to determine whether a timer is required by the connected
subsystem. If so, and if the time source is set to be SS_TIMESOURCE_SELF by
ssSetTimeSource, LibSetAsyncCounter is called to generate an RTOS (VxWorks)
tickGet function call and update the counter. In your implementation, you should
generate either an equivalent call to the target RTOS, or generate code to read the a
timer register on the target hardware.
Start Function
The Start function generates the required RTOS (VxWorks) calls (int_connect and
sysInt_Enable) to connect and enable each ISR. You should replace this with calls to
your target RTOS.
Terminate Function
The Terminate function generates the call sysIntDisable to disable each ISR. You
should replace this with calls to your target RTOS.
Like the Async Interrupt block, the Task Sync block sets up a timer, in this case with a
fixed resolution. The priority of the task associated with the block is obtained from the
Simulink task priority parameter. The SS_OPTION settings are the same as those used
for the Async Interrupt block.
ssSetAsyncTimerAttributes(S, 0.01);
18-54
Create a Customized Asynchronous Library
ssSetOptions(S, (SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_ASYNCHRONOUS |
SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME |
}
TLC Implementation
Generate #include Directives
%include "vxlib.tlc"
vxlib.tlc is a target-specific file that generates directives to include header files for the
example RTOS (VxWorks). You should replace this with a file that generates includes for
your target RTOS.
BlockInstanceSetup Function
The BlockInstanceSetup function derives the task name, block name, and other
identifiers used later in code generation. It also checks for and warns about unconnected
block conditions, and generates a storage declaration for a semaphore (stopSem) that is
used in case of interrupt overflow conditions.
Start Function
The Start function generates the required RTOS (VxWorks) calls to define storage for
the semaphore that is used in management of the task spawned by the Task Sync block.
Depending on the value of the CodeFormat TLC variable of the target, either a static
storage declaration or a dynamic memory allocation call is generated. This function also
creates a semaphore (semBCreate) and spawns an RTOS task (taskSpawn). You should
replace these with calls to your target RTOS.
Outputs Function
The Outputs function generates an example RTOS (VxWorks) task that waits for a
semaphore. When it obtains the semaphore, it updates the block's tick timer and calls the
downstream subsystem code, as described in “Spawn and Synchronize Execution of RTOS
Task” on page 18-15. Outputs also generates code (called from interrupt level) that
grants the semaphore.
18-55
18 Event-Based Scheduling in Simulink Coder
Terminate Function
The Terminate function generates the example RTOS (VxWorks) call taskDelete to
end execution of the task spawned by the block. You should replace this with calls to your
target RTOS.
Note also that if the target RTOS has dynamically allocated memory associated with the
task, the Terminate function should deallocate the memory.
The following table summarizes the public calls in the library. For details, see the library
source code and the vxinterrupt1.tlc and vxtask1.tlc files, which call the library
functions.
18-56
See Also
Function Description
LibBlockExecuteFcnCall For use by inlined S-functions with function call outputs.
Generates code to execute a function call subsystem.
LibGetBlockAttribute Returns a field value from a block record.
LibGetFcnCallBlock Given an S-Function block and call index, returns the block
record for the downstream function call subsystem block.
LibGetCallerClockTickCounter Provides access to the time counter of an upstream
asynchronous task.
LibGetCallerClockTickCounter‐ Provides access to the high word of the time counter of an
HighWord upstream asynchronous task.
LibManageAsyncCounter Determines whether an asynchronous task needs a counter
and manages its own timer.
LibNeedAsyncCounter If the calling block requires an asynchronous counter,
returns TLC_TRUE, otherwise returns TLC_FALSE.
LibSetAsyncClockTicks Returns code that sets clockTick counters that are to be
maintained by the asynchronous task.
LibSetAsyncCounter Generates code to set the tick value of the block's
asynchronous counter.
LibSetAsyncCounterHighWord Generates code to set the tick value of the high word of the
block's asynchronous counter
See Also
More About
• “Asynchronous Events” (Simulink Coder)
• “Generate Interrupt Service Routines” (Simulink Coder)
• “Spawn and Synchronize Execution of RTOS Task” (Simulink Coder)
• “Pass Asynchronous Events in RTOS as Input To a Referenced Model” (Simulink
Coder)
• “Timers in Asynchronous Tasks” (Simulink Coder)
18-57
18 Event-Based Scheduling in Simulink Coder
18-58
Import Asynchronous Event Data for Simulation
Capabilities
You can import asynchronous event data into a function-call subsystem via an Inport
block. For standalone fixed-step simulations, you can specify:
• The expression for the parameter Data Import/Export > Input must be a comma-
separated list of tables.
• The table corresponding to the input port outputting asynchronous events must be a
column vector containing time values for the asynchronous events.
• The time vector of the asynchronous events must be of double data type and
monotonically increasing.
• All time data must be integer multiples of the model step size.
• To specify multiple function calls at a given time step, you must repeat the time
value accordingly. In other words, if you wish to specify three asynchronous events
at t = 1 and two events at t = 9, then you must list 1 three times and 9 twice in
your time vector. (t = [1 1 1 9 9]')
• The table corresponding to normal data input port can be of any other supported
format.
See “Load Data to Root-Level Input Ports” (Simulink) for more information.
Example
In this model, a function-call subsystem is used to track the total number of asynchronous
events and to multiply a set of inputs by 2.
18-59
18 Event-Based Scheduling in Simulink Coder
Alternatively, you can enter the data as t, tu in the Data Import/Export pane:
18-60
Import Asynchronous Event Data for Simulation
Here, t is a column vector containing the times of asynchronous events for Inport
block In1 while tu is a table of input values versus time for Inport block In2.
2 By default, the Time and Output options are selected and the output variables are
named tout and yout.
3 Simulate the model.
4 Display the output by entering [tout yout] at the MATLAB command line and
obtain:
ans =
0 0 -1
1 2 2
2 2 2
3 2 2
4 2 2
5 3 10
6 3 10
7 3 10
8 3 10
9 6 18
10 6 18
The second column represents the output of Out1 — the total number of
asynchronous events. Since the function-call subsystem is triggered twice at t = 1,
the output is 2. It is not called again until t = 5, and so does not increase to 3 until
then. Finally, it is called three times at 9, so it increases to 6.
18-61
18 Event-Based Scheduling in Simulink Coder
The third column contains the output of Out2 obtained by multiplying the input value
at each asynchronous event time by 2. At any other time, the output is held at its
previous value
See Also
More About
• “Asynchronous Events” (Simulink Coder)
• “Pass Asynchronous Events in RTOS as Input To a Referenced Model” (Simulink
Coder)
• “Load Data to Root-Level Input Ports” (Simulink)
• “Rate Transitions and Asynchronous Blocks” (Simulink Coder)
18-62
Asynchronous Support Limitations
In this section...
“Asynchronous Task Priority” on page 18-63
“Convert an Asynchronous Subsystem into a Model Reference” on page 18-63
1 Convert the Async Interrupt and Count blocks into a subsystem. Select both blocks
and right-click Count. From the menu, select Subsystem & Model Reference >
Create Subsystem from Selection.
18-63
18 Event-Based Scheduling in Simulink Coder
2 To prepare for converting the new subsystem to a Model block, set the following
configuration parameters in the top model. Open the Configuration Parameters dialog
box.
• Under Diagnostics, navigate to the Sample Time pane. Then set Multitask rate
transition to error and Multitask conditionally executed subsystem to
error.
• Under Diagnostics, navigate to the Connectivity pane. Set Bus signal treated as
vector, and Invalid function-call connection to error. Also set Context-
dependent inputs to Enable All.
• Under Diagnostics, navigate to the Data Validity pane and set the Multitask data
store option to error.
• Set the Configuration Parameters > Diagnostics > Data Validity > Advanced
parameters > Underspecified initialization detection parameter to
Simplified.
• If your model is large or complex, run the Model Advisor checks in the folder
“Migrating to Simplified Initialization Mode Overview” (Simulink) and make the
suggested changes.
3 Convert the subsystem to an atomic subsystem. Select Edit > Subsystem
Parameters > Treat as atomic unit.
18-64
Asynchronous Support Limitations
4 Convert the subsystem to a Model block. Right-click the subsystem and select
Subsystem & Model Reference > Convert Subsystem to > Referenced Model.
A window opens with a model reference block inside of it.
5 Replace the subsystem in the top model with the new model reference block.
6 Move the Async Interrupt block from the model reference to the top model, before
the model reference block.
18-65
18 Event-Based Scheduling in Simulink Coder
7 Insert an Asynchronous Task Specification block in the model reference. Set the
priority of the Asynchronous Task Specification block. (For more information on
setting the priority, see Asynchronous Task Specification.)
8 In the model reference, double-click the input port to open its Source Block
Parameters dialog box. Click the Signal Attributes tab and select the Output
function call option. Click OK.
18-66
Asynchronous Support Limitations
9 Save your model and then perform Simulation > Update Diagram to verify your
settings.
18-67
18 Event-Based Scheduling in Simulink Coder
See Also
More About
• “Asynchronous Events” (Simulink Coder)
18-68
19
Scheduling Considerations in
Embedded Coder
In this section...
“Support for Discrete and Continuous Time Blocks” on page 19-2
“Support for Continuous Solvers” on page 19-2
“Support for Stop Time” on page 19-2
Note that use of certain blocks is not recommended for production code generation for
embedded systems. The Simulink Block Data Type Support table summarizes
characteristics of blocks in the Simulink and Fixed-Point Designer block libraries,
including whether or not they are recommended for use in production code generation. To
view this table, execute the following command and see the “Code Generation Support”
column of the table that appears:
showblockdatatypetable
Note Custom targets must be modified to support continuous time. The required
modifications are described in “Customize System Target Files” (Simulink Coder).
19-2
See Also
Note The ERT target provides both generated and static examples of the ert_main.c
file. The ert_main.c file controls the overall model code execution by calling the
model_step function and optionally checking the ErrorStatus/StopRequested flags
to terminate execution. For a custom target, if you provide your own custom static
main.c, you should consider including support for checking these flags.
See Also
More About
• “Time-Based Scheduling and Code Generation” on page 17-2
• “Configure Time-Based Scheduling” on page 17-37
• “Sample Times in Subsystems” (Simulink)
• “Sample Times in Systems” (Simulink)
19-3
19 Scheduling Considerations in Embedded Coder
Use rtmStepTask
The rtmStepTask macro is defined in model.h and its syntax is as follows:
boolean task_ready = rtmStepTask(rtm, idx);
rtmStepTask returns TRUE if the task's scheduling counter equals zero, indicating that
the task should be scheduled for execution on the current time step. Otherwise, it returns
FALSE.
If your target supports the Generate an example main program parameter, you can
generate calls to rtmStepTask using the TLC function RTMTaskRunsThisBaseStep.
The scheduling counters are updated by the base-rate task. The counters are clock rate
dividers that count up the sample period associated with each subrate task. When a given
subrate counter reaches a value that indicates it has a hit, the sample period for that rate
has elapsed and the counter is reset to zero. When this occurs, the subrate task must be
scheduled for execution.
19-4
Optimize Multirate Multitasking Execution for RTOS Run-Time Environments
The event flags indicate whether or not a given task is scheduled for execution. For a
multirate, multitasking model, the event flags are maintained by code in the main
program for the model. For each task, the code maintains a task counter. When the
counter reaches 0, indicating that the task's sample period has elapsed, the event flag for
that task is set.
On each time step, the counters and event flags are updated and the base-rate task
executes. Then, the scheduling flags are checked in tid order, and tasks whose event flag
is set is executed. Therefore, tasks are executed in order of priority.
For bareboard targets that cannot rely on an external RTOS, the event flags are
mandatory to allow overlapping task preemption. However, an RTOS target uses the
operating system itself to manage overlapping task preemption, making the maintenance
of the event flags redundant.
19-5
19 Scheduling Considerations in Embedded Coder
See Also
More About
• “Time-Based Scheduling and Code Generation” on page 17-2
• “Modeling for Multitasking Execution” on page 17-12
19-6
20
Representing a Software
Architecture by Creating Code
Generation Definitions
• “Define Storage Classes, Memory Sections, and Function Templates for Software
Architecture” on page 20-2
• “Deploy Code Generation Definitions” on page 20-6
• “Conform to Software Architecture by Sharing and Copying Default Code Generation
Settings Between Models” on page 20-15
• “Migrate Memory Section and Shared Utility Settings from Configuration Parameters
to Code Mapping Editor” on page 20-21
20 Representing a Software Architecture by Creating Code Generation Definitions
To create definitions that you and other users can use in the Code Mapping Editor, use an
Embedded Coder Dictionary.
When you create definitions in an Embedded Coder Dictionary, you must decide where to
store the definitions.
• If you need to use the definitions only in one model, create the definitions in the
Embedded Coder Dictionary of the model. If the model is not linked to a Simulink data
dictionary (see “What Is a Data Dictionary?” (Simulink)), open the Embedded Coder
Dictionary for the model as described in Embedded Coder Dictionary.
If you link the model to a data dictionary, you must store the definitions in the
Embedded Coder Dictionary of that data dictionary, or of a referenced data dictionary,
as described in “Share Embedded Coder Dictionary Definition Between Models” on
page 20-6.
• If you need to use the definitions in multiple models, including the models in a model
reference hierarchy, store the definitions in the Embedded Coder Dictionary of a
Simulink data dictionary. For general information about data dictionaries, see “What Is
a Data Dictionary?” (Simulink).
To use an Embedded Coder Dictionary, and for limitations with respect to code generation
definitions in an Embedded Coder Dictionary, see Embedded Coder Dictionary.
20-2
Define Storage Classes, Memory Sections, and Function Templates for Software Architecture
To create code definitions that you can apply through these other tools, use the Custom
Storage Class Designer. You can define storage classes and memory sections, which you
can apply only to data elements. For more information, see “Create Custom Storage
Classes by Using the Custom Storage Class Designer” on page 26-26 and “Control Data
and Function Placement in Memory by Inserting Pragmas” on page 30-2.
However, if you create a custom storage class by using the Custom Storage Class
Designer and set Type to FlatStructure, as described in “Generate Structured Data”
on page 26-33, or to Other, as described in “Finely Control Data Representation by
Writing TLC Code for a Custom Storage Class” on page 26-39, you cannot configure an
Embedded Coder Dictionary to refer to the package. Therefore, you cannot use the
storage class in the Code Mapping Editor.
To create a code generation definition in a package by using the Custom Storage Class
Designer, see “Create Custom Storage Classes by Using the Custom Storage Class
Designer” on page 26-26. Then, to configure an Embedded Coder Dictionary to refer to
the package, see “Refer to Code Generation Definitions in a Package”.
20-3
20 Representing a Software Architecture by Creating Code Generation Definitions
definitions is called deployment. For more information, see “Deploy Code Generation
Definitions” on page 20-6.
Depending on the storage location of the code definition, changing or deleting the
definition can break these usage points, requiring you to take action.
Package Definitions
If you created the code definition in a package, changing the name or deleting the
definition can break usage points, which you must fix manually.
• To fix usage points for individual data elements in a model, you can optionally write a
script. See the interactive and programmatic examples in “Apply Custom Storage
Classes to Individual Signal, State, and Parameter Data Elements” on page 26-19.
• To fix usage points in a package (for example, when you change the name of a memory
section that a storage class uses), you must use the Custom Storage Class Designer.
You cannot write a script.
If you loaded the package into one or more Embedded Coder Dictionaries (see “Refer to
Code Generation Definitions in a Package”), when you make any changes to the code
definition (including to properties other than the name) or delete the definition, you must:
1 Reload the package. In each dictionary, use the Manage Package button to unload,
and then reload the package.
Reloading the package breaks usage points in the Code Mapping Editor for affected
models, which you must fix manually.
2 Fix usage points in the Code Mapping Editor for affected models. To write a script
that fixes Code Mapping Editor usage points, see “Configure Default Data and
Function Code Generation Programmatically” on page 21-22.
20-4
See Also
• Changing the name of the code definition does not break usage points. Simulink
propagates the new name to the usage points.
• Deleting the code definition breaks usage points in the Code Mapping Editor for
affected models. In the Editor, drop-down lists display Unresolved. You must fix these
usage points manually. To fix them by writing a script, see “Configure Default Data and
Function Code Generation Programmatically” on page 21-22.
• coder.dictionary.copy
• coder.dictionary.move
• coder.dictionary.remove
See Also
Embedded Coder Dictionary | Code Mapping Editor
Related Examples
• “Environment for Configuring Model Data and Functions for Code Generation” on
page 21-2
• “Create Custom Storage Classes by Using the Custom Storage Class Designer” on
page 26-26
• “Conform to Software Architecture by Sharing and Copying Default Code Generation
Settings Between Models” on page 20-15
• “Control Data and Function Placement in Memory by Inserting Pragmas” on page
30-2
• “Configure Default Code Generation for Categories of Model Data and Functions” on
page 21-7
20-5
20 Representing a Software Architecture by Creating Code Generation Definitions
In a large organization with multiple models and users, you can share code generation
definitions by storing them in a mutually accessible location. The process of sharing code
definitions is called deployment.
• When you create definitions in a package by using the Custom Storage Class Designer,
for each user, place the folder containing the package folder on the MATLAB path. For
more information, see “What Is the MATLAB Search Path?” (MATLAB).
• When you create definitions in an Embedded Coder Dictionary, store the definitions in
a Simulink data dictionary. Then, link each model to a separate data dictionary.
Configure each separate dictionary to refer to the dictionary that contains the code
generation definitions. For an example, see “Share Embedded Coder Dictionary
Definition Between Models” on page 20-6.
20-6
Deploy Code Generation Definitions
Create a data dictionary. Then, create the storage class in the dictionary.
daexplr
2 In the Model Explorer, select File > New > Data Dictionary.
3 Name the dictionary coderDefs.sldd.
4 In the Model Explorer Model Hierarchy pane, right-click coderDefs and select
Show Empty Sections.
5 In the Model Hierarchy pane, select the Embedded Coder Dictionary node.
20-7
20 Representing a Software Architecture by Creating Code Generation Definitions
6 In the Dialog pane (the right pane), click Open Embedded Coder Dictionary.
7 In the Embedded Coder Dictionary dialog box, click Add.
8 For the new storage class, set these property values:
• Name to internalsInFile.
• Header File to $R_internal.h.
• Definition File to $R_internal.c.
9 In the Model Explorer Model Hierarchy pane, right-click coderDefs and select
Save Changes.
Link each model to a separate data dictionary. Then, configure each dictionary to refer to
the standalone dictionary (coderDefs.sldd).
rtwdemo_advsc
rtwdemo_roll
2 In rtwdemo_roll, select File > Model Properties > Link to Data Dictionary.
3 In the Model Properties dialog box, select Data Dictionary and click New.
4 Use the Create a new Data Dictionary dialog box to create a dictionary named
rtwdemo_roll_data.sldd.
5 In the Model Properties dialog box, click OK.
6 In the Link Model to Data Dictionary dialog box, click OK.
Simulink links the model to the new dictionary and attempts to migrate design data
from the base workspace to the dictionary. However, the model does not use data in
the base workspace, so the dictionary does not contain any data.
7 In the lower-left corner of the model, click the data dictionary badge, which opens
the dictionary in the Model Explorer.
8 In the Dialog pane, under Referenced Dictionaries, click Add.
9 In the Open Data Dictionary dialog box, double-click coderDefs.sldd.
10 Use the Model Hierarchy pane to save the changes you made to
rtwdemo_roll_data.sldd.
11 Link rtwdemo_advsc to a dictionary named rtwdemo_advsc_data.sldd and
configure the new dictionary to refer to coderDefs.sldd.
20-8
Deploy Code Generation Definitions
Confirm that the shared definition is available for use in the models by applying it as a
default setting for internal data and inspecting the generated code.
1 In rtwdemo_roll, select Code > C/C++ Code > Configure Model in Code
Perspective.
2 Under Code Mappings > Data Defaults, for the Internal data row, set Storage
Class to internalsInFile.
3 In rtwdemo_advsc, use the Code Perspective to set Storage Class to
internalsInFile for the Internal data row.
4 Generate code from rtwdemo_roll.
5 In the code generation report, inspect the generated file
rtwdemo_roll_internal.c. The file defines global variables that correspond to
state data in the model, such as the state of the Integrator block in the
BasicRollMode subsystem.
In this example, you create a storage class in the Embedded Coder Dictionary of a model
and use the storage class in the Code Mapping Editor. Then, you convert a subsystem to a
20-9
20 Representing a Software Architecture by Creating Code Generation Definitions
referenced model. To use the same Code Mapping Editor settings for the first model and
for the referenced model, you must extract the storage class into a shared data dictionary
(.sldd).
rtwdemo_roll
2 In the model, select Code > C/C++ Code > Configure Model in Code
Perspective.
3 Underneath the block diagram, in the Code Mapping Editor, click the Embedded
• Name to internalsInFile.
• Header File to $R_internal.h.
• Definition File to $R_internal.c.
6 In the model, in the Code Mapping Editor, for the Data Defaults > Internal data
row, set Storage Class to internalsInFile.
1 In the model, right-click the BasicRollMode subsystem and select Subsystem &
Model Reference > Convert to > Referenced Model.
2 In the Model Reference Conversion Advisor, click Convert.
The new referenced model, BasicRollMode, opens. The model file is in your current
folder.
By default, the referenced model cannot access the code generation definitions in the
Embedded Coder Dictionary of the parent model. Now, move the storage class out of the
parent model and into a shared data dictionary.
As a best practice, link each model to a separate data dictionary (.sldd), create a shared,
standalone data dictionary to store the code generation definition (the storage class), and
20-10
Deploy Code Generation Definitions
configure dictionary referencing so that all of the models can use the code generation
definition.
1 In the rtwdemo_roll model, select File > Model Properties > Link to Data
Dictionary.
2 In the Model Properties dialog box, select the Data Dictionary option and click
New.
3 Use the Create a new Data Dictionary dialog box to create a dictionary named
rtwdemo_roll_data.sldd.
4 In the Model Properties dialog box, click OK.
5 In the Link Model to Data Dictionary dialog box, click OK.
6 Click OK in response to the message about importing data from the base workspace.
7 In the BasicRollMode model, use the Model Properties dialog box to link the model
to a new data dictionary named basicRollMode_data.sldd. In response to the
message about changing dictionaries or moving data, click Move Data.
Selecting Move Data causes Simulink to configure the dictionary of the parent
model, rtwdemo_roll_data.sldd, to refer to basicRollMode_data.sldd. To
simulate and generate code from the model reference hierarchy, this reference must
be in place.
To create the shared, standalone dictionary and store the code generation definition in it:
1 In both models, at the lower-left corner of the block diagram, click the data
dictionary badge to open each dictionary in the Model Explorer.
2 In the Model Explorer, select File > New > Data Dictionary.
3 Create a data dictionary named coderDefs.sldd.
4 In the Model Explorer Model Hierarchy pane, select the rtwdemo_roll_data node.
5 In the Dialog pane (the right pane), under Referenced Dictionaries, click Add.
6 Add a reference to coderDefs.sldd.
7 Configure basicRollMode_data.sldd to refer to coderDefs.sldd.
8 In the Model Hierarchy pane, right-click the rtwdemo_roll_data node and select
Save Changes.
9 At the command prompt, move the code generation definitions from the
rtwdemo_roll model file to the coderDefs.sldd data dictionary.
coder.dictionary.move('rtwdemo_roll','coderDefs.sldd')
20-11
20 Representing a Software Architecture by Creating Code Generation Definitions
Copy Code Mapping Editor Settings from Parent Model to Referenced Model
By default, the new referenced model does not use the Code Mapping Editor settings that
the parent model uses. To copy the settings from the parent model to the referenced
model, use the programmatic interface of the Code Mapping Editor.
At the command prompt, copy the storage class setting for Internal data from
rtwdemo_roll to BasicRollMode.
roll_sc = coder.mapping.defaults.get('rtwdemo_roll','InternalData','StorageClass');
coder.mapping.create('BasicRollMode');
coder.mapping.defaults.set('BasicRollMode','InternalData','StorageClass',roll_sc);
Now, both models use the same Code Mapping Editor settings. For more information
about the programmatic interface of the Code Mapping Editor, see “Configure Default
Data and Function Code Generation Programmatically” on page 21-22.
To make code definitions available to a new model out of the box, write callbacks and
other code that immediately links the model to a data dictionary.
20-12
Deploy Code Generation Definitions
• For a simple example that shows how to link a model to a data dictionary
programmatically and for information about configuring dictionary referencing
programmatically, see “Store Data in Dictionary Programmatically” (Simulink).
• If you use Simulink projects, consider creating a project shortcut that creates a model
and immediately links the new model to a data dictionary. For information about
projects and project shortcuts, see “What Are Simulink Projects?” (Simulink).
If you want to store shared code generation definitions in a data dictionary but do not
want to migrate the design data of a model, in the data dictionary to which the model is
linked, select the Allow access to base workspace property. The model can use design
data from the base workspace and code generation definitions from the dictionary or from
a referenced dictionary. For more information about Allow access to base workspace,
see “Continue to Use Shared Data in the Base Workspace” (Simulink).
20-13
20 Representing a Software Architecture by Creating Code Generation Definitions
• When you link a model to a data dictionary, if the model file contains code generation
definitions in an Embedded Coder Dictionary, you cannot use code generation
definitions that the data dictionary provides. To use code generation definitions from
the data dictionary, use coder.dictionary.move or coder.dictionary.remove
to remove the Embedded Coder Dictionary from the model file.
See Also
Embedded Coder Dictionary
Related Examples
• “Define Storage Classes, Memory Sections, and Function Templates for Software
Architecture” on page 20-2
• “Conform to Software Architecture by Sharing and Copying Default Code Generation
Settings Between Models” on page 20-15
• “Partition Data for Model Reference Hierarchy Using Data Dictionaries” (Simulink)
• “Create Custom Storage Classes by Using the Custom Storage Class Designer” on
page 26-26
20-14
Conform to Software Architecture by Sharing and Copying Default Code Generation Settings Between Models
As projects expand and you and other users create more models, manually configuring
the default settings for each new model takes time. To reduce this manual data entry, you
can write scripts and create templates that apply these default settings to new models.
You can copy settings between models, enabling each model to later change the settings
independently of each other. Alternatively, you can share settings, enabling you to change
the settings for multiple models at once with minimal effort.
20-15
20 Representing a Software Architecture by Creating Code Generation Definitions
20-16
Conform to Software Architecture by Sharing and Copying Default Code Generation Settings Between Models
20-17
20 Representing a Software Architecture by Creating Code Generation Definitions
Technique Description
Create a template model. To create a model, you and other users can
instantiate the template. Each new model
can later change the settings independently
of other models.
Create a template project. The template project can contain models
and associated data dictionaries. Also,
through custom project shortcuts and
referenced projects, you can make shared
data stored in a dictionary available to new
models.
20-18
Conform to Software Architecture by Sharing and Copying Default Code Generation Settings Between Models
Technique Description
Write code by using programmatic You can execute this code in:
interfaces.
• A script.
• A model callback. For example, you can
use the PreLoadFcn callback, which
executes whenever you open a model.
For information about model callbacks,
see “Model Callbacks” (Simulink).
Consider storing the object in a data dictionary. Because you cannot create a template
model that is linked to a data dictionary, you must configure dictionary linking and
referencing for each new model.
• You cannot share default data and function settings that you specify in the Code
Mapping Editor.
20-19
20 Representing a Software Architecture by Creating Code Generation Definitions
See Also
Related Examples
• “Define Storage Classes, Memory Sections, and Function Templates for Software
Architecture” on page 20-2
• “Deploy Code Generation Definitions” on page 20-6
• “Partition Data for Model Reference Hierarchy Using Data Dictionaries” (Simulink)
20-20
Migrate Memory Section and Shared Utility Settings from Configuration Parameters to Code Mapping Editor
• To apply model-wide memory section settings, you do not use the model configuration
parameters under Code Generation > Advanced parameters > Memory Sections.
Instead, you use the Code Mapping Editor in the Code Perspective. To define the
memory sections, you can continue to use packages or you can use the new Embedded
Coder Dictionary.
• To set a naming rule for shared utility functions, you do not use the model
configuration parameter Code Generation > Symbols > Advanced parameters >
Shared utilities identifier format. Instead, you use the Embedded Coder Dictionary
to create a function customization template that specifies the naming rule, then apply
the template by using the Code Mapping Editor.
For general information about the Code Perspective, the Code Mapping Editor, and the
Embedded Coder Dictionary, see “Environment for Configuring Model Data and Functions
for Code Generation” on page 21-2.
In a model that you created in a release before R2018a, when you or another user opens
the Code Perspective, Simulink migrates memory section and shared utility settings from
the configuration parameters to the Code Mapping Editor of the model. If necessary, as
part of this migration, Simulink configures the Embedded Coder Dictionary that the
model uses:
• To refer to the package that defines the memory sections, as described in “Refer to
Code Generation Definitions in a Package”.
• To contain a function customization template that specifies the naming rule and, if
applicable, memory section settings that you specified for shared utilities.
Effects of Migration
• The migration process makes changes to the model file, which you must save. The
changes include:
20-21
20 Representing a Software Architecture by Creating Code Generation Definitions
• If the configuration parameters are stored in the model file (the model does not
refer to a Simulink.ConfigSet object), configuring the Embedded Coder
Dictionary of the data dictionary to refer to the memory section package and to
contain a function customization template.
The Code Perspective prompts you to accept the migration if your model meets either
of these conditions:
• The model has multiple configuration sets (one active and one or more inactive).
• The model refers to a Simulink.ConfigSet object.
20-22
Migrate Memory Section and Shared Utility Settings from Configuration Parameters to Code Mapping Editor
you to control where the Embedded Coder Dictionary resides in the dictionary
hierarchy. Create or identify a data dictionary at the bottom of the hierarchy so that all
of the models can access the memory section and function template definitions. Then,
when you initiate migration by opening the Code Perspective in a model, Simulink
configures that data dictionary.
20-23
20 Representing a Software Architecture by Creating Code Generation Definitions
However, if a model contains atomic subsystems that have nondefault memory section
settings, the model continues to depend on the Package setting in the configuration
parameters. See “Override Default Memory Placement for Subsystem Functions and
Data” on page 30-12.
• If a model refers to a Simulink.ConfigSet object, after migration, the model no
longer uses the memory section and shared utility settings in the object. If you used
the object to set the configuration parameters of multiple models:
• Changing memory section and shared utility settings in the object affects only
models that you have not migrated.
• Migrated models no longer acquire memory section and shared utility settings from
a single location (the Simulink.ConfigSet object). To change these settings for
these models, you must use the Code Mapping Editor of each individual model.
See Also
Embedded Coder Dictionary | Code Mapping Editor
Related Examples
• “Define Storage Classes, Memory Sections, and Function Templates for Software
Architecture” on page 20-2
• “Configure Default Code Generation for Categories of Model Data and Functions” on
page 21-7
• “Control Data and Function Placement in Memory by Inserting Pragmas” on page
30-2
20-24
Data, Function, and File
Definition
25
21
• “Environment for Configuring Model Data and Functions for Code Generation”
on page 21-2
• “Configure Default Code Generation for Categories of Model Data and Functions”
on page 21-7
21 Configuring Data and Functions in the Generated Code
To control the names and representation of the data and functions in the code, follow the
iterative paradigm shown in the diagram.
21-2
Environment for Configuring Model Data and Functions for Code Generation
In this paradigm:
• A software engineer directly interacts with and generates code from production
models.
• A system architect helps multiple engineers and multiple projects generate code that
conforms to the standards of a department or organization. The architect achieves this
21-3
21 Configuring Data and Functions in the Generated Code
To access tools such as the Code Mapping Editor, consider placing your model in the
Code Perspective. In the model, select Code > C/C++ Code > Configure Model in
Code Perspective.
• Read root-level input data from global variables defined by your external code.
• Store state data in structures whose placement in memory you can control.
• Name functions according to a rule that you specify.
The default settings can help you to reduce manual data entry.
• As you add blocks and signals to a model, the new data elements and functions inherit
the default settings.
• To change code generation settings for many data elements or functions at once, you
make the changes in one place—the default settings.
• You can use naming rules and other parameterized, abstract schemes to avoid
additional duplication of effort as you make changes elsewhere in the model.
For some categories of data, code generation optimizations can eliminate the data from
the code. For your default settings to apply, you must identify individual data elements
that you want to preserve against the optimizations. For more information, see
“Elimination of Parameters and Other Internal Data by Optimizations” on page 21-32.
21-4
See Also
• To create definitions that you want to appear in the Code Mapping Editor, use the
Embedded Coder Dictionary. See Embedded Coder Dictionary.
If you plan to use your Embedded Coder Dictionary definitions in one model, you can
store the definitions in the model file. Alternatively, to share the definitions between
models and projects, store the definitions in a Simulink data dictionary. With a data
dictionary, to modify a shared definition, you change a definition in one place—the
dictionary.
• To create definitions that you want to appear in other tools, such as the Model Data
Editor, use the Custom Storage Class Designer. See “Create Custom Storage Classes
by Using the Custom Storage Class Designer” on page 26-26.
For some definitions that you create by using the Custom Storage Class Designer, you
can make the definitions appear in the Code Mapping Editor by configuring an
Embedded Coder Dictionary to refer to them.
See Also
Code Mapping Editor | Code Mapping Editor | Embedded Coder Dictionary
21-5
21 Configuring Data and Functions in the Generated Code
Related Examples
• “Configure Default Code Generation for Categories of Model Data and Functions” on
page 21-7
• “Control Data and Function Interface in Generated Code” (Simulink Coder)
• “Control Generation of Function Interfaces” on page 53-2
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements”
(Simulink Coder)
• “Define Storage Classes, Memory Sections, and Function Templates for Software
Architecture” on page 20-2
21-6
Configure Default Code Generation for Categories of Model Data and Functions
• Categories of model data. When producing code for the data, the code generator uses
a storage class that you specify to determine properties, such as whether the data is
structured, naming rules for definition and header files, and whether the data is stored
in a memory section.
• Categories of functions. When producing code for the functions, the code generator
uses a function customization template that you specify to determine properties, such
as a function naming rule and whether the function code is stored in a memory
section.
You can specify the default configurations interactively in the Simulink model editing
environment from the Code Mapping Editor or programmatically by using an API.
• Click the perspective control in the lower-right corner and select Code.
• Select Code > C/C++ Code > Configure Model in Code Perspective.
The Code Mapping Editor appears below the model diagram. The editor display consists
of two tabbed tables: Data Defaults and Function Defaults. Use the tables to associate
categories of model data elements with storage classes and functions with function
customization templates. When you select a row in one of the tables, the Code section of
21-7
21 Configuring Data and Functions in the Generated Code
the Property Inspector shows the property settings for that data element category or
function category.
If you close the Code Mapping Editor, the Model Editor window remains in Code
Perspective mode. To reopen the Code Mapping Editor, select View > Code Mappings.
After you open the Code Perspective or use the default mapping programmatic interface
to configure one or more categories of data and functions for a model, setting memory
section and Shared utilities identifier format model configuration parameters has no
effect. Also, when you open the Perspective, Simulink migrates the model configuration
parameter settings to the Code Mapping Editor. If necessary, as part of the migration,
Simulink configures the Embedded Coder Dictionary that the model uses as described in
“Migrate Memory Section and Shared Utility Settings from Configuration Parameters to
Code Mapping Editor” on page 20-21.
21-8
Configure Default Code Generation for Categories of Model Data and Functions
The Code Mapping Editor presents valid storage class options for a given category. The
options can include:
• Unspecified storage class (Default). The code generator places the code for the
category of data elements in standard structures, such as B_, ExtY_, ExtU_, DW_, and
P_. See “Standard Data Structures in the Generated Code” on page 22-26.
• Relevant built-in storage class, such as ExportedGlobal.
• Relevant storage class in an available package, such as ImportFromFile.
• Storage class defined in an Embedded Coder Dictionary.
Consideration See
What categories are relevant to your The model element categories in the
model? preceding table
Does the model use several instances of “Configure Data Properties by Using the
data that are in a category? If the answer is Model Data Editor” (Simulink), “Apply
yes, applying default mappings is Storage Classes to Individual Signal, State,
beneficial. If the answer is no, consider and Parameter Data Elements” on page 22-
configuring code generation for each data 81, and “Apply Custom Storage Classes to
element individually by using the Model Individual Signal, State, and Parameter
Data Editor. Data Elements” on page 26-19
Which storage class aligns with your code “Choose a Storage Class for Controlling
generation requirements for each category? Data Representation in the Generated
Code” on page 22-69
21-9
21 Configuring Data and Functions in the Generated Code
Consideration See
Do you want the model data be structured? “Organize Data into Structures in
For example, if you configured the model Generated Code” on page 22-177
for multi-instance code generation,
structures can improve code efficiency and
readability.
Do categories require the code generator to “Define Storage Classes, Memory Sections,
store data in specific areas of memory? For and Function Templates for Software
example, consider whether to store Architecture” on page 20-2 and “Control
initialization data in slow memory and Data and Function Placement in Memory by
algorithmic or computational data in fast Inserting Pragmas” on page 30-2
memory.
Do you want to prevent optimizations from “Elimination of Parameters and Other
eliminating specific data from the code? Internal Data by Optimizations” on page 21-
32
Are there data elements for which you must Example below.
override the default configuration settings?
Do you need to define new storage classes “Define Storage Classes, Memory Sections,
that you can select in the Code Mapping and Function Templates for Software
Editor? Architecture” on page 20-2 and “Create
Custom Storage Classes by Using the
Custom Storage Class Designer” on page
26-26
This example shows how to use the Code Mapping Editor to specify code generation
requirements for model data. The model uses multiple execution rates and is configured
for single-instance usage.
21-10
Configure Default Code Generation for Categories of Model Data and Functions
To configure default code generation mappings for the model data, use the Code
Mapping Editor. Although the model uses single instances of some data, the example
configures default settings to demonstrate different types of mappings. As you add blocks
to the model, new data elements acquire the default code generation mappings.
File Description
exDblFloat.h Defines the project data type alias for double,
DBL_FLOAT. Simulink uses the PreLoadFcn
callback specified for the model to parse this
header file and create a corresponding
Simulink.AliasType object.
exInDataMem.c Includes exInDataMem.h and defines variable
ex_input1.
exInDataMem.h Includes exDbFloat.h and declares variable
ex_input1.
exInDataLut.c exInDataLut.c includes exInDataLut.h and
defines variables ex_input2, ex_input3, and
ex_input4.
exInDataLut.h Includes exDbFloat.h and declares variables
ex_input2, ex_input3, and ex_input4.
rtwdemo_configdefaul Example model.
ts.slx
21-11
21 Configuring Data and Functions in the Generated Code
3 To gain access to the Code Mapping Editor, open the Code Perspective. Click Code >
C/C++ Code > Configure Model in Code Perspective.
Specify an external header file that declares input data. Three of the four root inports
read input from variables declared in header file exInDataLut.h. Set that header file as
the default.
1 Under Code Mappings - C, in the Data Defaults tab, select category Inports and
set the storage class to ImportFromFile.
2 In the Property Inspector, set Header File to exInDataLut.h.
The default mappings for a model are stored as part of the model.
Override the default external header file setting for In1. That inport reads data from a
variable declared in header file exInDataMem.h.
21-12
Configure Default Code Generation for Categories of Model Data and Functions
Configure parameters UPPER, LOWER, K1, and K2. Those parameters are local parameters
for which parameter objects are stored in the model workspace. Map category Local
parameters to storage class ExportedGlobal, which makes the parameter objects
appear in the generated code as tunable global variables.
Prevent code generator optimizations from eliminating K1 from the generated code. The
data requirements indicate that K1 must be tunable. To prevent potential elimination of
the variable from the generated code, in the Code view of the Model Data Editor, find the
model workspace parameter for K1. Set the storage class to Model default. For more
information, see “Elimination of Parameters and Other Internal Data by Optimizations” on
page 21-32.
Define a memory section for storing the unit delay X, data that is internal to the model.
21-13
21 Configuring Data and Functions in the Generated Code
In the Code Mapping Editor, configure the code generator to place internal data in
memory section internalDataMem.
1 Select category Internal data.
2 In the Property Inspector, set Memory Section to internalDataMem.
Specify the default external header and definition files for variables to which the
generated code writes output. Map category Outports to storage class ExportToFile.
In the Property Inspector, set Header File to exSysOut.h and Definition File to
exSysOut.c. Save the model.
21-14
Configure Default Code Generation for Categories of Model Data and Functions
DBL_FLOAT Out1;
• Shared file exSysOut.h declares Out1. To gain access to Out1, external code can
include this header file.
extern DBL_FLOAT Out1;
A function customization template defines how the code generator produces code for a
category of functions. For a function category, you can define:
By default, the code generator uses the identifier naming rule $R$N to name entry-point
functions. $R is the name of the root model. $N is the default code generator name of the
21-15
21 Configuring Data and Functions in the Generated Code
function, for example, initialize, step, and terminate. To integrate generated code
with existing external code or to comply with naming standards or guidelines, you can
adjust the default naming rule. Adjusting the default naming rule can save time,
especially for multirate models for which the code generator produces a unique step
function for each rate.
Unless someone has defined function customization templates for a model, the Code
Mapping Editor presents Default as the only template option. To define a template, use
the Embedded Coder Dictionary. You can open the dictionary by clicking .
Before configuring default code generation settings for functions, consider these
questions.
Consideration See
What categories are relevant to your “Configure Code Generation for Model
model? Entry-Point Functions” on page 28-2
Do you have function naming “Configure Code Generation for Model
requirements? If the answer is yes, what Entry-Point Functions” on page 28-2 and
are they? To which categories do the “Identifier Format Control” on page 39-22
requirements apply?
Does the model use several instances of “Customize Generated C Function
functions that are in a category? If the Interfaces” on page 29-2 and “Customize
answer is yes, applying default mappings is Generated Function Interfaces for Simulink
beneficial. If the answer is no, consider Function and Function Caller Blocks” on
configuring code generation for each page 29-24
function separately by using function-
prototype control options as described in
the cited topics.
Does your application require the code “Define Storage Classes, Memory Sections,
generator to store function code in a and Function Templates for Software
specific area of memory? Architecture” on page 20-2 and “Control
Data and Function Placement in Memory by
Inserting Pragmas” on page 30-2
Do you need to define new function “Define Storage Classes, Memory Sections,
customization templates to include as and Function Templates for Software
options in the Code Mapping Editor? Architecture” on page 20-2
21-16
Configure Default Code Generation for Categories of Model Data and Functions
Consideration See
What function customization template “Define Function Customization Templates”
aligns with code generation requirements on page 21-18 and Embedded Coder
for each category? Dictionary
This example shows how to use the Code Mapping Editor to specify code generation
requirements for model functions. The model uses multiple execution rates and is
configured for single-instance usage. The code generator produces initialize, execution,
and terminate entry-point functions. Because the model uses multiple rates, the code
generator produces an execution function for each rate.
To configure default code generation settings for the functions, use the Embedded
Coder Dictionary and Code Mapping Editor.
Open Model
Define the two memory sections: functionSlowMem for initialize and terminate functions
and functionFastMem for execution functions.
1 Open the Embedded Coder Dictionary by clicking Code > C/C++ Code >
Embedded Coder Dictionary.
2 Click the Memory Sections tab.
3 Click Add.
4 In the new row at the bottom of the table, name the new memory section
functionFastMem. Then, set:
21-17
21 Configuring Data and Functions in the Generated Code
• Function Name to exFast_$N. This naming rule applies the prefix exFast_ to
the name that identifies the default code generator name of the function (for
example, initialize or step).
• Memory Section to functionFastMem. This mapping associates the memory
section that you defined in step 2 with the new template.
4 Click Add again. Name the template exSlowFunction. Then, set:
21-18
Configure Default Code Generation for Categories of Model Data and Functions
The default mappings for a model are stored as part of the model.
• The Code Interface Report section documents the generated entry-point functions:
• exSlow_initialize
• exFast_step (called periodically, every 0.5 seconds)
• exFast_step1 (called periodically, every 1 second)
• exFast_step2 (called periodically, every 1.5 seconds)
• exSlow_terminate
• To gain access to the entry-point function code in rtwdemo_configdefaults.c, use
the function name file links in the Code Interface Report. Verify that the correct
pragma control statements surround the function code. For example:
.
.
.
#pragma start FASTMEM
void exSlow_initialize(void)
{
/* (no initialization code required) */
}
21-19
21 Configuring Data and Functions in the Generated Code
1 If not already defined, define code definitions (storage classes, function customization
templates, and memory sections) in a data dictionary. For this example, use
definitions defined in the existing data dictionary exSharedCodeDefs.sldd. See
“Share Code Generation Definitions Between Multiple Models and Users” on page 20-
6.
2 Link the model to the data dictionary.
3 Map data and function default categories to code definitions in the dictionary.
21-20
Configure Default Code Generation for Categories of Model Data and Functions
Then, use the Code Mapping Editor to map data and function categories to code
definitions in the data dictionary.
1 In the model window for rtwdemo_config_defaults, select Code > C/C++ Code
> Configure Model in Code Perspective.
2 In the Code Mapping Editor, in the Data Defaults tab, select category Internal
data.
3 In the Property Inspector, set Memory Section to internalDataMem.
4 In the Function Defaults tab, for the Initialize/Terminate category, select the
function customization template exSlowFunction. For the Execution category,
select template exFastFunction.
5 Save the model.
6 Generate and review code.
21-21
21 Configuring Data and Functions in the Generated Code
For more information about setting up an Embedded Coder Dictionary, see “Define
Storage Classes, Memory Sections, and Function Templates for Software Architecture” on
page 20-2.
open_system('rtwdemo_configdefaults')
21-22
Configure Default Code Generation for Categories of Model Data and Functions
• Import project type definition for data of type double, DBL_FLOAT, from header file
exDblFloat.h.
• Import signal ex_input1 for computing a value stored in memory and used in an if-
else condition in the Switch block. Import the signal data from header
fileexInDataMem.h.
• Import signals ex_input2, ex_input3, and ex_input4 for lookup tables Table1
and Table2. Import the signal data from header file exInDataLut.h.
• Data imported into the model from hearder files exInDataMem.h and
exInDataLut.h is of type DBL_FLOAT, a project standard.
• Parameters UPPER, LOWER, K1, and K2 are parameter objects stored in the model
workspace. K1 must be tunable to enable calibration.
• Data store mode defines data that is shared within the model.
• Data element X represents the delay for the Unit Delay block.
• Store data that is internal to the model in memory section internalDataMem.
• Store generated initialize and terminate functions in memory section
functionSlowMem and execution functions in memory section functionFastMem.
• Use the identifier naming rule exSlow_$N to name initialize and terminate
entry-point functions. Use the naming rule exFast_$N to name execution functions.
• Export output data declarations to header file exSysOut.h and definitions to
exSysOut.c.
For this example someone, such as a system architect, has previously created these code
definitions in an Embedded Coder Dictionary that is part of Simulink data dictionary
ex_configdefault.sldd:
Create Environment for Configuring Code Generation for Data and Functions
Create an environment for configuring code generation for data and functions associated
with model rtwdemo_configdefaults by calling the function
coder.mapping.create. You can skip this step if you previously opened the model in
Code Perspective mode.
21-23
21 Configuring Data and Functions in the Generated Code
coder.mapping.create('rtwdemo_condigdefaults');
Align the code generation requirements for data with available data categories. Each
category has a set of properties that you can configure. Each property has a set of
possible values. Use calls to coder.mapping.defaults.dataCategories,
coder.mapping.defaults.allowedProperties, and
coder.mapping.defaults.allowedValues to review the list of names for categories,
properties, and values of interest.
For this example, you need to configure default settings for inports, outports, and
parameter objects stored in the model workspace. Get a list of the available data
categories by calling coder.mapping.defaults.dataCategories.
coder.mapping.defaults.dataCategories()
Columns 5 through 7
Column 8
{'Constants'}
coder.mapping.defaults.allowedProperties('rtwdemo_configdefaults', 'Outports')
21-24
Configure Default Code Generation for Categories of Model Data and Functions
{'HeaderFile' }
{'DefinitionFile'}
{'Owner' }
coder.mapping.defaults.allowedProperties('rtwdemo_configdefaults', 'LocalParameters')
coder.mapping.defaults.allowedProperties('rtwdemo_configdefaults', 'InternalData')
For data category and property combinations that you want to set, identify possible values
with calls to coder.mapping.defaults.allowedValues. Based on requirements and
the results of step b, specify:
You do not need to determine values for properties HeaderFile (for Inports and
Outports) and DefinitionFile (Outports).The values that you set for those
properties are known strings.
coder.mapping.defaults.allowedValues('rtwdemo_configdefaults', 'Inports', 'StorageClass
21-25
21 Configuring Data and Functions in the Generated Code
21-26
Configure Default Code Generation for Categories of Model Data and Functions
Align the code generation requirements for functions with available function categories.
For this example, you need to configure default settings for initialize, execution, and
terminate functions. Get a list of the available function categories by calling
coder.mapping.defaults.functionCategories.
coder.mapping.defaults.functionCategories()
For function category and property combinations that you want to set, identify possible
values with calls to coder.mapping.defaults.allowedValues. Based on
requirements and the results of calling
coder.mapping.defaults.allowedProperties, specify
FunctionCustomizationTemplate with categories InitializeTerminate and
Execution.
coder.mapping.defaults.allowedValues('rtwdemo_configdefaults', 'InitializeTerminate',..
'FunctionCustomizationTemplate')
21-27
21 Configuring Data and Functions in the Generated Code
coder.mapping.defaults.set('rtwdemo_configdefaults', 'Inports',...
'Storageclass', 'ImportFromFile',...
'HeaderFile', 'exInDataLut.h');
coder.mapping.defaults.set('rtwdemo_configdefaults', 'Outports',...
'Storageclass', 'ExportToFile',...
'HeaderFile', 'exSysOut.h',...
'DefinitionFile', 'exSysOut.c');
coder.mapping.defaults.set('rtwdemo_configdefaults', 'LocalParameters',...
'Storageclass', 'ExportedGlobal');
coder.mapping.defaults.set('rtwdemo_configdefaults', 'InternalData',...
'MemorySection', 'internalDataMem');
coder.mapping.defaults.set('rtwdemo_configdefaults', 'InitializeTerminate',...
'FunctionCustomizationTemplate', 'exSlowFunction');
coder.mapping.defaults.set('rtwdemo_configdefaults', 'Execution',...
'FunctionCustomizationTemplate', 'exFastFunction');
ans =
'ImportFromFile'
21-28
Configure Default Code Generation for Categories of Model Data and Functions
ans =
'exInDataLut.h'
ans =
'ExportToFile'
ans =
'exSysOut.h'
ans =
'exSysOut.c'
coder.mapping.defaults.get('rtwdemo_configdefaults', 'LocalParameters',...
'StorageClass')
ans =
'ExportedGlobal'
coder.mapping.defaults.get('rtwdemo_configdefaults', 'InternalData',...
'MemorySection')
ans =
'internalDataMem'
coder.mapping.defaults.get('rtwdemo_configdefaults', 'InitializeTerminate',...
'FunctionCustomizationTemplate')
ans =
'exSlowFunction'
coder.mapping.defaults.get('rtwdemo_configdefaults', 'Execution',...
'FunctionCustomizationTemplate')
ans =
'exFastFunction'
Override the header file setting for input signal ex_input1. Previously, you set the
default header file for data in the Inports category to exInDataLut.h. The
21-29
21 Configuring Data and Functions in the Generated Code
requirements specify that you import data for that signal from header file
exInDataMem.h.
temp_Obj =
Signal with properties:
In the nested Simulink.CoderInfo object, set the StorageClass property to CIn step
3, youustom. Then, use the CustomStorageClass property to specify the storage
classImportFromFile.
temp_Obj.CoderInfo.StorageClass = 'Custom';
temp_Obj.CoderInfo.CustomStorageClass = 'ImportFromFile';
temp_Obj.CoderInfo.CustomAttributes.HeaderFile='exInDataMem.h';
Embed the signal object in the target signal line by attaching a copy of the temporary
workspace object.
set_param(outH, 'SignalObject', temp_Obj);
21-30
Configure Default Code Generation for Categories of Model Data and Functions
Clear the object from the base workspace. The signal now uses an embedded copy of the
object.
clear tempObj
Related Links
• “Configure Default Code Generation for Categories of Model Data and Functions” on
page 21-7
• Code Mapping Editor
• Embedded Coder Dictionary
• In the second column of the Code Mapping Editor, select a different definition from the
Storage Classes, Function Customization Templates, or Memory Sections list.
• Replace or add an appropriate definition to the Embedded Coder Dictionary. Then,
update the mapping.
21-31
21 Configuring Data and Functions in the Generated Code
• Consult with someone else, such as the system architect for your project, about adding
an appropriate definition to the Embedded Coder Dictionary. Then, update the
mapping.
• Global parameters
• Local parameters
• Internal data
After eliminating data with optimizations, the code generator applies the default code
generation settings in the Code Mapping Editor to the remaining data. For parameters
and signal lines, optimizations can eliminate data for an entire category. If this happens,
default settings that you specify for that category do not apply to data.
21-32
Configure Default Code Generation for Categories of Model Data and Functions
Limitations
• For a referenced model, map data element categories Inports and Outports to
Default, a built-in storage class other than ParamStruct or SignalStruct, or a
package storage class.
• For these categories, use the built-in storage class SignalStruct or create your own
structured storage class in an Embedded Coder Dictionary.
• Inport
• Outport
• Internal data
• For these categories, set up default mappings to a storage class defined with property
Const selected or property Data Initialization set to Dynamic or None:
• Inports
• Outports
• Data store categories
• Internal data
• Map parameter categories to storage classes defined with the Data Initialization
property set to Static or None.
• Map categories Inport, Outport, and Internal data, where at least one data element
in the category is specified with symbolic dimensions (see “Define Variable-Size Data
for Code Generation” (Simulink)), to a storage class defined with the Data Scope
property set to Imported.
• Map data element categories Global parameters and Global data stores to
Default, a built-in storage class other than ParamStruct or SignalStruct, or a
package storage class.
• If a model includes a reusable subsystem (subsystem with block parameter Function
packaging set to Reusable function) that contains a shared local data store, map
the category Shared local data stores to a storage class that is defined in the
Embedded Coder Dictionary for that model. For more information, see “Generate
Reentrant Code from Subsystems” on page 6-42.
• For top and referenced models configured for multi-instance usage (see “Generate
Reentrant Code from Top Models” on page 6-24 and “Generate Reentrant Code from
Simulink Function Blocks” on page 6-30), map data element categories to storage
classes that have the Storage Type property set to Structured.
21-33
21 Configuring Data and Functions in the Generated Code
• If a model uses data object alignment, do not configure default data mappings for the
model. For more information, see Simulink.CoderInfo.
• If you configure a model with a code replacement library that includes a data
alignment specification, you cannot configure default code mappings that involve
storage classes defined in an Embedded Coder Dictionary. For more information, see
“Data Alignment for Code Replacement” on page 54-136.
• When evaluating storage class settings for variant control variables, the code
generator ignores default mappings. For more information, see “Represent Subsystem
and Model Variants in Generated Code” on page 15-23.
• Default mappings for global data categories must be the same across model reference
hierarchies.
• You cannot set up default mappings to:
.
• When a model is configured for compact file packaging, you cannot map a data
element category to a storage class defined with the Data Scope property set to
Exported and the Header File property set to a naming rule other than $N.h.
• Storage classes defined in an Embedded Coder Dictionary are not compatible with
models that contain nonreusable subsystems with separate data or are configured to
generate a C++ class interface.
• If a model contains a tunable, nonfinite parameter (for example, with a value of inf):
• If you specify the nonfinite value directly in the model, without using a MATLAB
variable or parameter object (such as Simulink.Parameter), in the generated
code, the parameter appears as a field of the default parameter data structure (see
“Standard Data Structures in the Generated Code” on page 22-26). The
parameter does not use the storage class that you specify for the corresponding
category of parameter data in the Code Mapping Editor.
• If you store the nonfinite value in a variable or parameter object, for the
corresponding category of parameter data in the Code Mapping Editor, you cannot
use a storage class that you create in an Embedded Coder Dictionary. When you try
to generate code, the model generates an error. Choose one of these workarounds:
21-34
See Also
• Apply a storage class other than Auto or Model default directly to the
nonfinite parameter as described in “Apply Storage Classes to Individual Signal,
State, and Parameter Data Elements” on page 22-81.
• If only one block uses the variable or object, instead of using the variable or
object, specify the nonfinite value directly in the model, in the block parameter.
See Also
More About
• “Choose a Storage Class for Controlling Data Representation in the Generated
Code” on page 22-69
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements” on
page 22-81
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
• “Define Storage Classes, Memory Sections, and Function Templates for Software
Architecture” on page 20-2
• “Customize Generated C Function Interfaces” on page 29-2
• “Conform to Software Architecture by Sharing and Copying Default Code Generation
Settings Between Models” on page 20-15
21-35
22
22-2
Configure Data Accessibility for Rapid Prototyping
Depending on the system target file that you use (such as grt.tlc), by default,
optimization settings can make the generated code more efficient by:
• Eliminating unnecessary global and local storage for signals and some states.
However, the optimizations do not eliminate storage for root-level Inport and Outport
blocks, which represent the primary inputs and outputs of a system. To access this
data, you do not need to take optimizations into consideration.
• Inlining the numeric values of block parameters. The code does not store the
parameters in memory, so you cannot interact with the parameters during code
execution.
To generate code that instead allocates addressable memory for this data, you can disable
the optimizations, or override the optimizations by specifying code generation settings for
individual data items.
22-3
22 Data Representation in Simulink Coder
22-4
Configure Data Accessibility for Rapid Prototyping
Limitations
For information about limitations that apply to the tunability of parameters in the
generated code, see “Limitations for Block Parameter Tunability in the Generated Code”
on page 22-135.
22-5
22 Data Representation in Simulink Coder
See Also
Related Examples
• “Deploy Algorithm Model for Real-Time Rapid Prototyping” on page 51-2
• “Access Signal, State, and Parameter Data During Execution” on page 22-7
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Create Tunable Calibration Parameter in the Generated Code” on page 22-121
• “Switch Between Sets of Parameter Values During Simulation and Code Execution”
on page 22-196
22-6
Access Signal, State, and Parameter Data During Execution
By default, optimization settings make the generated code more efficient by eliminating
unnecessary signal storage and inlining the numeric values of block parameters. To
generate code that instead allocates addressable memory for this data, you can disable
the optimizations or specify code generation settings for individual data items.
Run a script that prepares the model rtwdemo_basicsc for this example.
run(fullfile(matlabroot,'examples','simulinkcoder','main','prepare_rtwdemo_basicsc'));
rtwdemo_basicsc
22-7
22 Data Representation in Simulink Coder
The model loads numeric MATLAB variables into the base workspace. The workspace
variables set some block parameters in the model. However, The Gain block in the model
uses the literal value 2.
Disable Optimizations
In the model, clear the model configuration parameter Signal storage reuse. When you
clear this optimization and other optimizations such as Eliminate superfluous local
variables (expression folding), the generated code allocates memory for signal lines.
Clearing Signal storage reuse disables most of the other optimizations.
set_param('rtwdemo_basicsc','OptimizeBlockIOStorage','off')
Set the optimization Configuration Parameters > Optimization > Default parameter
behavior to Tunable. When set to Tunable, this configuration parameter causes the
generated code to allocate memory for block parameters and workspace variables.
set_param('rtwdemo_basicsc','DefaultParameterBehavior','Tunable')
22-8
Access Signal, State, and Parameter Data During Execution
rtwbuild('rtwdemo_basicsc')
In the code generation report, view the file rtwdemo_basicsc.h. This header file
defines a structure type that contains signal data. The structure contains fields that each
represent a signal line in the model. For example, the output signal of the Gain block,
whose name is Gain, appears as the field Gain.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.h');
rtwdemodbtype(file,'/* Block signals (default storage) */',...
'B_rtwdemo_basicsc_T;',1,1)
The file defines a structure type that contains block parameter data. For example, the
Gain parameter of the Gain block appears as the field Gain_Gain. The other fields of the
structure represent other block parameters and workspace variables from the model,
including initial conditions for signals and states.
rtwdemodbtype(file,'/* Parameters (default storage) */',...
'/* Real-time Model Data Structure */',1,0)
22-9
22 Data Representation in Simulink Coder
*/
real32_T T1Data[11]; /* Variable: T1Data
* Referenced by: '<Root>/Table1'
*/
real32_T T2Break[3]; /* Variable: T2Break
* Referenced by: '<Root>/Table2'
*/
real32_T T2Data[9]; /* Variable: T2Data
* Referenced by: '<Root>/Table2'
*/
real32_T UPPER; /* Variable: UPPER
* Referenced by: '<Root>/Constant1'
*/
real32_T Gain_Gain; /* Computed Parameter: Gain_Gain
* Referenced by: '<Root>/Gain'
*/
real32_T Delay_InitialCondition; /* Computed Parameter: Delay_InitialCondition
* Referenced by: '<Root>/Delay'
*/
uint32_T Table2_maxIndex[2]; /* Computed Parameter: Table2_maxIndex
* Referenced by: '<Root>/Table2'
*/
boolean_T DataStoreMemory_InitialValue;/* Computed Parameter: DataStoreMemory_Initial
* Referenced by: '<Root>/Data Store Memory'
*/
};
View the file rtwdemo_basicsc_data.c. This source file allocates global memory for a
parameter structure and initializes the field values based on the parameter values in the
model.
View the source file rtwdemo_basicsc.c. The code allocates global memory for a
structure variable that contains signal data.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* Block signals (default storage) */',...
'B_rtwdemo_basicsc_T rtwdemo_basicsc_B;',1,1)
The code algorithm in the model step function calculates the signal values. It then
assigns these values to the fields of the signal structure. To perform the calculations, the
algorithm uses the parameter values from the fields of the parameter structure.
22-10
Access Signal, State, and Parameter Data During Execution
When you want to select code generation optimizations such as Signal storage reuse,
you can preserve individual data items from the optimizations. The generated code then
allocates addressable memory for the items.
set_param('rtwdemo_basicsc','OptimizeBlockIOStorage','on')
set_param('rtwdemo_basicsc','LocalBlockOutputs','on')
set_param('rtwdemo_basicsc','DefaultParameterBehavior','Inlined')
In the Model Data Editor, select the check box in the Test Point column.
portHandle = get_param('rtwdemo_basicsc/Gain','PortHandles');
portHandle = portHandle.Outport;
set_param(portHandle,'TestPoint','on')
In the Model Data Editor, use the Value column to set the gain value to K1.
Next to K1, click the action button (with three vertical dots) and select Create.
In the Create New Data dialog box, set Value to Simulink.Parameter(2) and click
Create. A Simulink.Parameter object named K1, with value 2, appears in the base
workspace.
In the property dialog box for K1, apply a storage class other than Auto by using Storage
class. For example, use the storage class Model default to represent the parameter
object as a field of the global parameters structure.
22-11
22 Data Representation in Simulink Coder
set_param('rtwdemo_basicsc/Gain','Gain','K1');
K1 = Simulink.Parameter(2);
K1.StorageClass = 'Model default';
In the code generation report, view the file rtwdemo_basicsc.h. The structure that
contains signal data now defines only one field, Gain, which represents the test-pointed
output of the Gain block.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.h');
rtwdemodbtype(file,'/* Block signals (default storage) */',...
'B_rtwdemo_basicsc_T;',1,1)
The structure that contains block parameter data defines one field, K1, which represents
the parameter object K1.
rtwdemodbtype(file,'/* Parameters (default storage) */',...
'/* Real-time Model Data Structure */',1,0)
You can configure the generated code to contain extra code and files so that you can
access model data through standardized interfaces. For example, use the C API to log
signal data and tune parameters during execution.
Copy this custom source code into a file named ex_myHandCode.c in your current folder.
22-12
Access Signal, State, and Parameter Data During Execution
#include "ex_myHandHdr.h"
case SS_DOUBLE: {
real_T* dataAddress;
dataAddress = dataAddrMap[addrIdx];
/* At the 5-second mark, increment the parameter value by 1. */
if (*tPtr == 5) {
(*dataAddress)++;
}
printf("Parameter value is %f\n", *dataAddress);
break;
}
22-13
22 Data Representation in Simulink Coder
case SS_INT8: {
int8_T* dataAddress;
dataAddress = dataAddrMap[addrIdx];
if (*tPtr == 5) {
(*dataAddress)++;
}
printf("Parameter value is %i\n", *dataAddress);
break;
}
}
}
}
case SS_DOUBLE: {
real_T* dataAddress;
dataAddress = dataAddrMap[addrIdx];
printf("Signal value is %f\n", *dataAddress);
22-14
Access Signal, State, and Parameter Data During Execution
break;
}
case SS_SINGLE: {
real32_T* dataAddress;
dataAddress = dataAddrMap[addrIdx];
printf("Signal value is %f\n", *dataAddress);
break;
}
}
}
}
Copy this custom header code into a file named ex_myHandHdr.h in your current folder.
#include <stdio.h>
#include <string.h>
#include <math.h>
/* Include rtw_modelmap.h for definitions of C API macros. */
#include "rtw_modelmap.h"
#include "builtin_typeid_types.h"
#include "rtwtypes.h"
void tuneFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr);
void logFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr);
These files use the C API to access signal and parameter data in the code that you
generate from the example model.
In the model, set Configuration Parameters > Code Generation > Custom Code >
Insert custom C code in generated > Header file to #include "ex_myHandHdr.h".
In the same pane in the Configuration Parameters dialog box, set Additional Build
Information > Source files to ex_myHandCode.c.
set_param('rtwdemo_basicsc','CustomHeaderCode','#include "ex_myHandHdr.h"')
set_param('rtwdemo_basicsc','CustomSource','ex_myHandCode.c')
Select Configuration Parameters > MAT-file Logging. The generated executable runs
only until the simulation stop time (which you set in the model configuration parameters).
set_param('rtwdemo_basicsc','MatFileLogging','on')
Select all of the options under Configuration Parameters > Code Generation >
Interface > Generate C API for.
22-15
22 Data Representation in Simulink Coder
set_param('rtwdemo_basicsc','RTWCAPIParams','on')
set_param('rtwdemo_basicsc','RTWCAPISignals','on')
set_param('rtwdemo_basicsc','RTWCAPIStates','on')
set_param('rtwdemo_basicsc','RTWCAPIRootIO','on')
custcode
In the System Outputs block dialog box, set System Outputs Function Execution Code
to this code:
{
rtwdemo_basicsc_U.input2++;
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
tuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
}
In the block dialog box, set System Outputs Function Exit Code to this code:
22-16
Access Signal, State, and Parameter Data During Execution
{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
logFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
}
Alternatively, to configure the System Outputs block, at the command prompt, use these
commands:
temp.TLCFile = 'custcode';
temp.Location = 'System Outputs Function';
temp.Middle = sprintf(['{\nrtwdemo_basicsc_U.input2++;'...
'\nrtwCAPI_ModelMappingInfo *MMI = '...
'&(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);'...
'\ntuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));\n}']);
temp.Bottom = sprintf(['{\nrtwCAPI_ModelMappingInfo *MMI = '...
'&(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);'...
'\nlogFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));\n}']);
set_param('rtwdemo_basicsc/System Outputs','RTWdata',temp)
rtwbuild('rtwdemo_basicsc')
In the code generation report, view the interface file rtwdemo_basicsc_capi.c. This
file initializes the arrays of structures that you can use to interact with data items through
the C API. For example, in the array of structures rtBlockSignals, the first structure
(index 0) describes the test-pointed output signal of the Gain block in the model.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc_capi.c');
rtwdemodbtype(file,'/* Block output signal information */',...
'/* Individual block tuning',1,0)
22-17
22 Data Representation in Simulink Coder
0, 0, (NULL), (NULL), 0, 0, 0, 0, 0
}
};
The fields of the structure, such as addrMapIndex, indicate indices into other arrays of
structures, such as rtDataAddrMap, that describe the characteristics of the signal.
These characteristics include the address of the signal data (a pointer to the data), the
numeric data type, and the dimensions of the signal.
In the file rtwdemo_basicsc.c, view the code algorithm in the model step function.
The algorithm first executes the code that you specified in the System Outputs block.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* user code (Output function Body) */',...
'/* Logic: ''<Root>/LogOp'' incorporates:',1,0)
/* System '<Root>' */
{
rtwdemo_basicsc_U.input2++;
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
tuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
}
22-18
Access Signal, State, and Parameter Data During Execution
/* System '<Root>' */
{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
logFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
}
/* Matfile logging */
rt_UpdateTXYLogVars(rtwdemo_basicsc_M->rtwLogInfo,
(&rtwdemo_basicsc_M->Timing.taskTime0));
22-19
22 Data Representation in Simulink Coder
rtwdemo_basicsc_M->Timing.taskTime0 = rtwdemo_basicsc_M->Timing.clockTick0 *
rtwdemo_basicsc_M->Timing.stepSize0 + rtwdemo_basicsc_M->Timing.clockTickH0 *
rtwdemo_basicsc_M->Timing.stepSize0 * 4294967296.0;
}
/* initialize non-finites */
rt_InitInfAndNaN(sizeof(real_T));
22-20
Access Signal, State, and Parameter Data During Execution
{
rtliSetLogXSignalInfo(rtwdemo_basicsc_M->rtwLogInfo, (NULL));
rtliSetLogXSignalPtrs(rtwdemo_basicsc_M->rtwLogInfo, (NULL));
rtliSetLogT(rtwdemo_basicsc_M->rtwLogInfo, "tout");
rtliSetLogX(rtwdemo_basicsc_M->rtwLogInfo, "");
rtliSetLogXFinal(rtwdemo_basicsc_M->rtwLogInfo, "");
rtliSetLogVarNameModifier(rtwdemo_basicsc_M->rtwLogInfo, "rt_");
rtliSetLogFormat(rtwdemo_basicsc_M->rtwLogInfo, 0);
rtliSetLogMaxRows(rtwdemo_basicsc_M->rtwLogInfo, 1000);
rtliSetLogDecimation(rtwdemo_basicsc_M->rtwLogInfo, 1);
/*
* Set pointers to the data and signal info for each output
*/
{
static void * rt_LoggedOutputSignalPtrs[] = {
&rtwdemo_basicsc_Y.Out1
};
rtliSetLogYSignalPtrs(rtwdemo_basicsc_M->rtwLogInfo, ((LogSignalPtrsType)
rt_LoggedOutputSignalPtrs));
}
{
static int_T rt_LoggedOutputWidths[] = {
1
};
22-21
22 Data Representation in Simulink Coder
{ rt_LoggedOutputLabels },
(NULL),
(NULL),
(NULL),
22-22
Access Signal, State, and Parameter Data During Execution
{ rt_LoggedOutputBlockNames },
{ (NULL) },
(NULL),
rt_RTWLogDataTypeConvert
}
};
rtliSetLogYSignalInfo(rtwdemo_basicsc_M->rtwLogInfo,
rt_LoggedOutputSignalInfo);
rtliSetLogY(rtwdemo_basicsc_M->rtwLogInfo, "yout");
}
/* block I/O */
(void) memset(((void *) &rtwdemo_basicsc_B), 0,
sizeof(B_rtwdemo_basicsc_T));
/* states (dwork) */
(void) memset((void *)&rtwdemo_basicsc_DW, 0,
sizeof(DW_rtwdemo_basicsc_T));
/* external inputs */
(void)memset((void *)&rtwdemo_basicsc_U, 0, sizeof(ExtU_rtwdemo_basicsc_T));
/* external outputs */
rtwdemo_basicsc_Y.Out1 = 0.0F;
/* Matfile logging */
rt_StartDataLoggingWithStartTime(rtwdemo_basicsc_M->rtwLogInfo, 0.0,
rtmGetTFinal(rtwdemo_basicsc_M), rtwdemo_basicsc_M->Timing.stepSize0,
(&rtmGetErrorStatus(rtwdemo_basicsc_M)));
22-23
22 Data Representation in Simulink Coder
This code first perturbs the input signal input2 by incrementing the value of the signal
each time the step function executes. The code then uses the built-in macro
rtmGetDataMapInfo to extract model mapping information from the model data
structure rtwdemo_basicsc_M. The pointer MMI points to the extracted mapping
information, which allows the functions tuneFcn and logFcn to access the information
contained in the arrays of structures that the C API file rtwdemo_basicsc_capi.c
defines.
View the function tuneFcn in the file ex_myHandCode.c. This function uses the C API
(through the model mapping information mmi) and a pointer to the simulation time to
print the value of the parameter K1 at specific times during code execution. When the
simulation time reaches 5 seconds, the function changes the parameter value in memory.
By using a switch case block, the function can access the parameter data whether the
data type is int8 or double.
View the code algorithm in the model step function again. Near the end of the function,
the algorithm executes the code that you specified in the System Outputs block. This code
calls the function logFcn.
rtwdemodbtype(file,'/* user code (Output function Trailer) */',...
'/* Matfile logging */',1,0)
/* System '<Root>' */
{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
logFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
}
View the function logFcn in the file ex_myHandCode.c. The function uses the C API to
print the value of the test-pointed signal. The function can access the signal data whether
the data type is single or double.
22-24
See Also
system('rtwdemo_basicsc')
The parameter and signal values appear in the Command Window output.
For more information about data interfaces, including the C API, see “Data Exchange
Interfaces” (Simulink Coder).
See Also
Simulink.Parameter | Simulink.Signal | Simulink.Signal
Related Examples
• “Standard Data Structures in the Generated Code” on page 22-26
• “Configure Data Accessibility for Rapid Prototyping” on page 22-3
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements” on
page 22-81
• “Exchange Data Between Generated and External Code Using C API” on page 46-
2
22-25
22 Data Representation in Simulink Coder
The table shows some common data structures in the generated code. The name of the
structure type and, if applicable, structure variable in the code that you generate from a
model depends on the model settings. Regardless of the settings, the name of the
structure type in the code contains the short name from the Short Name of Structure
Type column in the table.
• Direct application of storage classes. For example, you can use storage classes to
represent signals, tunable parameters, and states as individual global variables. For
more information, see “Apply Storage Classes to Individual Signal, State, and
Parameter Data Elements” on page 22-81.
• Configuration parameters, such as those on the Optimization pane in the
Configuration Parameters dialog box. You can adjust these configuration parameters to
control the default representation of data. For more information, see “Optimization
Pane” (Simulink Coder).
22-26
See Also
For more information about configuration parameters that control names and other
identifiers in the generated code, see “Customize Generated Identifiers” on page 78-21.
See Also
“Combine signal/state structures” (Simulink Coder)
Related Examples
• “How Generated Code Exchanges Data with an Environment” on page 22-33
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Use the Real-Time Model Data Structure” on page 22-29
22-27
22 Data Representation in Simulink Coder
• “Access Signal, State, and Parameter Data During Execution” on page 22-7
• “Environment for Configuring Model Data and Functions for Code Generation” on
page 21-2
22-28
Use the Real-Time Model Data Structure
You need to use the set of macros rtmGetxxx and rtmSetxxx to access the real-time
model data structure. The rtModel is an optimized data structure that replaces
SimStruct as the top level data structure for a model. The rtmGetxxx and rtmSetxxx
macros are used in the generated code as well as from the main.c or main.cpp module.
If you are customizing main.c or main.cpp (either a static file or a generated file), you
need to use rtmGetxxx and rtmSetxxx instead of the ssSetxxx and ssGetxxx macros.
Usage of rtmGetxxx and rtmSetxxx macros is the same as for the ssSetxxx and
ssGetxxx versions, except that you replace SimStruct S by real-time model data
structure rtM. The following table lists rtmGetxxx and rtmSetxxx macros that are used
in grt_main.c and grt_main.cpp.
22-29
22 Data Representation in Simulink Coder
22-30
Use the Real-Time Model Data Structure
22-31
22 Data Representation in Simulink Coder
For additional details on usage, see “SimStruct Macros and Functions Listed by Usage”
(Simulink).
See Also
Related Examples
• “SimStruct Macros and Functions Listed by Usage” (Simulink)
• “Compare System Target File Support” on page 33-21
• “Standard Data Structures in the Generated Code” on page 22-26
• “How Generated Code Exchanges Data with an Environment” on page 22-33
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
22-32
How Generated Code Exchanges Data with an Environment
The set of input and output data and the exchange mechanisms constitute the interfaces
of the entry-point functions. When you understand the default interfaces and how to
control them, you can:
In a model, root-level Inport and Outport blocks represent the primary inputs and outputs
of the block algorithm. By default, the code generator aggregates these blocks into
standard structures that store input and output data.
For information about how the generated code stores internal data, which does not
participate in the model interface, see “How Generated Code Stores Internal Signal,
State, and Parameter Data” on page 22-50.
open_system('rtwdemo_roll')
22-33
22 Data Representation in Simulink Coder
At the root level, the model has a number of Inport blocks and one Outport block.
In the model, set Configuration Parameters > Code Generation > System target file
to grt.tlc.
set_param('rtwdemo_roll','SystemTargetFile','grt.tlc')
Inspect the setting for Configuration Parameters > Code Generation > Interface >
Code interface packaging. The setting Nonreusable function means that the
generated code is not reusable (not reentrant).
For this example, to generate simpler code, clear the Configuration Parameters >
Code Generation > Interface > Advanced parameters > Mat-file logging.
set_param('rtwdemo_roll','MatFileLogging','off')
rtwbuild('rtwdemo_roll')
22-34
How Generated Code Exchanges Data with an Environment
Inspect the file rtwdemo_roll.h. The file defines a structure type that represents input
data and a type that represents output data.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,...
'/* External inputs (root inport signals with default storage) */',...
'} ExtY_rtwdemo_roll_T;',1,1)
Each field corresponds to an Inport or Outport block at the root level of the model. The
name of each field derives from the name of the block.
The file also defines a structure type, the real-time model data structure, whose single
field stores a run-time indication of whether the generated code has encountered an error
during execution.
rtwdemodbtype(file,'/* Real-time Model Data Structure */',...
'/* Block states (default storage) */',1,0)
When you modify model configuration parameters to suit your application, this structure
can also contain other data that pertain to the entire model, such as scheduling
information.
22-35
22 Data Representation in Simulink Coder
For the structure type that represents the real-time model data structure, the file
rtwdemo_roll_types.h creates an alias (typedef) that the generated code later uses
to allocate memory for the structure.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll_types.h');
rtwdemodbtype(file,'/* Forward declaration for rtModel */',...
'RT_MODEL_rtwdemo_roll_T;',1,1)
Using these structure types, the file rtwdemo_roll.c defines (allocates memory for)
global structure variables that store input and output data for the generated algorithm.
The file also defines variables that represent the real-time model data structure and a
pointer to the structure.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,...
'/* External inputs (root inport signals with default storage) */',...
'= &rtwdemo_roll_M_;',1,1)
/* Real-time model */
RT_MODEL_rtwdemo_roll_T rtwdemo_roll_M_;
RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M = &rtwdemo_roll_M_;
The file rtwdemo_roll.h declares these structure variables. Your external code can
include (#include) this file, whose general name is model.h where model is the name
of the model, to access data that participate in the model interface.
In rtwdemo_roll.c, the model step function, which represents the primary model
algorithm, uses a void void interface (with no arguments).
rtwdemodbtype(file,...
'/* Model step function */','void rtwdemo_roll_step(void)',1,1)
22-36
How Generated Code Exchanges Data with an Environment
In the function definition, the algorithm reads input data and writes output data by
directly accessing the global structure variables. For example, near the end of the
algorithm, the code for the EngSwitch block reads the value of the AP_Eng field (which
represents an input) and, based on that value, conditionally writes a constant value to the
Ail_Cmd field (which represents an output).
if (rtwdemo_roll_U.AP_Eng) {
/* Outputs for Atomic SubSystem: '<Root>/BasicRollMode' */
/* Saturate: '<S1>/CmdLimit' */
if (rtwdemo_roll_Y.Ail_Cmd > 15.0F) {
/* Sum: '<S1>/Sum2' incorporates:
* Outport: '<Root>/Ail_Cmd'
*/
rtwdemo_roll_Y.Ail_Cmd = 15.0F;
} else {
if (rtwdemo_roll_Y.Ail_Cmd < -15.0F) {
/* Sum: '<S1>/Sum2' incorporates:
* Outport: '<Root>/Ail_Cmd'
*/
rtwdemo_roll_Y.Ail_Cmd = -15.0F;
}
Due to the void void interface and the direct data access, the function is not reentrant.
If you call the function multiple times in an application, each call reads and writes input
and output data to the same global structure variables, resulting in data corruption and
unintentional interaction between the calls.
22-37
22 Data Representation in Simulink Coder
{
/* Registration code */
/* external inputs */
(void)memset((void *)&rtwdemo_roll_U, 0, sizeof(ExtU_rtwdemo_roll_T));
/* external outputs */
rtwdemo_roll_Y.Ail_Cmd = 0.0F;
You can configure the generated code as reentrant, which means that you can call the
entry-point functions multiple times in an application. With this configuration, instead of
directly accessing global variables, the entry-point functions exchange input, output, and
other model data through formal parameters (pointer arguments). With these pointer
arguments, each call can read inputs and write outputs to a set of separate global
variables, preventing unintentional interaction between the calls.
In the model, set Configuration Parameters > Code Generation > Interface > Code
interface packaging to Reusable function.
set_param('rtwdemo_roll','CodeInterfacePackaging','Reusable function')
Now, in rtwdemo_roll.h, the real-time model data structure contains pointers to the
error indication, the input data, the output data, and additional data in the form of a
DWork substructure (which stores, for example, block states such as the state of a
Discrete-Time Integrator block).
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,'/* Real-time Model Data Structure */',...
'/* External data declarations for dependent source files */',1,0)
22-38
How Generated Code Exchanges Data with an Environment
To call the generated code multiple times in an application, your code must allocate
memory for a real-time model data structure per call. The file rtwdemo_roll.c defines a
specialized function that allocates memory for a new real-time model data structure and
returns a pointer to the structure. The function also allocates memory for the
substructures that the fields in the model data structure point to, such as the input and
output structures.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,'/* Model data allocation function */',...
'RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)',1,1)
In rtwdemo_roll.c, the model step function accepts an argument that represents the
real-time model data structure.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,...
'/* Model step function */','void rtwdemo_roll_step',1,1)
In the function definition, the algorithm first extracts each pointer from the real-time
model data structure into a local variable.
rtwdemodbtype(file,...
'*rtwdemo_roll_DW =','rtwdemo_roll_M->outputs;',1,1)
22-39
22 Data Representation in Simulink Coder
rtwdemo_roll_M->inputs;
ExtY_rtwdemo_roll_T *rtwdemo_roll_Y = (ExtY_rtwdemo_roll_T *)
rtwdemo_roll_M->outputs;
Then, to access the input and output data stored in global memory, the algorithm
interacts with these local variables.
if (rtwdemo_roll_U->AP_Eng) {
/* Outputs for Atomic SubSystem: '<Root>/BasicRollMode' */
/* Saturate: '<S1>/CmdLimit' */
if (rtwdemo_roll_Y->Ail_Cmd > 15.0F) {
/* Sum: '<S1>/Sum2' incorporates:
* Outport: '<Root>/Ail_Cmd'
*/
rtwdemo_roll_Y->Ail_Cmd = 15.0F;
} else {
if (rtwdemo_roll_Y->Ail_Cmd < -15.0F) {
/* Sum: '<S1>/Sum2' incorporates:
* Outport: '<Root>/Ail_Cmd'
*/
rtwdemo_roll_Y->Ail_Cmd = -15.0F;
}
}
Similarly, the model initialization function accepts the real-time model data structure as
an argument.
rtwdemodbtype(file,...
'/* Model initialize function */','void rtwdemo_roll_initialize',1,1)
22-40
See Also
Because each call that you make to an entry-point function interacts with a separate real-
time model data structure, you avoid unintentional interaction between the calls.
See Also
Related Examples
• “Standard Data Structures in the Generated Code” on page 22-26
• “Use the Real-Time Model Data Structure” on page 22-29
• “What Is External Code Integration?” on page 42-3
• “Analyze the Generated Code Interface” on page 38-19
• “Control Data and Function Interface in Generated Code” on page 22-42
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
22-41
22 Data Representation in Simulink Coder
By controlling the interfaces that appear in the generated code, you can:
• Minimize the modifications that you must make to your existing code.
• Generate stable interfaces that do not change or minimally change when you make
changes to the model.
• Generate code that exchanges data more efficiently (for example, by using pointers
and pass-by-reference arguments for nonscalar data).
With Embedded Coder, you can control these names. See “Control Characteristics of Data
Structures (Embedded Coder)” (Simulink Coder).
22-42
Control Data and Function Interface in Generated Code
• You can specify a literal name for a function, which overrides the default naming
rule that you specify with a function customization template in the Code Mapping
Editor.
• You can control the names of only step functions, initialization functions, and
Simulink functions.
You use different tools and dialog boxes to apply function prototype control based on
the kind of target function. For more information, see “Control Generation of Function
Interfaces” on page 53-2.
To remove the block from the standard I/O structures by creating a separate global
variable, apply a storage class, such as ExportedGlobal or ExportToFile, to the
signal that the block represents.
• To specify a default storage class for Inport blocks and a different default for Outport
blocks, use the Code Mapping Tool. As you add such blocks to the model, they acquire
the storage class that you specify. You do not need to configure each individual block.
22-43
22 Data Representation in Simulink Coder
For an example, see “Design Data Interface by Configuring Inport and Outport Blocks”
(Simulink Coder). For general information about storage classes, see “Choose a Storage
Class for Controlling Data Representation in the Generated Code” (Simulink Coder).
If your calling code already defines a global variable that you want the generated code to
use as input data or use to store output data, you can reuse the variable by preventing the
code generator from duplicating the definition. Apply a storage class to the corresponding
Inport or Outport block in the model. Choose a storage class that specifies an imported
data scope, such as ImportedExtern or ImportFromFile. For information about
applying storage classes, see “Apply Storage Classes to Individual Signal, State, and
Parameter Data Elements” (Simulink Coder) and “Apply Custom Storage Classes to
Individual Signal, State, and Parameter Data Elements” on page 26-19.
You can configure a single Inport or Outport block to appear in the generated code as a
custom structure that contains multiple input or output signals. You can also configure
the block to appear as a substructure of the default I/O structures or as a separate
structure variable.
Configure the block as a nonvirtual bus by using a Simulink.Bus object as the data type
of the block. If your external code defines the structure type, consider using the
Simulink.importExternalCTypes function to generate the bus object.
• To generate the bus signal as a substructure in the standard I/O structures, leave the
block storage class at the default setting, Auto. If you have Embedded Coder, in the
Code Mapping Editor, leave Data Defaults > Inports and Data Defaults > Outports
at the default setting, Default.
• To generate the bus signal as a separate global structure variable, apply a storage
class such as ExportedGlobal or ExportToFile.
For more information about grouping signals into custom structures in the generated
code, see “Organize Data into Structures in Generated Code” on page 22-177.
If your external code defines a function that returns input data for the generated code or
accepts output data that the generated code produces, you can configure an Inport or
22-44
Control Data and Function Interface in Generated Code
Outport block so that the generated code calls the function instead of accessing a global
variable. Apply the Embedded Coder storage class GetSet. For more information, see
“Access Data Through Functions with Custom Storage Class GetSet” on page 26-42.
With Embedded Coder, you can optionally configure the model execution function to
access inputs and outputs through arguments instead of directly reading and writing to
global variables. Completely control the argument characteristics such as name, order,
and passing mechanism (by reference or by value). This configuration can help to
integrate the generated code with your external code.
To pass inputs and outputs through arguments, apply function prototype control to the
model. Then, each Inport and Outport block at the root level of the model appears in the
code as an argument of the execution function. For more information, see “Customize
Generated C Function Interfaces” on page 29-2.
By default, for a nonreentrant referenced model, the generated code passes root-level
inputs and outputs through function arguments. A nonreentrant referenced model is one
in which you set Configuration Parameter Total number of instances allowed per top
model to One.
To pass this data through global variables instead (for a void-void interface), in the
referenced model, apply storage classes such as ExportedGlobal and ExportToFile
to root-level Inport and Outport blocks.
• To apply a default storage class to all such blocks, use the Code Mapping Editor, which
requires Embedded Coder. With this technique, as you add such blocks to the model,
the blocks acquire the default storage class, preserving the void-void interface. For
more information, see “Configure Default Code Generation for Data” on page 21-8.
• To override the default storage class, apply storage classes directly to individual
blocks by using the Model Data Editor. See “Apply Storage Classes to Individual
Signal, State, and Parameter Data Elements” on page 22-81.
• For an example that requires Embedded Coder, see “Establish Data Ownership in a
System of Components” on page 23-15.
22-45
22 Data Representation in Simulink Coder
For easier maintenance of your calling code, prevent changes to the interfaces of the
entry-point functions.
• If you exchange input and output data through arguments, configure the generated
code to package Inport and Outport blocks into structures instead of allowing each
block to appear as a separate argument (the default). Then, when you add or remove
Inport or Outport blocks, or change their properties such as name and data type, the
fields of the structures change, but the signatures of the entry-point functions do not
change. See “Reduce Number of Arguments by Using Structures” on page 22-47.
• Set the data types of Inport and Outport blocks explicitly instead of using an inherited
data type setting (which these blocks use by default). Inherited data type settings can
cause the blocks to use different data types depending on the data types of upstream
and downstream signals. For more information about configuring data types, see
“Control Signal Data Types” (Simulink).
• With Embedded Coder, specify function names that do not depend on the model name.
If you specify a naming rule with a function customization template, do not use the
token $R in the rule. See “Control Names of Generated Entry-Point Functions
(Embedded Coder)” (Simulink Coder).
22-46
Control Data and Function Interface in Generated Code
• Manually combine multiple Inport or Outport blocks so that they appear in the
generated code as fields of a structure or substructure of a standard data structure.
The generated entry-point function or functions accept the address of the structure
either as a separate argument or as a substructure (field) of the standard I/O
structures.
Replace the Inport or Outport blocks with a single block, and configure the new block
as a nonvirtual bus by using a Simulink.Bus object as the data type of the block. If
your external code defines the structure type, consider using the
Simulink.importExternalCTypes function to generate the bus object. See
“Organize Data into Structures in Generated Code” on page 22-177 and
Simulink.importExternalCTypes.
• When you generate reentrant code with Embedded Coder, configure Inport and
Outport blocks to appear in aggregated structures by default. Set Configuration
Parameters > Code Generation > Interface > Pass root-level I/O as to a setting
other than Individual arguments.
• To package all of the Inport and Outport blocks into the real-time model data
structure, select Part of model data structure. The code generator
aggregates the blocks into the default I/O structures, which the real-time model
data structure points to. The generated entry-point function or functions accept the
real-time model data structure as a single argument. If you choose this setting, the
function has the smallest number of arguments.
• To aggregate all Inport blocks into a structure and all Outport blocks into a
different structure, select Structure reference. The generated entry-point
function or functions accept the address of each structure as an argument. Another
argument accepts the real-time model data structure. If you choose this setting, the
inputs and outputs are more identifiable in the function signatures.
With this setting, if you remove all root-level Inport blocks or all root-level Outport
blocks, the function signature can change. Similarly, the signature can change if
you add a root-level Inport or Outport block to a model that does not have any such
blocks.
22-47
22 Data Representation in Simulink Coder
• For additional control over the characteristics of the structures, set Pass root-
level I/O as to Part of model data structure. Then, set the default storage
class for Inport and Outport blocks to a structured storage class that you create.
With this technique:
• You can create a single structure for all of the blocks or create two separate
structures.
• You can control the names of the structure types.
• The structures appear as substructures of the real-time model data structure.
You must set Pass root-level I/O as to Part of model data structure.
Create the storage class by using the Embedded Coder Dictionary (see “Define
Storage Classes, Memory Sections, and Function Templates for Software
Architecture” on page 20-2). Apply the storage class by using the Code Mapping
Editor (see “Configure Default Code Generation for Data” on page 21-8).
For more information about Pass root-level I/O as, see “Pass root-level I/O as”
(Simulink Coder).
22-48
See Also
See Also
Related Examples
• “Design Data Interface by Configuring Inport and Outport Blocks” on page 22-206
• “Interface Design” (Simulink)
• “Analyze the Generated Code Interface” on page 38-19
• “Control Generation of Function Interfaces” on page 53-2
• “How Generated Code Exchanges Data with an Environment” on page 22-33
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Configure Generated Code According to Interface Control Document Interactively”
on page 26-73
• “Environment for Configuring Model Data and Functions for Code Generation” on
page 21-2
22-49
22 Data Representation in Simulink Coder
• A block state such as the state of a Unit Delay block. The algorithm must retain the
state value between execution cycles, so the generated code typically stores states in
global memory (for example, as a global variable or a field of a global structure
variable).
• A block parameter, such as the Gain parameter of a Gain block, whose value the code
generator cannot inline in the code. For example, the code generator cannot inline the
value of a nonscalar parameter.
• The status indicator of a conditionally executed subsystem such as an enabled
subsystem.
For more efficient code, you can configure optimizations such as Configuration
Parameters > Default parameter behavior and Configuration Parameters > Signal
storage reuse that attempt to eliminate storage for internal data. However, the
optimizations cannot eliminate storage for some data, which consume memory in the
generated code.
When you understand the default format in which the generated code stores internal
data, you can:
• Make signals accessible and parameters tunable by default. You can then interact with
and monitor the code during execution.
• Generate efficient production code by eliminating storage for internal data and,
depending on your hardware and build toolchain, controlling the placement in memory
of data that the optimizations cannot eliminate.
• Promote pieces of internal data to the model interface so that other components and
systems can access that data.
For information about how the generated code exchanges data with a calling environment
through interfaces, see “How Generated Code Exchanges Data with an Environment” on
page 22-33.
22-50
How Generated Code Stores Internal Signal, State, and Parameter Data
open_system('rtwdemo_roll')
The model contains internal signals that do not connect to root-level Inport or Outport
blocks. Some of the signals have a name, such as the phiCmd signal.
The model also contains some blocks that maintain state data. For example, in the
BasicRollMode subsystem, a Discrete-Time Integrator block labeled Integrator
maintains a state.
In the model, set Configuration Parameters > Code Generation > System target file
to grt.tlc.
set_param('rtwdemo_roll','SystemTargetFile','grt.tlc')
22-51
22 Data Representation in Simulink Coder
Inspect the setting for Configuration Parameters > Code Generation > Interface >
Code interface packaging. The setting Nonreusable function means that the
generated code is not reusable (reentrant).
For this example, generate simpler code by clearing Configuration Parameters > Code
Generation > Interface > Advanced parameters > Mat-file logging.
set_param('rtwdemo_roll','MatFileLogging','off')
set_param('rtwdemo_roll','DefaultParameterBehavior','Tunable',...
'OptimizeBlockIOStorage','off')
rtwbuild('rtwdemo_roll')
The file rtwdemo_roll.h defines several structure types that represent internal data.
For example, the block input and output structure defines one field for each internal
signal in the model. Each field name derives from the name of the block that generates
the signal or, if you specify a name for the signal, from the name of the signal.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,...
'/* Block signals (default storage) */','} B_rtwdemo_roll_T;',1,1)
22-52
How Generated Code Stores Internal Signal, State, and Parameter Data
The file defines a structure type, the DWork structure, to represent block states such as
the state of the Discrete-Time Integrator block.
rtwdemodbtype(file,...
'/* Block states (default storage) for system','} DW_rtwdemo_roll_T;',1,1)
The file defines a structure type to represent parameter data. Each tunable block
parameter in the model, such as the Gain parameter of a Gain block, appears as a field of
this structure. If a block parameter acquires its value from a MATLAB variable or a
Simulink.Parameter object, the variable or object appears as a field, not the block
parameter.
The file also defines a structure type, the real-time model data structure, whose single
field represents a run-time indication of whether the generated code has encountered an
error during execution.
22-53
22 Data Representation in Simulink Coder
For the structure type that represents the real-time model data structure, the file
rtwdemo_roll_types.h creates an alias that the generated code later uses to allocate
memory for the structure.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll_types.h');
rtwdemodbtype(file,'/* Forward declaration for rtModel */',...
'RT_MODEL_rtwdemo_roll_T;',1,1)
Using these structure types, the file rtwdemo_roll.c defines (allocates memory for)
global structure variables that store internal data for the generated algorithm. The file
also defines variables that represent the real-time model data structure and a pointer to
the structure.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,'/* Block signals (default storage) */',...
'= &rtwdemo_roll_M_;',1,1)
/* Real-time model */
22-54
How Generated Code Stores Internal Signal, State, and Parameter Data
RT_MODEL_rtwdemo_roll_T rtwdemo_roll_M_;
RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M = &rtwdemo_roll_M_;
The model step function, which represents the primary model algorithm, uses a void
void interface (with no arguments).
rtwdemodbtype(file,...
'/* Model step function */','void rtwdemo_roll_step(void)',1,1)
In the function definition, the algorithm performs calculations and stores intermediate
results in the signal and state structures by directly accessing the global variables. The
algorithm also reads parameter data from the corresponding global variable. For
example, in the BasicRollMode subsystem, the code generated for the Integrator
block reads and writes signal, state, and parameter data from the structures.
rtwdemodbtype(file,'/* DiscreteIntegrator: ''<S1>/Integrator'' *',...
'/* End of DiscreteIntegrator: ''<S1>/Integrator'' */',1,1)
/* DiscreteIntegrator: '<S1>/Integrator' */
if (rtwdemo_roll_B.NotEngaged_e || (rtwdemo_roll_DW.Integrator_PrevResetState
!= 0)) {
rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.Integrator_IC;
}
rtwdemo_roll_B.Integrator = rtwdemo_roll_DW.Integrator_DSTATE;
Due to the void void interface and the direct data access, the function is not reentrant.
If you call the function multiple times in an application, each call writes data to the global
structure variables and the subsequent call can read that data, resulting in unintentional
interference between the calls.
22-55
22 Data Representation in Simulink Coder
/* block I/O */
(void) memset(((void *) &rtwdemo_roll_B), 0,
sizeof(B_rtwdemo_roll_T));
/* states (dwork) */
(void) memset((void *)&rtwdemo_roll_DW, 0,
sizeof(DW_rtwdemo_roll_T));
The function then initializes the block states in the DWork structure to the initial values
that the block parameters in the model specify. Two of the three states in the model have
tunable initial values, so the code initializes them by reading data from the parameters
structure.
rtwdemodbtype(file,...
'/* SystemInitialize for Atomic SubSystem: ''<Root>/RollAngleReference'' */',...
'/* Model terminate function */',1,0)
22-56
How Generated Code Stores Internal Signal, State, and Parameter Data
You can configure the generated code as reentrant, which means you can call the entry-
point functions multiple times in an application. With this configuration, instead of
directly accessing global variables, the entry-point functions accept internal data through
formal parameters (pointer arguments). With these pointer arguments, each call can
maintain internal data in a set of separate global variables, preventing unintentional
interaction between the calls.
In the model, set Configuration Parameters > Code Generation > Interface > Code
interface packaging to Reusable function.
set_param('rtwdemo_roll','CodeInterfacePackaging','Reusable function')
Now, in rtwdemo_roll.h, the real-time model data structure contains pointers to the
error indication, the internal data, and primary input and output data in the form of ExtU
and ExtY substructures (the fields of which represent Inport and Outport blocks at the
root level of the model).
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,'/* Real-time Model Data Structure */',...
'/* External data declarations for dependent source files */',1,0)
22-57
22 Data Representation in Simulink Coder
To call the generated code multiple times in an application, your code must allocate
memory for a real-time model data structure per call. The file rtwdemo_roll.c defines a
specialized function that allocates memory for a new real-time model data structure and
returns a pointer to the structure. The function also allocates memory for the
substructures that the fields in the model data structure point to, such as the DWork
structure.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,'/* Model data allocation function */',...
'RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)',1,1)
The model step function accepts an argument that represents the real-time model data
structure.
In the function definition, the algorithm first extracts each pointer from the real-time
model data structure into a local variable.
rtwdemodbtype(file,'*rtwdemo_roll_P_e =','rtwdemo_roll_M->outputs;',1,1)
Then, to access the internal data stored in global memory, the algorithm interacts with
these local variables.
22-58
How Generated Code Stores Internal Signal, State, and Parameter Data
/* DiscreteIntegrator: '<S1>/Integrator' */
if (rtwdemo_roll_B->NotEngaged_e ||
(rtwdemo_roll_DW->Integrator_PrevResetState != 0)) {
rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P_e->Integrator_IC;
}
rtwdemo_roll_B->Integrator = rtwdemo_roll_DW->Integrator_DSTATE;
Similarly, the model initialization function accepts the real-time model data structure as
an argument.
rtwdemodbtype(file,...
'/* Model initialize function */','void rtwdemo_roll_initialize',1,1)
Because each call that you make to an entry-point function interacts with a separate real-
time model data structure, you avoid unintentional interaction between the calls.
For more efficient code that consumes less memory, select the optimizations, such as
Default parameter behavior, that you cleared earlier.
set_param('rtwdemo_roll','DefaultParameterBehavior','Inlined',...
'OptimizeBlockIOStorage','on',...
'LocalBlockOutputs','on')
22-59
22 Data Representation in Simulink Coder
In this example, for simpler code, set Code interface packaging to Nonreusable
function.
set_param('rtwdemo_roll','CodeInterfacePackaging','Nonreusable function')
rtwbuild('rtwdemo_roll')
Now, rtwdemo_roll.h does not define a structure for block inputs and outputs. For all
of the internal signals in the model, the optimizations either eliminated storage or created
local function variables instead of global structure fields.
The optimizations were not able to eliminate storage for the three block states, so the file
continues to define the DWork structure type.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,...
'/* Block states (default storage) for system','} DW_rtwdemo_roll_T;',1,1)
The code generated for the Discrete-Time Integrator block now stores state and output
data only in the DWork structure.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,'/* Update for DiscreteIntegrator: ''<S1>/Integrator''',...
'/* End of Update for DiscreteIntegrator: ''<S1>/Integrator'' */',1,1)
22-60
How Generated Code Stores Internal Signal, State, and Parameter Data
} else {
if (rtwdemo_roll_DW.Integrator_DSTATE <= -5.0F) {
rtwdemo_roll_DW.Integrator_DSTATE = -5.0F;
}
}
rtwdemo_roll_DW.Integrator_PrevResetState = (int8_T)rtb_NotEngaged_f;
The optimizations also eliminated storage for the block parameters in the model. For
example, in the Discrete-Time Integrator block, the Upper saturation limit and Lower
saturation limit parameters are set to intLim and -intLim. intLim is a
Simulink.Parameter object that stores the value 5. In the code generated for the
Discrete-Time Integrator, these block parameters and intLim appear as inlined literal
numbers 5.0F and -5.0F.
If a model contains a parameter that the code generator cannot inline directly (for
example, an array parameter), the code defines a structure type that represents the data.
This constant parameters structure uses the const storage type qualifier, so some build
toolchains can optimize the assembly code further.
When you generate code for models that include test points, the build process allocates a
separate memory buffer for each test point. By default, test points are stored as members
of an appropriate standard data structure such as model_B.
22-61
22 Data Representation in Simulink Coder
• You can control the default representation of test points by specifying code generation
settings for the Internal data category of data in the Code Mapping Editor (see
“Configure Default Code Generation for Data” on page 21-8).
• You can specify that the build process ignore test points in the model, allowing optimal
buffer allocation, by using the “Ignore test point signals” (Simulink Coder) parameter.
Ignoring test points facilitates transitioning from prototyping to deployment and
avoids accidental degradation of generated code due to workflow artifacts. See
“Ignore test point signals” (Simulink Coder).
Virtual buses do not appear in generated code, even when associated with a test point. To
display a bus in generated code, use a nonvirtual bus or a virtual bus converted to a
nonvirtual bus by a Signal Conversion block.
When you set Default parameter behavior to Tunable, by default, workspace variables
appear in the generated code as tunable fields of the global parameters structure. If you
use such a variable to specify multiple block parameter values, the variable appears as a
single field of the global parameters structure. The code does not create multiple fields to
represent the block parameters. Therefore, tuning the field value during code execution
changes the mathematical behavior of the model in the same way as tuning the value of
the MATLAB variable or parameter object during simulation.
If you have Embedded Coder, you can control the default representation of workspace
variables by specifying code generation settings for categories of parameter data in the
Code Mapping Editor (see “Configure Default Code Generation for Data” on page 21-8).
• The Local parameters category applies to variables that you store in a model
workspace.
• The Global parameters category applies to variables that you store in the base
workspace or a data dictionary.
22-62
How Generated Code Stores Internal Signal, State, and Parameter Data
Depending on the reentrancy of the generated code, that is, the setting that you choose
for Code interface packaging, you can configure each data item in a model to
participate in the interface by appearing in the code as one of these entities:
The table shows the mechanisms that each category of data can use to participate in the
interface.
22-63
22 Data Representation in Simulink Coder
Single-Instance Algorithm
You can apply storage classes to signals, block states, and block parameters. (For block
parameters, you apply storage classes indirectly through parameter objects such as
Simulink.Parameter). However, for a signal, consider connecting the signal to an
Outport block at the root level of the model. Then, optionally, you can apply a storage
class to the block. In the block diagram, the Outport block shows that the signal
represents a system output.
For more information about storage classes, see “Apply Storage Classes to Individual
Signal, State, and Parameter Data Elements” on page 22-81.
Reentrant Algorithm
For a reentrant algorithm (you set Code interface packaging to Reusable function),
use different techniques to configure data items to appear in the code as formal
parameters (arguments) of the generated entry-point functions.
• For an internal signal, directly apply the storage class Model default (see “Apply
Storage Classes to Individual Signal, State, and Parameter Data Elements” on page
22-81). If you have Embedded Coder, in the Code Mapping Editor, for the Internal
data category, set the default storage class to Default or to a structured storage
class that you define in an Embedded Coder Dictionary (see “Create Code Definitions
for Use as Default Code Generation Settings” on page 20-2). Alternatively, configure
the signal as a test point (see “Appearance of Test Points in the Generated Code” on
22-64
How Generated Code Stores Internal Signal, State, and Parameter Data
page 22-61). By default, the signal appears as a field of one of the standard data
structures (see “How Generated Code Stores Internal Signal, State, and Parameter
Data” on page 22-50). If you do not want the signal to appear in production code, use a
test point so that you can later select the model configuration parameter Ignore test
point signals.
Alternatively, connect the signal to an Outport block at the root level of the model.
Connecting the signal to a root-level Outport block prevents optimizations from
eliminating the signal from the code. To help with signal routing in a large model, use
Goto and From blocks.
• For a block parameter, create a parameter object such as Simulink.Parameter and
directly apply a storage class other than Auto to the object. The storage class
prevents optimizations from inlining the parameter value in the code.
With the storage class, the parameter is shared between all instances of the model,
which are calls to the entry-point functions. The functions access the parameter data
directly, as a global symbol, not an argument. You cannot configure a parameter to
appear in the code as an argument, so you cannot enable each instance of the model
to use a different value for the parameter.
For information about applying storage classes, see “Apply Storage Classes to
Individual Signal, State, and Parameter Data Elements” (Simulink Coder).
Use the Code Mapping Editor to specify a default memory section for each category of
data such as states and signals (Internal data). In the generated code, your custom
pragmas or other decorations surround the data definitions and declarations.
You can also partition the structures according to atomic subsystems in your model so
that you can specify different default memory sections for the data of subroutines and
other algorithmic subcomponents.
22-65
22 Data Representation in Simulink Coder
For more information, see “Control Data and Function Placement in Memory by Inserting
Pragmas” on page 30-2.
Control Names of Types, Fields, and Global Variables for Standard Data
Structures
You can control some characteristics of the standard data structures. For more
information, see “Control Characteristics of Data Structures (Embedded Coder)”
(Simulink Coder).
For additional control over structure characteristics, such as placement in generated code
files, create your own structured storage class by using the Embedded Coder Dictionary.
Then, apply the storage class to categories of data by using the Code Mapping Editor. The
storage class removes the data from the standard structures, creating other structures
that you can more finely control. For more information about applying default storage
classes to categories of data, see “Configure Default Code Generation for Data” on page
21-8. For more information about creating a storage class, see “Define Storage Classes,
Memory Sections, and Function Templates for Software Architecture” on page 20-2.
• In the standard data structures, to create substructures that contain the data for a
single-instance (nonreentrant) subroutine or subcomponent, use an atomic subsystem
to encapsulate the corresponding blocks. In the subsystem parameters, set Function
packaging to Reusable function. For more information, see “Generate Modular
Function Code” on page 29-65.
Alternatively, encapsulate the blocks in a model and use a Model block. In the
referenced model, set Configuration Parameters > Model Referencing > Total
number of instances allowed per top model to Multiple. For more information,
see “Code Generation of Referenced Models” on page 4-2.
• To create separate, standalone structures that contain the data for a multi-instance
(reentrant) subroutine or subcomponent, in the model, use an atomic subsystem to
encapsulate the corresponding blocks. In the subsystem parameters, set Function
packaging to Nonreusable function and select Function with separate data.
For more information, see “Generate Modular Function Code” on page 29-65.
Alternatively, encapsulate the blocks in a model and use a Model block. In the
referenced model, choose one of these techniques:
22-66
How Generated Code Stores Internal Signal, State, and Parameter Data
Organize Signal and Parameter Data into Meaningful, Custom Structures and
Substructures
To organize arbitrary signals and parameters into custom structures and substructures,
create nonvirtual bus signals and parameter structures. Optionally, to prevent
optimizations from eliminating the data from the code, set the storage class of a bus
signal or parameter structure to a value other than Auto (the default setting).
As you add blocks to the model, you must explicitly place each new signal and parameter
into a bus or a structure.
For more information, see “Organize Data into Structures in Generated Code” on page
22-177.
To apply default storage classes to categories of data by using the Code Mapping Editor,
see “Configure Default Code Generation for Data” on page 21-8. To choose a storage
class, see “Choose a Storage Class for Controlling Data Representation in the Generated
Code” (Simulink Coder).
22-67
22 Data Representation in Simulink Coder
See Also
Related Examples
• “Standard Data Structures in the Generated Code” on page 22-26
• “Use the Real-Time Model Data Structure” on page 22-29
• “How Generated Code Exchanges Data with an Environment” on page 22-33
• “Environment for Configuring Model Data and Functions for Code Generation” on
page 21-2
22-68
Choose a Storage Class for Controlling Data Representation in the Generated Code
The table shows built-in storage classes that you can choose. These storage classes come
with Simulink Coder.
22-69
22 Data Representation in Simulink Coder
22-70
Choose a Storage Class for Controlling Data Representation in the Generated Code
22-71
22 Data Representation in Simulink Coder
If you have Embedded Coder, you can choose additional built-in storage classes, shown in
the next table.
22-72
Choose a Storage Class for Controlling Data Representation in the Generated Code
22-73
22 Data Representation in Simulink Coder
22-74
Choose a Storage Class for Controlling Data Representation in the Generated Code
22-75
22 Data Representation in Simulink Coder
When you generate reentrant, multi-instance code, limitations and restrictions apply if
you want to use storage classes. See “Use Storage Classes in Reentrant, Multi-Instance
Models and Components” (Simulink Coder).
• These built-in Simulink Coder storage classes do not allow you to specify additional
settings:
22-76
Choose a Storage Class for Controlling Data Representation in the Generated Code
• ExportedGlobal
• ImportedExtern
• ImportedExternPointer
• The built-in Embedded Coder storage classes typically allow you to specify declaration
and definition file names.
• When you create a storage class with the Custom Storage Class Designer, you can
choose whether the user of the storage class can specify additional settings. See
“Allow Users of Custom Storage Class to Specify Property Value” on page 26-32.
To reduce maintenance effort and data entry, when you specify Header file, you can omit
delimiters (" or <>) and use only the file name. You can then control the default delimiters
that the generated code uses for the corresponding #include directives. To use angle
brackets by default, set Configuration Parameters > Code Generation > Code
Placement > #include file delimiters to #include <header.h>.
• If you apply a grouped storage class to multiple data items, the storage class Data
scope property must be set to Imported and you must provide the data
declaration in an external header file. Grouped storage classes use a single
variable in the generated code to represent multiple data objects. For example, the
storage classes BitField and Struct are grouped storage classes.
22-77
22 Data Representation in Simulink Coder
See Also
Related Examples
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements”
(Simulink Coder)
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
• “Configure Default Code Generation for Categories of Model Data and Functions” on
page 21-7
• “Control Data and Function Interface in Generated Code” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
22-78
Use Storage Classes in Reentrant, Multi-Instance Models and Components
To avoid errors and unexpected generation of single-instance code and singleton data,
observe the guidelines and limitations below.
• To generate multi-instance code, you must apply the storage class only to parameter
objects, global data stores, and shared local data stores.
• The storage class yields only singleton data.
• For these data categories, you can generate only singleton data:
• Local parameters
• Global parameters
22-79
22 Data Representation in Simulink Coder
• Inports
• Outports
• Internal data
For these categories, you must use the built-in storage class SignalStruct or create
your own structured storage class by using an Embedded Coder Dictionary.
See Also
Related Examples
• “What Is Reentrant Code?” (Simulink Coder)
• “Choose a Storage Class for Controlling Data Representation in the Generated
Code” (Simulink Coder)
22-80
Apply Storage Classes to Individual Signal, State, and Parameter Data Elements
• Causes the data item to appear in the generated code as a global symbol, typically a
global variable.
• Prevents optimizations such as Default parameter behavior and Signal storage
reuse from eliminating the data item from the generated code.
• With Embedded Coder, you can configure the format in which the generated code
stores or otherwise defines the data item. For example, you can apply the storage type
qualifiers const or volatile or configure a parameter data item to appear as a
macro (#define).
For information about applying storage classes to categories of data by default, by using
the Code Mapping Editor, see “Configure Default Code Generation for Data” on page 21-
8.
open_system('rtwdemo_roll')
22-81
22 Data Representation in Simulink Coder
The subsystem contains an Integrator block, which maintains a piece of state data.
From the root level of the model, navigate into the RollAngleReference subsystem.
open_system('rtwdemo_roll/RollAngleReference')
22-82
Apply Storage Classes to Individual Signal, State, and Parameter Data Elements
In this example, you configure the state and output signal of the Integrator block and the
Constant value parameter of the Constant block to appear in the generated code as
separate global variables.
To see the data items in the subsystems, activate the Change scope button.
Optionally, use the Name column to specify a name for the output signal of the Integrator
block, such as mySignal.
Use the Storage Class column to apply the storage class ExportedGlobal.
22-83
22 Data Representation in Simulink Coder
Optionally, use the Name column to specify a name for the state, such as myState.
Use the Storage Class column to apply the storage class ExportedGlobal.
Select the Parameters tab. You cannot apply a storage class directly to a block
parameter. Instead, you must create a parameter object, such as Simulink.Parameter,
use the object to set the value of the block parameter, and apply the storage class to the
object.
Use the Value column to change the parameter value from 6 to UpThr.
While editing the parameter value, next to UpThr, click the action button (with three
vertical dots) and select Create.
In the Create New Data dialog box, set Value to Simulink.Parameter and click OK. A
Simulink.Parameter object named UpThr appears in the base workspace.
In the UpThr property dialog box, set Value to 6 and Storage class to
ExportedGlobal. Click OK.
Alternatively, you can use these commands at the command prompt to configure the
signal, state, and parameter data.
% Configure signal
portHandles = get_param('rtwdemo_roll/BasicRollMode/Integrator',...
'PortHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'Name','mySignal')
set_param(outportHandle,'StorageClass','ExportedGlobal')
% Configure state
set_param('rtwdemo_roll/BasicRollMode/Integrator',...
'StateName','myState')
set_param('rtwdemo_roll/BasicRollMode/Integrator',...
'StateStorageClass','ExportedGlobal')
% Configure parameter
set_param('rtwdemo_roll/RollAngleReference/UpThr','Value','UpThr')
22-84
Apply Storage Classes to Individual Signal, State, and Parameter Data Elements
UpThr = Simulink.Parameter(6);
UpThr.StorageClass = 'ExportedGlobal';
set_param('rtwdemo_roll','SystemTargetFile','grt.tlc')
rtwbuild('rtwdemo_roll')
Inspect the file rtwdemo_roll.c. The file defines the global variables.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,'/* Exported block signals */','real32_T myState;',1,1)
The file rtwdemo_roll.h declares the variables. To access these variables, your external
code can include (#include) this header file.
In rtwdemo_roll.c, search the file for the names of the variables, such as UpThr. The
model algorithm in the rtwdemo_roll_step function reads and writes to the variables.
22-85
22 Data Representation in Simulink Coder
• When you apply a storage class to a signal or state in a model, for example, by using
the Model Data Editor or the Property Inspector, you store the storage class
specification in the model file.
If you use this technique, you cannot control other characteristics of the data item,
such as data type, by using an external signal data object.
• When you create a signal or parameter data object, you apply the storage class by
using the CoderInfo property of the object. The value of the property is a
Simulink.CoderInfo object, whose StorageClass property you use to specify the
storage class. After you associate the data item in the model with the object, the data
item acquires the storage class from the object.
For signals, states, and Data Store Memory blocks, to decide whether to store the storage
class specification in the model or in a data object, see “Store Design Attributes of Signals
and States” (Simulink).
Apply Storage Classes to Outport Blocks by Using the Model Data Editor
You can use the Model Data Editor to apply a storage class directly to a root-level Outport
block or to the input signal that drives the block.
• To store the storage class specification in the Outport block, use the Inports/
Outports tab in the Model Data Editor. When you use this technique, the specification
remains after you delete the input signal that drives the block. Use this technique to
configure the model interface before you develop the internal algorithm.
• To store the specification in the input signal that drives the block, use the Signals tab
in the Model Data Editor.
22-86
Apply Storage Classes to Individual Signal, State, and Parameter Data Elements
To apply a storage class while focusing on a single signal, block state, or parameter, use
the Property Inspector (View > Property Inspector), the Signal Properties dialog box
(for a signal), or the block dialog box (for a state or parameter). Under Code Generation,
apply the storage class.
• For a parameter, first set the value of the parameter to the name that you want to use
for the required parameter object. Then, create and configure the parameter object as
shown in “Create Tunable Calibration Parameter in the Generated Code” on page 22-
121.
• For a signal, state, or Data Store Memory block, first give the signal or state a name,
which the code generator uses as the name of the corresponding global symbol. Then,
either specify a storage class using Storage class (in which case the model file stores
the specification) or create a signal data object as shown in “Use Data Objects in
Simulink Models” (Simulink) and apply a storage class to the object.
22-87
22 Data Representation in Simulink Coder
• For a Data Store Memory block, use set_param to interact with the block. Because
the data store already has a name, you do not need to specify a name. Apply the
storage class directly by using the StateStorageClass parameter or configure the
data store to acquire the storage class from a signal object.
To interact with a signal or parameter data object that you store in a model workspace or
data dictionary, use the programmatic interface of the workspace or dictionary. See
“Interact With Variables Programmatically” (Simulink).
This example shows how to programmatically apply a storage class directly to a signal
line.
rtwdemo_secondOrderSystem
2 Get a handle to the output of the block named Force: f(t).
portHandles = ...
get_param('rtwdemo_secondOrderSystem/Force: f(t)','PortHandles');
outportHandle = portHandles.Outport;
3 Set the name of the corresponding signal to ForceSignal.
set_param(outportHandle,'Name','ForceSignal')
4 Set the storage class of the signal to ExportedGlobal.
set_param(outportHandle,'StorageClass','ExportedGlobal')
5 Generate code from the model. The code declares and defines a global variable
ForceSignal to represent the signal.
This example shows how to programmatically apply a storage class to a block state.
rtwdemo_basicsc
2 Name the state of the Delay block as myState.
set_param('rtwdemo_basicsc/Delay','StateName','myState')
22-88
See Also
set_param('rtwdemo_basicsc/Delay',...
'StateStorageClass','ExportedGlobal')
4 Generate code from the model. The code declares and defines a global variable
myState to represent the state.
See Also
Related Examples
• “Choose a Storage Class for Controlling Data Representation in the Generated
Code” (Simulink Coder)
• “How Generated Code Exchanges Data with an Environment” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
22-89
22 Data Representation in Simulink Coder
For basic information about enumerated data types and their use in Simulink models, see
“Use Enumerated Data in Simulink Models” (Simulink). For information about
enumerated data types in Stateflow charts, see “Define Enumerated Data Types”
(Stateflow).
• Control the size of enumerated data types in the generated code by specifying a
superclass.
22-90
Use Enumerated Data in Generated Code
• int8
• uint8
• int16
• uint16
• int32
• Simulink.IntEnumType. Specify values in the range of the signed integer for your
hardware platform.
To specify an integer data type size, derive your enumeration class from the integer data
type.
To specify an integer data type size, specify the name-value pair StorageType as the
integer data type.
Simulink.defineIntEnumType('Colors',{'Red','Green','Blue'},...
[0;1;2],'StorageType','int8')
22-91
22 Data Representation in Simulink Coder
The first of these methods, getDefaultValue, is relevant to both simulation and code
generation, and is described in “Specify a Default Enumerated Value” (Simulink). The
other methods are relevant only to code generation. To customize the behavior of an
enumerated type, include a version of the method in the methods(Static) section of
the enumeration class definition. If you do not want to customize the type, omit the
methods(Static) section. The table summarizes the methods and the data to supply for
each one.
22-92
Use Enumerated Data in Generated Code
By default, the
generated #include
directive uses the
preprocessor delimiter
" instead of < and >. To
generate the directive
#include
<myTypes.h>, specify
the custom return value
as '<myTypes.h>'.
22-93
22 Data Representation in Simulink Coder
Specify a Description
To specify a description for an enumerated data type, include this method in the
methods(Static) section of the enumeration class:
Substitute a MATLAB character vector for description. The generated code that
defines the enumerated type includes the specified description.
To prevent generated code from defining an enumerated data type, which allows you to
provide the definition in an external file, include these methods in the methods(Static)
section of the enumeration class:
function retVal = getHeaderFile()
% GETHEADERFILE Specifies the file that defines this type in generated code.
% The method getDataScope determines the significance of the specified file.
retVal = 'imported_enum_type.h';
end
22-94
Use Enumerated Data in Generated Code
Instead of defining the type in model_types.h, which is the default behavior, generated
code imports the definition from the specified header file using a #include statement
like:
#include "imported_enum_type.h"
Generating code does not create the imported header file. You must provide the header
file, using the file name specified by the method getHeaderFile, that defines the
enumerated data type.
To generate a separate header file that defines an enumerated data type, include these
methods in the methods(Static) section of the enumeration class:
function retVal = getDataScope()
% GETDATASCOPE Specifies whether generated code imports or exports this type.
% Return one of:
% 'Auto': define type in model_types.h, or import if header file specified
% 'Exported': define type in a generated header file
% 'Imported': import type definition from specified header file
% If you do not define this method, DataScope is 'Auto' by default.
retVal = 'Exported';
end
Generated code exports the enumerated type definition to the generated header file
exported_enum_type.h.
22-95
22 Data Representation in Simulink Coder
By default, enumerated values in generated code have the same names that they have in
the enumeration class definition. Alternatively, your code can prefix every enumerated
value in an enumeration class with the name of the class. You can use this technique to
prevent identifier conflicts or to improve the readability of the code. To specify class name
prefixing, include this method in the methods(Static) section of an enumeration class:
function retVal = addClassNameToEnumNames()
% ADDCLASSNAMETOENUMNAMES Specifies whether to add the class name
% as a prefix to enumeration member names in generated code.
% Return true or false.
% If you do not define this method, no prefix is added.
retVal = true;
end
Specify the return value as true to enable class name prefixing or as false to suppress
prefixing. If you specify true, each enumerated value in the class appears in generated
code as EnumTypeName_EnumName. For the example enumeration class BasicColors in
“Enumerated Data Types” on page 22-90, the data type definition in generated code
might look like this:
#ifndef _DEFINED_TYPEDEF_FOR_BasicColors_
#define _DEFINED_TYPEDEF_FOR_BasicColors_
typedef enum {
BasicColors_Red = 0, /* Default value */
BasicColors_Yellow = 1,
BasicColors_Blue = 2,
} BasicColors;
#endif
The enumeration class name BasicColors appears as a prefix for each of the
enumerated names.
• An enum block. The native integer type of your hardware is the underlying integer
type for the enumeration members.
• A typedef statement and a series of #define macros. The typedef statement bases
the enumerated type name on a specific integer data type, such as int8. The macros
associate the enumeration members with the underlying integer values.
22-96
Use Enumerated Data in Generated Code
• In Simulink, define the enumerated type using a classdef block in a script file.
Derive the enumeration from the type Simulink.IntEnumType.
• Alternatively, use the function Simulink.defineIntEnumType. Do not specify the
property StorageType.
When you generate code, the type definition appears in an enum block.
#ifndef _DEFINED_TYPEDEF_FOR_BasicColors_
#define _DEFINED_TYPEDEF_FOR_BasicColors_
typedef enum {
Red = 0, /* Default value */
Yellow,
Blue,
} BasicColors;
#endif
To implement the type definition using a typedef statement and #define macros:
• In Simulink, define the enumerated type using a classdef block in a script file.
Derive the enumeration from a specific integer type such as int8.
• Alternatively, use the function Simulink.defineIntEnumType. Specify the property
StorageType using a specific integer type such as int8.
When you generate code, the type definition appears as a typedef statement and a
series of #define macros.
#ifndef _DEFINED_TYPEDEF_FOR_BasicColors_
#define _DEFINED_TYPEDEF_FOR_BasicColors_
22-97
22 Data Representation in Simulink Coder
#endif
A Simulink Data Type Conversion block accepts a signal of integer type. The block
converts the input to one of the underlying values of an enumerated type.
If the input value does not match any of the underlying values of the enumerated type
values, Simulink inserts a safe cast to replace the input value with the enumerated type
default value.
You can enable or disable safe casting for enumerations during code generation for a
Simulink Data Type Conversion block or a Stateflow block.
To control safe casting, enable or disable the Saturate on integer overflow block
parameter. The parameter works as follows:
• Enabled: Simulink replaces a nonmatching input value with the default value of the
enumerated values during simulation. The software generates a safe cast function
during code generation.
• Disabled: For a nonmatching input value, Simulink generates an error during
simulation. The software omits the safe cast function during code generation. In this
case, the code is more efficient. However, the code may be more vulnerable to run-
time errors.
22-98
See Also
output = 0;
if ((input >= 0) && (input <= 2)) {
/* Set output value to input value if it is a member of BasicColors */
output = input;
}
return output;
}
Through this function, the enumerated type’s default value is used if the input value does
not match one of underlying values of the enumerated type’s values.
If the block’s Saturate on integer overflow parameter is disabled, this function does not
appear in generated code.
See Also
Simulink.data.getEnumTypeInfo | Simulink.defineIntEnumType |
enumeration
Related Examples
• “Use Enumerated Data in Simulink Models” (Simulink)
• “Simulink Enumerations” (Simulink)
• “Exchange Structured and Enumerated Data Between Generated and External
Code” on page 24-34
22-99
22 Data Representation in Simulink Coder
22-100
Data Stores in Generated Code
6 Click Create. The Simulink.Signal object, which has the same name as the data
store, appears in the target workspace. Simulink selects the block parameter Data
store name must resolve to Simulink signal object.
Note When a Data Store Memory block is associated with a signal object, the mapping
between the Data store name and the signal object name must be one-to-one. If two or
more identically named entities map to the same signal object, the name conflict is
flagged as an error at code generation time. See “Resolve Conflicts in Configuration of
Signal Objects for Code Generation” (Simulink) for more information.
Data Store Memory blocks, like block states, have Auto storage class by default, and
their memory is stored within the DWork vector. The symbolic name of the storage
location is based on the data store name.
You can generate code from multiple Data Store Memory blocks that have the same data
store name, subject to the following restriction: at most one of the identically named
blocks can have a storage class other than Auto. An error is reported if this condition is
not met.
For blocks with Auto storage class, the code generator produces a unique symbolic name
for each block to avoid name clashes. For Data Store Memory blocks with storage classes
other than Auto, the generated code uses the data store name as the symbol.
In the following model, a Data Store Write block writes to memory declared by the Data
Store Memory block myData:
22-101
22 Data Representation in Simulink Coder
To control the storage declaration for a Data Store Memory block, use the Code
Generation > Signal object class and Code Generation > Storage class drop-down
lists of the Data Store Memory block dialog box. Set Signal object class to
Simulink.Signal (the default), and choose a storage class from the Storage class
drop-down list. The next figure shows the Data Store Memory block dialog box for the
preceding model.
To apply storage classes to data stores, you can alternatively use the Data Stores tab in
the Model Data Editor (in the model, View > Model Data Editor).
22-102
Data Stores in Generated Code
Data Store Memory blocks are nonvirtual because code is generated for their
initialization in .c and .cpp files and their declarations in header files. The following
table shows how the code generated for the Data Store Memory block in the preceding
model differs for different storage classes. The table gives the variable declarations and
MdlOutputs code generated for the myData block.
In model.c or model.cpp
/* Block states (auto storage) */
D_Work model_DWork;
In model.h
extern real_T myData;
For information about applying storage classes, see “Apply Storage Classes to Individual
Signal, State, and Parameter Data Elements” on page 22-81.
22-103
22 Data Representation in Simulink Coder
The next figure shows a model that uses blocks whose priorities have been modified to
achieve a particular order of execution:
1 The block Data Store Read buffers the current value of the data store A at its output.
2 The block Abs1 uses the buffered output of Data Store Read.
3 The block Data Store Write updates the data store.
4 The block Abs uses the buffered output of Data Store Read.
22-104
Data Stores in Generated Code
Because the output of Data Store Read is a buffer, both Abs and Abs1 use the same value:
the value of the data store at the time that Data Store Read executes.
1 The block Data Store Read buffers the current value of the data store A at its output.
2 Atomic Subsystem executes.
3 The Sum block adds the output of Atomic Subsystem to the output of Data Store
Read.
22-105
22 Data Representation in Simulink Coder
Simulink assumes that Atomic Subsystem might update the data store, so Simulink
buffers the data store. Atomic Subsystem executes after Data Store Read buffers its
output, and the buffer provides a way for the Sum block to use the value of the data store
as it was when Data Store Read executed.
In some cases, the code generator determines that it can optimize away the output buffer
for a Data Store Read block, and the generated code refers to the data store directly,
rather than a buffered value of it. The next figure shows an example:
In the generated code, the argument of the fabs() function is the data store A rather
than a buffered value.
22-106
Data Stores in Generated Code
Code interface packaging to Reusable function). If you implement the data store as
a Data Store Memory block and select the Share across model instances parameter:
• By default, the data store appears in the generated code as a separate global symbol.
• If you have Embedded Coder, to restrict access such that only the code generated from
the model can use the data store, configure the data store to appear as static by
applying the custom storage class FileScope. For more information about
FileScope and other custom storage classes, see “Choose a Storage Class for
Controlling Data Representation in the Generated Code” on page 22-69.
This example shows how to store several model signals in a structure in generated code
using a single data store. To store multiple signals in a data store, you configure the data
store to accept a composite signal, such as a nonvirtual bus signal or an array of
nonvirtual bus signals.
The model contains three subsystems that perform calculations on the inputs from
the top level of the model. In each subsystem, a Data Store Memory block stores an
intermediate calculated signal.
2 Generate code with the model. In the code generation report, view the file
ex_bus_struct_in_code.c. The code defines a global variable for each data store.
real_T BioBTURate;
real_T CoalBTURate;
real_T GasBTURate;
Suppose that you want to integrate code generated from the example model with other
existing code. Suppose also that the existing code requires access to all of the data from
the three data stores in a single structure variable. You can use a data store to assemble
all of the target data in a structure in generated code.
22-107
22 Data Representation in Simulink Coder
Configure a data store to contain multiple signals by creating a bus type to use as the
data type of the data store. Define the bus type using the same hierarchy of elements as
the structure that you want to appear in generated code.
buseditor
2 Define a new bus type Raw_BTU_Rate with one element for each of the three target
signals. Name the elements BioBTU, GasBTU, and CoalBTU.
3 At the top level of the example model, add a Data Store Memory block.
4 In the Simulink Editor, select View > Model Data Editor.
5 In the Model Data Editor, inspect the Data Stores tab.
6 For the new Data Store Memory block, use the Name column to set the data store
name to Raw_BTU_Data.
7 Use the Data Type column to set the data type of the data store to Bus:
Raw_BTU_Rate.
8 Set the Change view drop-down list to Code.
9 Use the Storage Class column to apply the storage class ExportedGlobal.
To write to a specific element of a data store, use a Data Store Write block. On the
Element Assignment tab in the dialog box, you can specify to write to a single element,
a collection of elements, or the entire contents of a data store.
22-108
Data Stores in Generated Code
4 On the Element Assignment tab, under Signals in the bus, expand the contents of
the data store Raw_BTU_Data. Click the element BioBTU, and then click Select.
Click OK.
22-109
22 Data Representation in Simulink Coder
typedef struct {
real_T BioBTU;
real_T GasBTU;
real_T CoalBTU;
} Raw_BTU_Rate;
3 View the file ex_bus_struct_in_code.c. The code represents the data store with
a global variable Raw_BTU_Data of the structure type Raw_BTU_Rate. In the model
step function, the code assigns the data from the calculated signals to the fields of
the global variable Raw_BTU_Data.
See Also
Related Examples
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements” on
page 22-81
• “Structures in Generated Code Using Data Stores” on page 22-107
• “When to Use a Data Store” (Simulink)
• “Generate Code That Dereferences Data from a Literal Memory Address” on page
52-21
22-110
Specify Single-Precision Data Type for Embedded Application
If you specify an inherited data type for signals, but data type propagation rules cannot
determine data types for the signals, the signal data types default to double. You can use
a model configuration parameter to specify the default data type as single.
model = 'rtwdemo_underspecified_datatype';
load_system(model)
set_param(model,'HideAutomaticNames','off')
open_system(model);
22-111
22 Data Representation in Simulink Coder
The root inports In2, In3, and In4 specify Inherit: Auto for the Data type block
parameter. The downstream blocks also use inherited data types.
The model starts with the configuration parameter System target file set to ert.tlc,
which requires Embedded Coder. Set System target file to grt.tlc instead.
set_param(model,'SystemTargetFile','grt.tlc')
rtwbuild(model)
22-112
Specify Single-Precision Data Type for Embedded Application
Open the Configuration Parameters dialog box. On the Math and Data Types pane,
select single in the Default for underspecified data type drop-down list.
22-113
22 Data Representation in Simulink Coder
typedef struct {
int8_T In1; /* '<Root>/In1' */
real32_T In2; /* '<Root>/In2' */
real32_T In3; /* '<Root>/In3' */
real32_T In4; /* '<Root>/In4' */
} ExtU_rtwdemo_underspecified_d_T;
See Also
Related Examples
• “Default for underspecified data type” (Simulink)
• “Subnormal Number Performance” on page 56-19
• “Standard math library” (Simulink Coder)
• “Control Data Type Names in Generated Code” on page 24-2
• “About Data Types in Simulink” (Simulink)
22-114
Tune Phase Parameter of Sine Wave Block During Code Execution
open_system('ex_phase_tunable')
Set Default parameter behavior to Tunable so that the parameters of the Sine Wave
block appear in the generated code as tunable fields of the global parameter structure.
set_param('ex_phase_tunable','DefaultParameterBehavior','Tunable')
rtwbuild('ex_phase_tunable')
In the code generation report, view the file ex_phase_tunable.c. The code algorithm
in the model step function calculates the Sine Wave block output. The parameters of the
block, including Phase, appear in the code as tunable structure fields.
file = fullfile('ex_phase_tunable_grt_rtw','ex_phase_tunable.c');
rtwdemodbtype(file,'/* Outport: ''<Root>/Out1'' incorporates:',...
'ex_phase_tunable_P.SineWave_Bias;',1,1)
22-115
22 Data Representation in Simulink Coder
ex_phase_tunable_Y.Out1 = sin(ex_phase_tunable_P.SineWave_Freq *
(((ex_phase_tunable_M->Timing.clockTick1+
ex_phase_tunable_M->Timing.clockTickH1* 4294967296.0)) * 1.0) +
ex_phase_tunable_P.SineWave_Phase) * ex_phase_tunable_P.SineWave_Amp +
ex_phase_tunable_P.SineWave_Bias;
During code execution, you can assign new values to the structure field that corresponds
to the Phase parameter.
See Also
Related Examples
• “Configure Data Accessibility for Rapid Prototyping” on page 22-3
22-116
Switch Between Output Waveforms During Code Execution for Waveform Generator Block
For a Waveform Generator block, you cannot make the parameters of a waveform, such as
amplitude and phase shift, tunable in the generated code. Instead, you can generate code
that enables you to choose an active waveform from a set of waveform variants that you
specify in the block. During execution of the code, you activate a variant by adjusting the
value of a global structure field.
You must set the model configuration parameter Default parameter behavior to
Tunable. Then, by default, block parameters in the model appear tunable in the
generated code. These parameters can consume large amounts of memory for a large
model.
open_system('ex_switch_waveform')
square(amp,10,0,dutyCycle)
amp = 2.71;
dutyCycle = 50;
This waveform represents the baseline stimulus that you want the application to use at
the start of execution.
22-117
22 Data Representation in Simulink Coder
Suppose that, during execution, you want to observe the effects of changing the waveform
frequency from 10 to 15 and the phase shift from 0 to 0.5. In the Waveform Generator
block, add these waveform variants:
square(amp,10,0.5,dutyCycle)
square(amp,15,0,dutyCycle)
square(amp,15,0.5,dutyCycle)
The generated file ex_switch_waveform.h defines the standard structure type that
stores tunable parameter data for the model. The structure contains a field whose value
represents the active waveform.
file = fullfile('ex_switch_waveform_grt_rtw','ex_switch_waveform.h');
rtwdemodbtype(file,'/* Parameters (default storage) */',...
'/* Real-time Model Data Structure */',1,0)
22-118
Switch Between Output Waveforms During Code Execution for Waveform Generator Block
P_ex_switch_waveform_T ex_switch_waveform_P = {
/* Mask Parameter: WaveformGeneratorStimulus_Selec
* Referenced by: '<S1>/Switch'
*/
1.0,
/* Expression: 3.5
* Referenced by: '<Root>/Gain (Control System)'
*/
3.5
};
The file ex_switch_waveform.c defines the model execution function. The function
uses a switch statement to determine the value of the active waveform, and then
calculates the value of the root-level Outport block, Out1.
file = fullfile('ex_switch_waveform_grt_rtw','ex_switch_waveform.c');
rtwdemodbtype(file,'switch ((int32_T)',...
'ex_switch_waveform_Y.Out1 =',1,1)
switch ((int32_T)ex_switch_waveform_P.WaveformGeneratorStimulus_Selec) {
case 1:
temp = temp - floor(temp) <= 0.5 ? 2.71 : -2.71;
break;
case 2:
temp = (temp - 0.79577471545947676) - floor(temp - 0.79577471545947676) <=
0.5 ? 2.71 : -2.71;
break;
case 3:
temp = temp_tmp_tmp - floor(temp_tmp_tmp) <= 0.5 ? 2.71 : -2.71;
break;
default:
temp = (temp_tmp_tmp - 1.1936620731892151) - floor(temp_tmp_tmp -
1.1936620731892151) <= 0.5 ? 2.71 : -2.71;
break;
}
22-119
22 Data Representation in Simulink Coder
*/
ex_switch_waveform_Y.Out1 = ex_switch_waveform_P.GainControlSystem_Gain * temp;
During code execution, to change the active waveform, adjust the value of the structure
field in the global parameters structure.
See Also
Related Examples
• “Configure Data Accessibility for Rapid Prototyping” on page 22-3
22-120
Create Tunable Calibration Parameter in the Generated Code
• Determine an optimal parameter value by tuning the parameter and monitoring signal
values during execution.
• Efficiently adapt an algorithm to different execution conditions by overwriting the
parameter value stored in memory. For example, you can use the same control
algorithm for multiple vehicles of different masses by storing different parameter
values in each vehicle’s engine control unit.
To make block parameters accessible in the generated code by default, for example for
rapid prototyping, set Default parameter behavior (see “Default parameter behavior”
(Simulink Coder)) to Tunable. For more information, see “Configure Data Accessibility
for Rapid Prototyping” on page 22-3.
Open the example model rtwdemo_paraminline and configure it to show the generated
names of blocks.
load_system('rtwdemo_paraminline')
set_param('rtwdemo_paraminline','HideAutomaticNames','off')
open_system('rtwdemo_paraminline')
22-121
22 Data Representation in Simulink Coder
In the model, click the G1 Gain block. The Model Data Editor highlights the row that
corresponds to the Gain parameter of the block.
In the Model Data Editor Value column, change the gain value from 2 to myGainParam.
Next to myGainParam, click the action button (with three vertical dots) and select
Create.
In the Create New Data block dialog box, set Value to Simulink.Parameter(2). Click
Create. A Simulink.Parameter object myGainParam stores the parameter value, 2, in
the base workspace.
In the myGainParam dialog box, set Storage class to ExportedGlobal and click OK.
This storage class causes the parameter object to appear in the generated code as a
tunable global variable.
Alternatively, to create the parameter object and configure the model, use these
commands at the command prompt:
22-122
Create Tunable Calibration Parameter in the Generated Code
set_param('rtwdemo_paraminline/G1','Gain','myGainParam')
myGainParam = Simulink.Parameter(2);
myGainParam.CoderInfo.StorageClass = 'ExportedGlobal';
Use the Model Data Editor to create a parameter object, myOtherGain, for the G2 Gain
block. Apply the storage class ExportedGlobal.
22-123
22 Data Representation in Simulink Coder
The generated code algorithm in the model step function uses myGainParam and
myOtherGain for calculations.
rtwdemodbtype(file,...
'/* Model step function */','/* Model initialize function */',1,0)
• On the Model Data Editor Parameters tab, with Change view set to Code, find the
row that corresponds to the variable. In the Storage Class column, from the drop-
down list, select Convert to parameter object. The Model Data Editor converts
the variable to a parameter object. Then, use the Storage Class column to apply a
storage class to the object.
22-124
Create Tunable Calibration Parameter in the Generated Code
converts variables to objects. Then, apply storage classes to the objects, for example,
by using the Model Data Editor or the Model Explorer.
In the generated code, the calibration parameters must appear as global variables defined
in a file named calPrms.c and declared in calPrms.h. The variable definitions must
look like these definitions:
#pragma SEC(CALPRM)
#pragma SEC()
The variables use the keywords const and volatile. The pragma #pragma
SEC(CALPRM) controls the placement of the variables in memory. To implement the
pragma, all of the variable definitions must appear in a contiguous block of code.
Also, the generated code must include an ASAP2 (a2l) description of each parameter.
Create Package for Storing Storage Class and Memory Section Definitions
Now, create a package in your current folder by copying the example package
+SimulinkDemos. The package stores the definitions of Parameter and Signal classes
that you later use to apply the storage class to data elements in models. Later, the
package also stores the definitions of the storage class and an associated memory section.
22-125
22 Data Representation in Simulink Coder
copyfile(fullfile(matlabroot,...
'toolbox','simulink','simdemos','dataclasses','+SimulinkDemos'),...
'+myPackage','f')
3 Navigate inside the +myPackage folder to the file Signal.m to edit the definition of
the Signal class.
4 Uncomment the methods section that defines the method setupCoderInfo. In the
call to the function useLocalCustomStorageClasses, replace 'packageName'
with 'myPackage'. When you finish, the section looks like this:
methods
function setupCoderInfo(h)
% Use custom storage classes from this package
useLocalCustomStorageClasses(h, 'myPackage');
end
end % methods
5 Save and close the file.
6 Navigate inside the +myPackage folder to the file Parameter.m to edit the definition
of the Parameter class. Uncomment the methods section that defines the method
setupCoderInfo and replace 'packageName' with 'myPackage'.
7 Save and close the file.
1 Set your current folder to the folder that contains the package folder +myPackage.
2 Open the Custom Storage Class Designer.
cscdesigner('myPackage')
3 In the Custom Storage Class Designer, on the Memory Sections tab, click New.
4 For the new memory section, set properties according to the table.
Property Value
Name CalMem
Statements Surround Group of variables
Pre Statement #pragma SEC(CALPRM)
Post Statement #pragma SEC()
Is const Select
Is volatile Select
5 Click Apply.
6 On the Custom Storage Class tab, click New.
22-126
Create Tunable Calibration Parameter in the Generated Code
7 For the new storage class, set properties according to the table.
Property Value
Name CalParam
For signals Clear
Data scope Exported
Header File calPrms.h
Definition File calPrms.c
Memory Section CalMem
8 Click OK. In response to the message about saving changes, click Yes.
To make applying the storage class easier, use the Model Explorer to change the default
parameter object from Simulink.Parameter to myPackage.Parameter.
daexplr
2 In the Model Explorer Model Hierarchy pane, select Base Workspace.
3 In the Model Explorer toolbar, click the arrow next to the Add Simulink Parameter
button. In the drop-down list, select Customize class lists.
4 In the Customize class lists dialog box, under Parameter classes, select the check
box next to myPackage.Parameter. Click OK.
5 In the Model Explorer toolbar, click the arrow next to the Add Simulink Parameter
button. In the drop-down list, select myPackage Parameter.
A myPackage.Parameter object appears in the base workspace. You can delete this
object.
Now, when you use tools such as the Model Data Editor to create parameter objects,
Simulink creates myPackage.Parameter objects instead of Simulink.Parameter
objects.
22-127
22 Data Representation in Simulink Coder
rtwdemo_roll
2 In the model, navigate into the BasicRollMode subsystem.
3 Select Code > C/C++ Code > Configure Model in Code Perspective.
4 Underneath the block diagram, open the Model Data Editor by selecting the Model
Data Editor tab.
5 In the Model Data Editor, select the Parameters tab and update the block diagram.
Now, the data table contains rows that correspond to workspace variables used by
the Gain blocks (which represent the P, I, and D parameters of the controller).
6 In the Model Data Editor, next to the Filter contents box, activate the Filter using
selection button.
7 In the model, select the three Gain blocks.
8 In the Filter contents box, enter model workspace.
The variables that the Gain blocks use are in the model workspace.
9 In the data table, select the three rows and, in the Storage Class column for any of
the rows, select Convert to parameter object.
Configure the model to generate a2l files. Select Configuration Parameters > Code
Generation > Interface > ASAP2 interface.
22-128
Create Tunable Calibration Parameter in the Generated Code
#pragma SEC()
/begin CHARACTERISTIC
/* Name */ dispGain
/* Long Identifier */ ""
/* Type */ VALUE
/* ECU Address */ 0x0000 /* @ECU_Address@dispGain@ */
/* Record Layout */ Scalar_FLOAT32_IEEE
/* Maximum Difference */ 0
/* Conversion Method */ rtwdemo_roll_CM_single
/* Lower Limit */ -3.4E+38
/* Upper Limit */ 3.4E+38
/end CHARACTERISTIC
#define numVessels 16
#define vesInitVol 18.2
This initialization technique preserves the mathematical relationship between the tunable
parameter and the system constants, which can make the generated code more readable
and easier to maintain. To generate this code:
numVessels = Simulink.Parameter(16);
vesInitVol = Simulink.Parameter(18.2);
2 Configure the objects to use the storage class Define, which yields a macro in the
generated code.
22-129
22 Data Representation in Simulink Coder
numVessels.CoderInfo.StorageClass = 'Custom';
numVessels.CoderInfo.CustomStorageClass = 'Define';
vesInitVol.CoderInfo.StorageClass = 'Custom';
vesInitVol.CoderInfo.CustomStorageClass = 'Define';
3 Create another parameter object that represents the tunable parameter. Configure
the object to use the storage class ExportedGlobal, which yields a global variable
in the generated code.
totalVol = Simulink.Parameter;
totalVol.CoderInfo.StorageClass = 'ExportedGlobal';
4 Set the value of totalVol by using the expression numVessels * vesInitVol. To
specify that the generated code preserve the expression, use the slexpr function.
For more information and limitations about using an expression to set the value of a
Simulink.Parameter object, see “Set Variable Value by Using a Mathematical
Expression” (Simulink).
The location of a parameter object can impact the file placement of the corresponding
data definition in the generated code.
• If you place a parameter object in the base workspace or a data dictionary, the code
generator assumes that the corresponding parameter data (for example, a global
variable) belongs to the system from which you generate code, not to any specific
component in the system. For example, if a model in a model reference hierarchy uses
a parameter object with a storage class other than Auto, the data definition appears in
22-130
Create Tunable Calibration Parameter in the Generated Code
the code generated for the top model in the hierarchy, not in the code generated for
the model that uses the object.
However, if you have Embedded Coder, some custom storage classes enable you to
specify the name of the model that owns a piece of data. When you specify an owner
model, the code generated for that model defines the data. For more information about
data ownership, see “Control Placement of Global Data Definitions and Declarations in
Generated Files” on page 23-2.
• If you place a parameter object in a model workspace, the code generator assumes
that the model owns the data. If you generate code from a reference hierarchy that
includes the containing model, the data definition appears in the code generated for
the containing model.
For more information about data ownership, see “Control Placement of Global Data
Definitions and Declarations in Generated Files” on page 23-2.
• If you apply a storage class other than Auto to a parameter object, the object appears
in the generated code as a global symbol. Therefore, in a model reference hierarchy,
two such objects in different model workspaces or dictionaries cannot have the same
name. The name of each object must be unique throughout the model hierarchy.
However, if you have Embedded Coder, you can use the storage class FileScope to
prevent name clashes between parameter objects in different model workspaces. See
“Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19.
22-131
22 Data Representation in Simulink Coder
• In the block dialog box that uses the parameter object. Use this technique to store the
minimum and maximum information in the model.
• By using the properties of a Simulink.Parameter object that you use to set the
parameter value. Use this technique to store the minimum and maximum information
outside the model.
For more information, see “Specify Minimum and Maximum Values for Block Parameters”
(Simulink).
22-132
See Also
See Also
Simulink.Breakpoint | Simulink.LookupTable | Simulink.Parameter
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Reuse Parameter Data in Different Data Type Contexts” on page 22-173
• “Limitations for Block Parameter Tunability in the Generated Code” (Simulink
Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements”
(Simulink Coder)
22-133
22 Data Representation in Simulink Coder
• “Access Structured Data Through a Pointer That External Code Defines” on page 26-
12
22-134
Limitations for Block Parameter Tunability in the Generated Code
Under certain conditions, the code generator cannot maintain tunability of a parameter,
variable, object, or expression. In this case, the code generator inlines the numeric value,
preventing you from changing the value during code execution.
To detect these conditions in your model, set the model configuration parameter Detect
loss of tunability (see “Detect loss of tunability” (Simulink)) to warning or error.
An expression that contains one or more tunable workspace variables, model arguments,
or tunable mask parameters is called a tunable expression. The expression is tunable
because the code generator attempts to preserve the expression in the code. Because the
code generator preserves the expression, you can change the values of the parameter
data during code execution.
22-135
22 Data Representation in Simulink Coder
The code generator reduces certain expressions to an inlined numeric value in the
generated code. The inlining renders workspace variables in the expression nontunable.
To avoid loss of tunability due to unsupported expressions, observe these guidelines:
• Expressions involving complex (i) workspace variables or parameter objects are not
supported.
• Certain operators and functions cause the code generator to reduce expressions and
remove tunability. To determine whether an operator or function causes loss of
tunability, use the information in this table.
22-136
Limitations for Block Parameter Tunability in the Generated Code
• Transfer Fcn
• State-Space
• Discrete State-Space
To set the Realization parameter, you must use the command prompt:
set_param(gcb,'Realization','auto')
• general: The block's numeric parameters appear tunable in the generated code.
• sparse: The generated code represents the block’s parameters as transformed values
that increase efficiency. The parameters are not tunable.
• auto: The default. If one or more of the block’s parameters are tunable (for example,
because you use a tunable parameter object to set a parameter value), then the block
uses the general realization. Otherwise, the block uses the sparse realization.
To tune the parameter values of one of these blocks during an external mode
simulation, the block must use the general realization.
Parameter Structures
As described in “Organize Data into Structures in Generated Code” on page 22-177, you
can create structures of parameter data in the generated code.
• If a parameter structure is tunable, the numeric fields of the structure are tunable in
the generated code. However, if any field contains a nontunable entity, such as a
multidimensional array, none of the structure fields are tunable.
• You cannot declare individual substructures or fields within a parameter structure as
tunable. You cannot use a Simulink.Parameter object as the value of a structure
field. Instead, you must store the entire structure in the parameter object.
22-137
22 Data Representation in Simulink Coder
See Also
Related Examples
• “Create Tunable Calibration Parameter in the Generated Code” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
22-138
Code Generation of Parameter Objects With Expression Values
22-139
22 Data Representation in Simulink Coder
parameter objects used in the expression must use either Auto or a storage class that
yields a macro in the generated code.
• You cannot set the value of a parameter object that represents a symbolic dimension
(see “Implement Dimension Variants for Array Sizes in Generated Code” on page 15-2)
to an expression.
• With Embedded Coder, you can generate code that preserves the expression, but only
for the purpose of statically initializing the value of a global variable or macro that
corresponds to the dependent parameter object. Follow the guidelines in “Expression
Preservation” (Simulink Coder).
Expression Preservation
If you want Embedded Coder to preserve expressions in the generated code, adhere to
these restrictions and guidelines.
• The dependent parameter object must use a storage class other than Auto. For
example, to generate a global variable and initialize it by using the expression, use
ExportedGlobal or ExportToFile.
• The parameter objects used in the expression must:
• Use a storage class that yields a macro in the generated code, such as Define.
• Have scalar, real values if the expression uses operators.
• The expression can use only these operators (in MATLAB syntax):
• Mathematical: +, -, *
• Relational: ==, ~=, <, >, <=, >=
• These data typing guidelines apply:
To use a value other than auto, you must set the DataType property of the object
that uses the expression to the same value. Otherwise, the code generator does not
preserve the expression.
• If you want to use a parameter object in multiple different expressions, and the
dependent parameter objects have different data types, leave the DataType
property of the independent object at the default value, auto. In the generated
code, the value of the macro is expressed as a floating-point number (with effective
22-140
See Also
data type double), and the code initializes the dependent parameters by
typecasting the result of each expression.
See Also
Simulink.Parameter
Related Examples
• “Create Tunable Calibration Parameter in the Generated Code” (Simulink Coder)
• “Share and Reuse Block Parameter Values by Creating Variables” (Simulink)
22-141
22 Data Representation in Simulink Coder
When you generate code from a model hierarchy that uses model arguments, the
arguments appear in the code as formal parameters of the referenced model entry-point
functions, such as the output (step) function. The generated code then passes the
instance-specific parameter values, which you specify in each Model block, to the
corresponding function calls.
Whether you use or do not use model arguments, you can use storage classes to configure
block parameters to appear in the generated code as tunable global variables. You can
also use storage classes to generate tunable model argument values, which the generated
code stores in memory and passes to the function calls. You can then change the values
during execution.
open_system('ex_arg_code_ref')
22-142
Specify Instance-Specific Parameter Values for Reusable Referenced Model
In the Model Data Editor, in the data table, use the Data Type column to set the data type
of the Inport block to single. Due to data type inheritance, the other signals in the
model use the same data type.
In the Model Data Editor, use the Value column to set the value of the Gain parameter to
gainArg.
In the Create New Data dialog box, set Value to Simulink.Parameter and Location to
Model Workspace. Click Create.
In the property dialog box, set Value to a number, for example, 3.17. Click OK.
Use the Model Data Editor to set the Numerator parameter by using a
Simulink.Parameter object named coeffArg whose value is 1.05. As with gainArg,
store the parameter object in the model workspace.
In the Model Data Editor, click the Show/refresh additional information button.
Use the Filter contents box to find each parameter object (gainArg and coeffArg). For
each object, select the check box in the Argument column.
22-143
22 Data Representation in Simulink Coder
Alternatively, at the command prompt, you can use these commands to configure the
blocks and the parameter objects:
set_param('ex_arg_code_ref/In1','OutDataTypeStr','single')
set_param('ex_arg_code_ref/Gain','Gain','gainArg')
modelWorkspace = get_param('ex_arg_code_ref','ModelWorkspace');
assignin(modelWorkspace,'gainArg',Simulink.Parameter(3.17));
set_param('ex_arg_code_ref/Discrete Filter','Numerator','coeffArg')
assignin(modelWorkspace,'coeffArg',Simulink.Parameter(1.05));
set_param('ex_arg_code_ref','ParameterArgumentNames','coeffArg,gainArg')
save_system('ex_arg_code_ref')
Create the model ex_arg_code_ref. This model uses multiple instances (Model blocks)
of the reusable algorithm.
open_system('ex_arg_code')
22-144
Specify Instance-Specific Parameter Values for Reusable Referenced Model
In the model, open the Model Data Editor Parameters tab (View > Model Data Editor).
The Model Data Editor shows four rows that correspond to the model arguments,
coeffArg and gainArg, that you can specify for the two Model blocks.
Use the Model Data Editor to set values for the model arguments. For example, use the
values in the figure.
Alternatively, at the command prompt, you can use these commands to set the values:
set_param('ex_arg_code/Model','ParameterArgumentValues',...
struct('coeffArg','0.98','gainArg','2.98'))
set_param('ex_arg_code/Model1','ParameterArgumentValues',...
struct('coeffArg','1.11','gainArg','3.34'))
rtwbuild('ex_arg_code')
22-145
22 Data Representation in Simulink Coder
The file ex_arg_code.c contains the definition of the top model entry-point function
ex_arg_code. This function calls the referenced model entry-point function
ex_arg_code_ref and uses the model argument values that you specified (such as 1.11
and 3.34) as the values of rtp_coeffArg and rtp_gainArg.
/* ModelReference: '<Root>/Model' incorporates:
* Inport: '<Root>/In1'
* Outport: '<Root>/Out1'
*/
ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out1,
&(ex_arg_code_DW.Model_InstanceData.rtdw), 0.98F, 2.98F);
22-146
Specify Instance-Specific Parameter Values for Reusable Referenced Model
You can configure the instance-specific values in the Model blocks to appear in the
generated code as tunable global variables. This technique enables you to store the
parameter values for each instance in memory and tune the values during code execution.
In the top model ex_arg_code, select the Model Data Editor Parameters tab.
Use the Model Data Editor to set the values of the model arguments according to this
figure.
set_param('ex_arg_code/Model','ParameterArgumentValues',...
struct('coeffArg','coeffForInst1','gainArg','gainForInst1'))
set_param('ex_arg_code/Model1','ParameterArgumentValues',...
struct('coeffArg','coeffForInst2','gainArg','gainForInst2'))
Copy gainArg and coeffArg from the ex_arg_code_ref model workspace to the base
workspace.
gainForInst1 = getVariable(modelWorkspace,'gainArg');
gainForInst1 = copy(gainForInst1);
coeffForInst1 = getVariable(modelWorkspace,'coeffArg');
coeffForInst1 = copy(coeffForInst1);
gainForInst2 = copy(gainForInst1);
coeffForInst2 = copy(coeffForInst1);
22-147
22 Data Representation in Simulink Coder
Set the instance-specific parameter values by using the Value property of the parameter
objects in the base workspace.
gainForInst1.Value = 2.98;
coeffForInst1.Value = 0.98;
gainForInst2.Value = 3.34;
coeffForInst2.Value = 1.11;
In the Model Data Editor for the top model ex_arg_code, click the Show/refresh
additional information button.
For the new parameter objects, set the value in the Storage Class column to
ExportedGlobal. This setting causes the parameter objects to appear in the generated
code as tunable global variables.
gainForInst1.StorageClass = 'ExportedGlobal';
coeffForInst1.StorageClass = 'ExportedGlobal';
gainForInst2.StorageClass = 'ExportedGlobal';
coeffForInst2.StorageClass = 'ExportedGlobal';
rtwbuild('ex_arg_code')
The file ex_arg_code.c defines the global variables that correspond to the parameter
objects in the base workspace.
22-148
Specify Instance-Specific Parameter Values for Reusable Referenced Model
In each call to ex_arg_code_ref, the top model algorithm uses the global variables to
set the values of the formal parameters.
/* ModelReference: '<Root>/Model' incorporates:
* Inport: '<Root>/In1'
* Outport: '<Root>/Out1'
*/
ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out1,
&(ex_arg_code_DW.Model_InstanceData.rtdw), coeffForInst1,
gainForInst1);
The global variables in the generated code use the data type real32_T (single).
• The parameter objects in the base workspace use context-sensitive data typing
because the DataType property is set to auto (the default). With this setting, the
parameter objects in the base workspace use the same data type as the model
arguments, single.
• The global variables in the generated code use the same data type as the parameter
objects in the base workspace.
Use the Model Explorer to copy gainArg and coeffArg from the ex_arg_code_ref
model workspace into the base workspace.
temp = getVariable(modelWorkspace,'gainArg');
gainArg = copy(temp);
temp = getVariable(modelWorkspace,'coeffArg');
coeffArg = copy(temp);
At the command prompt, combine these two parameter objects into a structure,
structArg.
structArg = Simulink.Parameter(struct('gain',gainArg.Value,...
'coeff',coeffArg.Value));
Use the Model Explorer to move structArg into the model workspace.
assignin(modelWorkspace,'structArg',copy(structArg));
clear structArg gainArg coeffArg
22-149
22 Data Representation in Simulink Coder
set_param('ex_arg_code_ref','ParameterArgumentNames','structArg')
In the ex_arg_code_ref model, select the Model Data Editor Parameters tab.
Use the Model Data Editor to set the value of the Gain parameter to structArg.gain
and the value of the Numerator parameter to structArg.coeff. Save the model.
set_param('ex_arg_code_ref/Gain','Gain','structArg.gain')
set_param('ex_arg_code_ref/Discrete Filter',...
'Numerator','structArg.coeff')
save_system('ex_arg_code_ref')
At the command prompt, combine the four parameter objects in the base workspace into
two structures. Each structure stores the parameter values for one instance of
ex_arg_code_ref.
structForInst1 = Simulink.Parameter(struct('gain',gainForInst1.Value,...
'coeff',coeffForInst1.Value));
structForInst2 = Simulink.Parameter(struct('gain',gainForInst2.Value,...
'coeff',coeffForInst2.Value));
In the top model ex_arg_code, set the Change view drop-down list to Design. Use the
Model Data Editor to set the argument values according to this figure.
22-150
Specify Instance-Specific Parameter Values for Reusable Referenced Model
set_param('ex_arg_code/Model','ParameterArgumentValues',...
struct('structArg','structForInst1'))
set_param('ex_arg_code/Model1','ParameterArgumentValues',...
struct('structArg','structForInst2'))
For the new parameter objects structForInst1 and structForInst2, use the Model
Data Editor to apply the storage class ExportedGlobal.
structForInst1.StorageClass = 'ExportedGlobal';
structForInst2.StorageClass = 'ExportedGlobal';
Simulink.Bus.createObject(structForInst1.Value);
myParamStructType = copy(slBus1);
In the Model Data Editor for ex_arg_code, set Change view to Design. Use the Data
Type column to set the data type of structForInst1 and structForInst2 to Bus:
myParamStructType.
In the Model Data Editor for ex_arg_code_ref, use the Model Data Editor to set the
data type of structArg to Bus: myParamStructType.
22-151
22 Data Representation in Simulink Coder
temp = getVariable(modelWorkspace,'structArg');
temp = copy(temp);
temp.DataType = 'Bus: myParamStructType';
assignin(modelWorkspace,'structArg',copy(temp));
save_system('ex_arg_code_ref')
When you use structures to group parameter values, you cannot take advantage of
context-sensitive data typing to control the data types of the fields of the structures (for
example, the fields of structForInst1). However, you can use the properties of the bus
object to control the field data types.
At the command prompt, set the data type of the elements in the bus object to single.
The corresponding fields in the structures (such as structForInst1 and structArg)
use the same data type.
myParamStructType.Elements(1).DataType = 'single';
myParamStructType.Elements(2).DataType = 'single';
rtwbuild('ex_arg_code')
typedef struct {
real32_T gain;
real32_T coeff;
} myParamStructType;
In the file ex_arg_code_ref.c, the referenced model entry-point function has a formal
parameter, rtp_structArg, that corresponds to the model argument structArg.
22-152
Specify Instance-Specific Parameter Values for Reusable Referenced Model
real32_T *rty_Out1,
DW_ex_arg_code_ref_f_T *localDW,
const myParamStructType *rtp_structArg)
The file ex_arg_code.c defines the global structure variables that correspond to the
parameter objects in the base workspace.
myParamStructType structForInst2 = {
3.34F,
1.11F
} ; /* Variable: structForInst2
* Referenced by: '<Root>/Model1'
*/
The top model algorithm in the file ex_arg_code.c passes the addresses of the structure
variables to the referenced model entry-point function.
/* ModelReference: '<Root>/Model' incorporates:
* Inport: '<Root>/In1'
* Outport: '<Root>/Out1'
*/
ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out1,
&(ex_arg_code_DW.Model_InstanceData.rtdw), &structForInst1);
• The block parameters that use the arguments (for certain blocks, such as those in the
Discrete library).
• The arguments in the referenced model workspace.
22-153
22 Data Representation in Simulink Coder
• In the model workspace, use a MATLAB variable whose data type is double or a
parameter object whose DataType property is set to auto. In this case, the variable
or object uses the same data type as the block parameter.
• When you set the argument values in Model blocks, take advantage of context-
sensitive data typing. To set an argument value, use an untyped value.
In these cases, the number, variable, or object uses the same data type as the model
argument in the referenced model workspace. If you also configure the model
argument to use context-sensitive data typing, you can control the data types of the
block parameter, the argument, and the argument value by specifying the type only for
the block parameter.
For basic information about controlling parameter data types, see “Parameter Data Types
in the Generated Code” on page 22-156.
If you use a model argument to set multiple block parameter values, and the data types of
the block parameters differ, you cannot use context-sensitive data typing (double or
auto) for the argument in the model workspace. You must explicitly specify a data type
for the argument. For example, if the argument in the model workspace is a parameter
object (such as Simulink.Parameter), set the DataType property to a value other than
auto. For more information about this situation, see “Reuse Parameter Data in Different
Data Type Contexts” on page 22-173.
In this case, you can continue to take advantage of context-sensitive data typing to control
the data type of the argument values that you specify in Model blocks. Each argument
value uses the data type that you specify for the corresponding argument in the model
workspace.
22-154
See Also
See Also
Related Examples
• “Code Generation of Referenced Models” on page 4-2
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Parameterize Instances of a Reusable Referenced Model” (Simulink)
• “Organize Data into Structures in Generated Code” on page 22-177
• “Parameter Data Types in the Generated Code” on page 22-156
22-155
22 Data Representation in Simulink Coder
For basic information about setting block parameter data types in a model, see “Control
Block Parameter Data Types” (Simulink).
• If you set the model configuration parameter Default parameter behavior (see
“Default parameter behavior” (Simulink Coder)) to Tunable, the Gain parameter of a
Gain block appears in the generated code as a field of a global structure that stores
parameter data. If you apply the data type single to the block parameter in the
model, the structure field in the code uses the corresponding data type, real32_T.
• If you apply the storage class ExportedGlobal to a Simulink.Parameter object,
the object appears in the generated code as a separate global variable. If you set the
DataType property of the object to int8, the global variable in the code uses the
corresponding data type, int8_T.
• If you configure a Simulink.Parameter object in a model workspace as a model
argument, the object appears in the generated code as a formal parameter (argument)
of a model entry-point function, such as the step function. The DataType property of
the object determines the data type of the formal parameter.
Other than determining the data type that the generated code uses to store parameter
values in memory, the data type of a parameter, variable, or object can also:
• Cause the block to cast the value of the parameter prior to code generation. The cast
can result in overflow, underflow, or quantization.
• Cause the generated code to include extra code, for example saturation code.
22-156
Parameter Data Types in the Generated Code
• The data type that you specify for a MATLAB variable or parameter object
(Simulink.Parameter) differs from the data type of a block parameter. The block
parameter typecasts the value of the variable or object.
• The data type that you specify for an initial value differs from the data type of the
initialized signal or state.
• The data type that you specify for a block parameter differs from the data type of the
signal or signals that the parameter operates on. Some blocks typecast the parameter
to perform the operation. For example, the Gain block performs this typecast.
If you configure a variable or object to use bias or fractional fixed-point slope, the block
parameter cannot perform the typecast. In this case, you must match the data type of the
variable or parameter object with the data type of the block parameter. Use one of these
techniques:
• Use context-sensitive data typing for the variable or parameter object. For a MATLAB
variable, use a double number to set the value of the variable. For a parameter
object, set the DataType property to auto.
• Use a Simulink.AliasType or Simulink.NumericType object to set the data type
of the block parameter and the data type of a parameter object.
Use this technique when you cannot rely on context-sensitive data typing, for example,
when you use the field of a structure to set the value of the block parameter.
• Manually specify the same data type for the block parameter and the variable or
parameter object.
Use this technique to reduce the dependence of the model on inherited and context-
sensitive data types and on external variables and objects.
For blocks that access parameter data through pointer or reference in the generated
code, if you specify different data types for the workspace variable and the block
22-157
22 Data Representation in Simulink Coder
parameter, the generated code implicitly casts the data type of the variable to the data
type of the block parameter. Note, that an implicit cast requires a data copy which could
significantly increase RAM consumption and slow down code execution speed for large
data sets. For example, Lookup Table blocks often access large vectors or matrices
through pointer or reference in the generated code.
For information about matching parameter data types when you use model arguments,
see “Control Data Types of Model Arguments and Argument Values” on page 22-153.
You can configure diagnostic configuration parameters to detect unintentional data type
mismatches that result in quantization and loss of parameter precision. See “Model
Configuration Parameters: Data Validity Diagnostics” (Simulink).
If you do not specify a minimum or maximum, Simulink chooses a data type based on the
value of the parameter. The chosen scaling might restrict the range of possible tuning
22-158
Parameter Data Types in the Generated Code
values. Therefore, it is a best practice to specify minimum and maximum values for each
tunable parameter.
A tunable parameter can use best-precision scaling even if you do not specify it in the
parameter data type. For example, the Gain block can choose a best-precision scaling if
the Parameter data type in the block dialog box is set to Inherit: Inherit via
internal rule. This setting is the default for the block.
When you use a structure as the value of a block parameter (for example to initialize a
bus signal), or when you organize multiple block parameter values into a single structure,
you can create a Simulink.Bus object to use as the data type of a
Simulink.Parameter object. You can then control the data types of individual fields in
the structure. See “Control Field Data Types and Characteristics by Creating Parameter
Object” (Simulink) and “Control Data Types of Initial Condition Structure Fields”
(Simulink).
Use this technique to separate the value of the table or breakpoint data from the data
type, which can improve readability and understanding of your design. You can then
use a Simulink.NumericType or Simulink.AliasType object to:
22-159
22 Data Representation in Simulink Coder
Set the DataType property of the embedded objects to the default value, auto. The
table and breakpoint data then acquire the data type that you use to set the Value
property.
Use this technique to store the data type information in the Value property, which can
simplify the way you interact with the Simulink.LookupTable and
Simulink.Breakpoint objects. You can leave the DataType property at the default
value.
When you later change the breakpoint or table data in the Value property, preserve
the data type information by using a typed expression. Alternatively, if you use a
command at the command prompt or a script to change the data, to avoid using a
typed expression, use subscripted assignment, (:).
myLUTObject.Table.Value(:) = [4 5 6];
When you change the data stored in the Value property, if you do not use a typed
expression or subscripted assignment, you lose the data type information.
You can use an expression to set the value of a parameter object (such as
Simulink.Parameter). The expression encodes mathematical relationships between
different objects. When you use this technique, different data typing rules apply. See “Set
Variable Value by Using a Mathematical Expression” (Simulink).
See Also
Related Examples
• “Generate Efficient Code by Specifying Data Types for Block Parameters” on page
22-162
• “Reuse Parameter Data in Different Data Type Contexts” on page 22-173
• “Data Types Supported by Simulink” (Simulink)
22-160
See Also
22-161
22 Data Representation in Simulink Coder
Open the example model rtwdemo_basicsc and configure it to show the generated
names of blocks.
load_system('rtwdemo_basicsc')
set_param('rtwdemo_basicsc','HideAutomaticNames','off')
open_system('rtwdemo_basicsc')
22-162
Generate Efficient Code by Specifying Data Types for Block Parameters
Identify the Gain block in the model, which uses the base workspace variable K1 to set
the value of the Gain parameter. The input signal of this block uses the data type single.
In the model, select the Gain block. In the Model Data Editor, the Data Type column
shows that the data type of the Gain parameter of the block is set to Inherit: Same as
input. With this setting, the Gain parameter of this block uses the same data type as the
input signal.
In the Model Data Editor, set the Change view drop-down list to Code.
Update the block diagram. Now, in the Model Data Editor, the data table shows rows that
correspond to workspace variables that the model uses, including K1.
In the Model Data Editor, find the row that corresponds to K1. For that row, in the
Storage Class column, select Convert to parameter object. Simulink converts K1
to a Simulink.Parameter object.
22-163
22 Data Representation in Simulink Coder
Use the Storage Class column to apply the storage class ExportedGlobal. With this
setting, the object appears in the generated code as a global variable.
In the data table, for the row that represents K1, in the Data Type column, select auto.
With this setting, the parameter object acquires its data type from the block parameters
that use the object (in this case, the Gain block parameter).
Alternatively, to create and configure the object, use these commands at the command
prompt:
K1 = Simulink.Parameter(2);
K1.CoderInfo.StorageClass = 'ExportedGlobal';
The generated file rtwdemo_basicsc.c defines the global variable K1 by using the data
type real32_T, which corresponds to the data type single in Simulink.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* Exported block parameters */','real32_T K1 = 2.0F;',1,1)
The generated code algorithm in the model step function uses K1 directly without
typecasting.
rtwdemodbtype(file,' rtwdemo_basicsc_DW.X = K1',...
' rtCP_Table1_bp01Data, rtCP_Table1_tableData,',1,1)
rtwdemo_basicsc_DW.X = K1 * look1_iflf_binlx(rtwdemo_basicsc_U.input2,
rtCP_Table1_bp01Data, rtCP_Table1_tableData, 10U);
On the Model Data Editor Parameters tab, you can can optionally set the data type of the
Gain block parameter to Inherit: Inherit via internal rule (the default). In
this case, the block parameter chooses the same data type as the input signal, single.
22-164
Generate Efficient Code by Specifying Data Types for Block Parameters
However, when you use Inherit: Inherit via internal rule, under other
circumstances (for example, when you use fixed-point data types), the block parameter
might choose a different data type.
When you use a Simulink.Parameter object to export or import parameter data from
the generated code to your external code, for example by applying the storage class
ImportedExtern, you can specify data type information in the parameter object. To
match the data type of the parameter object with a signal data type, create a
Simulink.NumericType or Simulink.AliasType object. You can strictly control the
data type that the parameter object uses in the generated code, eliminating the risk that
Simulink chooses a different data type when you make changes to the model.
myType = Simulink.NumericType;
myType.DataTypeMode = 'Single';
Use the Model Data Editor Data Type column to set these data types to myType:
Use the Model Data Editor Parameters tab to set the data type of the Gain block
parameter to Inherit: Inherit from 'Gain'. Use this data type object as the data
type of the parameter object.
Alternatively, to configure the object and the blocks, use these commands at the command
prompt:
K1.DataType = 'myType';
set_param('rtwdemo_basicsc/In2','OutDataTypeStr','myType')
set_param('rtwdemo_basicsc/Gain','ParamDataTypeStr','Inherit: Inherit from ''Gain''')
rtwbuild('rtwdemo_basicsc')
22-165
22 Data Representation in Simulink Coder
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* Exported block parameters */','real32_T K1 = 2.0F;',1,1)
run(fullfile(matlabroot,'examples','simulinkcoder',...
'main','prepare_rtwdemo_basicsc_2'))
22-166
Generate Efficient Code by Specifying Data Types for Block Parameters
Many of the signals in the model use the data type single.
Next to the Filter contents box, activate the Filter using selection button.
In the model, click the Gain block. The Model Data Editor shows one row that
corresponds to the Gain parameter of the block and one row that corresponds to the
MATLAB variable K1, which sets the parameter value to 2. K1 resides in the base
workspace.
In the Model Data Editor, set the Change view drop-down list to Code.
In the data table, for the row that corresponds to K1, in the Storage Class column, from
the drop-down list, select Convert to parameter object. Simulink converts K1 to a
Simulink.Parameter object.
22-167
22 Data Representation in Simulink Coder
K1 = Simulink.Parameter(K1);
Use the Storage Class column to apply the storage class ExportedGlobal to K1. With
this setting, K1 appears in the generated code as a global variable.
K1.CoderInfo.StorageClass = 'ExportedGlobal';
In the Model Data Editor, set Change view to Design and use the Data Type column to
apply the data type int8 to K1.
K1.DataType = 'int8';
For the row that represents the Gain block parameter, in the Data Type column, set the
drop-down list to Inherit: Inherit from 'Gain'. With this setting, the Gain
parameter of the block inherits the int8 data type from the parameter object.
set_param('rtwdemo_basicsc/Gain','ParamDataTypeStr',...
'Inherit: Inherit from ''Gain''')
The generated file rtwdemo_basicsc.c defines the global variable K1 by using the data
type int8_T, which corresponds to the data type int8 in Simulink.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* Exported block parameters */','int8_T K1 = 2;',1,1)
The code algorithm in the model step function uses K1 to calculate the output of the
Gain block. The algorithm casts K1 to the data type real32_T (single) because the
signals involved in the calculation use the data type real32_T.
rtwdemodbtype(file,' rtwdemo_basicsc_DW.X =','10U);',1,1)
22-168
Generate Efficient Code by Specifying Data Types for Block Parameters
Suppose you configure the signals in your model to use fixed-point data types. You want a
gain parameter to appear in the generated code as a tunable global variable. You know
the range of real-world values that you expect the parameter to assume (for example,
between 0 and 4). If you can meet your application requirements despite reduced
precision, you can reduce memory consumption by configuring the parameter to use a
different data type than the input and output signals of the block.
load_system('fxpdemo_direct_form2')
set_param('fxpdemo_direct_form2','HideAutomaticNames','off')
open_system('fxpdemo_direct_form2')
22-169
22 Data Representation in Simulink Coder
Update the block diagram. Signals in this model use signed fixed-point data types with a
word length of 16 and binary-point-only scaling.
Open the Gain5 block dialog box. The Gain parameter is set to 1.85. Suppose you want
to configure this parameter.
Click the action button (with three vertical dots) next to the parameter value. Select
Create.
In the Create New Data dialog box, set Value to Simulink.Parameter(1.85) and click
Create. The Simulink.Parameter object myGainParam appears in the base
workspace.
In the myGainParam property dialog box, set Storage class to ExportedGlobal and
click OK. With this setting, myGainParam appears in the generated code as a global
variable.
In the block dialog box, on the Parameter Attributes tab, set Parameter minimum to 0
and Parameter maximum to 4.
Click the Show Data Type Assistant button. The Data Type Assistant shows that the
expression fixdt(0,8) specifies an unsigned fixed-point data type with a word length of
8 and best-precision scaling. When you simulate or generate code, the block parameter
chooses a fraction length (scaling) that enables the data type to represent values between
the parameter minimum and maximum (0 and 4) with the best possible precision.
In the Data Type Assistant, set Scaling to Binary point. Click Calculate Best-
Precision Scaling, Fixed-point details, and Refresh Details. The information under
Fixed-point details shows that a fraction length of 5 can represent the parameter values
with a precision of 0.03125.
Set Scaling back to Best precision and click OK. In this example, when you simulate
or generate code, the block parameter chooses a fraction length of 5.
Altenatively, you can use these commands at the command prompt to create the object
and configure the block:
myGainParam = Simulink.Parameter(1.85);
myGainParam.CoderInfo.StorageClass = 'ExportedGlobal';
22-170
See Also
set_param('fxpdemo_direct_form2/Gain5','Gain','myGainParam')
set_param('fxpdemo_direct_form2/Gain5','ParamMin','0','ParamMax','4')
set_param('fxpdemo_direct_form2/Gain5','ParamDataTypeStr','fixdt(0,8)')
Configure the model to produce a code generation report. To reduce clutter in the
Command Window, clear the configuration parameter Verbose build.
set_param('fxpdemo_direct_form2','GenerateReport','on',...
'LaunchReport','on','RTWVerbose','off')
evalc('rtwbuild(''fxpdemo_direct_form2'')');
file = fullfile('fxpdemo_direct_form2_grt_rtw','fxpdemo_direct_form2.c');
rtwdemodbtype(file,'/* Exported block parameters */','uint8_T myGainParam = 59U;',1,1)
The code algorithm uses myGainParam to calculate the output of the Gain5 block. The
algorithm uses a C shift to scale the result of the calculation.
/* Gain: '<Root>/Gain5' */
fxpdemo_direct_form2_B.Gain5 = (int16_T)((myGainParam *
fxpdemo_direct_form2_B.UnitDelay1) >> 5);
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
22-171
22 Data Representation in Simulink Coder
22-172
Reuse Parameter Data in Different Data Type Contexts
ex_paramdt_contexts
In the Model Data Editor, on the Inports/Outports tab, use the Data Type column to set
the data type of the In1 Inport block to single and the data type of the In2 block to
int8.
On the Signals tab, set the data types of the Gain block outputs to Inherit: Same as
input.
On the Parameters tab, for the Gain parameters of the Gain blocks, set Data Type to
Inherit: Same as input.
Alternatively, to configure the blocks, use these commands at the command prompt:
22-173
22 Data Representation in Simulink Coder
set_param('ex_paramdt_contexts/In1','OutDataTypeStr','single')
set_param('ex_paramdt_contexts/In2','OutDataTypeStr','int8')
set_param('ex_paramdt_contexts/Gain - single','Gain','myGainParam',...
'OutDataTypeStr','Inherit: Same as input',...
'ParamDataTypeStr','Inherit: Same as input')
set_param('ex_paramdt_contexts/Gain - int8','Gain','myGainParam',...
'OutDataTypeStr','Inherit: Same as input',...
'ParamDataTypeStr','Inherit: Same as input')
In the Model Data Editor, for either Gain block parameter, click the cell in the Value
column. Next to myGainParam, click the action button (with three vertical dots) and
select Create.
In the Create New Data dialog box, set Value to Simulink.Parameter(3) and click
Create. A Simulink.Parameter object with value 3 appears in the base workspace.
In the myGainParam property dialog box, set Data type to int8 and Storage class to
ExportedGlobal. With the storage class ExportedGlobal, the object appears in the
generated code as a global variable.
Alternatively, to create and configure the parameter object, use these commands at the
command prompt:
myGainParam = Simulink.Parameter(3);
myGainParam.CoderInfo.StorageClass = 'ExportedGlobal';
myGainParam.DataType = 'int8';
In this model, you use the parameter object myGainParam to set two block parameter
values. The block parameters inherit different data types from the block input signals
(single or int8). To use myGainParam in these different data type contexts, you
explicitly specify the data type of the parameter object by setting the DataType property
to int8.
22-174
Reuse Parameter Data in Different Data Type Contexts
In the Model Data Editor, on the Inports/Outports tab, set the data type of the In2
Inport block to sharedType_int8.
On the Parameters tab, update the block diagram. The data table now contains a row
that represents the parameter object, myGainParam.
Use the Data Type column to set the data type of the parameter object to
sharedType_int8.
Alternatively, to configure the block and the object, use these commands at the command
prompt:
myGainParam.DataType = 'sharedType_int8';
set_param('ex_paramdt_contexts/In2','OutDataTypeStr','sharedType_int8')
The parameter object and the signal use the data type int8. To change this data type,
adjust the properties of the data type object sharedType_int8.
rtwbuild('ex_paramdt_contexts')
file = fullfile('ex_paramdt_contexts_grt_rtw','ex_paramdt_contexts.c');
rtwdemodbtype(file,'/* Exported block parameters */','int8_T myGainParam = 3;',1,1)
The generated code algorithm in the model step function uses myGainParam to calculate
the outputs of the two Gain blocks. In the case of the Gain block whose input signal uses
the data type single, the code algorithm casts myGainParam to the data type
real32_T, which corresponds to the data type single in Simulink.
22-175
22 Data Representation in Simulink Coder
See Also
Related Examples
• “Parameter Data Types in the Generated Code” on page 22-156
• “Generate Efficient Code by Specifying Data Types for Block Parameters” on page
22-162
• “Create Tunable Calibration Parameter in the Generated Code” on page 22-121
22-176
Organize Data into Structures in Generated Code
By default, the code generator aggregates data into standard structures (see “How
Generated Code Stores Internal Signal, State, and Parameter Data” on page 22-50). To
control the characteristics of these structures or to override this default behavior by
creating different structures, use the information in the table.
Goal Technique
Control the characteristics of the standard With Embedded Coder, see “Control
data structures. For example, specify the Characteristics of Data Structures
names of the structure types, structure (Embedded Coder)” on page 22-27.
variables, and field names.
Control the placement of the structures in With Embedded Coder, see “Control Data
memory, for example, by inserting pragmas and Function Placement in Memory by
or other code decorations. Inserting Pragmas” on page 30-2.
22-177
22 Data Representation in Simulink Coder
Goal Technique
Aggregate data into structures whose With Embedded Coder, apply a structured
names and other basic characteristics you custom storage class to a category of data
can control. As you add blocks and signals by using the Code Mapping Editor.
to the model, the resulting new data
appears in these structures by default. • When you generate nonreetrant, single-
instance code by setting the model
configuration parameter Code
interface packaging to Nonreusable
function, create flat, global structure
variables by applying the built-in
storage classes Struct, ParamStruct,
and SignalStruct. Alternatively,
create and apply your own structured
custom storage class.
• When you generate multi-instance
(reentrant) code from a model or a
component, for example by setting Code
interface packaging to a value other
than Nonreusable function, in the
Code Mapping Editor, you cannot use
the built-in storage class Struct or any
structured storage class that you create
in a package. Instead, create your own
structured custom storage class by
using an Embedded Coder Dictionary. If
you use the Embedded Coder Quick
Start tool on the model (see “Generate
Code by Using the Quick Start Tool” on
page 37-10), you can use the built-in
storage classes ParamStruct and
SignalStruct.
• You cannot use this technique to
aggregate global data stores or global
parameters (which include parameter
objects that you store in the base
workspace or a data dictionary). For
these kinds of data, use other
techniques to create structures.
22-178
Organize Data into Structures in Generated Code
Goal Technique
For more information about the Code
Mapping Editor, see “Configure Default
Code Generation for Categories of Model
Data and Functions” on page 21-7. To
create your own storage class, see “Define
Storage Classes, Memory Sections, and
Function Templates for Software
Architecture” on page 20-2.
Improve readability of the generated code Create a Simulink.Bus object that
by organizing individual data items into a represents the structure type that you
custom structure whose characteristics you want. Use the bus object to set the data
can finely control. types of nonvirtual bus signals and
parameter structures in your model.
22-179
22 Data Representation in Simulink Coder
Goal Technique
Reduce the number of arguments (formal • To reduce the number of arguments for
parameters) for generated functions. the entry-point functions of the model
from which you generate code, such as
model_step, see “Reduce Number of
Arguments by Using Structures” on
page 22-47.
• To reduce the number of arguments for
the entry-point functions of a referenced
model, in the referenced model:
22-180
Organize Data into Structures in Generated Code
Goal Technique
Generate bit fields. See “Bitfields” on page 14-89 and
“Optimize Generated Code By Packing
Boolean Data Into Bitfields” on page 60-
16.
• Apply a structured storage class to categories of data by using the Code Mapping
Editor. As you add blocks and signals to a model, new data elements acquire this
storage class by default.
• Apply a structured storage class, such as the built-in custom storage class Struct,
directly to individual data items by using the Model Data Editor.
• Create custom nonvirtual buses and parameter structures.
22-181
22 Data Representation in Simulink Coder
You cannot use default application to aggregate global data stores or global parameters
(parameter objects that you store in the base workspace or a data dictionary).
22-182
Organize Data into Structures in Generated Code
To apply default storage classes, use the Code Mapping Editor. In a model window, select
Code > C/C++ Code > Configure Model in Code Perspective. Then, under Code
Mappings > Data Defaults, apply storage classes by using the Storage Class column.
For more information about the Code Mapping Editor, see “Configure Default Code
Generation for Categories of Model Data and Functions” on page 21-7. To create your
own storage class by using an Embedded Coder Dictionary, see “Create Code Definitions
for Use as Default Code Generation Settings” on page 20-2.
To directly apply a storage class, use the Model Data Editor (View > Model Data
Editor). Set Change view to Code and apply the storage class by using the Storage
Class column.
For an example that shows how to use Struct, see “Organize Parameter Data into a
Structure by Using the Struct Custom Storage Class” on page 26-23. For more
information about applying storage classes, see “Apply Custom Storage Classes to
Individual Signal, State, and Parameter Data Elements” on page 26-19.
22-183
22 Data Representation in Simulink Coder
Structures of Parameters
Create a structure in the generated code. The structure stores parameter data.
C Construct
typedef struct {
double G1;
double G2;
} myStructType;
myStructType myStruct = {
2.0,
-2.0
} ;
Procedure
rtwdemo_paraminline
22-184
Organize Data into Structures in Generated Code
In the Model Data Editor, use the Value column to set the value of the Gain parameter to
myStruct.G1.
Use the Model Data Editor to set the value of the Gain parameter in the G2 block to
myStruct.G2.
Next to myStruct.G2, click the action button (with three vertical dots) and select
Create.
In the Create New Data dialog box, set Value to Simulink.Parameter(struct) and
click Create. A Simulink.Parameter object named myStruct appears in the base
workspace.
In the Simulink.Parameter property dialog box, next to the Value property, click the
action button and select Open Variable Editor.
In the Variable Editor, right-click the white space under the Field column and select New.
Name the new structure field G1. Use the Value column to set the value of the field to 2.
Use the Variable Editor to add a field G2 whose value is -2 and then close the Variable
Editor.
Alternatively, use these commands to configure the blocks and create myStruct.
rtwdemo_paraminline
set_param('rtwdemo_paraminline/G1','Gain','myStruct.G1')
set_param('rtwdemo_paraminline/G2','Gain','myStruct.G2')
myStruct.G1 = 2;
myStruct.G2 = -2;
myStruct = Simulink.Parameter(myStruct);
myStruct.CoderInfo.StorageClass = 'ExportedGlobal';
22-185
22 Data Representation in Simulink Coder
Results
rtwbuild('rtwdemo_paraminline')
file = fullfile('rtwdemo_paraminline_grt_rtw',...
'rtwdemo_paraminline_types.h');
rtwdemodbtype(file,'typedef struct {','} struct_6h72eH5WFuEIyQr5YrdGuB;',...
1,1)
typedef struct {
real_T G1;
real_T G2;
} struct_6h72eH5WFuEIyQr5YrdGuB;
The source file rtwdemo_paraminline.c defines and initializes the structure variable
myStruct.
file = fullfile('rtwdemo_paraminline_grt_rtw','rtwdemo_paraminline.c');
rtwdemodbtype(file,'struct_6h72eH5WFuEIyQr5YrdGuB myStruct',...
'/* Variable: myStruct',1,1)
struct_6h72eH5WFuEIyQr5YrdGuB myStruct = {
2.0,
-2.0
} ; /* Variable: myStruct
Optionally, specify a name to use for the structure type definition (struct).
Simulink.Bus.createObject(myStruct.Value);
22-186
Organize Data into Structures in Generated Code
The default name of the object is slBus1. Change the name by copying the object into a
new MATLAB variable.
myStructType = copy(slBus1);
In the Model Data Editor, click the Show/refresh additional information button.
In the data table, find the row that corresponds to myStruct. Use the Data Type column
to set the data type of myStruct to Bus: myStructType.
Alternatively, at the command prompt, use this command to set the data type of
myStruct.
myStruct.DataType = 'Bus: myStructType';
The code generates the definition of the structure type myStructType and uses this type
to define the global variable myStruct.
rtwdemodbtype(file,'myStructType myStruct = {','/* Variable: myStruct',...
1,1)
myStructType myStruct = {
2.0,
-2.0
} ; /* Variable: myStruct
Structures of Signals
This example shows how to create a structure of signal data in the generated code.
C Construct
typedef struct {
double signal1;
double signal2;
double signal3;
} my_signals_type;
22-187
22 Data Representation in Simulink Coder
Procedure
To represent a structure type in a model, create a Simulink.Bus object. Use the object
as the data type of bus signals in your model.
Create the ex_signal_struct model with Gain blocks, a Bus Creator block, and a Unit
Delay block. The Gain and Unit Delay blocks make the structure more identifiable in the
generated code.
To configure the Bus Creator block to accept three inputs, in the block dialog box, set
Number of inputs to 3.
Use the Bus Editor to create a Simulink.Bus object named my_signals_type that
contains three signal elements: signal1, signal2, and signal3. To create bus objects
with the Bus Editor, see “Create Bus Objects with the Bus Editor” (Simulink).
This bus object represents the structure type that you want the generated code to use.
22-188
Organize Data into Structures in Generated Code
In the Bus Creator block dialog box, set Output data type to Bus: my_signals_type.
Select Output as nonvirtual bus. Click OK. A nonvirtual bus appears in the generated
code as a structure.
In the Model Data Editor, on the Signals tab, from the Change view drop-down list,
select Code.
In the model, click the output signal of the Bus Creator block.
In the Model Data Editor, for the output of the Bus Creator block, set Name to
sig_struct_var.
Set Storage Class to ExportedGlobal. With this setting, the output of the Bus Creator
block appears in the generated code as a separate global structure variable named
sig_struct_var.
Results
typedef struct {
real_T signal1;
real_T signal2;
real_T signal3;
} my_signals_type;
The source file ex_signal_struct.c allocates memory for the global variable
sig_struct_var, which represents the output of the Bus Creator block.
22-189
22 Data Representation in Simulink Coder
In the same file, in the model step function, the algorithm accesses sig_struct_var
and the fields of sig_struct_var.
You can create nested structures of signal data in the generated code.
C Construct
typedef struct {
double signal1;
double signal2;
double signal3;
} B_struct_type;
typedef struct {
double signal1;
double signal2;
} C_struct_type;
typedef struct {
B_struct_type subStruct_B;
C_struct_type subStruct_C;
} A_struct_type;
Procedure
To represent a structure type in a model, create a Simulink.Bus object. Use the object
as the data type of bus signals in your model.
To nest a structure inside another structure, use a bus object as the data type of a signal
element in another bus object.
Create the ex_signal_nested_struct model with Gain blocks, Bus Creator blocks,
and a Unit Delay block. The Gain and Unit Delay blocks make the structure more
identifiable in the generated code.
22-190
Organize Data into Structures in Generated Code
To configure a Bus Creator block to accept three inputs, in the block dialog box, set
Number of inputs to 3.
Use the Bus Editor to create a Simulink.Bus object named A_struct_type that
contains two signal elements: subStruct_B and subStruct_C. To create bus objects
with the Bus Editor, see “Create Bus Objects with the Bus Editor” (Simulink). This bus
object represents the top-level structure type that you want the generated code to use.
For the subStruct_B element, set DataType to Bus: B_struct_type. Use a similar
type name for subStruct_C.
22-191
22 Data Representation in Simulink Coder
Each signal element in A_struct_type uses another bus object as a data type. Now,
these elements represent substructures.
Use the Bus Editor to create the Simulink.Bus objects B_struct_type (with three
signal elements) and C_struct_type (with two signal elements).
In the dialog box of the Bus Creator block that collects the three Gain signals, set Output
data type to Bus: B_struct_type. Click Apply.
In the dialog box of the other subordinate Bus Creator block, set Output data type to
Bus: C_struct_type and select Output as nonvirtual bus. Click OK.
In the last Bus Creator block dialog box, set Output data type to Bus: A_struct_type
and select Output as nonvirtual bus. Click OK.
In the Model Data Editor, on the Signals tab, from the Change view drop-down list,
select Code.
22-192
Organize Data into Structures in Generated Code
In the model, click the output signal of the A_struct_type Bus Creator block, which
feeds the Unit Delay block.
In the Model Data Editor, for the output of the Bus Creator block, set Name to
sig_struct_var.
Set Storage Class to ExportedGlobal. With this setting, the output of the Bus Creator
block appears in the generated code as a separate global structure variable named
sig_struct_var.
Results
typedef struct {
real_T signal1;
real_T signal2;
real_T signal3;
} B_struct_type;
typedef struct {
real_T signal1;
real_T signal2;
} C_struct_type;
typedef struct {
B_struct_type subStruct_B;
C_struct_type subStruct_C;
} A_struct_type;
22-193
22 Data Representation in Simulink Coder
In the same file, in the model step function, the algorithm accesses sig_struct_var
and the fields of sig_struct_var.
• Include a structure of signal data and a structure of parameter data in the same
parent structure.
• Nest structures while aggregating new data by default.
In the generated code, a flat parent structure, which corresponds to the structured
custom storage class, contains substructures, which correspond to each bus and
parameter structure. Choose one of these combined techniques:
• Apply the structured custom storage class directly to each bus and parameter
structure. For example, set the storage class of two nonvirtual bus signals to Struct.
Each bus appears in the generated code as a field (substructure) of a single structure.
• Leave the storage class of each bus and parameter structure at the default setting,
Auto, or at Model default, which prevents code generation optimizations from
eliminating the bus or parameter structure. Then, configure default storage classes
such that signal data and parameter data use the structured custom storage class by
default.
Arrays of Structures
You can further package multiple consistent bus signals or parameter structures into an
array. The array of buses or parameter structures appears in the generated code as an
array of structures. To create arrays of buses, see “Combine Buses into an Array of
Buses” (Simulink). To create arrays of parameter structures, see “Group Multiple
Parameter Structures into an Array” (Simulink).
Structure Padding
By default, the code generator does not explicitly add padding fields to structure types.
Structure types can appear in the generated code through, for example, the standard data
22-194
See Also
structures (see “Standard Data Structures in the Generated Code” (Simulink Coder)),
Simulink.Bus objects, and parameter structures that you use in a model.
However, when you use a code replacement library with Embedded Coder, you can specify
data alignment (including structure padding) as part of the replacement library. For more
information, see “Provide Data Alignment Specifications for Compilers” on page 54-138.
Limitations
• With built-in Simulink Coder and Embedded Coder features, you cannot generate or
use a custom structure that contains a field whose value is a pointer. You can do so
manually by creating an advanced custom storage class and writing accompanying
TLC code (see “Finely Control Data Representation by Writing TLC Code for a Custom
Storage Class” on page 26-39).
• You cannot use the built-in storage class Struct, or any structured storage class that
you create with the Custom Storage Class Designer (you set the storage class property
Type to FlatStructure), to set data defaults in the Code Mapping Editor.
See Also
Simulink.Bus
Related Examples
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” (Simulink Coder)
• “Environment for Configuring Model Data and Functions for Code Generation” on
page 21-2
• “Control Data and Function Placement in Memory by Inserting Pragmas” on page
30-2
• “Composite Signal Techniques” (Simulink)
22-195
22 Data Representation in Simulink Coder
open_system('sldemo_fuelsys_dd_controller')
This model represents the fueling system of a gasoline engine. The output of the model is
the rate of fuel flow to the engine.
open_system(['sldemo_fuelsys_dd_controller/fuel_calc/',...
'switchable_compensation'])
22-196
Switch Between Sets of Parameter Values During Simulation and Code Execution
This subsystem corrects and filters noise out of the fuel rate signal. The subsystem uses
different filter coefficients based on the fueling mode, which the control logic changes
based on sensor failures in the engine. For example, the control algorithm activates the
low_mode subsystem during normal operation. It activates the rich_mode subsystem in
response to sensor failure.
open_system(['sldemo_fuelsys_dd_controller/fuel_calc/',...
'switchable_compensation/low_mode'])
22-197
22 Data Representation in Simulink Coder
The Discrete Filter block filters the fuel rate signal. In the block dialog box, the
Numerator parameter sets the numerator coefficients of the filter.
The sibling subsystem rich_mode also contains a Discrete Filter block, which uses
different coefficients.
Update the model diagram to display the signal data types. The input and output signals
of the block use the single-precision, floating-point data type single.
In the lower-left corner of the model, click the data dictionary badge. The data dictionary
for this model, sldemo_fuelsys_dd_controller.sldd, opens in the Model Explorer.
In the Model Explorer Model Hierarchy pane, select the Design Data node.
In the Contents pane, view the properties of the Simulink.NumericType objects, such
as s16En15. All of these objects currently represent the single-precision, floating-point
data type single. The model uses these objects to set signal data types, including the
input and output signals of the Discrete Filter blocks.
Suppose that during simulation and execution of the generated code, you want each of
these subsystems to switch between different numerator coefficients based on a variable
whose value you control.
22-198
Switch Between Sets of Parameter Values During Simulation and Code Execution
lowBlock = ['sldemo_fuelsys_dd_controller/fuel_calc/'...
'switchable_compensation/low_mode/Discrete Filter'];
richBlock = ['sldemo_fuelsys_dd_controller/fuel_calc/'...
'switchable_compensation/rich_mode/Discrete Filter'];
params.lowNumerator = eval(get_param(lowBlock,'Numerator'));
params.richNumerator = eval(get_param(richBlock,'Numerator'));
params = Simulink.Parameter(params);
Copy the value of params into a temporary variable. Modify the field values in this
temporary structure, and assign the modified structure as the second element of params.
temp = params.Value;
temp.lowNumerator = params.Value.lowNumerator * 2;
temp.richNumerator = params.Value.richNumerator * 2;
params.Value(2) = temp;
clear temp
The value of params is an array of two structures. Each structure stores one set of filter
coefficients.
Ctrl = Simulink.Parameter(2);
Ctrl.DataType = 'uint8';
In the low_mode subsystem, in the Discrete Filter block dialog box, set the Numerator
parameter to the expression params(Ctrl).lowNumerator.
set_param(lowBlock,'Numerator','params(Ctrl).lowNumerator');
In the Discrete Filter block in the rich_mode subsystem, set the value of the Numerator
parameter to params(Ctrl).richNumerator.
set_param(richBlock,'Numerator','params(Ctrl).richNumerator');
The expressions select one of the structures in params by using the variable Ctrl. The
expressions then dereference one of the fields in the structure. The field value sets the
values of the numerator coefficients.
To switch between the sets of coefficients, you change the value of Ctrl to the
corresponding index in the array of structures.
22-199
22 Data Representation in Simulink Coder
Optionally, create a Simulink.Bus object to use as the data type of the array of
structures. You can:
Use the function Simulink.Bus.createObject to create the object and rename the
object as paramsType.
Simulink.Bus.createObject(params.Value)
paramsType = slBus1;
clear slBus1
You can use the Simulink.NumericType objects from the data dictionary to control the
data types of the structure fields. In the bus object, use the name of a data type object to
set the DataType property of each element.
paramsType.Elements(1).DataType = 's16En15';
paramsType.Elements(2).DataType = 's16En7';
Use the bus object as the data type of the array of structures.
Optionally, use an enumerated type as the data type of the switching variable. You can
associate each of the parameter sets with a meaningful name and restrict the allowed
values of the switching variable.
Simulink.defineIntEnumType('FilterCoeffs',{'Weak','Aggressive'},[1 2])
Use the enumerated type as the data type of the switching variable. Set the value of the
variable to Aggressive, which corresponds to the index 2.
Ctrl.Value = FilterCoeffs.Aggressive;
22-200
Switch Between Sets of Parameter Values During Simulation and Code Execution
You can also store enumerated types in data dictionaries. However, you cannot import the
enumerated type in this case because you cannot save changes to
sldemo_fuelsys_dd_controller.sldd. For more information about storing
enumerated types in data dictionaries, see “Enumerations in Data Dictionary” (Simulink).
Open the example model sldemo_fuelsys_dd, which references the controller model
sldemo_fuelsys_dd_controller.
open_system('sldemo_fuelsys_dd')
22-201
22 Data Representation in Simulink Coder
Set the simulation stop time to Inf so that you can interact with the model during
simulation.
Begin a simulation run and open the Scope block dialog box. The scope shows that the
fuel flow rate (the fuel signal) oscillates with significant amplitude during normal
operation of the engine.
Update the sldemo_fuelsys_dd model diagram. The scope shows that the amplitude of
the fuel rate oscillations decreases due to the less aggressive filter coefficients.
If you have Simulink Coder software, you can generate code that enables you to switch
between the parameter sets during code execution.
Use the StorageClass column to apply the storage class ExportedGlobal to params so
that the array of structures appears as a tunable global variable in the generated code.
Apply the same storage class to Ctrl so that you can change the value of the switching
variable during code execution.
tempEntryObj = getEntry(sectObj,'params');
params = getValue(tempEntryObj);
params.StorageClass = 'ExportedGlobal';
setValue(tempEntryObj,params);
tempEntryObj = getEntry(sectObj,'Ctrl');
Ctrl = getValue(tempEntryObj);
Ctrl.StorageClass = 'ExportedGlobal';
setValue(tempEntryObj,Ctrl);
22-202
Switch Between Sets of Parameter Values During Simulation and Code Execution
rtwbuild('sldemo_fuelsys_dd_controller')
#ifndef DEFINED_TYPEDEF_FOR_FilterCoeffs_
#define DEFINED_TYPEDEF_FOR_FilterCoeffs_
typedef enum {
Weak = 1, /* Default value */
Aggressive
} FilterCoeffs;
#endif
The code also defines the structure type paramsType, which corresponds to the
Simulink.Bus object. The fields use the single-precision, floating-point data type from
the model.
rtwdemodbtype(file,'#ifndef DEFINED_TYPEDEF_FOR_paramsType_',...
'#ifndef DEFINED_TYPEDEF_FOR_FilterCoeffs_',1,0)
#ifndef DEFINED_TYPEDEF_FOR_paramsType_
#define DEFINED_TYPEDEF_FOR_paramsType_
typedef struct {
real32_T lowNumerator[2];
real32_T richNumerator[2];
} paramsType;
#endif
22-203
22 Data Representation in Simulink Coder
file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',...
'sldemo_fuelsys_dd_controller.c');
rtwdemodbtype(file,'FilterCoeffs Ctrl = Aggressive;',...
'/* Block signals (default storage) */',1,0)
{ 0.0F, 0.2592F }
}, { { 17.5392F, -17.0208F },
{ 0.0F, 0.5184F }
} } ; /* Variable: params
The code algorithm in the model step function uses the switching variable to index into
the array of structures.
To switch between the parameter sets stored in the array of structures, change the value
of Ctrl during code execution.
See Also
Related Examples
• “Tune and Experiment with Block Parameter Values” (Simulink)
• “Create Tunable Calibration Parameter in the Generated Code” (Simulink Coder)
• “Organize Related Block Parameter Definitions in Structures” (Simulink)
22-204
See Also
• “Access Structured Data Through a Pointer That External Code Defines” on page 26-
12
22-205
22 Data Representation in Simulink Coder
At the top level of a model, Inport and Outport blocks represent the input and output
signals of the model. To customize the data interface in the generated code, configure
these blocks. Early in the design process, when a model can contain unconnected Inport
and Outport blocks, use this technique to specify the interface before developing the
internal algorithm.
When you apply storage classes to Inport and Outport blocks, each block appears in the
generated code as a field of a global structure or as a separate global variable that the
generated algorithm references directly. If you have Embedded Coder, you can use
function prototype control instead of storage classes to pass data into and out of the
model step function as formal parameters. See “Customize Generated C Function
Interfaces” on page 29-2.
open_system('rtwdemo_basicsc')
22-206
Design Data Interface by Configuring Inport and Outport Blocks
set_param('rtwdemo_basicsc','HideAutomaticNames','off')
In the Model Data Editor, select the Inports/Outports tab. Each row in the table
represents an Outport block or a signal that exits an Inport block.
Name the signal data that the Outport block Out1 represents. Set Signal Name to
output_sig.
For each of the signals that exit the Inport blocks, set Data Type to single or to a
different data type. Due to the data type inheritance settings that the other blocks in the
model use by default, downstream signals in the rest of the model use the same or a
similar data type.
Optionally, configure other design attributes such as Min and Max (minimum and
maximum values).
22-207
22 Data Representation in Simulink Coder
For the Outport block and all of the Inport blocks, set Storage Class to
ExportedGlobal. To configure all of the blocks at once, select all of the rows in the
table.
To configure the blocks and signals, you can use these commands at the command
prompt.
portHandles = get_param('rtwdemo_basicsc/In1','portHandles');
outPortHandle = portHandles.Outport;
set_param(outPortHandle,'StorageClass','ExportedGlobal');
portHandles = get_param('rtwdemo_basicsc/In2','portHandles');
outPortHandle = portHandles.Outport;
set_param(outPortHandle,'StorageClass','ExportedGlobal');
portHandles = get_param('rtwdemo_basicsc/In3','portHandles');
outPortHandle = portHandles.Outport;
set_param(outPortHandle,'StorageClass','ExportedGlobal');
portHandles = get_param('rtwdemo_basicsc/In4','portHandles');
outPortHandle = portHandles.Outport;
set_param(outPortHandle,'StorageClass','ExportedGlobal');
set_param('rtwdemo_basicsc/Out1','SignalName','output_sig',...
'StorageClass','ExportedGlobal')
View the generated file rtwdemo_basicsc.c. Because you applied the storage class
ExportedGlobal to the Inport and Outport blocks, the code creates separate global
variables that represent the inputs and the output.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* Exported block signals */','real32_T output_sig;',1,1)
22-208
Design Data Interface by Configuring Inport and Outport Blocks
The generated algorithm in the model step function directly references these global
variables to calculate and store the output signal value, output_sig.
While you use the Model Data Editor to configure the interface of a system, consider
using the interface display to view the system inputs and outputs (Inport and Outport
blocks) at a high level. See “Configure Data Interface for Component” (Simulink).
If you have Embedded Coder, you can configure a default storage class for Inport blocks
and Outport blocks. As you add such blocks to the model, they acquire the storage class
that you specify.
In the model, set Configuration Parameters > Code Generation > System target file
to ert.tlc.
In the model, select Code > C/C++ Code > Configure Model in Code Perspective.
Underneath the block diagram, under Code Mappings > Data Defaults, for the Inports
and Outports rows, set Storage Class to ExportedGlobal.
Underneath the block diagram, open the Model Data Editor by clicking the Model Data
Editor tab.
Use the Model Data Editor to set the storage class of the Inport and Outport blocks to
Auto. With this setting, the blocks acquire the default storage classes that you specified
in Code Mappings > Data Defaults.
With Auto, the global variables that correspond to the Inport and Outport blocks are
subject to a naming rule that you specify in the model configuration parameters. By
default, the naming rule adds the name of the model to the name of each variable. To
remove the model name, change the value of Configuration Parameters > Code
Generation > Symbols > Global variables from $R$N$M to $N$M. The token $R
represents the model name.
Alternatively, to configure the data defaults and the configuration parameter, at the
command prompt, use these commands:
22-209
22 Data Representation in Simulink Coder
set_param('rtwdemo_basicsc','SystemTargetFile','ert.tlc')
coder.mapping.create('rtwdemo_basicsc')
coder.mapping.defaults.set('rtwdemo_basicsc','Inports',...
'StorageClass','ExportedGlobal')
coder.mapping.defaults.set('rtwdemo_basicsc','Outports',...
'StorageClass','ExportedGlobal')
portHandles = get_param('rtwdemo_basicsc/In1','portHandles');
outPortHandle = portHandles.Outport;
set_param(outPortHandle,'StorageClass','Auto');
portHandles = get_param('rtwdemo_basicsc/In2','portHandles');
outPortHandle = portHandles.Outport;
set_param(outPortHandle,'StorageClass','Auto');
portHandles = get_param('rtwdemo_basicsc/In3','portHandles');
outPortHandle = portHandles.Outport;
set_param(outPortHandle,'StorageClass','Auto');
portHandles = get_param('rtwdemo_basicsc/In4','portHandles');
outPortHandle = portHandles.Outport;
set_param(outPortHandle,'StorageClass','Auto');
set_param('rtwdemo_basicsc/Out1','SignalName','output_sig',...
'StorageClass','Auto')
set_param('rtwdemo_basicsc','CustomSymbolStrGlobalVar','$N$M')
You can route a single signal to multiple Outport blocks and apply a different storage
class to each Outport. For example, use this technique to send signal data to a custom
function (such as a device driver) and to a global variable that your custom algorithmic
code can use:
22-210
See Also
open_system('ex_route_sig')
Limitations
You cannot apply a storage class to an Outport block if the input to the block has a
variable size. Instead, apply the storage class to the signal line.
See Also
Related Examples
• “Analyze the Generated Code Interface” on page 38-19
• “Trace Connections Using Interface Display” (Simulink)
• “Interface Design” (Simulink)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Configure Generated Code According to Interface Control Document Interactively”
on page 26-73
• “Customize Generated C Function Interfaces” on page 29-2
• “Configure Data Properties by Using the Model Data Editor” (Simulink)
• “Replace and Rename Data Types to Conform to Coding Standards” on page 24-27
22-211
22 Data Representation in Simulink Coder
In a model, you use bus signals to package multiple signals together into a single signal
line. You can create virtual or nonvirtual bus signals. The representation in the generated
code depends on:
• For a virtual bus, the generated code appears as if the bus did not exist.
• Generated code for a nonvirtual bus represents the bus data with a structure. When
you want to trace the correspondence between the model and the code, the use of a
structure in the generated code can be helpful. To generate structures using
nonvirtual bus signals, see “Organize Data into Structures in Generated Code” on
page 22-177.
For general information about buses, see and “Virtual and Nonvirtual Buses” (Simulink).
To generate efficient code from models that contain bus signals, eliminate unnecessary
data copies by following best practices as you construct the model.
• Setting bus diagnostic configuration parameters can make model development easier.
• The bus implementation techniques, and the choice of a nonvirtual or virtual bus, can
influence the speed, size, and clarity of the generated code.
• Some useful bus implementation techniques are not immediately obvious.
When you work with buses, these guidelines help you to improve the results. The
guidelines describe techniques to:
22-212
Generate Efficient Code for Bus Signals
There are some trade-offs among speed, size, and clarity. For example, the code for
nonvirtual buses is easier to read because the buses appear in the code as structures, but
the code for virtual buses is faster because virtual buses do not require copying signal
data. Apply some of the guidelines based on where you are in the application development
process.
22-213
22 Data Representation in Simulink Coder
Buses can contain subordinate buses. To generate efficient code, set the storage classes
of subordinate buses to Auto. Setting the storage class to Auto eliminates:
• Allocation of redundant memory for the subordinate bus signal and for the parent bus
signal
• Additional copy operations (copying data to the subordinate bus, and then copying
from the subordinate bus to the final bus)
This model contains nonvirtual bus signals. The subordinate bus signals Sub_Bus_1 and
Sub_Bus_2 use the storage class Auto.
The generated code algorithm efficiently assigns the input signal data to the bus signals.
void ex_nonvirtual_buses_step(void)
{
Nonvirtual_In_One.SimpleBus_1.A1 = A1;
Nonvirtual_In_One.SimpleBus_1.A2 = A2;
Nonvirtual_In_One.SimpleBus_2.A3 = A3;
Nonvirtual_In_One.SimpleBus_2.A4 = A4;
Nonvirtual_In_One.A5 = A5;
}
22-214
See Also
See Also
Simulink.Bus
Related Examples
• “Organize Data into Structures in Generated Code” on page 22-177
• “Specify Sample Times for Signal Elements” (Simulink)
22-215
22 Data Representation in Simulink Coder
For basic information about specifying initial values for signals and discrete states in a
model, see “Initialize Signals and Discrete States” (Simulink).
• RSim executables can use the Data Import/Export pane of the Configuration
Parameters dialog box to load input values from MAT-files. GRT and ERT executables
cannot load input values from MAT-files.
• The initial value for a block output signal or root level input or output signal can be
overwritten by an external (calling) program.
• Setting the initial value for persistent signals is relevant if the value is used or viewed
by an external application.
When you generate code, initialization statements are placed in model.c or model.cpp
in the model's initialize code.
22-216
Control Signal and State Initialization in the Generated Code
If you create and initialize signal objects in the base workspace, the code generator
places initialization code for the signals in the file rtwdemo_sigobj_iv.c under the
rtwdemo_sigobj_iv_initialize function, as shown below.
/* Model initialize function */
void rtwdemo_sigobj_iv_initialize(void)
{
.
.
.
/* exported global signals */
S3 = -3.0;
S2 = -2.0;
.
.
.
/* exported global states */
X1 = 0.0;
X2 = 0.0;
/* external inputs */
S1 = -4.5;
.
.
.
The following code shows the initialization code for the enabled subsystem's Unit Delay
block state X1 and output signal S2.
void MdlStart(void) {
.
.
.
/* InitializeConditions for UnitDelay: '<S2>/Unit Delay' */
X1 = aa1;
22-217
22 Data Representation in Simulink Coder
S2 = aa2;
For an enabled subsystem, the initial value is also used as a reset value if the subsystem's
Outport block parameter Output when disabled is set to reset. The following code
from rtwdemo_sigobj_iv.c shows the assignment statement for S3 as it appears in the
model output function rtwdemo_sigobj_iv_output.
/* Model output function */
S2 = aa2;
If you set Configuration Parameters > Optimization > Default parameter behavior
to Tunable, initial conditions appear as tunable fields of the global parameters structure.
Whether you set Default parameter behavior to Tunable or Inlined, you can use a
tunable parameter to specify the InitialValue property of a signal object or the Initial
condition parameter of a block. For basic information about tunable parameters, see
“Create Tunable Calibration Parameter in the Generated Code” (Simulink Coder).
This example shows how to use tunable parameters to specify initial conditions for signals
and states.
Open the example model rtwdemo_sigobj_iv and configure it to show the generated
names of blocks. The signal S2 uses a Simulink.Signal object in the base workspace.
22-218
Control Signal and State Initialization in the Generated Code
Double-click the Simulink.Signal object S2 to view its properties. The Initial value
property is set to aa2. The object uses the variable aa2 to specify an initial condition for
the signal S2. The Storage class property is set to ExportedGlobal. To use a
Simulink.Signal object to initialize a signal, the signal object must use a storage class
other than Auto or, if the corresponding data category in the Code Mapping Editor uses a
storage class setting other than Default, Model default.
On the Optimization pane, in the Configuration Parameters dialog box, click Configure.
The variable aa2 is a tunable parameter that uses the storage class ExportedGlobal.
In the model, open the Enabled Subsystem. In the Outport block dialog box, the
parameter Output when disabled is set to reset. When the subsystem becomes
disabled, the output signal S2 resets to the initial value aa2.
Open the Unit Delay block dialog box. On the State Attributes tab, the State name box
is set to X1.
Open the Enable block dialog box. The parameter States when enabling is set to reset.
When the subsystem transitions from a disabled state to an enabled state, it resets
internal block states, such as X1, to their initial values.
22-219
22 Data Representation in Simulink Coder
Double-click the Simulink.Parameter object aa1 to view its properties. The Storage
class property is set to ExportedGlobal. You can generate tunable initial conditions for
block states by using tunable parameters such as aa1 and Simulink.Signal objects
such as X1.
In the code generation report, view the file rtwdemo_sigobj_iv.c. The code uses
global variables to represent the block state X1 and the signal S2.
The code uses global variables to represent the tunable parameters aa1 and aa2.
The model initialization function uses the tunable parameter aa1 to initialize the state X1.
The function also uses the tunable parameter aa2 to initialize the signal S2.
22-220
Control Signal and State Initialization in the Generated Code
S2 = aa2;
In the model step function, when the Enabled Subsystem transitions from a disabled state
to an enabled state, the Unit Delay block state X1 resets to its initial value.
if (rtb_PulseGenerator > 0) {
if (!rtwdemo_sigobj_iv_DW.EnabledSubsystemstateX1inside_M) {
/* InitializeConditions for UnitDelay: '<S2>/Unit Delay' */
X1 = aa1;
rtwdemo_sigobj_iv_DW.EnabledSubsystemstateX1inside_M = true;
}
If the Enabled Subsystem becomes disabled during code execution, the algorithm uses
the tunable initial condition aa2 to set the value of the signal S2.
} else {
if (rtwdemo_sigobj_iv_DW.EnabledSubsystemstateX1inside_M) {
/* Disable for Outport: '<S2>/Out1' */
S2 = aa2;
rtwdemo_sigobj_iv_DW.EnabledSubsystemstateX1inside_M = false;
}
}
If you set Configuration Parameters > Optimization > Default parameter behavior
to Tunable, the initial condition appears as a tunable substructure of the global
parameters structure.
Whether you set Default parameter behavior to Tunable or Inlined, you can specify
the initial condition by using a tunable Simulink.Parameter object whose value is a
structure. If you apply a storage class other than Auto to the parameter object, the
structure is tunable in the generated code.
To generate efficient code by avoiding data type mismatches between the structure and
the bus signal, use either:
22-221
22 Data Representation in Simulink Coder
• Typed expressions to specify the values of the structure fields. Match the data type of
each field with the data type of the corresponding signal element.
• A Simulink.Bus object to control the data types of the structure fields and the signal
elements.
For basic information about using structures to initialize bus signals, and to decide how to
control field data types, see “Specify Initial Conditions for Bus Signals” (Simulink).
This example shows how to use a tunable structure parameter to initialize a virtual bus
signal.
On the Inports/Outports tab, the Data Types column shows that each Inport block in
the model uses a different output data type.
Open the Bus Creator block dialog box. The block output is a virtual bus.
In the Configuration Parameters dialog box, open the Optimization pane. The
configuration parameter Default parameter behavior is set to Tunable. By default,
block parameters, including initial conditions, appear in the generated code as tunable
fields of the global parameters structure.
22-222
Control Signal and State Initialization in the Generated Code
For the Unit Delay block, set Initial Value to a structure that specifies an initial condition
for each of the three signal elements. To generate efficient code, match the data types of
the structure fields with the data types of the corresponding signal elements. For
example, set Initial Value to the expression struct('thermocpl',
15.23,'magFlow',uint32(79),'posSwitch',false).
set_param('rtwdemo_tunable_init_struct/Unit Delay','InitialCondition',...
'struct(''thermocpl'',15.23,''magFlow'',uint32(79),''posSwitch'',false)')
#ifndef DEFINED_TYPEDEF_FOR_struct_mqGi1jsItE0G7cf1bNqMu_
#define DEFINED_TYPEDEF_FOR_struct_mqGi1jsItE0G7cf1bNqMu_
typedef struct {
real_T thermocpl;
uint32_T magFlow;
boolean_T posSwitch;
} struct_mqGi1jsItE0G7cf1bNqMu;
struct P_rtwdemo_tunable_init_struct_T_ {
struct_mqGi1jsItE0G7cf1bNqMu UnitDelay_InitialCondition;/* Mask Parameter: UnitDelay_
22-223
22 Data Representation in Simulink Coder
P_rtwdemo_tunable_init_struct_T rtwdemo_tunable_init_struct_P = {
/* Mask Parameter: UnitDelay_InitialCondition
* Referenced by:
* '<Root>/Unit Delay'
* '<Root>/Unit Delay'
* '<Root>/Unit Delay'
*/
{
15.23,
79U,
0
},
If you create a bus object, you can use it to specify the data type of the bus signal and the
tunable initial condition structure. Before code generation, the Simulink.Parameter
object casts the values of the structure fields to the data types of the signal elements. For
basic information about creating bus objects and using them in models, see “When to Use
Bus Objects” (Simulink).
22-224
Control Signal and State Initialization in the Generated Code
In the model, open the Model Data Editor (View > Model Data Editor). The Inports/
Outports tab shows that for the Inport block DataIn, the output data type (Data Type
column) is set to Bus: ComponentData.
At the command prompt, create the structure parameter initStruct. You can specify
the field values by using untyped expressions. To improve readability, specify the field
posSwitch with a Boolean value.
initStruct = struct(...
'thermocpl',15.23,...
'magFlow',79,...
'posSwitch',false ...
);
initStruct = Simulink.Parameter(initStruct);
In the model, click the Unit Delay block. The Model Data Editor highlights the row that
corresponds to the Initial condition parameter of the block.
In the Model Data Editor, set the parameter value (Value column) to initStruct.
22-225
22 Data Representation in Simulink Coder
Use the Data Type column to set the data type of initStruct to Bus:
ComponentData.
Use the Storage Class column to apply the storage class ExportedGlobal to
initStruct.
initStruct.StorageClass = 'ExportedGlobal';
#ifndef DEFINED_TYPEDEF_FOR_ComponentData_
#define DEFINED_TYPEDEF_FOR_ComponentData_
typedef struct {
real_T thermocpl;
uint32_T magFlow;
boolean_T posSwitch;
} ComponentData;
22-226
See Also
The model initialization function uses the structure fields to initialize the block states.
To change the data type of any of the three signal elements, specify the new type in the
bus object. The signal element in the model uses the new type. Before simulation and
code generation, the parameter object initStruct casts the corresponding structure
field to the new type.
See Also
State Reader | State Writer
Related Examples
• “Initialization Behavior Summary for Signal Objects” (Simulink)
• “Specify Initial Conditions for Bus Signals” (Simulink)
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements” on
page 22-81
• “Generate Code That Responds to Initialize, Reset, and Terminate Events” on page
9-2
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Initialization of Signal, State, and Parameter Data in the Generated Code” on page
22-228
• “Remove Initialization Code” on page 59-4
22-227
22 Data Representation in Simulink Coder
• Model a system that reinitializes states during execution, which means that the
application can restart the entire system.
• Store initial values in memory as variables, which can persist between execution runs.
You can then overwrite these values before starting or restarting a system.
• Generate efficient code by eliminating storage for invariant initial values and by
preventing the generation of code that unnecessarily or redundantly initializes data.
For basic information about initializing signals and states in a model, see “Initialize
Signals and Discrete States” (Simulink) and “Load State Information” (Simulink).
• Static initialization occurs in the same statement that defines (allocates memory for)
the variable. The initialization does not occur inside a function definition.
The code can be more efficient because none of the generated model functions
execute initialization statements.
• Dynamic initialization occurs inside a function. For each model or nonvirtual
subsystem, the code generator typically creates one or more functions that are
dedicated to initialization.
The generated code or your code can restart a system by calling the initialization
function or functions at any time during execution.
22-228
Initialization of Signal, State, and Parameter Data in the Generated Code
For some kinds of data, to represent a real-world ground value, a computer stores zero in
memory (all bits zero). However, for some other data, a computer stores a nonzero value
in memory. This data includes, for example:
• Fixed-point data with bias. The code initializes such a data item to the stored integer
value that, given the scaling and bias, represents real-world zero.
• An enumeration whose default member maps to an integer value other than zero. For
example, if the default member is High with an underlying integer value of 3, the code
initializes such a data item to High.
You can also initialize states by using State Writer blocks in Initialize Function
subsystems and the Initial states model configuration parameter.
By default, the generated code dynamically initializes signal and state data (and other
data, such as the model error status) in the generated initialization function. The function,
named model_initialize by default, performs signal and state initialization operations
in this order:
1 Initializes all of the signal and state data in the default generated structures, such as
the DWork structure, to a stored value of zero.
2 Initializes additional signal and state data that are not in the default generated
structures to the relevant real-world ground value.
This initialization applies only to data that meet both of these criteria:
22-229
22 Data Representation in Simulink Coder
For example, the code applies this operation to data items that use the storage class
ExportedGlobal.
3 Initializes each signal and state to the real-world value that the model specifies, for
example, through the Initial condition parameter of a Unit Delay block.
4 Initializes each state to the real-world value that you assign by using a State Writer
block. The function performs this initialization only if you use an Initialize Function
subsystem in the model.
5 Initializes each state to the real-world value that you specify with the configuration
parameter Initial states.
After this initialization function executes, each data item has the last real-world value that
the function assigned. For example, if you use a State Writer block to initialize a block
state to 5 while also using the Initial states configuration parameter to initialize the
same state to 10, the state ultimately uses 10 as an initial value.
To initialize signal or state data items that have contiguous storage to a stored value of
zero, the generated code can call memset in an initialization function. Data items that
have contiguous storage include the DWork structure, arrays, or data items that use a
multiword data type.
If your application requires it, you can prevent the generated code from using memset for
initializing floating-point data to stored zero. See “Use memset to initialize floats and
doubles to 0.0” (Simulink Coder).
You can configure the way that tunable block parameters, such as the Gain parameter of
a Gain block, appear in the generated code. Most block parameters that set initial values
(for example, Initial condition) are tunable. For example, the configuration parameter
Default parameter behavior can determine whether the initial values appear in the
generated code as inlined constants or as tunable global data. You can also use parameter
objects and storage classes to control the representation of these initial values.
22-230
Initialization of Signal, State, and Parameter Data in the Generated Code
For tunable initial values, in the model initialization function, the right-hand side of the
assignment statement is a global variable, structure field, or other data whose value you
can change in memory.
To make initial values tunable in the generated code, see “Control Signal and State
Initialization in the Generated Code” on page 22-216.
• Tunable block parameters, such as the Gain parameter of a Gain block, when you set
Default parameter behavior to Tunable. Each parameter appears as a field of a
dedicated global structure.
• Some tunable block parameters when you set Default parameter behavior to
Inlined. When the code generator cannot inline the value of a parameter as a literal
number, the parameter appears as a field of a dedicated global const structure.
• Simulink.Parameter objects to which you apply a storage class or custom storage
class that has an exported data scope. For example, the built-in storage class
ExportedGlobal has an exported data scope, but the storage class
ImportedExtern does not.
If you use this technique with Embedded Coder, you can generate code that initializes the
corresponding parameter data (global variable) by using the specified expression. For an
example, see “Initialize Parameter Value From System Constant or Other Macro
22-231
22 Data Representation in Simulink Coder
(Embedded Coder)” on page 22-129. For general information, including limitations, see
“Code Generation of Parameter Objects With Expression Values” (Simulink Coder).
open_system('rtwdemo_rtwintro')
22-232
Initialization of Signal, State, and Parameter Data in the Generated Code
In the Model Data Editor, inspect the States tab. For the Unit Delay block state, the
Initial Value is set to 0, the default, which means the initial value of the state is zero.
The state is named X.
set_param('rtwdemo_rtwintro/X','InitialCondition','5')
In the data table, set Storage Class to ExportedGlobal. With this setting, the block
state appears in the generated code as a separate global variable.
set_param('rtwdemo_rtwintro/X','StateStorageClass','ExportedGlobal')
In the Model Data Editor, inspect the Parameters tab and set the Change view drop-
down list to Design. To set and inspect initial values of signals and states, you can use
the Parameters tab instead of the States tab.
The Model Data Editor shows that for the Outport block, the Initial output
(InitialOutput) parameter is set to 0, the default. This subsystem output requires an
initial value because the subsystem executes conditionally. Leave the initial value at the
default.
In the model, clear Configuration Parameters > Signal storage reuse. When you
clear this setting, signal lines appear in the generated code as fields of a generated
structure whose purpose is to store signal data. This representation of the signals makes
it easier to see how the code generator initializes data.
set_param('rtwdemo_rtwintro','OptimizeBlockIOStorage','off')
In the Model Data Editor, click the Show/refresh additional information button.
Near the Filter contents box, click the Filter using selection button.
22-233
22 Data Representation in Simulink Coder
In the model, click the Constant block labeled INC. The Model Data Editor shows that the
Constant value (Value) parameter of the block is set to INC. INC is a MATLAB variable
in the base workspace.
Use the Storage Class column to apply the storage class ExportedGlobal to INC. With
this setting, the generated code defines INC as a global variable. Concerning
initialization, INC is an item of parameter data.
INC = Simulink.Parameter(INC);
INC.StorageClass = 'ExportedGlobal';
rtwbuild('rtwdemo_rtwintro');
In the generated file rtwdemo_rtwintro.c, outside the definition of any function, the
code statically initializes the parameter data INC. The value of INC is 1.
file = fullfile('rtwdemo_rtwintro_grt_rtw','rtwdemo_rtwintro.c');
rtwdemodbtype(file,'/* Exported block parameters */','uint8_T INC = 1U;',1,1)
/* block I/O */
(void) memset(((void *) &rtwdemo_rtwintro_B), 0,
sizeof(B_rtwdemo_rtwintro_T));
22-234
Initialization of Signal, State, and Parameter Data in the Generated Code
The function then initializes the Unit Delay state, X, to the appropriate ground value. In
this case, the ground value is zero.
The function also initializes other data, including the root-level inputs and outputs (Inport
and Outport blocks), to the appropriate ground values.
/* external inputs */
rtwdemo_rtwintro_U.Input = 0;
/* external outputs */
rtwdemo_rtwintro_Y.Output = 0;
rtwdemo_rtwintro_PrevZCX.Amplifier_Trig_ZCE = POS_ZCSIG;
The function then initializes X to the value that you specified in the Initial condition
block parameter.
22-235
22 Data Representation in Simulink Coder
For some data, even if the real-world initial value is zero, a computer stores a nonzero
value in memory. To observe this difference, apply a slope-bias fixed-point data type to the
block state, X. To run this example, you must have Fixed-Point Designer™.
In the model, click the output signal of the Switch block, switch_out.
Use the Data Type column of the Model Data Editor to set the signal data type to
fixdt(1,16,1,3). This expression represents a fixed-point data type with a slope of 1
and a bias of 3.
set_param('rtwdemo_rtwintro/Switch','OutDataTypeStr',...
'fixdt(1,16,1,3)')
In the model, select View > Property Inspector and click the Sum block.
In the Property Inspector, under Signal Attributes, clear Require all inputs to have
the same data type.
set_param('rtwdemo_rtwintro/Sum','InputSameDT','off')
The model initialization function first initializes X to the appropriate real-world ground
value, 0. Due to the slope-bias data type, which has bias 3, this real-world value
corresponds to a stored value of -3.
rtwdemodbtype(file,'/* exported global states */','X = -3;',1,1)
22-236
Initialization of Signal, State, and Parameter Data in the Generated Code
The function then initializes X to the real-world initial value that you specified in the
Initial condition block parameter, 5. This real-world value corresponds to a stored value
of 2.
Modeling Goals
Goal More Information
Explicitly model You can explicitly model initialization and reset behavior by using
initialization Initialize Function and Reset Function subsystems. In the
behavior by using subsystems, use State Writer blocks to calculate and assign an initial
blocks value for a state dynamically. The corresponding code appears in the
model initialization function.
• Data for which you specify a nonzero initial value by using a block
parameter.
• Data whose real-world initial value is zero but whose
corresponding stored value is not zero.
• Enumerated data whose default member maps to a nonzero
integer.
22-237
22 Data Representation in Simulink Coder
• The generated code does not initialize parameter data. Your code
must initialize imported parameter data.
• The generated initialization functions dynamically initialize some
signal and state data. Unlike data that the generated code
allocates, the code does not initialize imported signal or state
data to a stored value of zero. Instead, the code immediately
initializes the data to the real-world value that you specify in
Simulink.
See Also
model_initialize
Related Examples
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
22-238
Optimize Speed and Size of Signal Processing Algorithm by Using Fixed-Point Data
22-239
22 Data Representation in Simulink Coder
See Also
More About
• “Fixed Point” (Simulink)
• “Acoustic Noise Cancellation (LMS)” (DSP System Toolbox)
22-240
Optimize Generated Code Using Fixed-Point Data with Simulink®, Stateflow®, and MATLAB®
open_system ('rtwdemo_fixpt1');
22-241
22 Data Representation in Simulink Coder
See Also
More About
• “Fixed Point” (Simulink)
22-242
Declare Workspace Variables as Tunable Parameters Using the Model Parameter Configuration Dialog Box
Note You cannot use the Model Parameter Configuration dialog box to declare tunable
parameters for a referenced model. Use Simulink.Parameter objects instead.
• Select MATLAB workspace to view all of the numeric variables that are defined in
the base workspace.
• Select Referenced workspace variables to view only the numeric variables
in the base workspace that the model uses. Selecting this option begins a diagram
update and a search for used variables, which can take time for a large model.
3 In the Model Parameter Configuration dialog box, under Source list, select one or
more workspace variables.
4 Click Add to table. The variables appear as tunable parameters under Global
(tunable) parameters, and appear in italic font under Source list.
5 Optionally, select a parameter under Global (tunable) parameters, and adjust the
code generation settings for the parameter. For more information about adjusting the
22-243
22 Data Representation in Simulink Coder
code generation options for tunable parameters, see “Set Tunable Parameter Code
Generation Options” on page 22-244
6 Click OK to apply your selection of tunable parameters and close the dialog box.
1 In the Configuration Parameters dialog box, on the Optimization > Signals and
Parameters pane, click Configure.
2 In the Model Parameter Configuration dialog box, under Global (tunable)
parameters, click New.
3 Under the Name column, specify a name for the new tunable parameter.
4 Optionally, adjust the code generation settings for the new parameter. For more
information about adjusting the code generation options for tunable parameters, see
“Set Tunable Parameter Code Generation Options” on page 22-244
5 Click OK to apply your changes and close the dialog box.
22-244
Declare Workspace Variables as Tunable Parameters Using the Model Parameter Configuration Dialog Box
Property Description
Storage class Select one of the following to use for code generation:
• Model default
• ExportedGlobal
• ImportedExtern
• ImportedExternPointer
When parameters are MATLAB workspace variables, the Model Parameter Configuration
dialog box is the recommended way to see or set the properties of tunable parameters. In
addition to that dialog box, you can also use MATLAB get_param and set_param
commands.
Note You can also use Simulink.Parameter objects for tunable parameters. See
“Create Tunable Calibration Parameter in the Generated Code” on page 22-121 for
details.
The following commands return the tunable parameters and corresponding properties:
22-245
22 Data Representation in Simulink Coder
• get_param(gcs,'TunableVars')
• get_param(gcs,'TunableVarsStorageClass')
• get_param(gcs,'TunableVarsTypeQualifier')
• set_param(gcs,'TunableVars',str)
• Auto
• ExportedGlobal
• ImportedExtern
• ImportedExternPointer
• set_param(gcs,'TunableVarsTypeQualifier',str)
The following example declares the variable k1 to be tunable, with storage class
ExportedGlobal and type qualifier const. The number of variables and number of
specified storage class settings must match. If you specify multiple variables and storage
class settings, separate them with a comma.
set_param(gcs,'TunableVars','k1')
set_param(gcs,'TunableVarsStorageClass','ExportedGlobal')
set_param(gcs,'TunableVarsTypeQualifier','const')
22-246
Share Data Between Code Generated from Simulink, Stateflow, and MATLAB
open_system('rtwdemo_dynamicio')
22-247
22 Data Representation in Simulink Coder
Instructions
1 Compile the model (Simulation > Update Diagram) and note the displayed signal
types and sizes.
2 Change the data type and/or size of the Constant block and recompile the model.
Note that the attributes of the signals automatically adapt to the Constant block
specification.
3 Generate and inspect code using the blue buttons in the model. Note that K is shared
by the Gain and sfVerticalSum block.
Notes
• The data type and size of all Stateflow and MATLAB data is inherited from Simulink.
• The Gain block and the Stateflow chart sfVerticalSum share the Simulink parameter K,
which is defined in the MATLAB workspace as a Simulink.Parameter with Model
default storage class (i.e., rtP.K in the generated code).
22-248
23
You can control the file placement of the variable definitions and declarations. Use the
information in the table.
23-2
Control Placement of Global Data Definitions and Declarations in Generated Files
23-3
23 Data Definition and Declaration Management in Embedded Coder
23-4
Control Placement of Global Data Definitions and Declarations in Generated Files
23-5
23 Data Definition and Declaration Management in Embedded Coder
23-6
Control Placement of Global Data Definitions and Declarations in Generated Files
23-7
23 Data Definition and Declaration Management in Embedded Coder
23-8
Control Placement of Global Data Definitions and Declarations in Generated Files
23-9
23 Data Definition and Declaration Management in Embedded Coder
Goal Technique
Establish ownership of global data by When you divide a system into components
placing the data definitions with the code by using referenced models and atomic
generated for specific components subsystems, by default, global data is
typically defined by the code generated for
the top component in the hierarchy. Global
data includes parameters, signals, and
states to which you apply storage classes
(see “Apply Storage Classes to Individual
Signal, State, and Parameter Data
Elements” on page 22-81).
23-10
Control Placement of Global Data Definitions and Declarations in Generated Files
Goal Technique
that model defines the data. You do not
need to specify an owner (Owner) for
the object.
• In an atomic subsystem, use a storage
class such as ExportToFile and
explicitly specify the name of the
definition file by using the Definition
file custom attribute. However, you
cannot place the definition file with the
source files that belong to the
subsystem. Instead, the definition file
that you specify appears in the folder
generated for the model.
For an atomic subsystem, place the By default, the standard data structures for
standard data structures for the subsystem an atomic subsystem appear as
with the subsystem code substructures of the data structures for the
entire model.
• The model configuration parameter File packaging format. The setting that you
choose determines whether the code generator places the standard structures that
store tunable and constant parameter data in model_data.c instead of model.c. See
“File packaging format”.
• The Code Mapping Editor. For each category of model data, you can specify a default
storage class, which controls file placement. For example, apply the storage class
23-11
23 Data Definition and Declaration Management in Embedded Coder
• These configuration parameters do not affect data items to which you apply the
storage classes ExportedGlobal, ImportedExtern, and
ImportedExternPointer.
• If you apply a storage class that explicitly specifies definition and declaration files
for a data element, those specifications override the Data definition and Data
declaration configuration parameters.
• Apply the built-in storage class FileScope. For more information, see “Choose a
Storage Class for Controlling Data Representation in the Generated Code” on page 22-
69.
23-12
Control Placement of Global Data Definitions and Declarations in Generated Files
• If FileScope does not satisfy your requirements, create your own custom storage
class by using the Custom Storage Class Designer. In the Designer, set Data scope to
File or Auto.
• With File, the data element appears in the code as a static global variable.
• With Auto, the code generator first attempts to represent the data element with a
local variable in a function. If this attempt fails, the code generator uses a static
global variable.
For an example that shows how to create your own custom storage class by using the
Designer, see “Create and Apply a Custom Storage Class” on page 26-26.
You cannot apply static to the standard data structures such as the DWork structure.
To access static data, you can configure the generated code to include an interface
such as an a2l (ASAP2) file. For more information, see “Export ASAP2 File for Data
Measurement and Calibration” on page 47-2. To place the data in a specific memory
location by including pragmas or other decorations in the generated code, create your
own memory section and custom storage class. See “Control Data and Function
Placement in Memory by Inserting Pragmas” on page 30-2.
To reduce maintenance effort and data entry, when you specify Header file, you can omit
delimiters (" or <>) and use only the file name. You can then control the default delimiters
23-13
23 Data Definition and Declaration Management in Embedded Coder
that the generated code uses for the corresponding #include directives. To use angle
brackets by default, set Configuration Parameters > Code Generation > Code
Placement > #include file delimiters to #include <header.h>.
See Also
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Component-Based Modeling”
• “Manage File Packaging of Generated Code Modules” on page 37-14
• “How Generated Code Exchanges Data with an Environment” on page 22-33
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Environment for Configuring Model Data and Functions for Code Generation” on
page 21-2
23-14
Establish Data Ownership in a System of Components
When you create a global variable in the generated code by applying a storage class to a
data element in a referenced model (see “Apply Storage Classes to Individual Signal,
State, and Parameter Data Elements” on page 22-81), under certain conditions, the code
generator places the variable definition with the code generated from the top model in
the hierarchy. This default placement can make it more difficult to determine which
component is responsible for the data and to manage code changes in a team-based
development environment.
To establish ownership of a global variable by placing the definition with the code
generated from the relevant component, apply a storage class such as ExportToFile
and specify the Owner custom attribute. Alternatively, for parameter objects such as
Simulink.Parameter that you use in only one component, you can establish ownership
by storing the object in a model workspace instead of the base workspace or a data
dictionary.
[~, ~] = copyfile(fullfile(matlabroot,'examples','ecoder','main','prepare_sldemo_fuelsy
'prepare_sldemo_fuelsys_dd_ctrl.m','f');
Run the copy of the script in your current folder. The script opens the model
sldemo_fuelsys_dd_controller and prepares it for this example.
prepare_sldemo_fuelsys_dd_ctrl
open_system('sldemo_fuelsys_dd_controller')
23-15
23 Data Definition and Declaration Management in Embedded Coder
This controller model contains two component models, airflow_calc and fuel_calc.
The two outputs of airflow_calc, est_airflow and fb_correction, are inputs of
fuel_calc.
open_system('airflow_calc')
23-16
Establish Data Ownership in a System of Components
In the Model Data Editor, set the Change view drop-down list to Code.
In the Model Data Editor, inspect the value in the Storage Class column. The signal that
this block represents, est_airflow, uses the storage class ExportToFile. With this
setting, the signal appears in the generated code as a global variable. The Outport block
labeled fb_correction also uses this setting.
In the Model Data Editor, select the Parameters tab and click the Show/refresh
additional information button. The Model Data Editor now shows information about
workspace variables and objects, such as Simulink.Parameter objects, that the model
uses to set block parameter values.
23-17
23 Data Definition and Declaration Management in Embedded Coder
In the Filter contents box, enter e0. The signal e0, which is internal to the
airflow_calc component, also uses ExportToFile. The signal is internal because it is
not a root-level input or output of the model.
open_system('fuel_calc')
In the Model Data Editor for this model, on the Inports/Outports tab, set Change view
to Code. The Inport blocks est_airflow and fb_correction use the same storage
class, ExportToFile, as the corresponding Outport blocks in airflow_calc. The
Outport block labeled fuel_rate also uses ExportToFile.
rtwbuild('sldemo_fuelsys_dd_controller')
23-18
Establish Data Ownership in a System of Components
In the code generation report, under Referenced Models, click the hyperlink to inspect
the code generated for airflow_calc.
The file airflow_calc.c defines the global variable that represents the signal e0.
Because the blocks that write to and read from e0 exist only in airflow_calc, the code
generator assumes that this component owns the signal.
file = fullfile('slprj','ert','airflow_calc','airflow_calc.c');
rtwdemodbtype(file,'/* Definition for custom storage class: ExportToFile */',...
'real32_T e0;',1,1)
file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',...
'sldemo_fuelsys_dd_controller.c');
rtwdemodbtype(file,...
'/* Definition for custom storage class: ExportToFile */',...
'real32_T numerator_param[2] = { 0.01F, -0.01F } ;',1,1);
Because the signals est_airflow and fb_correction pass between the two
components and through the top-level controller model, the code generator assumes that
sldemo_fuelsys_dd_controller owns the signals. The code generator makes a
similar assumption about fuel_rate. Because the parameter object numerator_param
23-19
23 Data Definition and Declaration Management in Embedded Coder
exists in the base workspace, any model in the hierarchy can use the object. Therefore,
the code generator assumes that sldemo_fuelsys_dd_controller owns the
parameter.
You can configure each shared signal and the parameter object so that the corresponding
variable definition appears in the code generated for the relevant component.
• The code generated for the airflow_calc model defines the signals that pass
between the two components, est_airflow and fb_correction.
• The code generated for airflow_calc defines the parameter data,
numerator_param.
• The code generated for fuel_calc defines the output signal that it calculates,
fuel_rate.
In the row, click the icon in the left column. The Property Inspector shows the properties
of the Outport block.
For fb_correction, use the Model Data Editor and the Property Inspector to set Owner
to airflow_calc.
In the row, double-click the icon in the left column. The Model Explorer opens and
displays the properties of numerator_param.
In the Model Hierarchy pane, expand the airflow_calc node so that you can see the
subordinate Model Workspace node.
23-20
Establish Data Ownership in a System of Components
Use the Model Explorer to move numerator_param from the base workspace to the
airflow_calc model workspace. For example, in the Model Hierarchy pane, select
Base Workspace. Then, drag numerator_param from the Contents pane to the Model
Workspace node in the Model Hierarchy pane. With this change, the code generator
assumes that airflow_calc owns numerator_param, and places the variable definition
in the code generated for airflow_calc.
For the Inport blocks est_airflow and fb_correction, use the Model Data Editor and
the Property Inspector to set Owner to airflow_calc. With this configuration, the
fuel_calc code does not define the variables.
For the Outport block, use the Model Data Editor and the Property Inspector to set
Owner to fuel_calc.
Alternatively, to configure the data in the models, use these commands at the command
prompt:
temp = Simulink.Signal;
temp.CoderInfo.StorageClass = 'Custom';
temp.CoderInfo.CustomStorageClass = 'ExportToFile';
temp.CoderInfo.CustomAttributes.Owner = 'airflow_calc';
set_param('airflow_calc/est_airflow','SignalName','est_airflow')
set_param('airflow_calc/est_airflow','SignalObject',copy(temp))
set_param('airflow_calc/fb_correction','SignalName','fb_correction')
set_param('airflow_calc/fb_correction','SignalObject',copy(temp))
mdlwks = get_param('airflow_calc','ModelWorkspace');
assignin(mdlwks,'numerator_param',copy(numerator_param));
portHandles = get_param('fuel_calc/est_airflow','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'Name','est_airflow')
set_param(outportHandle,'SignalObject',copy(temp))
portHandles = get_param('fuel_calc/fb_correction','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'Name','fb_correction')
set_param(outportHandle,'SignalObject',copy(temp))
temp.CoderInfo.CustomAttributes.Owner = 'fuel_calc';
23-21
23 Data Definition and Declaration Management in Embedded Coder
set_param('fuel_calc/fuel_rate','SignalName','fuel_rate')
set_param('fuel_calc/fuel_rate','SignalObject',copy(temp))
In each of the three models, select Configuration Parameters > Use owner from data
object for data definition placement. With this setting cleared (the default), the code
generator ignores the values that you specify for Owner.
set_param('fuel_calc','EnableDataOwnership','on')
set_param('airflow_calc','EnableDataOwnership','on')
set_param('sldemo_fuelsys_dd_controller','EnableDataOwnership','on')
Now, the file sldemo_fuelsys_dd_controller.c does not define any of the global
variables.
In the code generation report, inspect the code generated for airflow_calc.
The file airflow_calc.c now defines the global variables that belong to
airflow_calc.
file = fullfile('slprj','ert','airflow_calc','airflow_calc.c');
rtwdemodbtype(file,'/* Definition for custom storage class: ExportToFile */',...
'real32_T numerator_param[2] = { 0.01F, -0.01F } ;',1,1)
23-22
Establish Data Ownership in a System of Components
real32_T e0;
real32_T est_airflow;
real32_T fb_correction;
real32_T numerator_param[2] = { 0.01F, -0.01F } ;
Inspect the code generated for fuel_calc. The file fuel_calc.c defines the global
variable fuel_rate.
file = fullfile('slprj','ert','fuel_calc','fuel_calc.c');
rtwdemodbtype(file,'/* Definition for custom storage class: ExportToFile */',...
'real32_T fuel_rate;',1,1)
Create Single Point of Specification for Signals That Pass Between Components
The signal data elements est_airflow and fb_correction are represented by Outport
blocks in airflow_calc and by Inport blocks in fuel_calc. If you want to change the
configuration of one of these signals, you must make the change in both models. For
example, if you want to change the storage class of est_airflow from ExportToFile
to Volatile, you must change the storage class twice: once for the Outport block in
airflow_calc and again for the Inport block in fuel_calc.
To make maintenance of each signal easier, store the code generation settings in a
Simulink.Signal object, which can exist in the base workspace or a data dictionary.
In the Model Data Editor for airflow_calc, on the Inports/Outports tab, find the row
that corresponds to est_airflow.
For that row, in the Signal Name column, click the cell.
In the cell, next to the est_airflow text, click the action button (with three vertical
dots). Select Create and Resolve.
In the Create New Data dialog box, set Value to Simulink.Signal and click Create. A
Simulink.Signal object named est_airflow appears in the base workspace. In the
Model Data Editor, for est_airflow, the check box in the Resolve check box is selected,
which means the Outport block acquires code generation settings from the signal object
in the base workspace.
23-23
23 Data Definition and Declaration Management in Embedded Coder
Use the Model Data Editor to create a similar signal object for fb_correction.
In the Model Data Editor for fuel_calc, on the Inports/Outports tab, in the Resolve
column, select the check boxes for est_airflow and fb_correction. Now, each Inport
block acquires code generation settings from the corresponding signal object.
Alternatively, to create the signal object and configure the blocks and lines in the model,
at the command prompt, use these commands:
est_airflow = Simulink.Signal;
est_airflow.CoderInfo.StorageClass = 'Custom';
est_airflow.CoderInfo.CustomStorageClass = 'ExportToFile';
est_airflow.CoderInfo.CustomAttributes.Owner = 'airflow_calc';
fb_correction = Simulink.Signal;
fb_correction.CoderInfo.StorageClass = 'Custom';
fb_correction.CoderInfo.CustomStorageClass = 'ExportToFile';
fb_correction.CoderInfo.CustomAttributes.Owner = 'airflow_calc';
set_param('airflow_calc/est_airflow','MustResolveToSignalObject','on')
set_param('airflow_calc/fb_correction','MustResolveToSignalObject','on')
portHandles = get_param('fuel_calc/est_airflow','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'MustResolveToSignalObject','on')
portHandles = get_param('fuel_calc/fb_correction','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'MustResolveToSignalObject','on')
save_system('airflow_calc')
save_system('fuel_calc')
rtwbuild('sldemo_fuelsys_dd_controller')
23-24
See Also
See Also
Related Examples
• “Control Placement of Global Data Definitions and Declarations in Generated Files”
on page 23-2
• “Code Generation of Referenced Models” on page 4-2
23-25
24
The code also aggregates signal, block parameter, and state data into structures (see
“How Generated Code Exchanges Data with an Environment” on page 22-33 and “How
Generated Code Stores Internal Signal, State, and Parameter Data” on page 22-50) by
default. You can specify a naming rule for these structure types. You can also place data
items into separate custom structures whose type names you can control.
• Conform to coding standards. For an example, see “Replace and Rename Data Types
to Conform to Coding Standards” on page 24-27.
• Integrate the generated code with your external code. For an example, see “Exchange
Structured and Enumerated Data Between Generated and External Code” on page 24-
34.
• Make the generated code more readable and meaningful.
For custom types, you can also specify that the generated code reuse type definitions, for
example, typedef statements, from your external code.
For information about data type names that you cannot control and about custom data
types that the generated code does not support, see “Limitations” on page 24-21.
To inform the code generator about the bit length of generic C types such as int and
short for your target hardware, use Hardware Implementation configuration
parameters. See “Configure Run-Time Environment Options” on page 7-2.
24-2
Control Data Type Names in Generated Code
myType = Simulink.AliasType;
Set the BaseType property to the name of the Simulink data type that corresponds to the
target Simulink Coder data type. For example, if the target type is int8_T, specify int8.
To identify the Simulink data type, use the information in the table.
• uint8
• int8
• intn*
int_T intn*
uint_T uintn*
char_T intn*
24-3
24 Data Types in Embedded Coder
For example, to replace the type name uint8_T with myType, set the BaseType property
of the Simulink.AliasType object to 'int8'.
myType.BaseType = 'int8';
Then, use one or both of these techniques to apply the type to data items in a model:
• Configure data type replacements. Throughout the code that you generate from a
model, you can replace a Simulink Coder data type name with the name of the
Simulink.AliasType object. You configure data type replacements through model
configuration parameters (Configuration Parameters > Code Generation > Data
Type Replacement.
For an example that shows how to use data type replacement, see “Replace and
Rename Data Types to Conform to Coding Standards” on page 24-27.
• Use the name of the Simulink.AliasType object to specify the data type of an
individual signal, that is, a block output, or block parameter. By default, due to data
type propagation and inheritance (see “Data Type Inheritance Rules” (Simulink)), the
signals, states, and parameters of other downstream blocks typically inherit the same
data type. Optionally, you can configure data items in upstream blocks to inherit the
type (Inherit: Inherit via back propagation) or stop the propagation at an
arbitrary block by specifying a noninherited data type setting.
To specify a data type for an individual data item, use the Model Data Editor (View >
Model Data Editor). You can use the name of the same Simulink.AliasType
object to specify the data types of multiple data items.
24-4
Control Data Type Names in Generated Code
24-5
24 Data Types in Embedded Coder
Use Simulink Data Type Names Instead of Simulink Coder Data Type Names
For consistency between the data type names that you see in a model and in the
generated code, you can configure data type replacements so the code uses Simulink type
names instead of Simulink Coder names. For each Simulink Coder type that you want to
rename, use the Simulink data type name to specify the replacement name. You do not
need to create Simulink.AliasType objects.
24-6
Control Data Type Names in Generated Code
• boolean
• uint8
• int8
• intn*
int_T intn*
uint_T uintn*
char_T intn*
24-7
24 Data Types in Embedded Coder
You cannot use this technique to replace real_T with double or real32_T with
single.
Some Simulink Coder type names map to C primitives that are implementation-
dependent. For example, the Simulink Coder type int_T maps to the C type int, whose
bit length depends on the native integer size of your target hardware. Other
implementation-dependent types include boolean_T, char_T, and uint_T.
For more readable, simpler code, you can use the same type name to replace multiple
Simulink Coder types of the same size. For example, if the native integer size of your
hardware is 32 bits, you can replace int_T and int32_T with the same type name, say,
myInt.
myInt = Simulink.AliasType('int32')
3 Configure the same data type replacement for int32_T and int_T.
24-8
Control Data Type Names in Generated Code
Note Many-to-one data type replacement does not support the char (char_T) built-in
data type. Use char only in one-to-one data type replacements.
This model shows user-defined types, consisting of numeric and alias types. Numeric
types allow you to define abstract numeric types, which is particularly useful for fixed-
point types. Alias types allow you to rename types, which allows you create a relationship
for types.
Open the example model and configure it to show the generated names of blocks.
load_system('rtwdemo_udt')
set_param('rtwdemo_udt','HideAutomaticNames','off')
open_system('rtwdemo_udt')
24-9
24 Data Types in Embedded Coder
Instructions
1 Inspect the user-defined types in the Model Explorer by double-clicking the first
yellow button below.
2 Inspect the replacement data type mapping by double-clicking the second yellow
button below.
3 Compile the diagram to display the types in this model (Simulation > Update
Diagram or Ctrl+D).
4 Generate code with the blue button below and inspect model files to see how user-
defined types appear in the generated code.
5 Modify the attributes of ENG_SPEED and ENG_SPEED_OFFSET and repeat steps 1-4.
24-10
Control Data Type Names in Generated Code
Notes
When you use nonvirtual buses and parameter structures to aggregate signals and block
parameters into a custom structure in the generated code, control the name of the
structure type by creating a Simulink.Bus object. For more information, see “Organize
Data into Structures in Generated Code” on page 22-177.
Instead of creating individual data type objects and enumerated types, and then
configuring them, consider creating the objects and types by using the
Simulink.importExternalCTypes function. By default, the function configures the
new objects and types so that the generated code imports (reuses) the type definitions
from your code. You can then use the objects and types to set data types in a model and to
configure data type replacements. For more information, see
Simulink.importExternalCTypes and “Exchange Structured and Enumerated Data
Between Generated and External Code” on page 24-34.
24-11
24 Data Types in Embedded Coder
When you integrate code generated from a model with code from other sources, your
model code can create an exported typedef statement. Therefore, all of the integrated
code can use the type. This example shows how to export the definition of a data type to a
generated header file.
mySingleAlias = Simulink.AliasType('single')
mySingleAlias =
Description: ''
DataScope: 'Auto'
HeaderFile: ''
BaseType: 'single'
Configure the object to export its definition to a header file called myHdrFile.h.
mySingleAlias.DataScope = 'Exported';
mySingleAlias.HeaderFile = 'myHdrFile.h';
open_system('rtwdemo_basicsc')
24-12
Control Data Type Names in Generated Code
Use the Data Type column to set the data type to mySingleAlias.
set_param('rtwdemo_basicsc/In1','OutDataTypeStr','mySingleAlias')
In the model, set Configuration Parameters > Code Generation > System target file
to ert.tlc. The code generator honors data type aliases such as mySingleAlias only if
you select an ERT-based system target file.
set_param('rtwdemo_basicsc','SystemTargetFile','ert.tlc')
24-13
24 Data Types in Embedded Coder
In the code generation report, view the file rtwdemo_basicsc_types.h. The code
creates a #include directive for the generated file myHdrFile.h.
file = fullfile('rtwdemo_basicsc_ert_rtw','rtwdemo_basicsc_types.h');
rtwdemodbtype(file,'#include "myHdrFile.h"',...
'#include "myHdrFile.h"',1,1)
#include "myHdrFile.h"
View the file myHdrFile.h. The code uses the identifier mySingleAlias as an alias for
the data type real32_T. By default, generated code represents the Simulink data type
single by using the identifier real32_T.
The code also provides a macro guard of the form RTW_HEADER_filename_h_. When
you export a data type definition to integrate generated code with code from other
sources, you can use macro guards of this form to prevent unintentional identifier
clashes.
file = fullfile('rtwdemo_basicsc_ert_rtw','myHdrFile.h');
rtwdemodbtype(file,'#ifndef RTW_HEADER_myHdrFile_h_',...
' * File trailer for generated code.',1,0)
#ifndef RTW_HEADER_myHdrFile_h_
#define RTW_HEADER_myHdrFile_h_
#include "rtwtypes.h"
#endif /* RTW_HEADER_myHdrFile_h_ */
/*
View the file rtwdemo_basicsc.h. The code uses the data type alias mySingleAlias to
define the structure field input1, which corresponds to the Inport block labeled In1.
file = fullfile('rtwdemo_basicsc_ert_rtw','rtwdemo_basicsc.h');
rtwdemodbtype(file,...
'/* External inputs (root inport signals with default storage) */',...
'} ExtU_rtwdemo_basicsc_T;',1,1)
24-14
Control Data Type Names in Generated Code
When you integrate code generated from a model with code from other sources, to avoid
redundant typedef statements, you can import a data type definition from the external
code. This example shows how to import your own definition of a data type from a header
file that you create.
Use a text editor to create a header file to import. Name the file
ex_myImportedHdrFile.h. Place it in your working folder. Copy the following code into
the file.
#ifndef HEADER_myImportedHdrFile_h_
#define HEADER_myImportedHdrFile_h_
#endif
The code uses the identifier myTypeAlias to create an alias for the data type float. The
code also uses a macro guard of the form HEADER_filename_h. When you import a data
type definition to integrate generated code with code from other sources, you can use
macro guards of this form to prevent unintentional identifier clashes.
myTypeAlias = Simulink.AliasType('single')
myTypeAlias =
24-15
24 Data Types in Embedded Coder
Description: ''
DataScope: 'Auto'
HeaderFile: ''
BaseType: 'single'
Configure the object so that generated code imports the type definition from the header
file ex_myImportedHdrFile.h.
myTypeAlias.DataScope = 'Imported';
myTypeAlias.HeaderFile = 'ex_myImportedHdrFile.h';
Use the Data Type column to set the data type to myTypeAlias.
set_param('rtwdemo_basicsc/In1','OutDataTypeStr','myTypeAlias')
In the model, set Configuration Parameters > Code Generation > System target file
to ert.tlc. The code generator honors data type aliases such as mySingleAlias only if
you select an ERT-based system target file.
set_param('rtwdemo_basicsc','SystemTargetFile','ert.tlc')
In the code generation report, view the file rtwdemo_basicsc_types.h. The code
creates a #include directive for your header file ex_myImportedHdrFile.h.
file = fullfile('rtwdemo_basicsc_ert_rtw','rtwdemo_basicsc_types.h');
rtwdemodbtype(file,'#include "ex_myImportedHdrFile.h',...
'/* Forward declaration for rtModel */',1,0)
#include "ex_myImportedHdrFile.h"
24-16
Control Data Type Names in Generated Code
View the file rtwdemo_basicsc.h. The code uses the data type alias myTypeAlias to
define the structure field input1, which corresponds to the Inport block labeled In1.
file = fullfile('rtwdemo_basicsc_ert_rtw','rtwdemo_basicsc.h');
rtwdemodbtype(file,...
'/* External inputs (root inport signals with default storage) */',...
'} ExtU_rtwdemo_basicsc_T;',1,1)
When you display signal data types on the model diagram by selecting Display > Signals
and Ports > Port Data Types, by default, the diagram displays aliases (such as
myTypeAlias) instead of base data types (such as int16). To display the base types,
choose an option for Display > Signals and Ports > Port Data Type Display Format.
For more information, see “Port Data Types” (Simulink).
The example model rtwdemo_fixpt1 uses fixed-point data types. So that you can more
easily see the fixed-point data type in the generated code, in this example, you create a
Simulink.Parameter object that appears in the code as a global variable.
Create a Simulink.AliasType object that defines a fixed-point data type. Name the
object myFixType. The generated code uses the name of the object as a data type.
myFixType = Simulink.AliasType('fixdt(1,16,4)');
open_system('rtwdemo_fixpt1')
24-17
24 Data Types in Embedded Coder
set_param('rtwdemo_fixpt1','HideAutomaticNames','off')
In the Model Data Editor, for the row that represents the Gain parameter of the Gain
block, in the Value column, specify myParam.
24-18
Control Data Type Names in Generated Code
Click the action button (with three vertical dots) next to the parameter value. Select
Create.
In the Create New Data dialog box, set Value to Simulink.Parameter(8). In this
example, for more easily readable code, you set the parameter value to 8 instead of -3.2.
Click Create. A Simulink.Parameter object named myParam appears in the base
workspace. The object stores the real-world value 8, which the Gain block uses for the
value of the Gain parameter.
In the Model Data Editor, use the Data Type column to set the data type of the Gain
parameter of the Gain block to myFixType.
On the Signals tab, use the Data Type column to set the data type of the Gain block
output to myFixType.
Use the Data Type column to set the data type of the Conversion block output to
myFixType.
Alternatively, you can use these commands at the command prompt to configure the
blocks and create the object:
set_param('rtwdemo_fixpt1/Gain','Gain','myParam','OutDataTypeStr','myFixType',...
'ParamDataTypeStr','myFixType')
myParam = Simulink.Parameter(8);
myParam.StorageClass = 'ExportedGlobal';
set_param('rtwdemo_fixpt1/Conversion','OutDataTypeStr','myFixType')
In the model, set Configuration Parameters > Code Generation > System target file
to ert.tlc. With this setting, the code generator honors data type aliases such as
myFixType.
set_param('rtwdemo_fixpt1','SystemTargetFile','ert.tlc')
24-19
24 Data Types in Embedded Coder
In the code generation report, view the file rtwdemo_fixpt1_types.h. The code
defines the type myFixType based on an integer type of the specified word length (16).
file = fullfile('rtwdemo_fixpt1_ert_rtw','rtwdemo_fixpt1_types.h');
rtwdemodbtype(file,'#ifndef DEFINED_TYPEDEF_FOR_myFixType_',...
'/* Forward declaration for rtModel */',1,0)
#ifndef DEFINED_TYPEDEF_FOR_myFixType_
#define DEFINED_TYPEDEF_FOR_myFixType_
#endif
View the file rtwdemo_fixpt1.c. The code uses the type myFixType, which is an alias
of the integer type int16, to define the variable myParam.
file = fullfile('rtwdemo_fixpt1_ert_rtw','rtwdemo_fixpt1.c');
rtwdemodbtype(file,'myFixType myParam = 128;','myFixType myParam = 128;',1,1)
The stored integer value 128 of myParam is not the same as the real-world value 8
because of the scaling that the fixed-point data type myFixType specifies. For more
information, see “Scaling” (Fixed-Point Designer) in the Fixed-Point Designer
documentation.
The line of code that represents the Gain block applies a right bit shift corresponding to
the fraction length specified by myFixType.
rtwdemodbtype(file,...
'rtwdemo_fixpt1_Y.Out1 = (myFixType)((myParam * rtb_Conversion) >> 4);',...
'rtwdemo_fixpt1_Y.Out1 = (myFixType)((myParam * rtb_Conversion) >> 4);',1,1)
24-20
Control Data Type Names in Generated Code
Limitations
• You cannot configure the generated code to use these custom C data types:
• Array types
• Pointer types
• const or volatile types
• You cannot configure the generated code to use generic C primitive types such as int
and short.
When you select the model configuration parameter Replace data type names in the
generated code on the Code Generation > Data Type Replacement pane of the
Configuration Parameters dialog box, these limitations apply:
• Data type replacement does not support multiple levels of mapping. Each replacement
data type name maps directly to one or more built-in data types.
• Data type replacement is not supported for simulation target code generation for
referenced models.
24-21
24 Data Types in Embedded Coder
• If you select the Classic call interface configuration parameter for your model, data
type replacement is not supported.
• Code generation performs data type replacements while generating .c, .cpp, and .h
files. Code generation places these files in build folders (including top and referenced
model build folders) and in the _sharedutils folder. Exceptions are as follows:
rtwtypes.h
multiword_types.h
model_reference_types.h
builtin_typeid_types.h
model_sf.c or .cpp (ERT S-function wrapper)
model_dt.h (C header file supporting external mode)
model_capi.c or .cpp
model_capi.h
• Data type replacement is not supported for complex data types.
• Many-to-one data type replacement is not supported for the char data type.
Attempting to use char as part of a many-to-one mapping to a custom data type
represents a violation of the MISRA C specification. For example, if you map char
(char_T) and either int8 (int8_T) or uint8 (uint8_T) to the same replacement
type, the result is a MISRA C violation. If you try to generate C++ code, the code
generator makes invalid implicit type casts, resulting in compile-time errors. Use char
only in one-to-one data type replacements.
• For ERT S-functions, replace the boolean data type with only an 8-bit integer, int8,
or uint8.
• Set the DataScope property of a Simulink.AliasType object to Auto (default) or
Imported.
See Also
Related Examples
• “Exchange Structured and Enumerated Data Between Generated and External
Code” on page 24-34
• “Replace and Rename Data Types to Conform to Coding Standards” on page 24-27
24-22
Control File Placement of Custom Data Types
When you import a data type definition (for example, by setting DataScope to
Imported), the generated model code creates an #include directive for your header file
in place of a type definition. You supply the header file that contains the definition.
24-23
24 Data Types in Embedded Coder
• If you use data type replacement to replace a built-in Simulink data type with your
own data type in generated code (see “Model Configuration Parameters: Code
Generation Data Type Replacement”), typedef statements and #include directives
appear in rtwtypes.h instead of model_types.h.
• When a Simulink.AliasType or Simulink.NumericType object participates in
data type replacements, you cannot set the DataScope property of the object to
Exported. Therefore, if you want the code generator to generate the corresponding
typedef statement, you cannot control the file placement of the statement. However,
you can set DataScope to Imported, which means that you can configure the code to
reuse the typedef statement that your external code provides.
As a workaround, instead of using the data type object as a data type replacement, use
the object to set the data types of individual data items in a model. To configure many
data items, you can use the Model Data Editor and take advantage of data type
propagation and inheritance. For more information, see “Control Names of Primitive
Data Types” on page 24-2.
You can use a Simulink.AliasType object with numerically complex data (i). In this
case, if you configure the generated code to import the type definition from your external
code (for example, by setting the DataScope property to Imported), your code must
provide two complementary typedef statements.
Suppose your external header file myAliasTypes.h defines the data type IAT_int32 as
an alias of a 32-bit integer. The file must define two types: IAT_int32 and cIAT_int32:
#ifndef myAliasTypes_H_
#define myAliasTypes_H_
#include "rtwtypes.h"
#endif
You do not need to create two Simulink.AliasType objects. In this example, you create
one object, IAT_int32. The generated code then creates complex data (variables) by
using both IAT_int32 and cIAT_int32.
24-24
Control File Placement of Custom Data Types
Macro Guards
When you export one or more data type definitions to a generated header file, the file
contains a file-level macro guard of the form RTW_HEADER_filename_h.
When you generate code, the guarded file myTypes.h contains the typedef statements:
#ifndef RTW_HEADER_myTypes_h_
#define RTW_HEADER_myTypes_h_
#include "rtwtypes.h"
#endif
When you export data type definitions to model_types.h, the file contains a macro
guard of the form _DEFINED_TYPEDEF_FOR_typename_ for each typedef statement.
Suppose you use a Simulink.AliasType object mySingleAlias with these properties:
When you generate code, the file model_types.h contains the guarded typedef
statement:
#ifndef _DEFINED_TYPEDEF_FOR_mySingleAlias_
#define _DEFINED_TYPEDEF_FOR_mySingleAlias_
#endif
24-25
24 Data Types in Embedded Coder
See Also
Simulink.AliasType | Simulink.Bus | Simulink.NumericType
Related Examples
• “Control Data Type Names in Generated Code” on page 24-2
24-26
Replace and Rename Data Types to Conform to Coding Standards
For information about controlling data types in a model, see “Control Signal Data Types”
(Simulink).
#include <stdbool.h>
open_system(fullfile(docroot,'toolbox','ecoder','examples',...
'ex_data_type_replacement'))
2 In the model, select View > Model Data Editor.
3 In the Model Data Editor, inspect the Signals tab.
4 Set the Change view drop-down list to Code. In the data table, the Storage Class
column shows that named signal lines such as temp use the storage class
ExportedGlobal. With this setting, the signal lines appear in the generated code as
separate global variables.
24-27
24 Data Types in Embedded Coder
Simulink assigns a specific data type to each signal that uses an inherited data type
setting such as Inherit: Inherit via internal rule.
7 In the data table, expand the width of the Data Type column. The column shows that
the signals in the model use a mix of the data types int16, double, and boolean.
You can also see these data types in the model.
8 Generate code from the model.
9 In the code generation report, inspect the shared utility file rtwtypes.h. The code
uses typedef statements to rename the primitive C data types by using standard
Simulink Coder aliases. For example, the code renames the primitive type double by
using the alias real_T.
The model step function defines local variables by using the same data type aliases.
real_T rtb_Add;
real_T rtb_FilterCoefficient;
Simulink.importExternalCTypes('my_types.h');
24-28
Replace and Rename Data Types to Conform to Coding Standards
For each object, the function sets the DataScope property to 'Imported' and the
HeaderFile property to 'my_types.h'. With these settings, the code generator
does not create a typedef statement for each object, but instead the generated code
reuses the statements from my_types.h by including (#include) the file.
2 In the model, in the Configuration Parameters dialog box, on the Code Generation >
Data Type Replacement pane, select Replace data type names in the generated
code.
3 Specify the options in the Replacement Name column according to the table.
6 Inspect the file ex_data_type_replacement.c. The code uses the custom data
type aliases my_dblPrecision, my_int16, and my_bool to define the global
variables such as flowIn, temp, and intlk.
The model step function defines local variables by using the custom data type
aliases.
my_dblPrecision rtb_Add;
my_dblPrecision rtb_FilterCoefficient;
24-29
24 Data Types in Embedded Coder
1 In the Model Data Editor Data Type column, use the Simulink.AliasType objects
to set the data types of these block outputs. You can select a signal line in the model,
which highlights the corresponding row in the Model Data Editor, or search for the
signals in the Model Data Editor by using the Filter contents box.
With these data type settings, some of the named signals, such as temp and flowIn,
use data types that evoke real-world quantities, such as liquid flow rate and
temperature.
6 At the command prompt, create Simulink.AliasType objects to represent these
new custom data type aliases.
flow_T = Simulink.AliasType('double');
diffTemp_T = Simulink.AliasType('int16');
ctrl_T = Simulink.AliasType('double');
In the model, the signals flowIn and flowSetPt use the primitive data type
double, so the data type alias flow_T maps to double.
7 Update the block diagram.
Due to data type inheritance, other signals also use the custom data type aliases. For
example, the output data type of the Add block fed by the third Inport block is set to
Inherit: Inherit via internal rule. The internal rule chooses the same data
type that the block inputs use, flow_T.
8 Generate code from the model.
9 The file ex_data_type_replacement_types.h defines the new data types
flow_T, diffTemp_T, and ctrl_T as aliases of my_dblPrecision and my_int16.
24-30
Replace and Rename Data Types to Conform to Coding Standards
To more easily make this change, you can create a Simulink.NumericType object and
configure both Simulink.AliasType objects to refer to it. Then, you need to modify
only the Simulink.NumericType object. A Simulink.NumericType object enables
you to share a data type without creating a data type alias.
sharedType = Simulink.NumericType;
sharedType.DataTypeMode = 'Single';
2 Configure the Simulink.AliasType objects flow_T and ctrl_T to acquire an
underlying data type from this new object.
24-31
24 Data Types in Embedded Coder
flow_T.BaseType = 'sharedType';
ctrl_T.BaseType = 'sharedType';
3 In the model, select Display > Signals and Ports > Port Data Type Display
Format > Base and Alias Types (see “Port Data Types” (Simulink)). Update the
block diagram.
The data type indicators in the model show that the aliases flow_T and ctrl_T map
to the primitive type single. To change this underlying primitive type, you can
modify the DataTypeMode property of the Simulink.NumericType object,
sharedType.
If you generate code from the model while the Simulink.NumericType object
represents the data type single, the generated code maps flow_T and ctrl_T to the
default Simulink Coder data type alias real32_T, which maps to the C data type float.
You can replace real32_T in the same way that you replaced real_T, int16_T, and
boolean_T (Configuration Parameters > Code Generation > Data Type
Replacement).
24-32
See Also
See Also
Related Examples
• “Control Code Style” on page 39-38
• “Unit Specification in Simulink Models” (Simulink)
• “Design Data Interface by Configuring Inport and Outport Blocks” on page 22-206
• “Choose an External Code Integration Workflow” on page 42-4
• “Control File Placement of Custom Data Types” on page 24-23
24-33
24 Data Types in Embedded Coder
#include "ex_cc_algorithm.h"
inSigs_T inSigs;
float_32 my_alg(void)
{
if (inSigs.err == TMP_HI) {
return 27.5;
}
else if (inSigs.err == TMP_LO) {
return inSigs.sig1 * calPrms.cal3;
}
else {
return inSigs.sig2 * calPrms.cal3;
}
}
The C code defines a global structure variable named inSigs. The code also defines a
function, my_alg, that uses inSigs and another structure variable named calPrms.
#ifndef ex_cc_algorithm_h
#define ex_cc_algorithm_h
typedef enum {
24-34
Exchange Structured and Enumerated Data Between Generated and External Code
TMP_HI = 0,
TMP_LO,
NORM,
} err_T;
float_32 my_alg(void);
#endif
The file defines float_32 as an alias of the C data type float. The file also defines an
enumerated data type, err_T, and two structure types, inSigs_T and calPrms_T.
The function my_alg is designed to calculate a return value by using the fields of inSigs
and calPrms, which are global structure variables of the types inSigs_T and
calPrms_T. The function requires another algorithm to supply the signal data that
inSigs stores.
This code allocates memory for inSigs, but not for calPrms. Create a model whose
generated code:
24-35
24 Data Types in Embedded Coder
Simulink.importExternalCTypes('ex_cc_algorithm.h',...
'DataDictionary','ex_cc_integ.sldd');
24-36
Exchange Structured and Enumerated Data Between Generated and External Code
24-37
24 Data Types in Embedded Coder
• Number of inputs to 3
• Output data type to Bus: inSigs_T
• Output as nonvirtual bus to selected
3 Delete the three existing Outport blocks (but not the signals that enter the blocks).
4 Connect the three remaining signal lines to the inputs of the Bus Creator block.
5 Add an Outport block after the Bus Creator block. Connect the output of the Bus
Creator to the Outport.
6 In the Outport block, set the Data type parameter to Bus: inSigs_T.
7 In the model, select View > Model Data Editor.
8 On the Inports/Outports tab, for the Inport blocks labeled In2 and In3, change
Data Type from Inherit: auto to float_32.
9 Change the Change View drop-down list from Design to Code.
10 For the Outport block, set Signal Name to inSigs.
11 Set Storage Class to ImportFromFile.
12 Set Header File to ex_cc_algorithm.h.
13 Inspect the Signals tab.
14 In the model, select the output signal of the Multiport Switch block.
15 In the Model Data Editor, for the selected signal, set Name to err.
16 Set the name of the output signal of the Gain block to sig1.
17 Set the name of the output signal of the Gain1 block to sig2.
When you finish, the model stores output signal data (such as the signals err and sig1)
in the fields of a structure variable named inSigs.
24-38
Exchange Structured and Enumerated Data Between Generated and External Code
Because you set Storage Class to ImportFromFile, the generated code does not
allocate memory for inSigs.
1 In the Model Explorer Model Hierarchy pane, under the dictionary node
ex_cc_integ, select the Design Data node.
2 In the Contents pane, select the Simulink.Bus object calPrms_T.
3 In the Dialog pane (the right pane), click Launch Bus Editor.
4 In the Bus Editor, in the left pane, select calPrms_T.
24-39
24 Data Types in Embedded Coder
• For the fields cal1 and cal2, use the numeric values that the Gain blocks in the
model previously used.
• For cal3, use a nonzero number such as 15.2299995.
24-40
See Also
The generated algorithm in the model step function defines a local variable for
buffering the value of the signal err.
err_T rtb_err;
The algorithm then calculates and stores data in the fields of inSig.
inSigs.err = rtb_err;
inSigs.sig1 = (rtU.In2 + rtDW.DiscreteTimeIntegrator_DSTATE) * calPrms.cal1;
inSigs.sig2 = (real32_T)(calPrms.cal2 * rtDW.DiscreteTimeIntegrator_DSTATE);
See Also
Simulink.importExternalCTypes
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” (Simulink Coder)
• “Control Data Type Names in Generated Code” on page 24-2
• “Use Enumerated Data in Generated Code” on page 22-90
• “Organize Data into Structures in Generated Code” on page 22-177
24-41
24 Data Types in Embedded Coder
For example, to change the default identifiers for the 8-bit integer data limit minimum
and maximum to s4g_S4MIN and s4g_S4MAX, respectively:
set_param(gcs,'MinIdInt8','s4g_S4MIN');
set_param(gcs,'MaxIdInt8','s4g_S4MAX')
If you do not import a header file, the generated file rtwtypes.h defines the 8-bit
integer data minimum and maximum identifiers:
24-42
Specify Boolean and Data Type Limit Identifiers
If you do import a header file defining the data type limit identifiers, the header file is
included in rtwtypes.h.
Boolean Identifiers
You can control the Boolean identifiers in the generated code by using the command-line
parameters in this table. When changing boolean identifiers, you must define false to be
numerically equivalent to 0, and true to be numerically equivalent to 1.
For example, to change the default Boolean true and false identifiers:
set_param(gcs,'BooleanTrueId','bTrue');
set_param(gcs,'BooleanFalseId','bFalse')
If you do not import a header file, the generated file rtwtypes.h defines the Boolean
identifiers:
If you do import a header file defining the Boolean identifiers, the header file is included
in rtwtypes.h.
Note When changing boolean identifiers, you must define false to be numerically
equivalent to 0, and true to be numerically equivalent to 1.
24-43
24 Data Types in Embedded Coder
For example, if you have a header file myfile.h with data type limit definitions, use
TypeLimitIdReplacementHeaderFile to include the definitions in the generated
code:
set_param(gcs,'TypeLimitIdReplacementHeaderFile','myfile.h');
See Also
Related Examples
• “Replace and Rename Data Types to Conform to Coding Standards” on page 24-27
• “Model Configuration Parameters: Code Generation Data Type Replacement”
24-44
25
The following table describes the properties and property values for mpt.Parameter and
mpt.Signal data objects that appear in the Model Explorer.
Note You can create mpt.Signal and mpt.Parameter objects in the base MATLAB or
model workspace. However, if you create a signal object in a model workspace, the
object's storage class must be set to Auto.
The figure below shows an example of the Model Explorer. When you select an
mpt.Parameter or mpt.Signal data object in the middle pane, its properties and
property values display in the rightmost pane.
In the Properties column, the table lists the properties in the order in which they appear
on the Model Explorer.
25-2
MPT Data Object Properties
25-3
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder
25-4
MPT Data Object Properties
25-5
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder
25-6
MPT Data Object Properties
25-7
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder
25-8
MPT Data Object Properties
25-9
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder
25-10
MPT Data Object Properties
25-11
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder
25-12
MPT Data Object Properties
25-13
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder
25-14
MPT Data Object Properties
25-15
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder
Notice also the Signal display level and Parameter tune level fields on the Code
Placement pane of the Configuration Parameters dialog box, as illustrated in the next
figure.
25-16
MPT Data Object Properties
The Signal display level field allows you to specify whether or not the code generator
defines a signal data object as global data in the generated code. The number you specify
in this field is relative to the number you specify in the Persistence level field. The
Signal display level number is for mpt (module packaging tool) signal data objects in
the model. The Persistence level number is for a particular mpt signal data object. If the
data object's Persistence level is equal to or less than the Signal display level, the
signal appears in the generated code as global data with the custom attributes that you
specified. For example, this would occur if Persistence level is 2 and Signal display
level is 5.
Otherwise, the code generator automatically determines how the particular signal data
object appears in the generated code. Depending on the settings on the Optimization
25-17
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder
pane of the Configuration Parameters dialog box, the signal data object could appear in
the code as local data without the custom attributes you specified for that data object. Or,
based on expression folding, the code generator could remove the data object so that it
does not appear in the code.
The Parameter tune level field allows you to specify whether or not the code generator
declares a parameter data object as tunable global data in the generated code.
The number you specify in this field is relative to the number you specify in the
Persistence level field. The Parameter tune level number is for mpt parameter data
objects in the model. The Persistence level number is for a particular mpt parameter
data object. If the data object's Persistence level is equal to or less than the Parameter
tune level, the parameter appears tunable in the generated code with the custom
attributes that you specified. For example, this would occur if Persistence level is 2 and
Parameter tune level is 5.
Otherwise, the parameter is inlined in the generated code, and the code generation
settings determine its exact form.
Note that, in the initial stages of development, you might be more concerned about
debugging than code size. Or, you might want one or more particular data objects to
appear in the code so that you can analyze intermediate calculations of an equation. In
this case, you might want to specify the Parameter tune level (Signal display level for
signals) to be higher than Persistence level for some mpt parameter (or signal) data
objects. This results in larger code size, because the code generator defines the
parameter (or signal) data objects as global data, which have the custom properties you
specified. As you approach production code generation, however, you might have more
concern about reducing the size of the code and less need for debugging or intermediate
analyses. In this stage of the tradeoff, you could make the Parameter tune level (Signal
display level for signals) greater than Persistence level for one or more data objects,
generate code and observe the results. Repeat until satisfied.
1 With the model open, in the Configuration Parameters dialog box, select Code
Generation > Code Placement.
2 Type the desired number in the Signal display level or Parameter tune level field,
and click Apply.
3 In the Model Explorer, type the desired number in the Persistence field for the
selected signal or parameter, and click Apply.
4 Save the model and generate code.
25-18
MPT Data Object Properties
Introduction
Embedded Coder allows you to create custom mpt object types and specify properties and
property values to be associated with them. Once created, a user object type can be
applied to data objects displayed in Model Explorer. When you apply a user object type to
a data object, by selecting a type name in the User object type pull-down list in Model
Explorer, the data object is automatically populated with the properties and property
values that you specified for the user object type.
To register mpt user object type customizations, use the Simulink customization file
sl_customization.m. This file is a mechanism that allows you to use MATLAB code to
perform customizations of the standard Simulink user interface. The Simulink software
reads the sl_customization.m file, if present on the MATLAB path, when it starts and
the customizations specified in the file are applied to the Simulink session. For more
information on the sl_customization.m customization file, see “Registering
Customizations” (Simulink).
As a starting point for your customizations, the sl_customization function must first
get the default (factory) customizations, using the following assignment statement:
hObj = cm.slDataObjectCustomizer;
You then invoke methods to register your customizations. The customization manager
object includes the following methods for registering mpt user object type customizations:
25-19
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder
Registers the specified user object type, along with specified values for object
properties, and adds the object type to the top of the user object type list, as displayed
in the User object type pull-down list in the Model Explorer.
Moves the specified user object type to the top of the user object type list, as displayed
in the User object type pull-down list in the Model Explorer.
• moveMPTObjectTypeToEnd(hObj, objectTypeName)
Moves the specified user object type to the end of the user object type list, as
displayed in the User object type pull-down list in the Model Explorer.
• removeMPTObjectType(hObj, objectTypeName)
Removes the specified user object type from the user object type list.
Your instance of the sl_customization function should use these methods to register
mpt object type customizations for your Simulink installation.
The Simulink software reads the sl_customization.m file when it starts. If you
subsequently change the file, to use the changes, you must restart your MATLAB session.
The sl_customization.m file shown in “mpt User Object Type Customization Using
sl_customization.m” on page 25-20 uses the addMPTObjectType method to register the
user signal types EngineType and FuelType for mpt objects.
25-20
MPT Data Object Properties
hObj.addMPTObjectType(...
'FuelType','Signal',...
'DataType', 'int16',...
'Min', -12,...
'Max', 3000,...
'Unit','mg/hr');
end
If you include the above file on the MATLAB path of the Simulink installation that you
want to customize, the specified customizations will appear in Model Explorer. For
example, you could view the customizations as follows:
25-21
26
• “Reuse Parameter Data from External Code in the Generated Code” on page 26-2
• “Import Parameter Data with Conditionally Compiled Dimension Length”
on page 26-7
• “Access Structured Data Through a Pointer That External Code Defines”
on page 26-12
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
• “Create Custom Storage Classes by Using the Custom Storage Class Designer”
on page 26-26
• “Finely Control Data Representation by Writing TLC Code for a Custom Storage Class”
on page 26-39
• “Access Data Through Functions with Custom Storage Class GetSet” on page 26-42
• “Integrate External Application Code with Code Generated from PID Controller”
on page 26-62
• “Configure Generated Code According to Interface Control Document Interactively”
on page 26-73
• “Configure Generated Code According to Interface Control Document” on page 26-83
• “Generate Local Variables with Localizable Custom Storage Class” on page 26-94
26 Custom Storage Classes in Embedded Coder
Suppose your external code defines a vector parameter myGains with three elements.
Save the definition in your current folder in a file called ex_vector_import_src.c.
#include "ex_vector_import_decs.h"
my_int8 myGains[3] = {
2,
4,
6
};
#include "ex_vector_import_cust_types.h"
Save the data type definition my_int8 in your current folder in a file called
ex_vector_import_cust_types.h.
In your current folder, right-click the file ex_vector_import_src.c and select Import
Data.
26-2
Reuse Parameter Data from External Code in the Generated Code
Import the data by clicking the green check mark. The MATLAB variable tempVar
appears in the base workspace.
Use the Value column to set the value of the Gain parameter in the Gain block to
myGains.
26-3
26 Custom Storage Classes in Embedded Coder
Click the Show/refresh additional information button. The data table now contains a
row that represents the parameter object, myGains.
Use the Data Type column to set the data type of myGains to my_int8.
For the other row (which represents the Gain parameter of the Gain block), set Data
Type to Inherit: Inherit from 'Gain'. With this setting, the Gain parameter
inherits the data type my_int8 from myGains.
Alternatively, use these commands at the command prompt to configure the object and
the block:
set_param('ex_vector_import/Gain','Gain','myGains',...
'ParamDataTypeStr','Inherit: Inherit from ''Gain''')
myGains.DataType = 'my_int8';
myGains.CoderInfo.StorageClass = 'Custom';
myGains.CoderInfo.CustomStorageClass = 'ImportFromFile';
myGains.CoderInfo.CustomAttributes.HeaderFile = 'ex_vector_import_decs.h';
Set Configuration Parameters > Code Generation > Custom Code > Additional
build information > Source files to ex_vector_import_src.c.
set_param('ex_vector_import','CustomSource','ex_vector_import_src.c')
26-4
Reuse Parameter Data from External Code in the Generated Code
file = fullfile('ex_vector_import_ert_rtw','ex_vector_import.h');
rtwdemodbtype(file,'#include "ex_vector_import_cust_types.h"',...
'#include "ex_vector_import_cust_types.h"',1,1)
rtwdemodbtype(file,'/* Includes for objects with custom storage classes. */',...
'#include "ex_vector_import_decs.h"',1,1)
#include "ex_vector_import_cust_types.h"
The generated code algorithm in the model step function in the generated file
ex_vector_import.c uses myGains for calculations.
file = fullfile('ex_vector_import_ert_rtw','ex_vector_import.c');
rtwdemodbtype(file,'/* Model step function */','/* Model initialize function */',1,0)
The generated code does not define (allocate memory for) or initialize the global variable
myGains because the data scope of the corresponding parameter object is imported.
When you simulate the model in Simulink, the model uses the value stored in the Value
property of the parameter object. However, if you use external mode simulation, the
26-5
26 Custom Storage Classes in Embedded Coder
external executable begins the simulation by using the value from your code. See
“Considerations for Other Modeling Goals” on page 42-100.
See Also
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Import Parameter Data with Conditionally Compiled Dimension Length” on page
26-7
26-6
Import Parameter Data with Conditionally Compiled Dimension Length
Save the definition of the breakpoint set data T1Break and lookup table data T1Data in
your current folder in a file called ex_vec_symdim_src.c. These global variables have
either 9 or 11 elements depending on the value of the macro bpLen.
#include "ex_vec_symdim_decs.h"
#if bpLen == 11
double T1Break[bpLen] = {
-5.0,
-4.0,
-3.0,
-2.0,
-1.0,
0.0,
1.0,
2.0,
3.0,
4.0,
5.0
} ;
double T1Data[bpLen] = {
-1.0,
-0.99,
-0.98,
-0.96,
-0.76,
0.0,
0.76,
0.96,
0.98,
0.99,
1.0
26-7
26 Custom Storage Classes in Embedded Coder
} ;
#endif
#if bpLen == 9
double T1Break[bpLen] = {
-4.0,
-3.0,
-2.0,
-1.0,
0.0,
1.0,
2.0,
3.0,
4.0
} ;
double T1Data[bpLen] = {
-0.99,
-0.98,
-0.96,
-0.76,
0.0,
0.76,
0.96,
0.98,
0.99
} ;
#endif
Save the declarations of the variables and the definition of the macro in your current
folder in a file called ex_vec_symdim_decs.h.
#define bpLen 11
open_system('rtwdemo_basicsc')
26-8
Import Parameter Data with Conditionally Compiled Dimension Length
Open the Table1 block dialog box. The block refers to variables, T1Data and T1Break, in
the base workspace. These variables store the lookup table and breakpoint set data with
11 elements.
Configure the objects to import the data definitions from your external code.
T1Data.CoderInfo.StorageClass = 'Custom';
T1Data.CoderInfo.CustomStorageClass = 'ImportFromFile';
T1Data.CoderInfo.CustomAttributes.HeaderFile = 'ex_vec_symdim_decs.h';
T1Break.CoderInfo.StorageClass = 'Custom';
T1Break.CoderInfo.CustomStorageClass = 'ImportFromFile';
T1Break.CoderInfo.CustomAttributes.HeaderFile = 'ex_vec_symdim_decs.h';
26-9
26 Custom Storage Classes in Embedded Coder
bpLen = Simulink.Parameter(11);
bpLen.Min = 9;
bpLen.Max = 11;
bpLen.DataType = 'int32';
bpLen.CoderInfo.StorageClass = 'Custom';
bpLen.CoderInfo.CustomStorageClass = 'ImportedDefine';
bpLen.CoderInfo.CustomAttributes.HeaderFile = 'ex_vec_symdim_decs.h';
Use bpLen to set the dimensions of the lookup table and breakpoint set data. Configure
the model to enable symbolic dimensions by selecting the configuration parameter Allow
symbolic dimension specification.
Set Configuration Parameters > Code Generation > Custom Code > Additional
build information > Source files to ex_vec_symdim_src.c.
set_param('rtwdemo_basicsc','CustomSource','ex_vec_symdim_src.c')
To generate code with custom storage classes such as ImportFromFile, you must use
an ERT-based system target file. Set Configuration Parameters > Code Generation >
System target file to ert.tlc.
set_param('rtwdemo_basicsc','SystemTargetFile','ert.tlc')
rtwbuild('rtwdemo_basicsc')
The generated code algorithm is in the model step function in the generated file
rtwdemo_basicsc.c. The algorithm passes T1Break, T1Data, and bpLen as argument
values to the function that performs the table lookup. In this case, bpLen controls the
upper bound of the binary search that the function uses.
file = fullfile('rtwdemo_basicsc_ert_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'.X = look1_iflf_binlx','bpLen - 1U',1,1)
26-10
See Also
rtwdemo_basicsc_DW.X = look1_iflf_binlx(rtwdemo_basicsc_U.input2,
(&(T1Break[0])), (&(T1Data[0])), bpLen - 1U) * 2.0F;
For more information about symbolic dimensions, see “Implement Dimension Variants for
Array Sizes in Generated Code” on page 15-2.
See Also
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Reuse Parameter Data from External Code in the Generated Code” on page 26-2
26-11
26 Custom Storage Classes in Embedded Coder
The code defines a function that copies the field values from ReferenceStruct to
WorkingStruct.
26-12
Access Structured Data Through a Pointer That External Code Defines
Finally, the code defines a function that can dynamically set StructPointer to point to
either ReferenceStruct or WorkingStruct.
#include "rtwtypes.h"
typedef enum {
Reference=0,
Working
} Dataset_T;
The file also declares the global variables and the functions.
The code is designed so that the source code of a control algorithm (whether generated
or handwritten) can read data from either ReferenceStruct or WorkingStruct by
26-13
26 Custom Storage Classes in Embedded Coder
Later, in preparation for calibration while the algorithm executes, a calibration tool can
make StructPointer point to WorkingStruct. The tool can then modify the fields of
WorkingStruct.
If necessary for safety or in preparation for shutting down the application, the calibration
tool can point StructPointer to ReferenceStruct instead. ReferenceStruct stores
default parameter values that do not change during execution.
26-14
Access Structured Data Through a Pointer That External Code Defines
The model creates variables and objects in the base workspace. The Constant block and
the Gain block use the ECoderDemos.Parameter objects GAIN and OFFSET to set the
Constant value and Gain block parameters. ECoderDemos is an example custom
package that defines two classes, Parameter and Signal, and some custom storage
classes.
26-15
26 Custom Storage Classes in Embedded Coder
The Model Data Editor shows rows that correspond to the Constant value and Gain
parameters of the blocks and rows that corresponds to OFFSET and GAIN, which set the
parameter values. In the Storage Class column, OFFSET and GAIN use the custom
storage class StructPointer, which the ECoderDemos package defines.
Open the Custom Storage Class Designer and inspect the custom storage classes in the
ECoderDemos package. At the command prompt, use this command:
cscdesigner('ECoderDemos')
Under Custom storage class definitions, click StructPointer. The settings for this
custom storage class enable the generated code to interact with the pointer variable,
StructPointer, from the external code. For example, the custom storage class uses
these settings:
• Data scope is set to Imported because the example external code defines (allocates
memory for) StructPointer. With this setting, the code generator avoids generating
unnecessary, duplicate definitions for the data items, such as the
ECoderDemos.Parameter objects, that use the custom storage class.
• Data access is set to Pointer because in the example external code,
StructPointer is a pointer.
• Memory section is set to ConstVolatile because the example external code
defines StructPointer as constant, volatile data (const volatile).
• Type is set to FlatStructure because in the example external code,
StructPointer points to a structure. With this setting, the generated code treats
each data item (ECoderDemos.Parameter object) as a field of a flat structure whose
variable name and type name you can specify.
• On the Structure Attributes tab, Struct name is set to StructPointer. For a
FlatStructure custom storage class, Struct name specifies the name of the
26-16
Access Structured Data Through a Pointer That External Code Defines
In the model, in the Configuration Parameters dialog box, inspect the Code
Generation > Custom Code pane.
Under Insert custom C code in generated, select Initialize function. In this model,
this configuration parameter is set so that the generated code calls the
Init_WorkingStruct function before execution of the primary algorithm.
Init_WorkingStruct initializes the fields of WorkingStruct with the values from
ReferenceStruct.
Under Additional build information, select Source files. This configuration parameter
identifies the example external code file rtwdemo_importstruct_user.c for inclusion
in the build process after code generation.
/*
The algorithm in the model execution (step) function dereferences the pointer variable
StructPointer.
26-17
26 Custom Storage Classes in Embedded Coder
{
/* Gain: '<Root>/Gain' incorporates:
* Constant: '<Root>/Offset'
* Inport: '<Root>/In'
* Sum: '<Root>/Sum'
*/
Sensor_Out = (int16_T)((int16_T)(Sensor_In - StructPointer->OFFSET) *
StructPointer->GAIN);
}
See Also
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Create Tunable Calibration Parameter in the Generated Code” on page 22-121
• “Switch Between Sets of Parameter Values During Simulation and Code Execution”
on page 22-196
• “Create Custom Storage Classes by Using the Custom Storage Class Designer” on
page 26-26
26-18
Apply Custom Storage Classes to Individual Signal, State, and Parameter Data Elements
To achieve C code patterns such as grouping variables into flat structures and to control
declaration and definition file placement, you can use the custom storage classes from the
built-in package Simulink.
For information about applying storage classes to categories of data by default, by using
the Code Mapping Editor, see “Configure Default Code Generation for Data” on page 21-
8.
To apply a custom storage class from a package other than Simulink (such as a package
that you create):
26-19
26 Custom Storage Classes in Embedded Coder
• To apply the custom storage class to a signal, state, or Data Store Memory block
(without creating a data object), configure the data item to use custom storage classes
from the target package instead of the Simulink package. For example, if the name
of the target package is myPackage, in a Signal Properties dialog box or the Property
Inspector, set Signal object class to myPackage.Signal. If the target class does not
appear in the list, see “Target Class Does Not Appear in List of Signal Object Classes”
on page 26-20.
If you use the Model Data Editor, to identify the target package, you must use a
different technique. See “Apply Custom Storage Class from Specific Package to Signal,
State, or Data Store Memory Block Using the Model Data Editor” on page 26-20.
• To apply the custom storage class by using a data object (required for block
parameters), instead of creating a Simulink.Signal or Simulink.Parameter
object, create a myPackage.Signal or myPackage.Parameter object. To create
data objects from your package, see “Create Data Objects from Another Data Class
Package” (Simulink). For an example that shows how to create and apply your own
custom storage class, see “Create and Apply a Custom Storage Class” on page 26-26.
When you use the Signal object class drop-down list in a dialog box or in the Property
Inspector, if the class that you want does not appear in the list:
If you created your own package, the classes that the package defines appear in the
dialog box only if you put the package folder in your current folder or put the parent
folder of the package folder on the MATLAB path.
3 From the drop-down list, select the option that corresponds to what you selected. For
example, select mpt.Signal.
Apply Custom Storage Class from Specific Package to Signal, State, or Data
Store Memory Block Using the Model Data Editor
When you use the Model Data Editor, to apply custom storage classes from a specific
package, use the Model Explorer to create a signal object from the target package. Then,
when you open the Model Data Editor, the Storage class column displays custom storage
classes from the target package.
26-20
Apply Custom Storage Classes to Individual Signal, State, and Parameter Data Elements
An object of the target signal class appears in the base workspace. Optionally, delete
this unnecessary object.
7 Use the Model Data Editor to apply custom storage classes from the target package
to other data items. In the Model Data Editor, in the Storage class column, the drop-
down list allows you to select custom storage classes from the target package.
To learn how to use the Model Data Editor to configure a data interface, see “Design Data
Interface by Configuring Inport and Outport Blocks” (Simulink Coder).
1 Create a signal or parameter data object from the target package. For example,
create a Simulink.Signal object or a myPackage.Parameter object.
myParam = Simulink.Parameter(5.2);
2 In the nested Simulink.CoderInfo object, set the StorageClass property to
'Custom'. Then, use the CustomStorageClass property to specify the custom
storage class.
myParam.CoderInfo.StorageClass = 'Custom';
myParam.CoderInfo.CustomStorageClass = 'ExportToFile';
3 If the custom storage class allows you to specify additional settings such as Header
file (see “Specify File Names and Other Data Attributes With Storage Class
(Embedded Coder)” on page 22-76), in the nested Simulink.CoderInfo object, use
the CustomAttributes property to specify values for the additional settings.
myParam.CoderInfo.CustomAttributes.HeaderFile = 'myHeader.h';
26-21
26 Custom Storage Classes in Embedded Coder
4 Choose one of these techniques to apply the custom storage class to a data item in a
model:
• To apply the custom storage class directly to a signal, state, or Data Store Memory
block, name the signal or state. Then, use the data object you created to set the
SignalObject signal property, the SignalObject block parameter (for an
Outport block), or the StateSignalObject block parameter. Clear the data
object you created. For an example, see “Apply Custom Storage Class Directly to
Signal Line Programmatically” on page 26-22.
• To apply the custom storage class by keeping the data object you created
(required for parameters), associate the data object with the data item in the
model. To make this association, see “Use Data Objects in Simulink Models”
(Simulink).
This example shows how to apply a custom storage class directly to a signal line in a
model, without an external data object.
rtwdemo_secondOrderSystem
2 Create a handle to the output of the block named Force: f(t).
portHandles = get_param('rtwdemo_secondOrderSystem/Force: f(t)','PortHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'Name','ForceSignal')
4 In the base workspace, create a signal object and specify a custom storage class and
relevant additional settings such as HeaderFile.
tempObj = Simulink.Signal;
tempObj.CoderInfo.StorageClass = 'Custom';
tempObj.CoderInfo.CustomStorageClass = 'ExportToFile';
tempObj.CoderInfo.CustomAttributes.HeaderFile = 'myHdrFile.h';
You can create the object from the data class package Simulink, or from any other
package, such as a package that you create.
5 Embed the signal object in the target signal line by attaching a copy of the temporary
workspace object.
26-22
Apply Custom Storage Classes to Individual Signal, State, and Parameter Data Elements
set_param(outportHandle,'SignalObject',tempObj);
6 Clear the object from the base workspace. The signal now uses an embedded copy of
the object.
clear tempObj
To modify an existing embedded signal object, copy the object into the base workspace,
modify the copy, and reattach the copy to the signal or state. For example, to change the
custom storage class of the embedded signal object that you attached to the signal
ForceSignal in “Apply Custom Storage Class Directly to Signal Line Programmatically”
on page 26-22:
1 Copy the existing embedded signal object into the base workspace.
tempObj = get_param(outportHandle,'SignalObject');
2 Modify the properties of the object in the workspace.
tempObj.CoderInfo.CustomStorageClass='ImportFromFile';
tempObj.CoderInfo.CustomAttributes.HeaderFile = 'myOtherHdrFile.h';
3 Reattach a copy of the signal object.
set_param(outportHandle,'SignalObject',tempObj);
clear tempObj
To create a custom structure of parameter data in the generated code, consider creating a
corresponding structure in Simulink. See “Organize Data into Structures in Generated
Code” on page 22-177.
1 Create the ex_struct_param model with three Constant blocks and three Outport
blocks.
26-23
26 Custom Storage Classes in Embedded Coder
The data table now contains rows that correspond to the new parameter objects.
12 Use the Storage Class column to apply the custom storage class Struct to all three
parameter objects.
13 Use the Struct Name column to set the structure name to my_struct.
14 Press Ctrl+B to generate code.
26-24
See Also
real_T p3;
} my_struct_type;
/* p2 */
2.0,
/* p3 */
3.0
};
See Also
Related Examples
• “Configure Data Interface by Applying Custom Storage Classes”
• “Create and Apply a Custom Storage Class” on page 26-26
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Create Custom Storage Classes by Using the Custom Storage Class Designer” on
page 26-26
• “Data Objects” (Simulink)
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
• “Configure Generated Code According to Interface Control Document” on page 26-
83
• “Environment for Configuring Model Data and Functions for Code Generation” on
page 21-2
26-25
26 Custom Storage Classes in Embedded Coder
A package also defines Signal and Parameter data classes (see “Data Objects”
(Simulink)). A data object from a package such as Simulink can use custom storage
classes defined in that package but not custom storage classes that are defined in
packages.
For information about using the Custom Storage Class Designer to create memory
sections, see “Control Data and Function Placement in Memory by Inserting Pragmas” on
page 30-2.
Open the model rtwdemo_cscpredef. You can control code generated from this model by
defining your own data classes and creating your own custom storage classes.
In this example, you export the declarations and definitions of multiple signals and
parameters in the model to one declaration header file and one definition file.
To create custom storage classes, you first create a data class package to contain the
custom storage class definitions. Data objects that you create from your package can use
all of the custom storage classes that the package defines.
26-26
Create Custom Storage Classes by Using the Custom Storage Class Designer
1 Create your own data class package by copying the example package folder
+SimulinkDemos. Navigate to the example package folder.
cd(currentPath)
4 Paste the +SimulinkDemos folder from your clipboard into your working folder.
Rename the copied folder to +myPackage.
5 Navigate inside the +myPackage folder to the file Signal.m to edit the definition of
the Signal class.
6 Uncomment the methods section that defines the method setupCoderInfo. In the
call to the function useLocalCustomStorageClasses, replace 'packageName'
with 'myPackage'. When you finish, the section appears as follows:
methods
function setupCoderInfo(h)
% Use custom storage classes from this package
useLocalCustomStorageClasses(h, 'myPackage');
end
end % methods
26-27
26 Custom Storage Classes in Embedded Coder
You can use the Custom Storage Class Designer to create or to edit the custom storage
classes that a data class package defines.
1 Set your current folder to the folder that contains the package myPackage.
2 Open the Custom Storage Class Designer.
cscdesigner('myPackage')
3 Select the custom storage class ExportToFile.
4 In the Name field, rename the custom storage class to ExportToGlobal.
5 In the Header file drop-down list, change the selection from Instance specific
to Specify. In the new field, provide the header file name global.h.
6 In the Definition file drop-down list, change the selection from Instance
specific to Specify. In the new field, provide the definition file name global.c.
7 Click OK. Click Yes to save changes to the data class package myPackage.
To apply your own custom storage class, you create data objects from your package and
configure the objects to use your custom storage class.
1 Create data objects to represent some of the parameters and signals in the example
model. Create the objects using the data class package myPackage.
% Parameters
templimit = myPackage.Parameter(202);
pressurelimit = myPackage.Parameter(45.2);
O2limit = myPackage.Parameter(0.96);
rpmlimit = myPackage.Parameter(7400);
% Signals
tempalarm = myPackage.Signal;
pressurealarm = myPackage.Signal;
O2alarm = myPackage.Signal;
rpmalarm = myPackage.Signal;
2 Set the custom storage class of each object to ExportToGlobal.
% Parameters
templimit.CoderInfo.StorageClass = 'Custom';
templimit.CoderInfo.CustomStorageClass = 'ExportToGlobal';
26-28
Create Custom Storage Classes by Using the Custom Storage Class Designer
pressurelimit.CoderInfo.StorageClass = 'Custom';
pressurelimit.CoderInfo.CustomStorageClass = 'ExportToGlobal';
O2limit.CoderInfo.StorageClass = 'Custom';
O2limit.CoderInfo.CustomStorageClass = 'ExportToGlobal';
rpmlimit.CoderInfo.StorageClass = 'Custom';
rpmlimit.CoderInfo.CustomStorageClass = 'ExportToGlobal';
% Signals
tempalarm.CoderInfo.StorageClass = 'Custom';
tempalarm.CoderInfo.CustomStorageClass = 'ExportToGlobal';
pressurealarm.CoderInfo.StorageClass = 'Custom';
pressurealarm.CoderInfo.CustomStorageClass = 'ExportToGlobal';
O2alarm.CoderInfo.StorageClass = 'Custom';
O2alarm.CoderInfo.CustomStorageClass = 'ExportToGlobal';
rpmalarm.CoderInfo.StorageClass = 'Custom';
rpmalarm.CoderInfo.CustomStorageClass = 'ExportToGlobal';
3 Select the Signal name must resolve to Simulink signal object option for each of
the target signals in the model. You can select the option by using the Signal
Properties dialog box, the Resolve column in the Model Data Editor, or by using the
command prompt.
% Signal tempalarm
portHandles = get_param('rtwdemo_cscpredef/RelOp1','PortHandles');
outputPortHandle = portHandles.Outport;
set_param(outputPortHandle,'MustResolveToSignalObject','on')
% Signal pressurealarm
portHandles = get_param('rtwdemo_cscpredef/RelOp2','PortHandles');
outputPortHandle = portHandles.Outport;
set_param(outputPortHandle,'MustResolveToSignalObject','on')
% Signal O2alarm
portHandles = get_param('rtwdemo_cscpredef/RelOp3','PortHandles');
outputPortHandle = portHandles.Outport;
set_param(outputPortHandle,'MustResolveToSignalObject','on')
% Signal rpmalarm
portHandles = get_param('rtwdemo_cscpredef/RelOp4','PortHandles');
outputPortHandle = portHandles.Outport;
set_param(outputPortHandle,'MustResolveToSignalObject','on')
Generate Code
26-29
26 Custom Storage Classes in Embedded Coder
rtwbuild('rtwdemo_cscpredef')
2 In the code generation report, view the generated header file global.h. The file
contains the extern declarations of all of the model signals and parameters that use
the custom storage class ExportToGlobal.
26-30
Create Custom Storage Classes by Using the Custom Storage Class Designer
cscdesigner('mypkg')
The name of the folder that represents a package begins with a +. When you use
cscdesigner, omit the + from the name of the target package.
To control the effect that a custom storage class has on data in a model, you specify
properties of the storage class in the Custom Storage Class Designer. To determine how
to generate a particular kind of code, use the information in the table.
26-31
26 Custom Storage Classes in Embedded Coder
For some properties of a custom storage class, such as Data scope, instead of specifying
a value in the Custom Storage Class Designer, you can allow users of the storage class to
specify the value. You can create a single, flexible custom storage class instead of multiple
custom storage classes that vary only by a few property values.
For example, suppose you create a custom storage class that yields a global variable in
the generated code. You can configure the storage class so that a user can set the Data
scope property to Exported for a signal in a model and set the property to Imported for
a different signal.
In the Custom Storage Class Designer, for each property that you want to configure in
this way, set the property value to Instance specific. Then, when a user applies the
custom storage class to a data item, the property appears to the user as a custom
attribute for that data item. For information about instance-specific custom attributes, see
“Specify File Names and Other Data Attributes With Storage Class (Embedded Coder)” on
page 22-76.
Generate a Macro
To create a custom storage class that yields a macro in the generate code, set Data
initialization to Macro and clear For signals.
When you set Data initialization to Macro, Definition file has no meaning. To prevent
users of the custom storage class from specifying a meaningless definition file, in the
Custom Storage Class Designer, set Definition file to Specify and leave the text box
empty.
• To define the macro in a header file (#define), specify the name of the header file
with the Header file property.
• To provide the macro definition as a compiler option or compiler flag, set Data access
to Imported and Header file to Specify. Leave the Header file text box empty.
Then, the generated code does not define the macro and does not include (#include)
a header file.
26-32
Create Custom Storage Classes by Using the Custom Storage Class Designer
To specify the compiler option or flag, use the model configuration parameter
Configuration Parameters > Code Generation > Custom Code > Additional
build information > Defines. See Code Generation Pane: Custom Code: Additional
Build Information: Defines (Simulink Coder).
To create a custom storage class that aggregates data items into a flat structure (similar
to the built-in custom storage class Struct), set Type to FlatStructure. The
Structure Attributes tab appears.
• To control the name of the global structure variable that appears in the generated
code, use the Struct name property and text box.
• If you set Struct name to Instance specific, users of the custom storage class
specify the name of the structure variable. In this case, the code generator derives the
name of the structure type from the name of the variable.
To more precisely control the name and other characteristics of the structure type, set
Struct name to Specify. Control the type characteristics by using the additional
properties that appear.
• To generate a structure with bit fields (similar to the built-in custom storage class
BitField), select Bit-pack booleans. Data items that use the data type boolean
appear in the generated code as bit fields of the structure.
• To use the default Simulink Coder initialization strategy, set Data initialization to the
default value, Auto.
26-33
26 Custom Storage Classes in Embedded Coder
Using the built-in custom storage class GetSet, you can generate code that calls your
external, custom functions instead of directly interacting with variables. For general
information about GetSet, see “Access Data Through Functions with Custom Storage
Class GetSet” on page 26-42.
• To apply the same get or set function naming scheme to all data items that use
the custom storage class, set Get function and Set function to Specify. Then, in
the text boxes, specify the function naming scheme, for example, get_myData_$N.
Use the token $N in a naming scheme to represent the name of each data item. If
you do not use the token, each data item uses the same specified get or set
function name, so the model generates an error when you generate code.
• To specify a different get or set function name for each data item, set Get
function or Set function to Instance specific. Later, when you create a data
item and apply the custom storage class, specify the function name by configuring
the custom attributes of the data item.
• Specify the name of the header file that declares the get and set functions with the
Header file property. In this case, Definition file has no meaning. To prevent users of
the custom storage class from specifying a meaningless definition file, set Definition
file to Specify and leave the text box empty.
• If you implement the get mechanism for scalar or array data as a macro instead of a
function, you can generate code that omits parentheses when reading that data. On
the Access Function Attributes tab, select Get data through macro (omit
parentheses).
When your external code defines data, to avoid generating a duplicate definition, you
must configure the generated code to read and write to the existing data. In the Custom
Storage Class Designer, set Data scope to Imported. The code generator does not
generate a definition for the global variable or macro.
• If your code defines a pointer variable, to generate code that interacts with the
pointer, set Data access to Pointer.
26-34
Create Custom Storage Classes by Using the Custom Storage Class Designer
• If you generate structured data by setting Type to FlatStructure, your code must
define the structure type and the global structure variable.
• If your code initializes state or signal data, you can prevent the generated code from
overwriting your initialization by setting Data initialization to None. See “Prevent
Duplicate Initialization Code for Global Variables” on page 42-103
To customize the comments that appear in the generated code, on the Comments tab, set
Comment rules to Specify. To specify a comment that appears with the declaration of
each data item, use the Declaration comment box. To specify a comment that appears
with the definition, use the Definition comment box.
For structured data (you set Type to FlatStructure), to specify a comment that
appears with the structure type definition, use the Type comment box.
For example, validating the custom storage class warns you if you accidentally set Data
initialization to Macro with For signals selected. A signal cannot appear in the
generated code as a macro.
26-35
26 Custom Storage Classes in Embedded Coder
Then, the defining package and any referencing packages can use the custom storage
class. When you want to make a change to the custom storage class, you make the change
only once, in the defining package.
To configure a package to refer to a custom storage class that another package defines:
1 In the Custom Storage Class Designer, select the Custom Storage Class tab.
2 Use Select Package to select the referencing package. The package must be
writable.
3 In the Custom storage class definitions pane, select the existing definition below
which you want to insert the reference.
4 Click New Reference.
A new reference with a default name and properties appears below the previously
selected definition. The new reference is selected and a Reference tab appears that
shows the initial properties.
5 Use Name to specify a name for the new reference. The name must be unique in the
importing package, but can duplicate the name in the source package. The name
cannot be a TLC keyword.
6 Set Refer to custom storage class in package to specify the package that contains
the custom storage class that you want to reference.
7 Set Custom storage class to reference to specify the custom storage class to be
referenced.
8 Click OK or Apply. To save the changes permanently, click Save.
• To control the order of the custom storage classes in the list, in the Custom Storage
Class Designer, use the Up and Down buttons. The order of the custom storage
classes in drop-down lists matches the order that you specify in the Custom Storage
Class Designer.
• To prevent a user of a custom storage class from applying the storage class to
parameter data or to signal and state data, use the For parameters and For signals
check boxes. When you clear one of these properties, for the corresponding kind of
data, the custom storage class does not appear in the drop-down list.
26-36
See Also
For example, if your custom storage class yields a macro in the generated code
because you set Data initialization to Macro, to prevent users from applying the
custom storage class to signal data, clear For signals.
You can prevent changes to the custom storage class definitions of an entire package by
converting the csc_registration.m file from a MATLAB file to a P-file. Use the pcode
function.
See Also
Related Examples
• “Create and Apply a Custom Storage Class” on page 26-26
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
26-37
26 Custom Storage Classes in Embedded Coder
• “Define Storage Classes, Memory Sections, and Function Templates for Software
Architecture” on page 20-2
• “Data Objects” (Simulink)
• “Finely Control Data Representation by Writing TLC Code for a Custom Storage
Class” on page 26-39
• “Access Structured Data Through a Pointer That External Code Defines” on page 26-
12
26-38
Finely Control Data Representation by Writing TLC Code for a Custom Storage Class
For an example, see “Generate Code That Dereferences Data from a Literal Memory
Address” on page 52-21. For general information about TLC code, see “Why Use the
Target Language Compiler?” (Simulink Coder).
When you create a custom storage class with Type set to Other, to add your own
instance-specific properties that are not built into the Custom Storage Class Designer,
create a custom attributes class for your package. A custom attributes class is a MATLAB
class that you create as a subclass of Simulink.CustomStorageClassAttributes.
Each property that you add to your custom attributes class appears to the user of the
custom storage class as an instance-specific property.
To create your custom attributes class, see “Define Data Classes” (Simulink).
26-39
26 Custom Storage Classes in Embedded Coder
cscdesigner -advanced
2 Select your package and create a custom storage class.
3 For the custom storage class, set Type to Other. In the Other Attributes pane,
specify the name of your TLC file and the name of your custom attributes class.
4 Set the properties on the Other Attributes pane.
• Is grouped: Select this option if you intend to combine multiple data items into a
single entity in the generated code. For example, the built-in custom storage
classes BitField and Struct are grouped because they can aggregate multiple
data items into a single structure variable.
• TLC file name: Enter the name of your TLC file. The Custom Storage Class
Designer assumes that the file exists in the package tlc folder, so specify only the
name of the file, not the file path.
• CSC attributes class name: (optional) If you created a custom attributes class,
enter the full name of the class, including the package name. For example, specify
myPackage.myCustomAttsClass. For more information, see “Create Custom
Attributes Class for Custom Storage Class” on page 26-39.
5 On the General and Comments panes, specify values for the remaining properties.
26-40
See Also
See Also
Related Examples
• “Introduction to the Target Language Compiler” (Simulink Coder)
• “Generate Code That Dereferences Data from a Literal Memory Address” on page
52-21
• “Create and Apply a Custom Storage Class” on page 26-26
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
• “Create Custom Storage Classes by Using the Custom Storage Class Designer” on
page 26-26
• “Define Storage Classes, Memory Sections, and Function Templates for Software
Architecture” on page 20-2
• “Data Object Information in model.rtw” (Simulink Coder)
26-41
26 Custom Storage Classes in Embedded Coder
To generate code that conforms to the AUTOSAR standard by accessing data through Rte
function calls, use the Configure AUTOSAR Interface dialog box. See “AUTOSAR
Component Configuration”.
View the example legacy header file ComponentDataHdr.h. The file defines a large
structure type ComponentData.
rtwdemodbtype('ComponentDataHdr.h','/* ComponentData */','} ComponentData;',1,1)
/* ComponentData */
typedef struct {
ScalarData scalars;
VectorData vectors;
StructData structs;
MatricesData matrices;
} ComponentData;
The field scalars is a substructure that uses the structure type ScalarData. The
structure type ScalarData defines three scalar fields: inSig, scalarParam, and
outSig.
rtwdemodbtype('ComponentDataHdr.h','/* ScalarData */','} ScalarData;',1,1)
/* ScalarData */
typedef struct {
26-42
Access Data Through Functions with Custom Storage Class GetSet
double inSig;
double scalarParam;
double outSig;
} ScalarData;
View the example legacy source file getsetSrc.c. The file defines and initializes a global
variable ex_getset_data that uses the structure type ComponentData. The
initialization includes values for the substructure scalars.
rtwdemodbtype('getsetSrc.c','/* Field "scalars" */','/* End of "scalars" */',1,1)
/* Field "scalars" */
{
3.9,
12.3,
0.0
},
/* End of "scalars" */
The file also defines functions that read from and write to the fields of the substructure
scalars. The functions simplify data access by dereferencing the leaf fields of the global
structure variable ex_getset_data.
rtwdemodbtype('getsetSrc.c',...
'/* Scalar get() and set() functions */','/* End of scalar functions */',1,1)
double get_inSig(void)
{
return ex_getset_data.scalars.inSig;
}
double get_scalarParam(void)
{
return ex_getset_data.scalars.scalarParam;
26-43
26 Custom Storage Classes in Embedded Coder
double get_outSig(void)
{
return ex_getset_data.scalars.outSig;
}
View the example legacy header file getsetHdrScalar.h. The file contains the extern
prototypes for the get and set functions defined in getsetSrc.c.
Open the example model rtwdemo_getset_scalar. The model creates the data objects
inSig, outSig, and scalarParam in the base workspace. The objects correspond to the
signals and parameter in the model.
open_system('rtwdemo_getset_scalar')
In the base workspace, double-click the object inSig to view its properties. The object
uses the custom storage class GetSet. The GetFunction and SetFunction properties
are set to the defaults, get_$N and set_$N. The generated code uses the function names
that you specify in GetFunction and SetFunction to read from and write to the data.
The code replaces the token $N with the name of the data object. For example, for the
data object inSig, the generated code uses calls to the legacy functions get_inSig and
set_inSig.
26-44
Access Data Through Functions with Custom Storage Class GetSet
For the data object inSig, the HeaderFile property is set to getsetHdrScalar.h.
This legacy header file contains the get and set function prototypes. The data objects
outSig and scalarParam also use the custom storage class GetSet and the header file
getsetHdrScalar.h.
In the model Configuration Parameters dialog box, on the Code Generation > Custom
Code pane, under Include list of additional, select Source files. The Source files box
identifies the source file getsetSrc.c for inclusion during the build process. This legacy
source file contains the get and set function definitions and the definition of the global
structure variable ex_getset_data.
rtwbuild('rtwdemo_getset_scalar');
In the code generation report, view the file rtwdemo_getset_scalar.c. The model
step function uses the legacy get and set functions to execute the algorithm. The
generated code accesses the legacy signal and parameter data by calling the custom,
handwritten get and set functions.
rtwdemodbtype(fullfile('rtwdemo_getset_scalar_ert_rtw','rtwdemo_getset_scalar.c'),...
'/* Model step function */','}',1,1)
You can generate code that calls your custom get and set functions as long as the
functions that you write accept and return the expected values. For scalar data, the
functions must have these characteristics:
• The get function must return a single scalar numeric value of the appropriate data
type, and must not accept any arguments (void).
26-45
26 Custom Storage Classes in Embedded Coder
• The set function must not return anything (void), and must accept a single scalar
numeric value of the appropriate data type.
View the example legacy header file ComponentDataHdr.h. The file defines a large
structure type ComponentData.
/* ComponentData */
typedef struct {
ScalarData scalars;
VectorData vectors;
StructData structs;
MatricesData matrices;
} ComponentData;
The field vectors is a substructure that uses the structure type VectorData. The
structure type VectorData defines three vector fields: inVector, vectorParam, and
outVector. The vectors each have five elements.
/* VectorData */
typedef struct {
double inVector[5];
double vectorParam[5];
double outVector[5];
} VectorData;
View the example legacy source file getsetSrc.c. The file defines and initializes a global
variable ex_getset_data that uses the structure type ComponentData. The
initialization includes values for the substructure vectors.
26-46
Access Data Through Functions with Custom Storage Class GetSet
/* Field "vectors" */
{
{5.7, 6.8, 1.2, 3.5, 10.1},
The file also defines functions that read from and write to the fields of the substructure
vectors. The functions simplify data access by dereferencing the leaf fields of the global
structure variable ex_getset_data. To access the vector data, all of the functions
accept an integer index argument. The get function returns the vector value at the input
index. The set function assigns the input value to the input index.
rtwdemodbtype('getsetSrc.c',...
'/* Vector get() and set() functions */','/* End of vector functions */',1,1)
26-47
26 Custom Storage Classes in Embedded Coder
return ex_getset_data.vectors.outVector[index];
}
View the example legacy header file getsetHdrVector.h. The file contains the extern
prototypes for the get and set functions defined in getsetSrc.c.
Open the example model rtwdemo_getset_vector. The model creates the data objects
inVector, outVector, and vectorParam in the base workspace. The objects
correspond to the signals and parameter in the model.
open_system('rtwdemo_getset_vector')
In the base workspace, double-click the object inVector to view its properties. The
object uses the custom storage class GetSet. The property HeaderFile is specified as
getsetHdrVector.h. This legacy header file contains the get and set function
prototypes.
In the model Configuration Parameters dialog box, on the Code Generation > Custom
Code pane, the example legacy source file getsetSrc.c is identified for inclusion during
the build process. This legacy source file contains the get and set function definitions
and the definition of the global structure variable ex_getset_data.
rtwbuild('rtwdemo_getset_vector');
26-48
Access Data Through Functions with Custom Storage Class GetSet
In the code generation report, view the file rtwdemo_getset_vector.c. The model
step function uses the legacy get and set functions to execute the algorithm.
rtwdemodbtype(fullfile('rtwdemo_getset_vector_ert_rtw','rtwdemo_getset_vector.c'),...
'/* Model step function */','}',1,1)
When you use the custom storage class GetSet with vector data, the get and set
functions that you provide must accept an index input. The get function must return a
single element of the vector. The set function must write to a single element of the
vector.
View the example legacy header file ComponentDataHdr.h. The file defines a large
structure type ComponentData.
rtwdemodbtype('ComponentDataHdr.h',...
'/* ComponentData */','} ComponentData;',1,1)
/* ComponentData */
typedef struct {
ScalarData scalars;
VectorData vectors;
StructData structs;
MatricesData matrices;
} ComponentData;
26-49
26 Custom Storage Classes in Embedded Coder
The field structs is a substructure that uses the structure type StructData. The
structure type StructData defines three fields: inStruct, structParam, and
outStruct.
/* StructData */
typedef struct {
SigBus inStruct;
ParamBus structParam;
SigBus outStruct;
} StructData;
The fields inStruct, structParam, and outStruct are also substructures that use the
structure types SigBus and ParamBus. Each of these two structure types define three
scalar fields.
/* SigBus */
typedef struct {
double cmd;
double sensor1;
double sensor2;
} SigBus;
/* ParamBus */
typedef struct {
double offset;
double gain1;
double gain2;
} ParamBus;
View the example legacy source file getsetSrc.c. The file defines and initializes a global
variable ex_getset_data that uses the structure type ComponentData. The
initialization includes values for the substructure structs.
rtwdemodbtype('getsetSrc.c',...
'/* Field "structs" */','/* End of "structs" */',1,1)
26-50
Access Data Through Functions with Custom Storage Class GetSet
/* Field "structs" */
{
{1.3, 5.7, 9.2},
The file also defines functions that read from and write to the fields of the substructure
structs. The functions simplify data access by dereferencing the fields of the global
structure variable ex_getset_data. The functions access the data in the fields
inStruct, structParam, and outStruct by accepting and returning complete
structures of the types SigBus and ParamBus.
rtwdemodbtype('getsetSrc.c',...
'/* Structure get() and set() functions */',...
'/* End of structure functions */',1,1)
SigBus get_inStruct(void)
{
return ex_getset_data.structs.inStruct;
}
ParamBus get_structParam(void)
{
return ex_getset_data.structs.structParam;
}
SigBus get_outStruct(void)
26-51
26 Custom Storage Classes in Embedded Coder
{
return ex_getset_data.structs.outStruct;
}
View the example legacy header file getsetHdrStruct.h. The file contains the extern
prototypes for the get and set functions defined in getsetSrc.c.
Open the example model rtwdemo_getset_struct. The model creates the data objects
inStruct, structParam, and outStruct in the base workspace. The objects
correspond to the signals and parameter in the model.
open_system('rtwdemo_getset_struct')
In the base workspace, double-click the object inStruct to view its properties. The
object uses the custom storage class GetSet. The property HeaderFile is specified as
getsetHdrStruct.h. This legacy header file contains the get and set function
prototypes.
26-52
Access Data Through Functions with Custom Storage Class GetSet
The model also creates the bus objects ParamBus and SigBus in the base workspace.
The signals and parameter in the model use the bus types that these objects define. The
property DataScope of each bus object is set to Imported. The property HeaderFile is
set to ComponentDataHdr.h. The generated code imports these structure types from the
legacy header file ComponentDataHdr.h.
In the model Configuration Parameters dialog box, on the Code Generation > Custom
Code pane, the example legacy source file getsetSrc.c is identified for inclusion during
the build process. This legacy source file contains the get and set function definitions
and the definition of the global structure variable ex_getset_data.
rtwbuild('rtwdemo_getset_struct');
In the code generation report, view the file rtwdemo_getset_struct.c. The model
step function uses the legacy get and set functions to execute the algorithm.
rtwdemodbtype(fullfile('rtwdemo_getset_struct_ert_rtw',...
'rtwdemo_getset_struct.c'),...
'/* Model step function */','}',1,1)
26-53
26 Custom Storage Classes in Embedded Coder
When you use the custom storage class GetSet with structured data, the get and set
functions that you provide must return and accept complete structures. The generated
code dereferences individual fields of the structure that the get function returns.
The output signal of the Bus Creator block is a test point. This signal is the input for a
Signal Conversion block. The test point and the Signal Conversion block exist so that the
generated code defines a variable for the output of the Bus Creator block. To provide a
complete structure argument for the function set_outStruct, you must configure the
model to create this variable.
View the example legacy header file ComponentDataHdr.h. The file defines a large
structure type ComponentData.
rtwdemodbtype('ComponentDataHdr.h',...
'/* ComponentData */','} ComponentData;',1,1)
/* ComponentData */
typedef struct {
ScalarData scalars;
VectorData vectors;
StructData structs;
MatricesData matrices;
} ComponentData;
The field matrices is a substructure that uses the structure type MatricesData. The
structure type MatricesData defines three fields: matrixInput, matrixParam, and
matrixOutput. The fields store matrix data as serial arrays. In this case, the input and
parameter fields each have 15 elements. The output field has nine elements.
rtwdemodbtype('ComponentDataHdr.h'...
,'/* MatricesData */','} MatricesData;',1,1)
26-54
Access Data Through Functions with Custom Storage Class GetSet
/* MatricesData */
typedef struct {
double matrixInput[15];
double matrixParam[15];
double matrixOutput[9];
} MatricesData;
View the example legacy source file getsetSrc.c. The file defines and initializes a global
variable ex_getset_data that uses the structure type ComponentData. The
initialization includes values for the substructure matrices.
rtwdemodbtype('getsetSrc.c',...
'/* Field "matrices" */','/* End of "matrices" */',1,1)
/* Field "matrices" */
{
{12.0, 13.9, 7.4,
0.5, 11.8, 6.4,
4.7, 5.3, 13.0,
0.7, 16.1, 13.5,
1.6, 0.5, 3.1},
The input matrix has five rows and three columns. The matrix parameter has three rows
and five columns. The matrix output has three rows and three columns. The file defines
macros that indicate these dimensions.
rtwdemodbtype('getsetSrc.c',...
'/* Matrix dimensions */','/* End of matrix dimensions */',1,1)
/* Matrix dimensions */
26-55
26 Custom Storage Classes in Embedded Coder
#define MATRIXINPUT_NROWS 5
#define MATRIXINPUT_NCOLS 3
#define MATRIXPARAM_NROWS 3
#define MATRIXPARAM_NCOLS 5
The file also defines functions that read from and write to the fields of the substructure
matrices.
rtwdemodbtype('getsetSrc.c',...
'/* Matrix get() and set() functions */','/* End of matrix functions */',1,1)
26-56
Access Data Through Functions with Custom Storage Class GetSet
The code that you generate from a model represents matrices as serial arrays. Therefore,
each of the get and set functions accept a single scalar index argument.
The generated code uses column-major format to store and to access matrix data.
However, many C applications use row-major indexing. To integrate the generated code
with the example legacy code, which stores the matrices matrixInput and
matrixParam using row-major format, the custom get functions use the column-major
index input to calculate an equivalent row-major index. The generated code algorithm,
which interprets matrix data using column-major format by default, performs the correct
matrix math because the get functions effectively convert the legacy matrices to column-
major format. The set function for the output, matrixOutput, also calculates a row-
major index so the code writes the algorithm output to matrixOutput using row-major
format. Alternatively, to integrate the column-major generated code with your row-major
legacy code, you can manually convert the legacy code to column-major format by
transposing your matrix data and algorithms.
View the example legacy header file getsetHdrMatrix.h. The file contains the extern
prototypes for the get and set functions defined in getsetSrc.c.
Open the example model rtwdemo_getset_matrix. The model creates the data objects
matrixInput, matrixParam, and matrixOutput in the base workspace. The objects
correspond to the signals and parameter in the model.
load_system('rtwdemo_getset_matrix')
set_param('rtwdemo_getset_matrix','SimulationCommand','Update')
open_system('rtwdemo_getset_matrix')
26-57
26 Custom Storage Classes in Embedded Coder
In the base workspace, double-click the object matrixInput to view its properties. The
object uses the custom storage class GetSet. The property HeaderFile is specified as
getsetHdrMatrix.h. This legacy header file contains the get and set function
prototypes.
In the model Configuration Parameters dialog box, on the Code Generation > Custom
Code pane, the example legacy source file getsetSrc.c is identified for inclusion during
the build process. This legacy source file contains the get and set function definitions
and the definition of the global structure variable ex_getset_data.
rtwbuild('rtwdemo_getset_matrix');
In the code generation report, view the file rtwdemo_getset_matrix.c. The model
step function uses the legacy get and set functions to execute the algorithm.
rtwdemodbtype(fullfile('rtwdemo_getset_matrix_ert_rtw',...
'rtwdemo_getset_matrix.c'),'/* Model step function */','}',1,1)
26-58
Access Data Through Functions with Custom Storage Class GetSet
int32_T matrixOutput_tmp;
To configure a single header file, get function naming scheme, or set function naming
scheme to use for every data item, you can use the Custom Storage Class Designer to
create your own copy of GetSet. You can specify the header file or function names in a
single location.
Follow these steps to create your own custom storage class by creating your own data
class package, creating a copy of GetSet, and applying the new custom storage class to
data items in your model.
1 Create your own data class package, myPackage, by copying the example package
folder +SimulinkDemos and renaming the copied folder as +myPackage. Modify the
Parameter and Signal class definitions so that they use the custom storage class
definitions from myPackage. For an example, see “Create Data Class Package” on
page 26-26.
2 Set your current folder to the folder that contains the package folder. Alternatively,
add the folder containing the package folder to your MATLAB path.
3 Open the Custom Storage Class Designer.
cscdesigner('myPackage')
26-59
26 Custom Storage Classes in Embedded Coder
4 Select the custom storage class GetSet. Click Copy to create a copy called
GetSet_1.
5 Select the new custom storage class GetSet_1. In the General tab, set Name to
myGetSet.
6 Set the drop-down list Header file to Specify. In the new text box, set Header file
to myFcnHdr.h. Click Apply.
7 On the Access Function Attributes tab, set the drop-down lists Get function and
Set function to Specify.
8 In the new boxes, set Get function to myGetFcn_$N and Set function to
mySetFcn_$N. Click OK. Click Yes in response to the message about saving changes.
When you generate code, the token $N expands into the name of the data item that
uses this custom storage class.
9 Apply the custom storage class myGetSet from your package to a data item. For
example, create a myPackage.Parameter object in the base workspace.
myParam = myPackage.Parameter(15.23);
myParam.CoderInfo.StorageClass = 'Custom';
myParam.CoderInfo.CustomStorageClass = 'myGetSet';
10 Use the object to set a parameter value in your model. When you generate code, the
code algorithm accesses the parameter through the functions that you specified. The
code uses an #include directive to include the header file that you specified.
• For scalar data, your macro must yield the scalar value.
• For array data, your macro must yield the starting memory address.
Create your own AccessFunction storage class by using the Custom Storage Class
Designer, as described in “Specify Header File or Function Naming Scheme for All Data
Items” on page 26-59. In the Designer, on the Access Function Attributes tab, select
Get data through macro (omit parentheses).
26-60
See Also
See Also
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Create and Apply a Custom Storage Class” on page 26-26
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
• “Finely Control Data Representation by Writing TLC Code for a Custom Storage
Class” on page 26-39
• “Generate Code That Dereferences Data from a Literal Memory Address” on page
52-21
26-61
26 Custom Storage Classes in Embedded Coder
Copy the script prepare_ext_code to your current folder and run the script. The script
copies external code files into several folders.
try
copyfile(fullfile(matlabroot,'examples','ecoder','main','prepare_ext_code.m'),...
'prepare_ext_code.m','f');
catch
end
run('prepare_ext_code.m');
type('ext_code_main.c')
In the shared folder, inspect ex_ext_projTypes.h. The file defines two custom data
types (typedef) that the data in the modules use.
type(fullfile('shared','ex_ext_projTypes.h'))
type(fullfile('io_drivers','ex_sensor_accessors.c'))
26-62
Integrate External Application Code with Code Generated from PID Controller
type(fullfile('ex_ext_inputs_proc','ex_ext_inputs_proc.c'))
The filter algorithm in this module and the algorithms in the other two modules require
state data, which must persist between execution cycles of the application. Each module
stores relevant state data as global variables. For example, in the ex_ext_inputs_proc
module, ex_ext_inputs_proc.c defines these variables:
• flowFilterIn_state_data
• tempFilterIn_state_data
• flowFilterIn_tmp_data
• tempFilterIn_tmp_data
The empty ex_ext_ctrl_alg folder is a placeholder for the generated code. The
ex_ext_ctrl_alg module must perform PID control on the filtered flow and
temperature measurements. Later, you examine the requirements for this code, which are
based on the code in the other modules.
type(fullfile('ex_ext_outputs_proc','ex_ext_outputs_proc.c'))
The actuator functions are defined in the io_drivers folder in the file
ex_actuator_accessors.c.
The figure shows the intended flow of data through the system. The figure also shows the
code files that define and declare the data (global variables) that cross the module
boundaries.
26-63
26 Custom Storage Classes in Embedded Coder
26-64
Integrate External Application Code with Code Generated from PID Controller
The blocks in the model implement the required PID control algorithm. The model uses
default code generation settings for an ERT-based system target file (ert.tlc).
• Use the custom data types dataPath_flow_T and dataPath_temp_T from the
external file ex_ext_projTypes.h.
• Read filtered sensor data from the global variables PROC_INPUT_FLOW and
PROC_INPUT_TEMP. The generated code must not define these variables because the
module ex_ext_inputs_proc defines them, declaring them in
ex_ext_proc_inputs.h.
• Write PID control signals to global variables named CONTR_SIG_FLOW and
CONTR_SIG_TEMP. The generated code must define these variables and declare them
in a file named ex_ext_ctrl_sigs.h. Then, the ex_ext_outputs_proc module
can read the raw control signals from them.
• Conform to variable naming standards that govern the external application. For
example, the generated code must store state data in global variables whose names
end in _data. In addition, for this example, the names of local function variables must
end in _local.
• Conform to standards that govern the organization of the code in each of the external
files. For example, each file contains sections, delimited by comments, that aggregate
similar code constructs such as type definitions, variable declarations, and function
definitions.
So that you and others can interact with the control algorithm during execution, for this
example, you also configure the generated code to define and declare const global
variables named PARAM_setpoint_flow and PARAM_setpoint_temp, which represent
the PID controller setpoints. The definitions must appear in a file named
ex_ext_ctrl_params.c and the declarations must appear in a file named
ex_ext_ctrl_params.h.
26-65
26 Custom Storage Classes in Embedded Coder
cd('shared')
Simulink.importExternalCTypes('ex_ext_projTypes.h');
In the Model Data Editor, for the Inport block that represents PROC_INPUT_FLOW, set
Data Type to dataPath_flow_T.
For the Inport block that represents PROC_INPUT_TEMP, set Data Type to
dataPath_temp_T.
In the model, select the output signal of each Constant block. In the Model Data Editor,
set Data Type to Inherit: Inherit via back propagation. With this setting, each
Constant block inherits its output data type from the block immediately downstream, in
this case, a Sum block.
Alternatively, to configure the data types, at the command prompt, use these commands.
set_param('ex_ext_ctrl_alg/In1','OutDataTypeStr','dataPath_flow_T')
set_param('ex_ext_ctrl_alg/In2','OutDataTypeStr','dataPath_temp_T')
set_param('ex_ext_ctrl_alg/Flow Setpt','OutDataTypeStr',...
'Inherit: Inherit via back propagation')
set_param('ex_ext_ctrl_alg/Temp Setpt','OutDataTypeStr',...
'Inherit: Inherit via back propagation')
Update the block diagram. The diagram shows that, due to data type inheritance and
propagation, all of the signals in the model use a custom data type.
Configure the model to generate code that accesses and defines the correct global
variables such as PROC_INPUT_FLOW and CONTR_SIG_TEMP.
In the Model Data Editor, select the Inports/Outports tab and set the Change view
drop-down list to Code.
26-66
Integrate External Application Code with Code Generated from PID Controller
For either row, set Storage Class to ImportFromFile and Header File to
ex_ext_proc_inputs.h. With the storage class ImportFromFile, each Inport block
appears in the generated code as a global variable. However, the generated code does not
define the variable, instead including (#include) the variable declaration from
ex_ext_proc_inputs.h.
Alternatively, to configure the signals, at the command prompt, use these commands.
temp = Simulink.Signal;
temp.CoderInfo.StorageClass = 'Custom';
temp.CoderInfo.CustomStorageClass = 'ImportFromFile';
temp.CoderInfo.CustomAttributes.HeaderFile = 'ex_ext_proc_inputs.h';
portHandles = get_param('ex_ext_ctrl_alg/In1','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'SignalObject',copy(temp))
portHandles = get_param('ex_ext_ctrl_alg/In2','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'SignalObject',copy(temp))
temp.CoderInfo.CustomStorageClass = 'ExportToFile';
temp.CoderInfo.CustomAttributes.HeaderFile = 'ex_ext_ctrl_sigs.h';
temp.CoderInfo.CustomAttributes.DefinitionFile = 'ex_ext_ctrl_sigs.c';
set_param('ex_ext_ctrl_alg/Out1','SignalObject',copy(temp))
set_param('ex_ext_ctrl_alg/Out2','SignalObject',copy(temp))
To apply a storage class to a block parameter, such as the Constant value parameter of a
Constant block, you must create a parameter object such as Simulink.Parameter. You
can use the Model Data Editor to create parameter objects.
26-67
26 Custom Storage Classes in Embedded Coder
Next to PARAM_setpoint_flow, click the action button (with three vertical dots) and
select Create.
For the other Constant block, use the Model Data Editor to create a
Simulink.Parameter object named PARAM_setpoint_temp with value 2.
Alternatively, to configure the blocks, at the command prompt, use these commands.
PARAM_setpoint_flow = Simulink.Parameter(3);
PARAM_setpoint_flow.CoderInfo.StorageClass = 'Custom';
PARAM_setpoint_flow.CoderInfo.CustomStorageClass = 'Const';
PARAM_setpoint_flow.CoderInfo.CustomAttributes.HeaderFile = 'ex_ext_ctrl_params.h';
PARAM_setpoint_flow.CoderInfo.CustomAttributes.DefinitionFile = 'ex_ext_ctrl_params.c';
PARAM_setpoint_temp = copy(PARAM_setpoint_flow);
PARAM_setpoint_temp.Value = 2;
mdlwks = get_param('ex_ext_ctrl_alg','ModelWorkspace');
assignin(mdlwks,'PARAM_setpoint_flow',copy(PARAM_setpoint_flow))
assignin(mdlwks,'PARAM_setpoint_temp',copy(PARAM_setpoint_temp))
set_param('ex_ext_ctrl_alg/Flow Setpt','Value','PARAM_setpoint_flow')
set_param('ex_ext_ctrl_alg/Temp Setpt','Value','PARAM_setpoint_temp')
In the external code, internal data that does not participate in the module interfaces, such
as state data and local variables in functions, conform to naming schemes. In the model,
26-68
Integrate External Application Code with Code Generated from PID Controller
configure internal data that appears in the generated code to mimic these naming
schemes.
In the model Configuration Parameters dialog box, inspect the Code Generation >
Symbols pane. When you specify values for the naming schemes under Identifier
format control:
Set Global variables to $R$N_data$M. This setting controls the names of global
variables, such as those that represent state data. The naming scheme $R$N_data_$M
most closely approximates the scheme that the state variables in the external code use.
Set Local temporary variables and Local block output variables to $N_local$M.
Alternatively, to set the configuration parameters, at the command prompt, use these
commands.
set_param('ex_ext_ctrl_alg','CustomSymbolStrGlobalVar','$R$N_data$M')
set_param('ex_ext_ctrl_alg','CustomSymbolStrTmpVar','$N_local$M')
set_param('ex_ext_ctrl_alg','CustomSymbolStrBlkIO','$N_local$M')
Configure the state data in the model to appear in the generated code as separate global
variables instead of fields of the standard DWork structure. In the model, select Code >
C/C++ Code > Configure Model in Code Perspective.
Underneath the block diagram, under Code Mappings > Data Defaults, for the
Internal data row, in the Storage Class column select ExportedGlobal.
Alternatively, to configure this default storage class, use these commands at the command
prompt:
coder.mapping.create('ex_ext_ctrl_alg');
coder.mapping.defaults.set('ex_ext_ctrl_alg','InternalData',...
'StorageClass','ExportedGlobal');
26-69
26 Custom Storage Classes in Embedded Coder
cd(fullfile('..','ex_ext_ctrl_alg'))
At the command prompt, navigate to the folder that contains the built-in code generation
template ert_code_template.cgt. By default, when you generate code with the
system target file ert.tlc, this template governs the organization and, in part, the
appearance of the code in each generated file.
currentFolder = pwd;
cd(fullfile(matlabroot,'toolbox','rtw','targets','ecoder'))
cd(currentFolder)
clear currentFolder
Paste the file into the ex_ext_ctrl_alg folder. Rename the file as
ex_my_code_template.cgt.
Open the file and replace all of the contents with this code.
type(fullfile(matlabroot,'examples','ecoder','ex_my_code_template.cgt'))
This new template conforms more closely to the organization of the external files. For
example, the template organizes similar code constructs into named sections (delimited
by comments) and, at the top of the template, specifies only minimal information about
each generated file.
In the model, select Configuration Parameters > Code Generation > Templates.
Under Code templates and Data templates, set the four configuration parameters to
ex_my_code_template.cgt.
Alternatively, to copy the file and set the parameters, at the command prompt, use these
commands.
copyfile(fullfile(matlabroot,'examples','ecoder','ex_my_code_template.cgt'),...
'ex_my_code_template.cgt','f')
set_param('ex_ext_ctrl_alg','ERTSrcFileBannerTemplate','ex_my_code_template.cgt')
set_param('ex_ext_ctrl_alg','ERTHdrFileBannerTemplate','ex_my_code_template.cgt')
26-70
Integrate External Application Code with Code Generated from PID Controller
set_param('ex_ext_ctrl_alg','ERTDataSrcFileTemplate','ex_my_code_template.cgt')
set_param('ex_ext_ctrl_alg','ERTDataHdrFileTemplate','ex_my_code_template.cgt')
Because the external code already defines a main function, select Configuration
Parameters > Generate code only and clear Configuration Parameters > Generate
an example main program.
set_param('ex_ext_ctrl_alg','GenCodeOnly','on')
set_param('ex_ext_ctrl_alg','GenerateSampleERTMain','off')
rtwbuild('ex_ext_ctrl_alg')
In the code generation report, inspect the generated files. The code meets the
requirements. For example, ex_ext_ctrl_sigs.c defines the control output signals,
CONTR_SIG_FLOW and CONTR_SIG_TEMP.
file = fullfile('ex_ext_ctrl_alg_ert_rtw','ex_ext_ctrl_sigs.c');
rtwdemodbtype(file,'dataPath_flow_T CONTR_SIG_FLOW;',...
'dataPath_temp_T CONTR_SIG_TEMP;',1,1)
file = fullfile('ex_ext_ctrl_alg_ert_rtw','ex_ext_ctrl_params.c');
rtwdemodbtype(file,'const dataPath_flow_T PARAM_setpoint_flow = 3.0;',...
'const dataPath_temp_T PARAM_setpoint_temp = 2.0;',1,1)
The file ex_ext_ctrl_alg.c defines global variables to store state data. The variables
follow the naming scheme that you specified.
file = fullfile('ex_ext_ctrl_alg_ert_rtw','ex_ext_ctrl_alg.c');
rtwdemodbtype(file,'dataPath_temp_T ex_ext_Integrator_DSTATE_b_data',...
'dataPath_flow_T ex_ext_ctrl__Filter_DSTATE_data;',1,1)
In the same file, the model execution function, ex_ext_ctrl_alg_step, creates local
function variables to store temporary calculations. The variables follow the naming
scheme that you specified.
rtwdemodbtype(file,'dataPath_flow_T Diff_local;',...
'dataPath_temp_T FilterCoefficient_localn;',1,1)
26-71
26 Custom Storage Classes in Embedded Coder
Some of the global and local variable names contain extra mangling characters that
prevent name clashes. These extra characters correspond to the $M token that you
specified in the naming schemes.
The generated code files are in the generated folders ex_ext_ctrl_alg_ert_rtw and
slprj. You must configure file management systems and build tools to use these folders
and files.
See Also
Related Examples
• “Choose an External Code Integration Workflow” on page 42-4
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Control Data and Function Interface in Generated Code” on page 22-42
• “Configure Generated Code According to Interface Control Document Interactively”
on page 26-73
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Specify Templates For Code Generation” on page 39-59
26-72
Configure Generated Code According to Interface Control Document Interactively
An ICD describes the data interface between two software components. To exchange and
share data, the components declare and define global variables that store signal and
parameter values. The ICD names the variables and lists characteristics such as data
type, physical units, and parameter values. When you create models of the components in
Simulink, you can configure the generated code to conform to the interface specification.
• ex_ICD_PCG_inter.xls
Inspect the cell values in the worksheet. The Owner column indicates the name of the
component that allocates memory for each signal. The DataType column indicates the
signal data type in memory. For example, the worksheet uses the expression Bus:
EngSensors to indicate a structure type named EngSensors.
In the Parameters worksheet, the Value column indicates the value of each parameter.
If the value of the parameter is nonscalar, the value is stored in its own separate
worksheet, which has the same name as the parameter.
In the Numeric Types worksheet, each row represents a named numeric data type. In
this ICD, the data use fixed-point data types (Fixed-Point Designer). The IsAlias column
indicates whether the C code uses the name of the data type (for example, s16En3) or
uses the name of the primitive integer data type that corresponds to the word length
(such as short). The DataScope column indicates whether the generated code exports
or imports the definition of the type.
26-73
26 Custom Storage Classes in Embedded Coder
In the Structure Types worksheet, each row represents either a structure type or a
field of a structure type. For structure types, the value in the DataType column is
struct. Subsequent rows that do not use struct represent fields of the preceding
structure type. This ICD defines a structure type, EngSensors, with four fields:
throttle, speed, ego, and map.
In the Enumerated Types worksheet, similar to the Structure Types worksheet, each
row represents either an enumerated type or an enumeration member. This ICD defines
an enumerated type sldemo_FuelModes.
Some data items in the ICD belong to other_component, which is a component that
exists outside of MATLAB. Create the code files that define and declare this external data.
Create the header file ex_inter_types.h in your current folder. This file defines the
structure type EngSensors and numeric data types such as u8En7.
#ifndef INTER_TYPES_H__
#define INTER_TYPES_H__
/* Engine speed. */
s16En3 speed;
/* EGO sensors. */
s16En7 ego;
/* Manifold pressure. */
u8En7 map;
} EngSensors;
26-74
Configure Generated Code According to Interface Control Document Interactively
#endif
Create the source file ex_inter_sigs.c in your current folder. This file defines the
imported signal sensors.
#include "ex_inter_sigs.h"
#include "ex_inter_types.h"
run(fullfile(matlabroot,'examples','ecoder','main','prepare_sldemo_fuelsys_dd_inter'))
sldemo_fuelsys_dd
26-75
26 Custom Storage Classes in Embedded Coder
This system model references a controller model. In this example, you generate code from
the controller model.
sldemo_fuelsys_dd_controller
26-76
Configure Generated Code According to Interface Control Document Interactively
Some of the signals in the controller model have names, for example, the input signal
sensors. Some block parameters in the model refer to Simulink.Parameter objects in
a data dictionary. For example, in the airflow_calc subsystem, the Pumping
Constant block uses the parameter objects PumpCon, SpeedVect, and PressVect.
These parameter objects set the values of the corresponding block parameters. You can
apply code generation settings to the signals and parameter objects.
Navigate to the root level of the controller model and select View > Model Data Editor.
26-77
26 Custom Storage Classes in Embedded Coder
In the Model Data Editor, activate the Change scope button. The Model Data Editor now
shows information about data items in the subsystems.
Click the Show/refresh additional information button. The Model Data Editor now
shows information about data objects (the Simulink.Parameter objects in the data
dictionary) that the model uses.
In the model, select the Inport block labeled sensors. The Model Data Editor highlights
the corresponding row.
Use the Model Data Editor to configure the signal according to the information in the
ICD:
• Set the value in the Data Type column to Bus: EngSensors. In this case, the value is
already set.
• Set the Change view drop-down list to Code and, for sensors, set Storage Class to
ImportFromFile. Use this storage class because the Owner column in the ICD
implies that a different component, not sldemo_fuelsys_dd_controller, provides
the C-code definition of the sensors variable. With this storage class, the generated
code does not define the variable.
• Set Header File to ex_inter_sigs.h. When you use a storage class that represents
imported data, such as ImportFromFile, you cannot specify Definition File in the
Model Data Editor. Instead, include the definition file (in this case,
ex_inter_sigs.c) in the code generation and build process by using Configuration
Parameters > Code Generation > Custom Code > Additional build information
> Source files.
Use the Model Data Editor to configure fuel_rate according to the ICD. To access
design properties such as minimum value (Min) and physical unit (Unit), set Change
view to Design. For code generation settings, because the ICD specifies
sldemo_fuelsys_dd_controller as the owner of the other signals, set Storage Class
to ExportToFile.
26-78
Configure Generated Code According to Interface Control Document Interactively
Set Change view to Code and configure code generation settings for the signal
fuel_mode.
You cannot use the Model Data Editor to configure design properties for fuel_mode
(such as data type) because fuel_mode is an output of a Stateflow chart. In the model,
navigate into the chart.
In the Model Explorer Contents pane (the middle pane), select the fuel_mode data item.
In the Dialog pane (the right pane), configure fuel_mode according to the ICD. In this
case, the signal data type is already set, so you can specify only the description.
In the ICD and the Model Data Editor, select the Parameters tab. In the Model Data
Editor, set Change view to Design.
In the Model Data Editor, use the Filter contents box to search for the first parameter,
PressEst. The Model Data Editor shows two rows: One row that corresponds to the
parameter object PressEst and one row that corresponds to the block parameter that
uses PressEst.
Use the Model Data Editor to configure PressEst according to the ICD. The parameter
value (the Value column) is already set. Because the ICD specifies
sldemo_fuelsys_dd_controller as the owner of PressEst, set Storage Class to
ExportToFile.
Use the Model Data Editor to configure the other parameters. Optionally, to apply a
change to multiple parameters at once, select multiple rows in the data table.
In the lower-left corner of the model, click the dictionary badge to open the data
dictionary in the Model Explorer.
In the Contents pane (the middle pane), select the Simulink.NumericType object
u8En7. This object represents one of the primitive typedef statements in
ex_inter_types.h.
26-79
26 Custom Storage Classes in Embedded Coder
Use the Model Explorer Dialog pane (the right pane) to configure the object according to
the ICD.
Use the Model Explorer to configure the other Simulink.NumericType objects. You can
use the Contents pane to perform batch operations.
In the Contents pane, click the Simulink.Bus object EngSensors. This object
represents the structure type that ex_inter_types.h defines.
In the Dialog pane (the right pane), click Launch Bus Editor.
Use the Bus Editor to configure the bus object and the signal elements in the bus (such as
throttle) according to the ICD.
In the Model Explorer Contents pane, click the enumerated type definition
sldemo_FuelModes.
Use the Dialog pane to configure the type according to the ICD. Set Storage Type to
Native Integer and Data Scope to Exported.
Configure the controller model to compile the generated code into an executable by
clearing the model configuration parameter Generate code only.
typedef enum {
LOW = 1, /* Default value */
RICH,
DISABLED
} sldemo_FuelModes;
26-80
Configure Generated Code According to Interface Control Document Interactively
#include "ex_inter_types.h"
The data header file global_data.h declares the exported parameters and signals that
the ICD specifies. To share this data, other components can include this header file.
The data definitions (memory allocation) appear in the source files that the ICD specifies:
params.c and signals.c. For example, params.c defines and initializes the parameter
RampRateKiZ.
s16En15 RampRateKiZ[25] = { 393, 786, 1180, 1573, 1966, 786, 1573, 2359, 3146,
3932, 1180, 2359, 3539, 4719, 5898, 1573, 3146, 4719, 6291, 7864, 1966, 3932,
5898, 7864, 9830 } ;
26-81
26 Custom Storage Classes in Embedded Coder
See Also
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Replace and Rename Data Types to Conform to Coding Standards” on page 24-27
• “Control Data and Function Interface in Generated Code” on page 22-42
• “Data Import and Export” (MATLAB)
• “What Is a Data Dictionary?” (Simulink)
• “Configure Generated Code According to Interface Control Document” on page 26-
83
• “Integrate External Application Code with Code Generated from PID Controller” on
page 26-62
26-82
Configure Generated Code According to Interface Control Document
An ICD describes the data interface between two software components. To exchange and
share data, the components declare and define global variables that store signal and
parameter values. The ICD names the variables and lists characteristics such as data
type, physical units, and parameter values. When you create models of the components in
Simulink, you can configure the generated code to conform to the interface specification.
• ex_ICD_PCG.xls
• ex_importICD_PCG.m
Inspect the cell values in the worksheet. The Owner column indicates the name of the
component that allocates memory for each signal. The DataType column indicates the
signal data type in memory. For example, the worksheet uses the expression Bus:
EngSensors to represent a structure type named EngSensors.
In the Parameters worksheet, the Value column indicates the value of each parameter.
If the value of the parameter is nonscalar, the value is stored in its own separate
worksheet, which has the same name as the parameter.
In the Numeric Types worksheet, each row represents a named numeric data type. In
this ICD, the data use fixed-point data types (Fixed-Point Designer). The IsAlias column
26-83
26 Custom Storage Classes in Embedded Coder
indicates whether the C code uses the name of the data type (for example, u8En7) or uses
the name of the primitive integer data type that corresponds to the word length. The
DataScope column indicates whether the generated code exports or imports the
definition of the type.
In the Structure Types worksheet, each row represents either a structure type or a
field of a structure type. For structure types, the value in the DataType column is
struct. Subsequent rows that do not use struct represent fields of the preceding
structure type. This ICD defines a structure type, EngSensors, with four fields:
throttle, speed, ego, and map.
In the Enumerated Types worksheet, similar to the Structure Types worksheet, each
row represents either an enumerated type or an enumeration member. This ICD defines
an enumerated type sldemo_FuelModes.
Some data items in the ICD belong to other component, which is a component that
exists outside of MATLAB. Create the code files that define and declare this external data.
Create the source file ex_inter_sigs.c in your current folder. This file defines the
imported signal sensors.
#include "ex_inter_sigs.h"
#include "ex_inter_types.h"
Create the header file ex_inter_types.h in your current folder. This file defines the
structure type EngSensors and numeric data types such as u8En7.
#ifndef INTER_TYPES_H__
#define INTER_TYPES_H__
26-84
Configure Generated Code According to Interface Control Document
/* Engine speed. */
s16En3 speed;
/* EGO sensors. */
s16En7 ego;
/* Manifold pressure. */
u8En7 map;
} EngSensors;
#endif
run(fullfile(matlabroot,'examples','ecoder','main','prepare_sldemo_fuelsys_dd'))
sldemo_fuelsys_dd
26-85
26 Custom Storage Classes in Embedded Coder
This system model references a controller model. In this example, you generate code from
the controller model.
sldemo_fuelsys_dd_controller
26-86
Configure Generated Code According to Interface Control Document
To configure code generation settings for the data items, import the settings from the
ICD.
Open the example script ex_importICD_PCG. The script imports the data from each
worksheet of the ICD into variables in the base workspace. It then configures the
properties of the Simulink.Signal and Simulink.Parameter objects in the base
workspace by using the imported data.
edit('ex_importICD_PCG')
If the base workspace already contains a data object that corresponds to a target data
item in the ICD, the script configures the properties of the existing object. If the object
does not exist, the script creates the object.
26-87
26 Custom Storage Classes in Embedded Coder
run('ex_importICD_PCG')
The script configures the data objects in the base workspace for code generation
according to the specifications in the ICD. The Simulink.Bus object EngSensors
represents the structure type from the ICD. The Simulink.NumericType objects, such
as u8En7, represent the fixed-point data types.
ans =
'Cannot redefine enumerated type sldemo_FuelModes because open models and existing
Configure the controller model to compile the generated code into an executable by
clearing the model configuration parameter Generate code only.
typedef enum {
LOW = 1, /* Default value */
RICH,
DISABLED
} sldemo_FuelModes;
#include "ex_inter_types.h"
26-88
Configure Generated Code According to Interface Control Document
The data header file global_data.h declares the exported parameters and signals that
the ICD specifies. To share this data, other components can include this header file.
The data definitions (memory allocation) appear in the source files that the ICD specifies,
params.c and signals.c. For example, params.c defines and initializes the parameter
RampRateKiZ.
s16En15 RampRateKiZ[25] = { 393, 786, 1180, 1573, 1966, 786, 1573, 2359, 3146,
3932, 1180, 2359, 3539, 4719, 5898, 1573, 3146, 4719, 6291, 7864, 1966, 3932,
5898, 7864, 9830 } ; /* Lookup table to determine throttle rate. */
26-89
26 Custom Storage Classes in Embedded Coder
When you make changes to the ICD, you can reuse the ex_importICD_PCG script to
reconfigure the model. Change the ownership of the signal sensors, the structure type,
and the fixed-point data types from other_component to
sldemo_fuelsys_dd_controller.
In the ICD, on the signals worksheet, for the signal sensors, set these cell values:
• Owner to sldemo_fuelsys_dd_controller
• HeaderFile to global_data.h
• DefinitionFile to signals.c
On the Numeric Types worksheet, for all of the fixed-point data types, set:
• DataScope to Exported
• HeaderFile to exported_types.h.
On the Structure Types worksheet, for the structure type EngSensors, set:
• DataScope to Exported
• HeaderFile to exported_types.h.
ans =
'Cannot redefine enumerated type sldemo_FuelModes because open models and existing
The generated file exported_types.h defines the structure type EngSensors and the
fixed-point data types.
26-90
Configure Generated Code According to Interface Control Document
The file signals.c now includes the definition of the signal sensors.
Objects and variables that you create in the base workspace (for example,
Simulink.Parameter objects) are not saved with the model. When you end your
MATLAB session, the objects and variables do not persist. To permanently store the
objects and variables, link one or more models to one or more data dictionaries.
Data dictionaries also enable you to track changes made to the objects and variables,
which helps you to:
• Reconcile the data stored in MATLAB with the data stored in the ICD.
• Export data from MATLAB to the ICD.
1 In the top model, sldemo_fuelsys_dd, select File > Model Properties > Link to
Data Dictionary.
2 In the Model Properties dialog box, select Data Dictionary. Click New.
3 In the Create a new Data Dictionary dialog box, set File name to sysDict and click
Save.
4 In the Model Properties dialog box, click OK.
5 Click OK in response to the message about migrating referenced variables.
26-91
26 Custom Storage Classes in Embedded Coder
6 Click Yes in response to the message about removing the imported items from the
base workspace.
7 Click OK in response to the message about enumerated type migration.
The variables and objects that the models use all exist in the new data dictionary
sysDict.sldd, which is in your current folder. All three models in the model reference
hierarchy are linked to this dictionary.
To establish clear ownership of the data that you store in a dictionary, create reference
dictionaries.
The variables and objects that the controller model uses now exist in the referenced
dictionary ctrlDict.sldd. Because sysDict.sldd references ctrlDict.sldd, you
can view all of the data by opening sysDict.sldd in the Model Explorer.
Now that the model data acquire code generation settings from objects and variables that
are stored in data dictionaries, you can modify the ex_importICD_PCG script so it
accesses the dictionaries instead of the base workspace. For more information about the
programmatic interface for data dictionaries, see “Store Data in Dictionary
Programmatically” (Simulink).
You can import the definition of the enumerated type sldemo_FuelModes into the
controller dictionary. See “Enumerations in Data Dictionary” (Simulink).
Store Signal and State Design Attributes Inside or Outside of Model File
In this example, you use Simulink.Signal objects to specify design attributes such as
data types, minimum and maximum values, and physical units. The signal objects store
these specifications outside of the model file.
26-92
See Also
Alternatively, you can store these specifications in the model file by using block and port
parameters, which you can access through the Model Data Editor, the Property Inspector,
and other dialog boxes.
To decide where to store the specifications, see “Store Design Attributes of Signals and
States” (Simulink).
See Also
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Replace and Rename Data Types to Conform to Coding Standards” on page 24-27
• “Control Data and Function Interface in Generated Code” on page 22-42
• “Data Import and Export” (MATLAB)
• “What Is a Data Dictionary?” (Simulink)
• “Data Objects” (Simulink)
• “Configure Generated Code According to Interface Control Document Interactively”
on page 26-73
26-93
26 Custom Storage Classes in Embedded Coder
Minimizing the use of global variables by using local variables interacts with stack usage
control. For example, stack size can determine the number of local and global variables
that the code generator can allocate in the generated code. For more information, see
“Customize Stack Space Allocation” (Simulink Coder).
Example Model
The model rtwdemo_localizable_csc contains two signals that have a Localizable
custom storage class. In the Latching subsystem, the signal with the label Latch has a
Localizable custom storage class. In the Debug subsystem, the signal with the label
Debug has a Localizable custom storage class.
26-94
Generate Local Variables with Localizable Custom Storage Class
model='rtwdemo_localizable_csc';
open_system(model);
2 To observe the specification, for each signal, open the Signal Properties dialog box
and select the Code Generation tab. The Signal object class parameter is set to
26-95
26 Custom Storage Classes in Embedded Coder
Both functions contain variables for holding intermediate values. The Debug_b
function contains the variable Debug. The Latching function contains the variable
Latch.
real_T Debug[6];
real_T Latch[6];
26-96
Generate Local Variables with Localizable Custom Storage Class
The code readability and observability is the same as with the Localizable storage
class specification except the labeled signals are global variables.
2 Remove the Debug and Latch labels. Build the model. The Debug_b function
contains this code:
static void Debug(const real_T rtu_In1[6], const real_T rtu_In2[6], real_T
rtd_A[6])
{
int32_T i;
for (i = 0; i < 6; i++) {
rtd_A[i] += rtu_In1[i] * rtu_In2[i];
}
}
26-97
26 Custom Storage Classes in Embedded Coder
Additional Information
• For the code generator to localize signals with the Localizable Custom storage
class specification, in the Configuration Parameters dialog box, you must select the
Enable Local Block Outputs parameter. This parameter is on by default.
• You can specify the same Localizable storage class on two signals that are in
different reusable subsystems. Therefore, you can create a library block from a
reusable subsystem with a Localizable custom storage class specification.
• The code generator does not create a local variable for a signal that must stay global.
A few cases in which the code generator can not localize a signal are:
• Input and output signals of a Nonreusable subsystem even when the Function
interface parameter is set to Allow arguments.
• Signal is holding a state because its receiver and drive blocks execute at different
rates.
• Localizable specification is on a signal that crosses the boundary of a
conditionally executed subsystem.
See Also
More About
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
• “Choose a Storage Class for Controlling Data Representation in the Generated
Code” on page 22-69
26-98
27
You can use the Data Object Wizard to create data objects for:
This example shows how to use the Data Object Wizard to create and configure data
objects for code generation from the built-in package Simulink.
open_system('rtwdemo_basicsc')
27-2
Create Data Objects for Code Generation with Data Object Wizard
The model creates numeric variables in the base workspace. Blocks in the model use
these variables to set parameter values (such as the Gain parameter of a Gain block).
Some of the signals and block states in the model have explicit names, such as input1.
In the model, select Code > Data Objects > Data Object Wizard.
27-3
27 Data Object Wizard in Embedded Coder
27-4
Create Data Objects for Code Generation with Data Object Wizard
In the Data Object Wizard, click Find. The wizard proposes the creation of
Simulink.Parameter objects to replace the variables and the creation of
Simulink.Signal objects to represent the signals and states.
27-5
27 Data Object Wizard in Embedded Coder
27-6
Create Data Objects for Code Generation with Data Object Wizard
The wizard finds only signals, parameters, data stores, and states whose storage class is
set to Auto. For example, if you use the Signal Properties dialog box to specify a storage
class other than Auto for a signal line, the wizard does not propose a data object.
For detailed information about the options that you can choose in the Data Object Wizard,
see “Create Data Objects for a Model Using Data Object Wizard” (Simulink).
Storage classes determine how the generated code uses variables to represent signals,
parameters, and states. For data objects from the built-in package Simulink, the default
storage class is Auto. To specify storage classes for the new data objects, you can use the
Model Explorer.
27-7
27 Data Object Wizard in Embedded Coder
In the Contents pane, from the drop-down list Column View, select Storage Class.
Select all of the new data objects. For example, select the object input1, hold Shift, and
select the object X.
Set the property StorageClass for all of the data objects to ExportToFile. To change
the storage class for all of the selected objects, in the StorageClass column, click any of
the objects. In the drop-down list, select ExportToFile. The change that you make
propagates to all of the selected objects.
27-8
Create Data Objects for Code Generation with Data Object Wizard
In the model, set Configuration Parameters > Code Generation > System target file
to ert.tlc. With this setting, the code generator honors custom storage classes such as
ExportToFile.
In the code generation report, view the generated file myExportedHdrFile.h. The file
contains extern declarations for the global variables that correspond to the data objects.
View the file rtwdemo_basicsc.c. The file contains the definitions for the global
variables. The code assigns numeric values for the variables that correspond to
parameter objects.
27-9
27 Data Object Wizard in Embedded Coder
real32_T T2Data[9] = { 4.0F, 16.0F, 10.0F, 5.0F, 19.0F, 18.0F, 6.0F, 20.0F,
23.0F } ;
See Also
Simulink.Parameter | Simulink.Signal
Related Examples
• “Data Objects” (Simulink)
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements”
(Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
27-10
28
When producing code for a model, the code generator defines a set of entry-point
functions that you can call to execute the generated code. You can call the generated
functions from external code or from a version of the generated main function that you
modify.
The Code Interface Report section of the code generation report lists the entry-point
functions that the code generator produces for a model. For more information, see
“Analyze the Generated Code Interface” on page 38-19.
Depending on the style and configuration of a model, the code generator produces one or
more of these entry-point functions.
28-2
Configure Code Generation for Model Entry-Point Functions
28-3
28 Entry-Point Functions and Scheduling in Simulink Coder
If your application requires reusable, multi-instance entry-point function code, you can
configure the code generator to call each function (instance) with unique data. In this
case, the code is reentrant.
You configure whether entry-point functions are reusable with the model configuration
parameter “Code interface packaging” (Simulink Coder) and related parameters. The
parameter settings that you choose depend on factors such as configuration selections for
the system target file, programming language, and argument interface.
By default, for GRT- and ERT-based system target files, the code generator produces
single-instance C entry-point functions. The generated code:
The default model configuration parameter settings for configuring single-instance entry-
point function code are:
You can configure the code generator to produce reusable entry-point functions in C for
either a GRT- or ERT-based system target file. However, the function interfaces that the
code generator produces by default varies. Assuming that model configuration parameter
“Language” (Simulink Coder) is set to C and “Code interface packaging” (Simulink Coder)
is set to Reusable function, the code generator produces this entry-point function
code for each system target file scenario.
28-4
Configure Code Generation for Model Entry-Point Functions
If you are using an ERT-based system target file and want to generate reusable, multi-
instance C entry-point functions that are reentrant, set “Language” (Simulink Coder) to C
and set “Code interface packaging” (Simulink Coder) to Reusable function. Also
consider:
• Using dynamic memory allocation to initialize model data structures. Select “Use
dynamic memory allocation for model initialization” (Simulink Coder).
• Packing values of model root-level Inport blocks into a structure, packing values of
root-level Outport blocks into a second structure, and passing the structures to the
execution function as arguments by reference. Set “Pass root-level I/O as” (Simulink
Coder) to Structure reference.
• Packing values of model root-level Inport blocks and Output blocks into the real-time
model data structure and passing that structure to the execution function as an
argument by reference. Set “Pass root-level I/O as” (Simulink Coder) to Part of
model data structure.
The C++ class interface encapsulates model data as class properties and entry-point
functions as class methods. That interface is available for use with ERT-based system
28-5
28 Entry-Point Functions and Scheduling in Simulink Coder
target files. To use the interface, set “Language” (Simulink Coder) to C++ and set “Code
interface packaging” (Simulink Coder) to C++ class . You can:
• Preview and customize the C++ class interface by clicking “Configure C++ Class
Interface” (Simulink Coder). Customization means that you can generate code for
integration with external code and, if necessary, make sure that the code complies
with coding standards.
• Configure the visibility of class inheritance by specifying whether to generate the
block parameter structure as a public, private, or protected data member. Set
“Parameter visibility” (Simulink Coder) to public , private, or protected.
• Generate C++ interface code for model block parameters that meet code performance
or tunability requirements. The code can be noninlined or inlined access methods. Set
“Parameter access” (Simulink Coder) to Method or Inlined method.
• Generate C++ interface code for model root-level Inport and Outport blockset that
meets code performance, data tunability, or data packaging requirements. The code
can be one of these types of access methods.
• Apply a default function naming rule to a category of functions across a model. For
example, a default naming rule can produce a model_step function for each rate in
the multi-rate model. In the Code Mapping Editor, map a function category to a
function customization template that is defined to use the function naming rule (see
Code Mapping Editor). If necessary, you can override the default naming of function by
using function prototype control (see “Customize Generated C Function Interfaces” on
page 29-2 or “Customize Generated C++ Class Interfaces” on page 29-36).
28-6
Configure Code Generation for Model Entry-Point Functions
28-7
28 Entry-Point Functions and Scheduling in Simulink Coder
See Also
More About
• “Generate Reentrant Code from Top Models” (Simulink Coder)
• “Configure Default Code Generation for Categories of Model Data and Functions” on
page 21-7
• “Execution of Code Generated from a Model” (Simulink Coder)
• “Use the Real-Time Model Data Structure” on page 22-29
• “Deploy Generated Standalone Executable Programs To Target Hardware” on page
52-2
• “How Generated Code Exchanges Data with an Environment” (Simulink Coder)
• “Environment for Configuring Model Data and Functions for Code Generation” on
page 21-2
• “Generate Code That Responds to Initialize, Reset, and Terminate Events” (Simulink
Coder)
• “Configure a System Target File” on page 33-2
28-8
Generate C++ Class Interface to Model or Subsystem Code
C++ class encapsulation also works for right-click builds of nonvirtual subsystems. (For
information on requirements that apply, see “Generate C++ Class Interface to Nonvirtual
Subsystem Code” on page 28-10.)
1 Set the Configuration Parameters dialog box parameter Code Generation >
Language to C++. This selection also enables C++ class code interface packaging
for the model.
2 On the Code Generation > Interface pane, verify that the parameter Code
interface packaging (Simulink Coder) is set to C++ class.
3 Examine the setting of Multi-instance code error diagnostic (Simulink Coder).
Leave the parameter at its default value Error unless you need to alter the severity
level for diagnostics displayed when a model violates requirements for generating
multi-instance code.
28-9
28 Entry-Point Functions and Scheduling in Simulink Coder
/* Constructor */
rtwdemo_secondOrderSystemModelClass();
/* Destructor */
~rtwdemo_secondOrderSystemModelClass();
For more information about generating and calling model entry-point functions, see
“Configure Code Generation for Model Entry-Point Functions” (Simulink Coder).
Note If you have an Embedded Coder license and you have selected an ERT target for
your model, use additional Code Generation > Interface pane parameters to customize
the generated C++ class interface.
• The model is configured for the C++ language and C++ class code interface
packaging.
28-10
Generate C++ Class Interface to Model or Subsystem Code
To configure C++ class interfaces for a subsystem that meets the requirements:
Note If you have an Embedded Coder license and you have selected an ERT target for
your model, you can use the MATLAB command RTW.configSubsystemBuild to
customize the generated C++ class interface to subsystem code.
28-11
28 Entry-Point Functions and Scheduling in Simulink Coder
See Also
More About
• “Generate Reentrant Code from Top Models” (Simulink Coder)
• “Configure Code Generation for Model Entry-Point Functions” (Simulink Coder)
• “Execution of Code Generated from a Model” (Simulink Coder)
• “Rapid Prototyping Model Functions” (Simulink Coder)
28-12
Execution of Code Generated from a Model
The code generator also provides an interface that executes the generated model code.
The interface and model code are compiled together to create an executable program.
The next figure shows a high-level object-oriented view of the executable.
Run-Time Interface
In general, the conceptual design of the model execution driver does not change between
the rapid prototyping and embedded style of generated code. The following sections
describe model execution for single-tasking and multitasking environments both for
simulation (non-real-time) and for real time. For most model code, the multitasking
environment provides the most efficient model execution (that is, fastest sample rate).
The following concepts are useful in describing how model code executes.
• Initialization: model_initialize initializes the interface code and the model code.
• ModelOutputs: Calls blocks in your model that have a sample hit at the current time
and has them produce their output. model_output can be done in major or minor
time steps. In major time steps, the output is a given simulation time step. In minor
time steps, the interface integrates the derivatives to update the continuous states.
• ModelUpdate: model_update calls blocks that have a sample hit at the current point
in time and has them update their discrete states or similar type objects.
28-13
28 Entry-Point Functions and Scheduling in Simulink Coder
• ModelDerivatives: Calls blocks in your model that have continuous states and has
them update their derivatives. model_derivatives is only called in minor time
steps.
• ModelTerminate: model_terminate terminates the program if it is designed to run
for a finite time. It destroys the real-time model data structure, deallocates memory,
and can write data to a file.
Program Execution
A real-time program cannot require 100% of the CPU time. This requirement provides an
opportunity to run background tasks during the free time.
Background tasks include operations such as writing data to a buffer or file, allowing
access to program data by third-party data monitoring tools, or using Simulink external
mode to update program parameters.
It is important, however, that the program be able to preempt the background task so the
model code can execute in real time.
The way the program manages tasks depends on capabilities of the environment in which
it operates.
Program Timing
Real-time programs require careful timing of the task invocations (either by using an
interrupt or a real-time operating system tasking primitive) so that the model code
executes to completion before another task invocation occurs. The timing includes time to
read and write data to and from external hardware.
28-14
Execution of Code Generated from a Model
time
Time to execute
the model code Time available to process background tasks
time
Time to execute the model code
Task Timing
The sample interval must be long enough to allow model code execution between task
invocations.
In the figure above, the time between two adjacent vertical arrows is the sample interval.
The empty boxes in the upper diagram show an example of a program that can complete
one step within the interval and still allow time for the background task. The gray box in
the lower diagram indicates what happens if the sample interval is too short. Another task
invocation occurs before the task is complete. Such timing results in an execution error.
Note also that, if the real-time program is designed to run forever (that is, the final time is
0 or infinite so that the while loop never exits), then the shutdown code does not
execute.
For more information on how the timing engine works, see “Absolute and Elapsed Time
Computation” (Simulink Coder).
28-15
28 Entry-Point Functions and Scheduling in Simulink Coder
If you examine how LogTXY is called in the single-tasking and multitasking environments,
you will notice that for single-tasking LogTXY is called after ModelOutputs. During this
ModelOutputs call, blocks that have a hit at time t execute, whereas in multitasking,
LogTXY is called after ModelOutputs(tid=0), which executes only the blocks that have
a hit at time t and that have a task identifier of 0. This results in differences in the logged
values between single-tasking and multitasking logging. Specifically, consider a model
with two sample times, the faster sample time having a period of 1.0 second and the
slower sample time having a period of 10.0 seconds. At time t = k*10, k=0,1,2... both the
fast (tid=0) and slow (tid=1) blocks execute. When executing in multitasking mode,
when LogTXY is called, the slow blocks execute, but the previous value is logged,
whereas in single-tasking the current value is logged.
• Any root outport block has a sample time that is slower than the fastest sample time
• Any block with states has a sample time that is slower than the fastest sample time
• Any block in an enabled subsystem where the signal driving the enable port is slower
than the rate of the blocks in the enabled subsystem
For the first two cases, even though the logged values are different between single-
tasking and multitasking, the model results are not different. The only real difference is
where (at what point in time) the logging is done. The third (enabled subsystem) case
results in a delay that can be seen in a real-time environment.
28-16
Execution of Code Generated from a Model
The initialization phase begins first. This consists of initializing model states and setting
up the execution engine. The model then executes, one step at a time. First
ModelOutputs executes at time t, then the workspace I/O data is logged, and then
ModelUpdate updates the discrete states. Next, if your model has continuous states,
ModelDerivatives integrates the continuous states' derivatives to generate the states
for time tnew = t + h , where h is the step size. Time then moves forward to tnew and the
process repeats.
During the ModelOutputs and ModelUpdate phases of model execution, only blocks
that reach the current point in time execute.
28-17
28 Entry-Point Functions and Scheduling in Simulink Coder
Initialization
While (time < final time)
ModelOutputs(tid=0) -- Major time step.
LogTXY -- Log time, states, and root
-- outports.
ModelUpdate(tid=0) -- Major time step.
Integrate -- Integration in minor time step for
-- models with continuous states.
ModelDerivatives
Do 0 or more
ModelOutputs(tid=0)
ModelDerivatives
EndDo (Number of iterations depends upon the solver.)
Integrate derivatives to update continuous states.
EndIntegrate
For i=1:NumTids
ModelOutputs(tid=i) -- Major time step.
ModelUpdate(tid=i) -- Major time step.
EndFor
EndWhile
Termination
}
Multitasking operation is more complex than single-tasking execution because the output
and update functions are subdivided by the task identifier (tid) that is passed into these
functions. This allows for multiple invocations of these functions with different task
identifiers using overlapped interrupts, or for multiple tasks when using a real-time
operating system. In simulation, multiple tasks are emulated by executing the code in the
order that would occur if no preemption existed in a real-time system.
Multitasking execution assumes that all task rates are multiples of the base rate. The
Simulink product enforces this when you create a fixed-step multitasking model. The
multitasking execution loop is very similar to that of single-tasking, except for the use of
the task identifier (tid) argument to ModelOutputs and ModelUpdate.
Note You cannot use tid values from code generated by a target file and not by Simulink
Coder. Simulink Coder tracks the use of tid when generating code for a specific
subsystem or function type. When you generate code in a target file, this argument
cannot be tracked because the scope does not have subsystem or function type.
Therefore, tid becomes an undefined variable and your target file fails to compile.
28-18
Execution of Code Generated from a Model
rtOneStep()
{
Check for interrupt overflow
Enable "rtOneStep" interrupt
ModelOutputs -- Major time step.
LogTXY -- Log time, states and root outports.
ModelUpdate -- Major time step.
Integrate -- Integration in minor time step for models
-- with continuous states.
ModelDerivatives
Do 0 or more
ModelOutputs
ModelDerivatives
EndDo (Number of iterations depends upon the solver.)
Integrate derivatives to update continuous states.
EndIntegrate
}
main()
{
Initialization (including installation of rtOneStep as an
interrupt service routine, ISR, for a real-time clock).
While(time < final time)
Background task.
EndWhile
Mask interrupts (Disable rtOneStep from executing.)
Complete any background tasks.
Shutdown
}
At the interval specified by the program's base sample rate, the interrupt service routine
(ISR) preempts the background task to execute the model code. The base sample rate is
the fastest in the model. If the model has continuous blocks, then the integration step size
determines the base sample rate.
28-19
28 Entry-Point Functions and Scheduling in Simulink Coder
For example, if the model code is a controller operating at 100 Hz, then every 0.01
seconds the background task is interrupted. During this interrupt, the controller reads its
inputs from the analog-to-digital converter (ADC), calculates its outputs, writes these
outputs to the digital-to-analog converter (DAC), and updates its states. Program control
then returns to the background task. All of these steps must occur before the next
interrupt.
rtOneStep()
{
Check for interrupt overflow
Enable "rtOneStep" interrupt
ModelOutputs(tid=0) -- Major time step.
LogTXY -- Log time, states and root outports.
ModelUpdate(tid=0) -- Major time step.
Integrate -- Integration in minor time step for
-- models with continuous states.
ModelDerivatives
Do 0 or more
ModelOutputs(tid=0)
ModelDerivatives
EndDo (Number of iterations depends upon the solver.)
Integrate derivatives and update continuous states.
EndIntegrate
For i=1:NumTasks
If (hit in task i)
ModelOutputs(tid=i)
ModelUpdate(tid=i)
EndIf
EndFor
}
main()
{
Initialization (including installation of rtOneStep as an
interrupt service routine, ISR, for a real-time clock).
While(time < final time)
Background task.
EndWhile
28-20
Execution of Code Generated from a Model
tSingleRate()
{
MainLoop:
If clockSem already "given", then error out due to overflow.
Wait on clockSem
ModelOutputs -- Major time step.
LogTXY -- Log time, states and root
-- outports
ModelUpdate -- Major time step
Integrate -- Integration in minor time step
-- for models with continuous
-- states.
ModelDeriviatives
Do 0 or more
ModelOutputs
ModelDerivatives
EndDo (Number of iterations depends upon the solver.)
Integrate derivatives to update continuous states.
EndIntegrate
EndMainLoop
}
main()
{
Initialization
Start/spawn task "tSingleRate".
Start clock that does a "semGive" on a clockSem semaphore.
Wait on "model-running" semaphore.
Shutdown
}
28-21
28 Entry-Point Functions and Scheduling in Simulink Coder
tSubRate(subTaskSem,i)
{
Loop:
Wait on semaphore subTaskSem.
ModelOutputs(tid=i)
ModelUpdate(tid=i)
EndLoop
}
tBaseRate()
{
MainLoop:
If clockSem already "given", then error out due to overflow.
Wait on clockSem
For i=1:NumTasks
If (hit in task i)
If task i is currently executing, then error out due to
overflow.
Do a "semGive" on subTaskSem for task i.
EndIf
EndFor
ModelOutputs(tid=0) -- major time step.
LogTXY -- Log time, states and root outports.
ModelUpdate(tid=0) -- major time step.
Loop: -- Integration in minor time step for
-- models with continuous states.
ModelDeriviatives
Do 0 or more
ModelOutputs(tid=0)
ModelDerivatives
EndDo (number of iterations depends upon the solver).
Integrate derivatives to update continuous states.
EndLoop
28-22
Execution of Code Generated from a Model
EndMainLoop
}
main()
{
Initialization
Start/spawn task "tSubRate".
Start/spawn task "tBaseRate".
In this multitasking environment, the model is executed using real-time operating system
tasking primitives. Such environments require several model tasks (tBaseRate and
several tSubRate tasks) to run the model code. The base rate task (tBaseRate) has a
higher priority than the subrate tasks. The subrate task for tid=1 has a higher priority
than the subrate task for tid=2, and so on. The base rate task is invoked when a clock
tick occurs. The clock tick gives a clockSem to tBaseRate. The first thing tBaseRate
does is give semaphores to the subtasks that have a hit at the current point in time.
Because the base rate task has a higher priority, it continues to execute. Next it executes
the fastest task (tid=0), consisting of blocks in your model that have the fastest sample
time. After this execution, it resumes waiting for the clock semaphore. The clock ticks are
configured to occur at the fundamental step size for your model.
The Embedded Coder product provides a different framework called the embedded
program framework. The embedded program framework provides an optimized API that
is tailored to your model. When you use the embedded style of generated code, you are
modeling how you would like your code to execute in your embedded system. Therefore,
the definitions defined in your model should be specific to your embedded targets. Items
such as the model name, parameter, and signal storage class are included as part of the
API for the embedded style of code.
One major difference between the rapid prototyping and embedded style of generated
code is that the latter contains fewer entry-point functions. The embedded style of code
can be configured to have only one function, model_step.
28-23
28 Entry-Point Functions and Scheduling in Simulink Coder
For more information about how generated embedded code executes, see “Configure
Code Generation for Model Entry-Point Functions” on page 28-2.
See Also
More About
• “Time-Based Scheduling and Code Generation” on page 17-2
• “Sample Times in Subsystems” (Simulink)
• “Sample Times in Systems” (Simulink)
• “Time-Based Scheduling Example Models” on page 17-39
28-24
Rapid Prototyping Model Functions
• Model(): The model registration function. This function initializes the work areas (for
example, allocating and setting pointers to various data structures) used by the model.
The model registration function calls the MdlInitializeSizes and
MdlInitializeSampleTimes functions. These two functions are very similar to the
S-function mdlInitializeSizes and mdlInitializeSampleTimes methods.
• MdlStart(void): After the model registration functions MdlInitializeSizes and
MdlInitializeSampleTimes execute, the main program starts execution by calling
MdlStart. This routine is called once at startup.
• Code to initialize the states for each block in the root model that has states. A
subroutine call is made to the “initialize states” routines of conditionally executed
subsystems.
• Code generated by the one-time initialization (start) function for each block in the
model.
• Code to enable the blocks in the root model that have enable methods, and the
blocks inside triggered or function-call subsystems residing in the root model.
Simulink blocks can have enable and disable methods. An enable method is called
just before a block starts executing, and the disable method is called just after the
block stops executing.
• Code for each block in the model whose output value is constant. The block code
appears in the MdlStart function only if the block parameters are not tunable in
the generated code and if the code generator cannot eliminate the block code
through constant folding.
• MdlOutputs(int_T tid): MdlOutputs updates the output of blocks. The tid (task
identifier) parameter identifies the task that in turn maps when to execute blocks
based upon their sample time. This routine is invoked by the main program during
major and minor time steps. The major time steps are when the main program is
taking an actual time step (that is, it is time to execute a specific task). If your model
contains continuous states, the minor time steps will be taken. The minor time steps
are when the solver is generating integration stages, which are points between major
outputs. These integration stages are used to compute the derivatives used in
advancing the continuous states.
28-25
28 Entry-Point Functions and Scheduling in Simulink Coder
• MdlUpdate(int_T tid): MdlUpdate updates the states and work vector state
information (that is, states that are neither continuous nor discrete) saved in work
vectors. The tid (task identifier) parameter identifies the task that in turn indicates
which sample times are active, allowing you to conditionally update only states of
active blocks. This routine is invoked by the interface after the major MdlOutputs has
been executed. The solver is also called, and model_Derivatives is called in minor
steps by the solver during its integration stages. All blocks that have continuous states
have an identical number of derivatives. These blocks are required to compute the
derivatives so that the solvers can integrate the states.
• MdlTerminate(void): MdlTerminate contains any block shutdown code.
MdlTerminate is called by the interface, as part of the termination of the real-time
program.
The contents of the above functions are directly related to the blocks in your model. A
Simulink block can be generalized to the following set of equations.
y = f 0 (t, xc , xd ,u)
Output y is a function of continuous state xc, discrete state xd, and input u. Each block
writes its specific equation in a section of MdlOutputs.
xd +1 = fu (t, xd , u)
The discrete states xd are a function of the current state and input. Each block that has a
discrete state updates its state in MdlUpdate.
x& = f d (t, xc , u)
The derivatives x are a function of the current input. Each block that has continuous
states provides its derivatives to the solver (for example, ode5) in model_Derivatives.
The derivatives are used by the solver to integrate the continuous state to produce the
next value.
The output, y, is generally written to the block I/O structure. Root-level Outport blocks
write to the external outputs structure. The continuous and discrete states are stored in
the states structure. The input, u, can originate from another block's output, which is
located in the block I/O structure, an external input (located in the external inputs
structure), or a state. These structures are defined in the model.h file that the Simulink
Coder software generates.
28-26
Rapid Prototyping Model Functions
The next example shows the general contents of the rapid prototyping style of C code
written to the model.c file.
The next figure shows a flow chart describing the execution of the rapid prototyping
generated code.
28-27
28 Entry-Point Functions and Scheduling in Simulink Coder
Start Execution
MdlStart
MdlOutputs
model_Derivatives
MdlOutputs
model_Derivatives
Integration in Minor Time Steps
MdlTerminate
End
Each block places code in specific Mdl routines according to the algorithm that it is
implementing. Blocks have input, output, parameters, and states, as well as other general
items. For example, in general, block inputs and outputs are written to a block I/O
structure (model_B). Block inputs can also come from the external input structure
(model_U) or the state structure when connected to a state port of an integrator
(model_X), or ground (rtGround) if unconnected or grounded. Block outputs can also go
to the external output structure (model_Y). The next figure shows the general mapping
between these items.
28-28
Rapid Prototyping Model Functions
External External
Block I/O outputs
inputs struct
struct model_B struct
model_U model_Y
rtGround Block
Work
structs
rtRWork,
rtIWork,
rtPWork,
States Parameter ....
struct struct
model_X model_P
The following list defines the structures shown in the preceding figure:
• Block I/O structure (model_B): This structure consists of persistent block output
signals. The number of block output signals is the sum of the widths of the data output
ports of all nonvirtual blocks in your model. If you activate block I/O optimizations, the
Simulink and Simulink Coder products reduce the size of the model_B structure by
See “How Generated Code Stores Internal Signal, State, and Parameter Data”
(Simulink Coder) for more information on these optimizations.
Structure field names are determined either by the block's output signal name (when
present) or by the block name and port number when the output signal is left
unlabeled.
• Block states structures: The continuous states structure (model_X) contains the
continuous state information for blocks in your model that have continuous states.
Discrete states are stored in a data structure called the DWork vector
(model_DWork).
28-29
28 Entry-Point Functions and Scheduling in Simulink Coder
See Also
More About
• “Time-Based Scheduling and Code Generation” on page 17-2
• “How Generated Code Exchanges Data with an Environment” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
28-30
29
To Configure See
Default naming for categories of functions “Configure Default Code Generation for
(initialize/terminate, execution, and shared Functions” on page 21-15
utility) across a rate-based model
Function names for individual initialize and “Configure Names for Generated C
step (execute) functions for a rate-based Initialize and Step Functions” on page 29-
model interactively 5
Function arguments (return value, C type “Configure C Step Function Arguments” on
qualifiers, names, and order) for individual page 29-9
step functions for a rate-based model
interactively
Pair of function input and output arguments “Combine I/O Arguments in Model Step
as one shared argument for optimizing Interface” on page 29-13
buffer usage
Function name and arguments (C type “Configure C Initialize and Step Function
qualifiers, names, and order) for individual Interfaces Interactively” on page 29-16
step functions for a rate-based model
interactively
Function name and arguments (C type “Configure C Initialize and Step Function
qualifiers, names, and order) for individual Interfaces Programmatically” on page 29-
step functions for a rate-based model 19
programmatically
Function interfaces (function name, return “Customize Generated Function Interfaces
value, and argument C type qualifiers, for Simulink Function and Function Caller
names, and order) for Simulink Function Blocks” on page 29-24
and Function Caller blocks interactively
29-2
Customize Generated C Function Interfaces
To Configure See
Interfaces (function name and argument C “Customize Function Interfaces for
type qualifiers and names) for initialize and Nonvirtual Subsystems” on page 29-32
step functions for nonvirtual subsystems
interactively
• You can configure function arguments for single-instance models only. To generate
code for a single-instance model, set the model configuration parameter Code
interface packaging to Nonreusable function. For referenced models, select One
for the Total number of instances allowed per top model parameter.
• For reference models, if you set Code interface packaging to Reusable function,
the code generator ignores function argument settings.
• You must select the model configuration parameter Single output/update function.
• Multirate models are supported, but you must configure the models for single tasking.
• You must configure root-level inports and outports to use the Default storage class.
• Do not configure function interface with the static ert_main.c provided by
MathWorks. Specifying a function interface configuration other than the default
creates a mismatch between the generated code and the default static ert_main.c.
• The code generator removes the data structure for the root inports of the model unless
a subsystem implemented by a nonreusable function uses the value of one or more of
the inports.
• The code generator removes the data structure for the root outports of the model
except when you enable MAT-file logging, or if the sample time of one or more of the
outports is not the fundamental base rate (including a constant rate).
• If you copy a subsystem block to create a block in a new model or the same model, the
function interface information from the original subsystem block does not get copied
to the new subsystem block.
• If you have a Stateflow license, for a Stateflow chart that uses a model root inport
value, or that calls a subsystem that uses a model root inport value, do one of the
following to generate code:
29-3
29 Function and Class Interfaces in Embedded Coder
• Clear the Execute (enter) Chart At Initialization check box in the Stateflow
chart.
• Make the Stateflow function a nonreusable function.
• Insert a Simulink Signal Conversion block immediately after the root inport. In the
Signal Conversion block parameters dialog box, and select Exclude this block
from 'Block reduction' optimization.
• If a model root inport value connects to a Simscape conversion block, insert a
Simulink Signal Conversion block between the root inport and the Simscape
conversion block. In the Signal Conversion block parameters dialog box, select
Exclude this block from 'Block reduction' optimization.
• When building a referenced model that is configured with a function interface, do not
use virtual buses as inputs or outputs to the referenced model. When bus signals cross
referenced model boundaries, use nonvirtual buses.
• If the C function interface is not the default, the value is ignored for the model
configuration parameter Pass fixed-size scalar root inputs by value for code
generation. For more information, see “Pass fixed-size scalar root inputs by value for
code generation” (Simulink).
See Also
Related Examples
• “How Generated Code Exchanges Data with an Environment” on page 22-33
• “Customize Arguments In Generated Step Function Prototype”
• “Environment for Configuring Model Data and Functions for Code Generation” on
page 21-2
29-4
Configure Names for Generated C Initialize and Step Functions
• Align the interface of code generated for a model that you are integrating with
external code.
• Comply with code standards or guidelines.
You can configure the arguments for a generated step function interactively by using the
Configure C/C++ Function Interface dialog box. Or, you can configure the arguments
programmatically.
An interface preview for the step function updates dynamically as you make changes.
For more information about configuring step function names, see “Configure C Step
Function Arguments” on page 29-9.
29-5
29 Function and Class Interfaces in Embedded Coder
If arguments have previously been configured for the model, the dialog box displays
the current settings.
29-6
Configure Names for Generated C Initialize and Step Functions
3 If necessary, change the names of the initialize and step functions by entering new
names for C Initialize Function and C Step Function Name. Click Apply.
The function preview changes to reflect the new step function name.
Function names that you specify in this dialog box override function names previously
configured with default mappings.
29-7
29 Function and Class Interfaces in Embedded Coder
When you build a model as a top model, the C Initialize Function parameter
controls the name of the function that initializes states to nonzero values. The code
generator produces this function only if it contains such states or requires the
function for some other less common task. The code generator determines the names
of other initialization functions.
A referenced model contains at least one initialization function. When you build a
model as a referenced model, C Initialize Function does not control the name of the
Model Initialize fcn for ModelReference Block. The code generator
determines the name of this function for referenced model builds.
See Also
Related Examples
• “Configure C Step Function Arguments” on page 29-9
• “Configure C Initialize and Step Function Interfaces Interactively” on page 29-16
• “Configure C Initialize and Step Function Interfaces Programmatically” on page 29-
19
• “Customize Generated C Function Interfaces” on page 29-2
29-8
Configure C Step Function Arguments
• Align the interface of code generated for a model that you are integrating with
external code.
• Comply with code standards or guidelines.
For more information about configuring step function names, see “Configure Names
for Generated C Initialize and Step Functions” on page 29-5.
If arguments have previously been configured for the model, the dialog box displays
the current settings.
29-9
29 Function and Class Interfaces in Embedded Coder
29-10
Configure C Step Function Arguments
5 Configure the step function return argument by setting C return argument to void
or Out1.
The function preview changes to reflect the updated step function interface.
6 Configure step function input and output arguments. For each external inport or
outport, you can specify a C type qualifier and an argument name.
The function preview changes to reflect the updated step function interface.
• C type qualifier
These values are the possible values for the C type qualifier.
Auto –– Value
Const const arg Value with the const
qualifier
Pointer to const const *arg Value with const
qualifier and
referenced by pointer
Pointer *arg Referenced by pointer
Const pointer to const *const arg Value with const
const qualifier, referenced by
pointer, and the pointer
itself
When a model includes a referenced model, the code generator does the
following:
• For the referenced model, sets the type qualifier for a root input argument in
the step function interface to Auto. The code generator honors the interface
specification by generating a type cast that discards the const qualifier from
the source signal.
• For the parent of the reference model, sets the type qualifier for the source
signal to a value other than Auto.
To override this behavior, add a const type qualifier to the referenced model.
• Argument order
29-11
29 Function and Class Interfaces in Embedded Coder
You can adjust the argument order by selecting and dragging a row in the
argument table.
• Referenced model arguments and prototype preview
When you use a model as a reference model, the list of input and output
arguments in the prototype preview might not include arguments that appear in
the prototype in the generated code. For example, a model named
mdlref_counter has an inport with argument name arg_input, an outport
with argument name arg_output, and a saturation block whose limits have
workspace parameter argument names lower_saturation_limit and
upper_saturation_limit.
mdlref_counter_custom(arg_input, *arg_output)
The function prototype in the generated code, with the additional model
parameter arguments, is:
mdlref_counter_custom(
real_T arg_input,
real_T *arg_output,
real_T rtp_lower_saturation_limit,
real_T rtp_upper_saturation_limit)
7 Validate the step function interface by clicking Validate. If failures occur, correct
them and revalidate.
See Also
Related Examples
• “Configure Names for Generated C Initialize and Step Functions” on page 29-5
• “Combine I/O Arguments in Model Step Interface” on page 29-13
• “Configure C Initialize and Step Function Interfaces Interactively” on page 29-16
• “Configure C Initialize and Step Function Interfaces Programmatically” on page 29-
19
• “Customize Generated C Function Interfaces” on page 29-2
29-12
Combine I/O Arguments in Model Step Interface
The following requirements apply to combining model step function input and output
arguments:
• Assign the input and output arguments the same argument name.
• The corresponding Inport and Outport blocks must have the same data type and
sample rate.
• The sample rate of the Inport and Outport blocks must be the same as the base rate of
the model.
• A conditionally executed subsystem cannot drive the Outport block.
• A single, nonvirtual block output must drive the Outport block. For example, a Mux
block, which merges multiple buffers, cannot drive the Outport block.
This example shows how to configure a step function with combined input and output
arguments for example model rtwdemo_fcnprotoctrl:
29-13
29 Function and Class Interfaces in Embedded Coder
29-14
See Also
The interface preview is updated to reflect your changes. When you generate code
from the model, the arguments are combined in the function prototype.
6 Generate code and a report. Use the report to verify that the generated step function
code appears as expected.
boolean_T rtwdemo_fcnprotoctrl_step_custom(const real_T argIn1, const BusObject *
argIn2, uint8_T *argIn4, BusObject *sharedArg)
{
boolean_T Out1;
if (*argIn4 != 0) {
S1 = *argIn2;
} else {
S1 = *sharedArg;
}
*sharedArg = S1;
rtDWork.UnitDelay_DSTATE = argIn1;
return Out1;
}
For this example, the shared argument appears in read code for the inport and write
code for the outport.
See Also
Related Examples
• “Configure Names for Generated C Initialize and Step Functions” on page 29-5
• “Configure C Step Function Arguments” on page 29-9
• “Configure C Initialize and Step Function Interfaces Interactively” on page 29-16
• “Configure C Initialize and Step Function Interfaces Programmatically” on page 29-
19
• “Customize Generated C Function Interfaces” on page 29-2
29-15
29 Function and Class Interfaces in Embedded Coder
1 Open the model and save a copy to a writable working folder. The model is configured
with the ERT system target file.
2 Generate code and a report.
3 From the report, open the generated file rtwdemo_counter.c. Locate and review
the generated code for entry-point functions rtwdemo_counter_initialize and
rtwdemo_counter_step.
After reviewing the code, close the report window. Optionally, save
rtwdemo_counter.c and other generated files to a different location for later
comparison.
4 Configure the function names. In the Configure C Step Function Interface dialog box,
set C Initialize Function Name to rtwdemo_counter_cust_init. Set C Step
Function Name to rtwdemo_counter_cust_run.
5 Configure the step function arguments. For this example, change the configuration of
the input port. Select Configure arguments for step function prototype. Then,
click Get default. In the argument table, for Input port, set C Type Qualifier to
Pointer to const. Click Apply.
29-16
Configure C Initialize and Step Function Interfaces Interactively
Validation errors in this context prevent the code generator from producing code. If
failures occur, resolve the errors before proceeding.
7 Click OK. Then, save the model.
8 Generate code and a report.
29-17
29 Function and Class Interfaces in Embedded Coder
9 Verify that the generated code for the initialize and step entry-point functions is
consistent with the prototype configuration changes that you made. From the report,
open the generated file rtwdemo_counter.c. Locate and review the generated code
for entry-point functions rtwdemo_counter_cust_run and
rtwdemo_counter_cust_init.
/* Model step function */
void rtwdemo_counter_cust_run(const int32_T *arg_Input, int32_T *arg_Output)
{
...
}
You can use software-in-the-loop (SIL) testing to verify code generated for customized
initialize and step functions. Create a SIL block by using your generated code. Then,
integrate the SIL block into a model to verify that the generated code provides the
same result as the original model or nonvirtual subsystem. For more information, see
“Choose a SIL or PIL Approach” on page 67-12.
See Also
Related Examples
• “Configure C Step Function Arguments” on page 29-9
• “Configure Names for Generated C Initialize and Step Functions” on page 29-5
• “Configure C Initialize and Step Function Interfaces Programmatically” on page 29-
19
• “Customize Generated C Function Interfaces” on page 29-2
29-18
Configure C Initialize and Step Function Interfaces Programmatically
Function Description
RTW.ModelSpecificCPrototype.addArgConf Add step function argument configuration
information for Simulink model port to
model-specific C function prototype
RTW.ModelSpecificCPrototype.attachToMode Attach model-specific C function prototype to
l loaded ERT-based Simulink model
RTW.ModelSpecificCPrototype.getArgCatego Get step function argument category for
ry Simulink model port from model-specific C
function prototype
RTW.ModelSpecificCPrototype.getArgName Get step function argument name for
Simulink model port from model-specific C
function prototype
RTW.ModelSpecificCPrototype.getArgPositi Get step function argument position for
on Simulink model port from model-specific C
function prototype
RTW.ModelSpecificCPrototype.getArgQualif Get step function argument type qualifier for
ier Simulink model port from model-specific C
function prototype
RTW.ModelSpecificCPrototype.getDefaultCo Get default configuration information for
nf model-specific C function prototype from
Simulink model to which it is attached
RTW.ModelSpecificCPrototype.getFunctionN Get function names from model-specific C
ame function prototype
RTW.ModelSpecificCPrototype.getNumArgs Get number of step function arguments from
model-specific C function prototype
RTW.ModelSpecificCPrototype.getPreview Get model-specific C function prototype code
previews
29-19
29 Function and Class Interfaces in Embedded Coder
Function Description
RTW.configSubsystemBuild Open UI to configure C function prototype or
C++ class interface for right-click build of
specified subsystem
RTW.getFunctionSpecification Get handle to model-specific C function
prototype object
RTW.ModelSpecificCPrototype.runValidatio Validate model-specific C function prototype
n against Simulink model to which it is
attached
RTW.ModelSpecificCPrototype.setArgCatego Set step function argument category for
ry Simulink model port in model-specific C
function prototype
RTW.ModelSpecificCPrototype.setArgName Set step function argument name for
Simulink model port in model-specific C
function prototype
RTW.ModelSpecificCPrototype.setArgPositi Set step function argument position for
on Simulink model port in model-specific C
function prototype
RTW.ModelSpecificCPrototype.setArgQualif Set step function argument type qualifier for
ier Simulink model port in model-specific C
function prototype
RTW.ModelSpecificCPrototype.setFunctionN Set function names in model-specific C
ame function prototype
29-20
Configure C Initialize and Step Function Interfaces Programmatically
You can use other functions on the returned handle only if the test
isa(obj,'RTW.ModelSpecificCPrototype') returns 1. If the model does not
have a function interface configuration, the function returns []. If the function
returns a handle to an object of type RTW.FcnDefault, you cannot modify the
existing function interface.
2 Use the Get and Set functions to test and reset such items as the function names,
argument names, argument positions, argument categories, and argument type
qualifiers.
3 Validate the function interface by using
RTW.ModelSpecificCPrototype.runValidation.
4 If validation succeeds, save your model, and then generate code by using the
rtwbuild function.
29-21
29 Function and Class Interfaces in Embedded Coder
Note Do not use the same model-specific C function interface object across multiple
models. If you do, changes that you make to the step and initialize functions in one model
are propagated to other models, which is usually not what you want.
29-22
See Also
See Also
Related Examples
• “Configure C Step Function Arguments” on page 29-9
• “Configure Names for Generated C Initialize and Step Functions” on page 29-5
• “Configure C Initialize and Step Function Interfaces Interactively” on page 29-16
• “Customize Generated C Function Interfaces” on page 29-2
29-23
29 Function and Class Interfaces in Embedded Coder
You cannot customize the generated C/C++ function interface for a scoped Simulink
Function block that is not located at the root level of a model. For more information, see
“Scoped and Global Simulink Function Blocks” (Simulink).
By opening a dialog box from a selected Simulink Function or Function Caller block, you
can customize the C/C++ function prototype generated for that block. Your changes for
the selected block also update other corresponding Simulink Function and Function
Caller blocks in the model. The function visibility, global or scoped, set in the function
Trigger Port block, determines which function attributes you can modify:
• For a global function, you can change the generated C/C++ function name, and the
names, type qualifiers, and order of function arguments.
• For an exported scoped function, you can change the generated C/C++ function type
qualifiers and the order of function arguments. You cannot change the function and
argument names.
Your changes do not graphically alter the model and do not affect the Simulink function
prototype defined in the block.
Embedded Coder supports Simulink function code interface configuration for ERT and
ERT-derived targets, except for the AUTOSAR target.
29-24
Customize Generated Function Interfaces for Simulink Function and Function Caller Blocks
The dialog box displays the Simulink function prototype defined in the block, y =
f3(u), and the initial default C/C++ function prototype, void f3(rtu_u, *
rty_y).
3 Examine the dialog box settings for the C/C++ function name and the C/C++
argument identifier names — $N and rt$I$N$M.
In the Configuration Parameters dialog box, Code Generation > Symbols pane, the
Subsystem method arguments parameter defines the default identifier format for
Simulink Function arguments.
rt is a text prefix. $I, $N, and $M are identifier format macros. For more information,
see “Subsystem method arguments” (Simulink Coder).
29-25
29 Function and Class Interfaces in Embedded Coder
4 In the Configure C/C++ Function Interface dialog box, modify the function and
argument identifier names. Changes that you make in the dialog box override model
configuration parameter defaults.
In the C/C++ function name field, and in the C/C++ Identifier Name field for
each function argument, enter a custom name or identifier format. Specify valid C-
identifier characters, identifier format macros, or a combination. This example uses
function name function3 and, for both arguments, identifier format $N$M.
To see tips about available macros, hover over the C/C++ function name and C/C+
+ Identifier Name fields. For more information about the identifier format macros,
see “Identifier Format Control” on page 39-22.
5 For the u argument, change the C/C++ Type Qualifier field from Auto to Pointer
to const.
6 To reorder the generated arguments, drag the y argument row above the u argument
row, and drop.
7 Click Apply and examine the updated C/C++ function prototype: void
function3(* y, const * u).
29-26
Customize Generated Function Interfaces for Simulink Function and Function Caller Blocks
Optionally, you could change C/C++ return argument from void to y. The resulting
C/C++ function prototype is y = function3(const * u).
8 Save the model changes and generate code for rtwdemo_functions.
9 Open the generated file rtwdemo_functions.c and search for function3. The
generated function code reflects the changes to the generated C/C++ function
prototype.
/* Output and update for Simulink Function: '<Root>/f3' */
void function3(real_T *y, const real_T *u)
{
...
adder_h(rtB.Subtract, rtU.U2, *u, &rtB.FunctionCaller);
...
*y = rtB.FunctionCaller;
...
}
29-27
29 Function and Class Interfaces in Embedded Coder
For an exported scoped function, you can modify the generated C/C++ return argument
and the C/C++ type qualifiers and order of generated function arguments. You cannot
change the generated C/C++ function name and C/C++ argument identifier names.
The dialog box displays the Simulink function prototype defined in the block, y =
f3(u), and the initial default C/C++ function prototype, void
rtwdemo_functions_f3(rtu_u, * rty_y).
29-28
Customize Generated Function Interfaces for Simulink Function and Function Caller Blocks
4 For the u argument, change the C/C++ Type Qualifier field from Auto to Pointer
to const.
5 To reorder the generated arguments, drag the y argument row above the u argument
row, and drop.
6 Click Apply and examine the updated C/C++ function prototype: void
rtwdemo_functions_f3(* rty_y, const * rtu_u).
29-29
29 Function and Class Interfaces in Embedded Coder
Optionally, you could change C/C++ return argument from void to y. The resulting
C/C++ function prototype is y = rtwdemo_functions_f3(const * rtu_u).
7 Save the model changes and generate code for rtwdemo_functions.
8 Open the generated file rtwdemo_functions.c and search for _f3. The generated
function code reflects the changes to the generated C/C++ function prototype.
/* Output and update for Simulink Function: '<Root>/f3' */
void rtwdemo_functions_f3(real_T *rty_y, const real_T *rtu_u)
{
...
adder_h(rtB.Subtract, rtU.U2, *rtu_u, &rtB.FunctionCaller);
...
*rty_y = rtB.FunctionCaller;
...
}
29-30
See Also
• Simulink function code interface configuration does not support Simulink functions
and function callers in Stateflow.
See Also
Function Caller | Simulink Function
More About
• “Customize Generated Identifier Naming Rules” on page 39-14
• “Function and Class Interfaces”
• “Design Models for Generated Embedded Code Deployment” on page 1-2
• “Customize Generated C Function Interfaces” on page 29-2
• “Environment for Configuring Model Data and Functions for Code Generation” on
page 21-2
29-31
29 Function and Class Interfaces in Embedded Coder
• Triggered subsystems
• Enabled subsystems
• Enabled trigger subsystems
• While subsystems
• For subsystems
• Stateflow blocks
• MATLAB function block
This example shows how to configure the function interfaces for the Amplifier
subsystem in the example model rtwdemo_counter. In the Model Interface for
Subsystem dialog box, open the model containing the subsystem and invoke the function.
RTW.configSubsystemBuild('rtwdemo_counter/Amplifier');
29-32
Customize Function Interfaces for Nonvirtual Subsystems
29-33
29 Function and Class Interfaces in Embedded Coder
4 Expand the interface for configuring the prototypes by clicking Get Default
Configuration.
As you make changes, the step function preview (under the table) is updated.
5 Configure the function names. Specify values for Initialize function name and Step
function name.
29-34
Customize Function Interfaces for Nonvirtual Subsystems
6 Configure the step function arguments. For each argument, you can specify whether
the argument is passed by value or by reference with a pointer (Category column), a
name, and whether to apply a C type qualifier. Click Apply.
7 Validate the prototypes. Check the step function preview and click Validate. The
interface validation reports success or whether failures occur.
8 Generate code for the subsystem. From the subsystem context menu, select C/C++
Code > Build This Subsystem. The code generator produces the initialize and step
functions for the subsystem based on your customizations.
29-35
29 Function and Class Interfaces in Embedded Coder
C++ class encapsulation also works for right-click builds of nonvirtual subsystems. (For
information on requirements that apply, see “Configure C++ Class Interfaces for
Nonvirtual Subsystems” on page 29-55.)
The general procedure for generating C++ class interfaces to model code is as follows:
1 Configure your model to use an ert.tlc system target file provided by MathWorks.
2 Select the C++ language for your model.
3 Select C++ class code interface packaging for your model.
4 Optionally, configure related C++ class interface settings for your model code, using
either a graphical user interface (GUI) or application programming interface (API).
5 Generate model code and examine the results.
To get started with an example, see “Simple Use of C++ Class Control” on page 29-37.
For more details about configuring C++ class interfaces for your model code, see
“Customize C++ Class Interfaces Using Graphical Interfaces” on page 29-44 and
“Customize C++ Class Interfaces Programmatically” on page 29-55. For limitations that
apply, see “C++ Class Interface Control Limitations” on page 29-62.
Note For an example of C++ class code generation, see the example model
rtwdemo_cppclass.
In this section...
“Simple Use of C++ Class Control” on page 29-37
29-36
Customize Generated C++ Class Interfaces
In this section...
“Customize C++ Class Interfaces Using Graphical Interfaces” on page 29-44
“Customize C++ Class Interfaces Programmatically” on page 29-55
“Configure Step Method for Model Class” on page 29-59
“Specify Custom Storage Class for C++ Class Code Generation” on page 29-60
“Model Class Copy Constructor and Assignment Operator” on page 29-61
“C++ Class Interface Control Limitations” on page 29-62
Note For details about setting C++ class parameters, see the sections that follow this
example, beginning with “Customize C++ Class Interfaces Using Graphical Interfaces” on
page 29-44.
1 Open a model for which you would like to generate C++ class code interfaces. This
example uses the model rtwdemo_counter.
2 Configure the model to use an ert.tlc system target file provided by MathWorks.
For example, open the Configuration Parameters dialog box, go to the Code
Generation pane, select a target value from the System target file menu, and click
Apply.
3 On the Code Generation pane of the Configuration Parameters dialog box, set the
Language parameter to C++.
On the Code Generation > Interface pane, check that the Code interface
packaging parameter is set to C++ class.
Click Apply.
29-37
29 Function and Class Interfaces in Embedded Coder
Note To immediately generate the default style of C++ class code, without exploring
the related model configuration options, skip steps 4–8 and go directly to step 9.
4 Go to the Interface pane of the Configuration Parameters dialog box and examine
the Code interface subpane.
When you select C++ class code interface packaging for your model, additional C+
+ class interface controls become available in the Code interface subpane. See
“Configure Code Interface Options” on page 29-44 for descriptions of these controls.
You might want to modify the default settings according to your application.
5 Click the Configure C++ Class Interface button. This action opens the Configure C
++ class interface dialog box, which allows you to configure the step method for your
generated model class. The dialog box initially displays a view for configuring a
Default step method for the model class. In this view, you can specify the model
class name, step method name, and namespace for your model.
29-38
Customize Generated C++ Class Interfaces
See “Configure Step Method for Your Model Class” on page 29-47 for descriptions of
these controls.
Note If the default interface style meets your needs, you can skip steps 6–8 and go
directly to step 9.
6 If you want root-level model input and output to be arguments on the step method,
select the value I/O arguments step method from the Function specification
menu. The dialog box displays a view for configuring an I/O arguments style step
method for the model class.
29-39
29 Function and Class Interfaces in Embedded Coder
See “Configure Step Method for Your Model Class” on page 29-47 for descriptions of
these controls.
7 Click the Get Default Configuration button. This action causes a Configure C++
class interface subpane to appear in the dialog box. The subpane displays the initial
interface configuration for your model, which provides a starting point for further
customization.
29-40
Customize Generated C++ Class Interfaces
See “Passing I/O Arguments” on page 29-50 for descriptions of these controls.
8 Perform this optional step only if you want to customize the configuration of the I/O
arguments generated for your model step method.
Note If you choose to skip this step, you should click Cancel to exit the dialog box.
If you choose to perform this step, first you must check that the required option
Remove root level I/O zero initialization is selected on the Optimization pane,
and then navigate back to the I/O arguments step method view of the Configure
C++ class interface dialog box.
Now you can use the dialog box controls to configure I/O argument attributes. For
example, in the Configure C++ class interface subpane, in the row for the Input
argument, you can change the value of Category from Value to Pointer and
change the value of Qualifier from none to const *. The preview updates to reflect
your changes. Click the Validate button to validate the modified interface
configuration.
Continue modifying and validating until you are satisfied with the step method
configuration.
29-41
29 Function and Class Interfaces in Embedded Coder
29-42
Customize Generated C++ Class Interfaces
Note If you configured custom I/O arguments for the model step method (optional step
8), examine the generated code for the step method in rtwdemo_counter.h and
rtwdemo_counter.cpp. The arguments should reflect your changes. For example, if you
performed the Input argument modifications in step 8, the input argument should
appear as const int32_T *arg_Input.
29-43
29 Function and Class Interfaces in Embedded Coder
To select C++ class code interface packaging, in the Configuration Parameters dialog
box, on the Code Generation pane, set the Language parameter to C++. Then, in the
Code Generation > Interface pane, check that the Code interface packaging
parameter is set to C++ class:
• Disables model configuration options that C++ class does not support. For details,
see “C++ Class Interface Control Limitations” on page 29-62.
• Adds additional C++ class interface parameters, which are described in the next
section.
When you select C++ class code interface packaging for your model, the Code
interface parameters shown below are displayed on the Interface pane.
29-44
Customize Generated C++ Class Interfaces
Specifies the severity level for diagnostics displayed when a model violates
requirements for generating multi-instance code.
Specifies whether to omit the error status field from the generated real-time model
data structure rtModel (off by default). Selecting this option reduces memory usage.
Be aware that selecting this option can cause the code generator to omit the rtModel
data structure from generated code.
• Parameter visibility
Specifies whether to generate access methods for block parameters for the C++
model class (None by default). You can select noninlined access methods (Method) or
inlined access methods (Inlined method).
• External I/O access
Specifies whether to generate access methods for root-level I/O signals for the C++
model class (None by default). If you want to generate access methods, you have the
following options:
29-45
29 Function and Class Interfaces in Embedded Coder
Note This parameter affects generated code only if you are using the default style
step method for your model class; not if you are explicitly passing arguments for root-
level I/O signals using an I/O arguments style step method. For more information, see
“Passing Default Arguments” on page 29-48 and “Passing I/O Arguments” on page
29-50.
• Configure C++ Class Interface
Opens the Configure C++ class interface dialog box, which allows you to configure the
step method for your model class. For more information, see “Configure Step Method
for Your Model Class” on page 29-47.
Interface parameters that are related, but are less commonly used, appear under
Advanced parameters:
Specifies whether to combine global block signals and global state data into one data
structure in the generated code (off by default). Selecting this option reduces RAM
and improves readability of the generated code.
• Internal data visibility
Specifies whether to generate internal data structures, such as Block I/O, DWork
vectors, Runtime model, Zero-crossings, and continuous states, as public, private,
or protected data members of the C++ model class (private by default).
• Internal data access
Specifies whether to generate access methods for internal data structures, such as
Block I/O, DWork vectors, Runtime model, Zero-crossings, and continuous states, for
the C++ model class (None by default). You can select noninlined access methods
(Method) or inlined access methods (Inlined method).
29-46
Customize Generated C++ Class Interfaces
• Generate destructor
Specifies whether to generate a destructor for the C++ model class (on by default).
• Use dynamic memory allocation for model block instantiation (Simulink Coder)
For a model containing Model blocks, specifies whether generated code should use
dynamic memory allocation, during model object registration, to instantiate objects for
referenced models configured with a C++ class interface (off by default). If you select
this option, during instantiation of an object for the top model in a model reference
hierarchy, the generated code uses the operator new to instantiate objects for
referenced models.
Selecting this option frees a parent model from having to maintain information about
referenced models beyond its direct children. Clearing this option means that a parent
model maintains information about its referenced models, including its direct and
indirect children.
Note
• If you select this option, be aware that a bad_alloc exception might be thrown,
per the C++ standard, if an out-of-memory error occurs during the use of new. You
must provide code to catch and process the bad_alloc exception in case an out-
of-memory error occurs for a new call during construction of a top model object.
• If Use dynamic memory allocation for model block instantiation is selected
and the base model contains a Model block, the build process might generate copy
constructor and assignment operator functions in the private section of the model
class. The purpose of the functions is to prevent pointer members within the model
class from being copied by other code. For more information, see “Model Class
Copy Constructor and Assignment Operator” on page 29-61.
To configure the step method for your model class, on the Code Generation > Interface
pane, click the Configure C++ Class Interface button, which is available when you
select C++ class code interface packaging for your model. This action opens the
Configure C++ class interface dialog box, where you can configure the step method for
your model class in either of two styles:
29-47
29 Function and Class Interfaces in Embedded Coder
Note The Default step method supports single-rate models and multirate models.
The model can be configured for single-tasking operation or multi-tasking operation. This
method also supports virtual bus crossing boundaries.
The I/O arguments step method supports single-rate models and multirate models.
The model can be configured for single-tasking operation.
The Configure C++ class interface dialog box initially displays a view for configuring a
Default step method for the model class.
29-48
Customize Generated C++ Class Interfaces
Allows you to specify a step method name other than the default, step.
• Class name
Allows you to specify a model class name other than the default, modelModelClass.
• Namespace
Allows you to specify a namespace for the model class. If specified, the namespace is
emitted in the generated code for the model class. The Namespace parameter
provides a means of scoping C++ model classes. In a model reference hierarchy, you
can specify a different namespace for each referenced model.
29-49
29 Function and Class Interfaces in Embedded Coder
Displays a preview of the model step function prototype as currently configured. The
preview display is dynamically updated after you validate your current configuration.
Note The list of step function arguments has an entry for each of the model’s root-
level I/O ports. This list does not include model parameter arguments that can appear
in the generated code when the model is used as a referenced model. For example, a
model sldemo_mdlref_counter_paramargs has an inport with argument name
arg_input, an outport with argument name arg_output, and a saturation block
whose limits have workspace parameter argument names
lower_saturation_limit and upper_saturation_limit.
The function prototype in the generated code differs from the preview. The prototype
in the generated code (with the additional model parameter arguments) is:
sldemo_mdlref_counter_paramargsModelClass::step (
real_T arg_input,
real_T *arg_output,
real_T rtp_lower_saturation_limit,
real_T rtp_upper_saturation_limit)
• Validate
Validates your current model step function configuration. The Validation pane
displays the status and an explanation of any failure.
If you select I/O arguments step method from the Function specification menu,
the dialog box displays a view for configuring an I/O arguments style step method for the
model class.
Note To use the I/O arguments style step method, you must select the option Remove
root level I/O zero initialization on the Optimization pane of the Configuration
Parameters dialog box.
29-50
Customize Generated C++ Class Interfaces
Click this button to get the initial interface configuration that provides a starting point
for further customization.
• Step function preview
Displays a preview of the model step function prototype as currently configured. The
preview dynamically updates as you make configuration changes.
• Validate
Validates your current model step function configuration. The Validation pane
displays the status and an explanation of any failure.
29-51
29 Function and Class Interfaces in Embedded Coder
When you click Get Default Configuration, the Configure C++ class interface
subpane appears in the dialog box, displaying the initial interface configuration. For
example:
Allows you to specify a step method name other than the default, step.
• Class name
Allows you to specify a model class name other than the default, modelModelClass.
• Namespace
Allows you to specify a namespace for the model class. If specified, the namespace is
emitted in the generated code for the model class. The Namespace parameter
provides a means of scoping C++ model classes. In a model reference hierarchy, you
can specify a different namespace for each referenced model.
• Order
Displays the numerical position of each argument. Use the Up and Down buttons to
change argument order.
• Port Name
Displays the port name of each argument (not configurable using this dialog box).
• Port Type
Displays the port type, Inport or Outport, of each argument (not configurable using
this dialog box).
• Category
29-52
Customize Generated C++ Class Interfaces
Displays the passing mechanism for each argument. To change the passing mechanism
for an argument, select Value, Pointer, or Reference from the argument's
Category menu.
• Argument Name
Displays the name of each argument. To change an argument name, click in the
argument's Argument name field, position the cursor for text entry, and enter the
new name.
• Qualifier
Displays the const type qualifier for each argument. To change the qualifier for an
argument, select an available value from the argument's Qualifier menu. The possible
values are:
• none
• const (value)
• const* (value referenced by the pointer)
• const*const (value referenced by the pointer and the pointer itself)
• const & (value referenced by the reference)
Tip When a model includes a referenced model, the const type qualifier for the root
input argument of the referenced model's specified step function interface is set to none
and the qualifier for the source signal in the referenced model's parent is set to a value
other than none, code generation honors the referenced model's interface specification
by generating a type cast that discards the const type qualifier from the source signal.
To override this behavior, add a const type qualifier to the referenced model.
Embedded Coder provides namespace control for scoping model classes generated using
C++ class code interface packaging. In the Configure C++ class interface dialog box, use
the Namespace parameter to specify a namespace for a model class. If specified, the
namespace is emitted in the generated code for the model class. To scope the C++ model
classes in a model reference hierarchy, you can specify a different namespace for each
referenced model.
For an example of namespace control, see the example model rtwdemo_cppclass. This
model assigns namespaces as follows:
29-53
29 Function and Class Interfaces in Embedded Coder
If you build the model with its default settings, you can examine the generated header
and source files for each model to see where the namespace is emitted. For example, the
Namespace setting for the model rtwdemo_cppclass_refmid is shown below, followed
by excerpts of the emitted namespace code in the model header and source files.
15 #include "rtwdemo_cppclass_refmid.h"
16 #include "rtwdemo_cppclass_refmid_private.h"
17
18 namespace MiddleNS
19 {
20 // Model step function
21 void MiddleClass::StepMethod(const real_T *arg_In1, const real_T &arg_In2,
22 real_T *arg_Out1, real_T *arg_Out2)
23 {
...
43 }
...
83 }
29-54
Customize Generated C++ Class Interfaces
You can configure C++ class interfaces for right-click builds of nonvirtual subsystems in
Simulink models, if the following requirements are met:
• The model is configured for the C++ language and C++ class code interface
packaging.
• The subsystem is convertible to a Model block using the function
Simulink.SubSystem.convertToModelReference. For referenced model
conversion requirements, see the Simulink reference page
Simulink.SubSystem.convertToModelReference.
To configure C++ class interfaces for a subsystem that meets the requirements:
RTW.configSubsystemBuild(gcb)
where gcb is the Simulink function gcb, returning the full block path name of the
current block.
This command opens a subsystem equivalent of the Configure C++ class interface
dialog sequence that is described in detail in the preceding section, “Configure Step
Method for Your Model Class” on page 29-47. (For more information about using the
MATLAB command, see RTW.configSubsystemBuild.)
3 Use the Configure C++ class interface dialog boxes to configure C++ class settings
for the subsystem.
4 Right-click the subsystem and select C/C++ Code > Build This Subsystem.
5 When the subsystem build completes, you can examine the C++ class interfaces in
the generated files and the HTML code generation report.
29-55
29 Function and Class Interfaces in Embedded Coder
• Create and validate a new step method interface, starting with default
configuration information from your Simulink model
1 Get the handle to an existing model-specific C++ class interface that is attached
to your loaded ERT-based Simulink model using obj =
RTW.getClassInterfaceSpecification(modelName), where modelName is
a character vector specifying the name of a loaded ERT-based Simulink model,
and obj returns a handle to a C++ class interface attached to the specified
model. If the model does not have an attached C++ class interface configuration,
the function returns [].
2 Use the Get and Set functions listed in C++ Class Interface Control Functions to
test or reset the model class name and model step method name. Additionally, if
the returned interface uses the I/O arguments style step method, you can test and
reset argument names, argument positions, argument categories, and argument
type qualifiers.
3 Validate the C++ class interface using runValidation. (If validation fails, use
the error message information that runValidation returns to address the
issues.)
4 Save your model and then generate code using the rtwbuild function.
29-56
Customize Generated C++ Class Interfaces
Note You should not use the same model-specific C++ class interface control object
across multiple models. If you do, changes that you make to the step method
configuration in one model propagate to other models, which is usually not desirable.
29-57
29 Function and Class Interfaces in Embedded Coder
Function Description
attachToModel Attach model-specific C++ class interface to loaded ERT-based
Simulink model
getArgCategory Get argument category for Simulink model port from model-
specific C++ class interface
getArgName Get argument name for Simulink model port from model-
specific C++ class interface
getArgPosition Get argument position for Simulink model port from model-
specific C++ class interface
getArgQualifier Get argument type qualifier for Simulink model port from
model-specific C++ class interface
getClassName Get class name from model-specific C++ class interface
getDefaultConf Get default configuration information for model-specific C++
class interface from Simulink model to which it is attached
getNamespace Get namespace from model-specific C++ class interface
getNumArgs Get number of step method arguments from model-specific C+
+ class interface
getStepMethodName Get step method name from model-specific C++ class interface
RTW.configSubsystemBuild Open GUI to configure C function prototype or C++ class
interface for right-click build of specified subsystem
RTW.getClass‐ Get handle to model-specific C++ class interface control object
InterfaceSpecification
runValidation Validate model-specific C++ class interface against Simulink
model to which it is attached
setArgCategory Set argument category for Simulink model port in model-
specific C++ class interface
setArgName Set argument name for Simulink model port in model-specific
C++ class interface
setArgPosition Set argument position for Simulink model port in model-
specific C++ class interface
29-58
Customize Generated C++ Class Interfaces
Function Description
setArgQualifier Set argument type qualifier for Simulink model port in model-
specific C++ class interface
setClassName Set class name in model-specific C++ class interface
setNamespace Set namespace in model-specific C++ class interface
setStepMethodName Set step method name in model-specific C++ class interface
%% Select C++ class as the code interface packaging for the model
set_param(gcs,'CodeInterfacePackaging','C++ class')
%% Set required option for I/O arguments style step method (cmd off = GUI on)
set_param(gcs,'ZeroExternalMemoryAtStartup','off')
%% Create a C++ class interface using an I/O arguments style step method
a=RTW.ModelCPPArgsClass
%% Get the default C++ class interface configuration from the model
getDefaultConf(a)
29-59
29 Function and Class Interfaces in Embedded Coder
1 Open an ERT-based model for which Language is set to C++ and Code interface
packaging is set to C++ class.
2 Open the Configuration Parameters dialog box.
3 On the Code Generation > Interface pane, set the Multi-instance code error
diagnostic (Simulink Coder) parameter to a value other than Error.
Note C++ class code generation does not support the following CSCs:
29-60
Customize Generated C++ Class Interfaces
• The model option Use dynamic memory allocation for model block instantiation
(Simulink Coder) is set to on.
• The base model contains a Model block. The Model block is not directly or indirectly
within a subsystem for which Function packaging is set to Reusable function.
Under these conditions, the software generates a private copy constructor and
assignment operator to prevent pointer members within the model class from being
copied by other code.
Note To prevent generation of these functions, consider clearing the option Use
dynamic memory allocation for model block instantiation.
The code excerpt below shows generated model.h code for a model class that has a
pointer member. (Look for instances of MiddleClass_ptr). The copy constructor and
assignment operator declarations are shown in bold.
class MiddleClass; // class forward declaration for <S1>/Bottom model instance
typedef MiddleClass* MiddleClass_ptr;
...
// Block states
D_Work_cppclass_top cppclass_top_DWork;
// Real-Time Model
RT_MODEL_cppclass_top cppclass_top_M;
29-61
29 Function and Class Interfaces in Embedded Coder
//Copy Constructor
Top(const Top &rhs);
//Assignment Operator
Top& operator= (const Top &rhs);
• Output has a slower sample time than the fundamental rate of the model when the
model is used as a referenced model.
• Output is written to in a conditionally executed subsystem.
• Output is written to by an S-function that might conditionally update the output.
• Output is written to by a Hit Crossing block.
• Output is written to by a Rate Transition block.
• The C++ class code interface packaging option does not support some Simulink
model configuration options. Selecting C++ class disables the following items in the
Configuration Parameters dialog box:
Note The code and data templates on the Templates pane are supported for C++
class code generation. However, the following template file features that are
supported for other language selections are not supported for C++ class generated
code:
29-62
Customize Generated C++ Class Interfaces
• Global data placement (custom storage classes only) subpane on the Code
Placement pane
Selecting C++ class also disables the Code Mapping Editor (see “Configure Default
Code Generation for Categories of Model Data and Functions” on page 21-7). You
cannot apply default storage classes, memory sections, or function templates to the
model.
• Among the data exchange interfaces available on the Interface pane of the
Configuration Parameters dialog box, only the C API interface is supported for C++
class code generation. If you select External mode or ASAP2 interface, code
generation fails with a validation error.
• The I/O arguments style of step method specification supports single-rate models and
multirate single-tasking models, but not multirate multitasking models.
• If you have a Stateflow license, for a Stateflow chart that resides in a root model
configured to use the I/O arguments step method function specification, and that
uses a model root inport value or calls a subsystem that uses a model root inport
value, you must do one of the following to generate code:
• Clear the Execute (enter) Chart At Initialization check box in the Stateflow
chart.
• Insert a Simulink Signal Conversion block immediately after the root inport. In the
Signal Conversion block parameters dialog box, select Exclude this block from
'Block reduction' optimization.
• If a model root inport value connects to a Simscape conversion block, you must insert
a Simulink Signal Conversion block between the root inport and the Simscape
conversion block. In the Signal Conversion block parameters dialog box, select
Exclude this block from 'Block reduction' optimization.
• When building a referenced model that is configured to generate a C++ class
interface:
• Do not use a C++ class interface in cases when a referenced model cannot have a
combined output/update function. Cases include a model that has a continuous
sample time or saves states.
• Do not use virtual buses as inputs or outputs to the referenced model when the
referenced model uses the I/O arguments step method. When bus signals cross
referenced model boundaries, either use nonvirtual buses or use the Default step
method.
• If the C++ encapsulation interface is not the default, the value is ignored for the
Configuration Parameters > Model Referencing > Pass fixed-size scalar root
29-63
29 Function and Class Interfaces in Embedded Coder
inputs by value for code generation parameter. For more information, see “Pass
fixed-size scalar root inputs by value for code generation” (Simulink).
See Also
Related Examples
• “Customize Interface to Generated C++ Code That Is Called By C Code”
29-64
Generate Modular Function Code
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.
• 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, see “Systems and Subsystems” (Simulink).
• Your subsystem must use the Nonreusable function setting for Code Generation
> Function 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 Function with separate data option. See “Configure Subsystem for Generating
Modular Function Code” on page 29-66 and “Modular Function Code for Nonvirtual
Subsystems” on page 29-70 for details. For limitations that apply, see “Nonvirtual
Subsystem Modular Function Code Limitations” on page 29-75.
29-65
29 Function and Class Interfaces in Embedded Coder
For more information about generating code for atomic subsystems, see the sections
“Control Generation of Subsystem Functions” (Simulink Coder) and “Generate Code and
Executables for Individual Subsystems” (Simulink Coder).
3 If the Subsystem Parameters dialog box option Treat as atomic unit is available for
selection but not selected, the subsystem is neither atomic nor conditionally
29-66
Generate Modular Function Code
executed. Select the option Treat as atomic unit, which enables Function
packaging on the Code Generation tab. Select the Code Generation tab.
4 For the Function packaging parameter, select the value Nonreusable function.
After you make this selection, the Function with separate data option is displayed.
29-67
29 Function and Class Interfaces in Embedded Coder
Note Before you generate nonvirtual subsystem function code with the Function
with separate data option selected, you might want to generate function code with
the option deselected and save the generated function .c and .h files in a separate
directory for later comparison.
5 Select the Function with separate data option. After you make this selection,
additional configuration parameters are displayed.
29-68
Generate Modular Function Code
Note To control the naming of the subsystem function and the subsystem files in the
generated code, you can modify the subsystem parameters Function name options
and File name options.
6 To save your subsystem parameter settings and exit the dialog box, click OK.
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, see “Control
Generation of Subsystem Functions” (Simulink Coder). For examples of generated
subsystem function code, see “Modular Function Code for Nonvirtual Subsystems” on
page 29-70.
29-69
29 Function and Class Interfaces in Embedded Coder
1 Open MATLAB and open the model rtwdemo_atomic using the MATLAB command
rtwdemo_atomic.
Examine the Simulink model. This model shows how to preserve the boundary of a
virtual subsystem. By selecting the Subsystem Parameters option Treat 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 option Code Generation
Function Packaging. You can specify that the subsystem is translated to any of the
following types of implementation:
29-70
Generate Modular Function Code
Close the Block Parameters dialog box when you are finished.
4 Change the System target file for the mode from grt.tlc to ert.tlc. Select the
Configuration Parameters > Code Generation tab and specify ert.tlc for the
System target file parameter. Click OK twice to confirm the change. Using the ERT
target provides more code generation options for the atomic subsystem.
5 Create a variant of rtwdemo_atomic that illustrates function code without data
separation.
a In the rtwdemo_atomic model, right-click the SS1 subsystem and select Block
Parameters (Subsystem). In the Subsystem Parameters dialog box that
appears, verify that
Do not select the option Function with separate data. Click Apply to apply the
changes and click OK to exit the dialog box.
c Save this model variant to a personal work directory, for example,
rtwdemo_atomic1 in d:/atomic.
6 Create a variant of rtwdemo_atomic that illustrates function code with data
separation.
29-71
29 Function and Class Interfaces in Embedded Coder
In this example, there are not significant differences in the generated variants of
ert_main.c, model_private.h, model_types.h, or rtwtypes.h.
1 Selecting Function with separate data causes typedefs for subsystem data to be
generated in the myfun.h file for rtwdemo_atomic2:
29-72
Generate Modular Function Code
29-73
29 Function and Class Interfaces in Embedded Coder
void myfun_initialize(void) {
{
((real_T*)&rtwdemo_atomic2_myfunB.Integrator)[0] = 0.0;
}
rtwdemo_atomic2_myfunDW.Integrator_DSTATE = 0.0;
}
void rtwdemo_atomic2_initialize(void)
{
...
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;
...
}
29-74
Generate Modular Function Code
2 Selecting Function with separate data generates the following declarations in the
myfun.c file for rtwdemo_atomic2:
rtDW_myfun rtwdemo_atomic2_myfunDW;
• The Function with separate data option 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.
29-75
29 Function and Class Interfaces in Embedded Coder
• When you select Function with separate data for a subsystem, the model that
contains the subsystem cannot contain a Data Store Memory block with Share across
model instances selected. See Data Store Memory.
See Also
More About
• “Design Models for Generated Embedded Code Deployment” on page 1-2
29-76
30
• Apply default pragmas or other decorations to categories of model data and entry-
point functions. To configure these defaults, use the Code Mapping Editor. For
example, you can:
• Apply a default pragma to internal data, which includes block states that the code
generator cannot eliminate through optimizations. You can apply a different default
pragma to constant parameters, such as nonscalar parameters that the generated
code must store in memory.
• Apply a default pragma to categories of generated functions, including entry-point
functions such as model_step.
• Override the default pragmas for individual data items such as block parameters,
states, and signals. To do so, create your own storage class.
• Override the default pragmas for individual functions that correspond to atomic
subsystems, which you can configure to appear in the generated code as separate
functions with separate data. Use the subsystem parameters dialog box.
30-2
Control Data and Function Placement in Memory by Inserting Pragmas
The model is configured to generate efficient production code. For example, the
configuration parameter Default parameter behavior is set to Inlined.
2 Generate code from the model.
3 In the code generation report, inspect the file rtwdemo_roll.h. The file defines
structure types that represent data that the algorithm needs. For example, the file
defines a structure type that represents block states such as the states of Discrete-
Time Integrator blocks.
/* Block states (default storage) for system '<Root>' */
typedef struct {
real32_T FixPtUnitDelay1_DSTATE; /* '<S7>/FixPt Unit Delay1' */
real32_T Integrator_DSTATE; /* '<S1>/Integrator' */
int8_T Integrator_PrevResetState; /* '<S1>/Integrator' */
} DW_rtwdemo_roll_T;
30-3
30 Memory Sections in Embedded Coder
In this example, assume your linker configuration file defines named sections
MYALGORITHM_DATA and MYALGORITHM_CODE in a SECTIONS directive. You can
configure the model so that the generated code includes pragmas, placing the memory
allocated for the data and functions in these named sections.
#pragma SEC_MYALGORITHM_DATA("myVar")
double myVar;
• For a function named myFunction, the pragma syntax is the same except for the
section name:
#pragma SEC_MYALGORITHM_CODE("myFunction")
void myFunction(void)
In this example, you use two pragmas with different syntaxes, so you must create two
memory sections.
1 In the model window, select Code > C/C++ Code > Configure Model in Code
Perspective. Simulink places the model in the code perspective, which you can use
to configure code generation settings for the model.
2 Underneath the block diagram, under Code Mappings > Data Defaults, click the
Embedded Coder Dictionary icon.
3 In the Embedded Coder Dictionary dialog box, select the Memory Sections tab.
4 Click the Add button.
5 For the new memory section, set these options:
• Name to MYALGORITHM_DATA.
• Statements Surround to Each variable.
• Pre Statement to #pragma SEC_MYALGORITHM_DATA("$N"). The token $N
stands for the name of each variable that uses the memory section.
6 Create another, similar memory section that corresponds to MYALGORITHM_CODE.
30-4
Control Data and Function Placement in Memory by Inserting Pragmas
1 In the model, inspect the Code Mappings > Data Defaults tab.
2 In the table, select the Inports row.
3 In the Property Inspector, set Memory Section to MYALGORITHM_DATA.
4 For the other rows in the table, set Memory Section to MYALGORITHM_DATA.
5 Under Function Defaults, for each row in the table, set Memory Section to
MYALGORITHM_CODE.
6 In your current folder, delete the existing slprj folder.
7 Configure the model to generate only code. Select the configuration parameter
Configuration Parameters > Generate code only.
8 Generate code from the model.
Now, the rtwdemo_roll.c file applies the pragmas to the definitions of the structure
variables and the functions. For each category of data and functions that you configured
in the Code Mapping Editor, the code applies a pragma. For example, the code applies the
MYALGORITHM_DATA pragma to each of the structures that store block states, root-level
inputs, and root-level outputs.
/* Block states (default storage) */
#pragma SEC_MYALGORITHM_DATA("rtwdemo_roll_DW")
DW_rtwdemo_roll_T rtwdemo_roll_DW;
ExtU_rtwdemo_roll_T rtwdemo_roll_U;
ExtY_rtwdemo_roll_T rtwdemo_roll_Y;
In the Code Mapping Editor, you can use the Storage Class and Function
Customization Template columns to control the default appearance of data and
functions in the generated code. When you use these columns to apply a setting other
than Default, the Code Mapping Editor discards the memory section that you applied in
the Property Inspector. To retain the memory section, use the Embedded Coder Dictionary
to create a storage class or function template, then apply the memory section to that
storage class or function template.
30-5
30 Memory Sections in Embedded Coder
In this example, you configure the nonparameter data of the model, such as signals and
states, to appear in the same structure by creating a storage class. To retain the
MYALGORITHM_DATA memory section, you apply the memory section to the storage class.
1 In the Embedded Coder Dictionary for the model, select the Storage Classes tab and
click the Add button.
2 For the new storage class, set:
• Name to STRUCT_DATA.
• Storage Type to Structured.
• Memory Section to MYALGORITHM_DATA.
3 In the Code Mapping Editor, under Data Defaults, in the Storage Class column,
select STRUCT_DATA for all of the rows except:
• Global parameters
• Local parameters
• Global data stores
• Constants
4 Generate code from the model.
5 Inspect rtwdemo_roll.c. Now, the file defines a single structure variable that
contains the nonparameter data, applying the pragma to that variable.
rtwdemo_roll_STRUCT_DATA STRUCT_DATA_rtwdemo_roll;
To override the default storage classes that you specify in Code Mappings > Data
Defaults, you can apply a storage class directly to a data item by using the Model Data
Editor. Directly applying any storage class other than Auto or Model default bypasses
the default memory section that you specify in Data Defaults. To retain the memory
section, you must migrate the memory section definition out of the Embedded Coder
Dictionary and into a package, which is a folder that can contain storage class and
memory section definitions. Then, you can create a storage class in the package, apply
the memory section to the storage class, and apply the storage class directly to individual
data items in the Model Data Editor.
30-6
Control Data and Function Placement in Memory by Inserting Pragmas
signals of these blocks so that the generated code allocates memory for them and places
the memory in the MYALGORITHM_DATA section. You also configure the signals so that the
code defines them in mySigs.c and declares them in mySigs.h.
1 In your current folder, create a folder named +myPackage. The folder defines a
package named myPackage.
To make the package available outside of your current folder, optionally, you can add
the folder containing the +myPackage folder to the MATLAB path.
2 Open the Custom Storage Class designer.
cscdesigner('myPackage');
3 In the Custom Storage Class Designer, select the Memory Section tab.
4 Click New.
5 For the new memory section, set these options, which match the options that you set
for MYALGORITHM_DATA in the Embedded Coder Dictionary:
• Name to MYALGORITHM_DATA.
• Statements surround to Each variable.
• Pre statement to #pragma SEC_MYALGORITHM_DATA("$N").
6 Click Apply and Save.
7 In the myPackage package folder, create a folder named @Signal.
8 In the @Signal folder, create a file named Signal.m.
classdef Signal < Simulink.Signal
methods
function setupCoderInfo(h)
useLocalCustomStorageClasses(h, 'myPackage');
end
function h = Signal()
% SIGNAL Class constructor.
end % End of constructor
end % methods
end % classdef
The file defines a class named myPackage.Signal, which is derived from the built-
in class Simulink.Signal. The class definition overrides the setupCoderInfo
30-7
30 Memory Sections in Embedded Coder
• Name to myCSC.
• Clear For parameters.
• Memory section to MYALGORITHM_DATA.
• Data scope to Exported.
• Header file to mySigs.h.
• Definition file to mySigs.c.
13 Click Apply and Save.
1 In the model, select View > Model Explorer > Model Explorer.
2 In the Model Explorer Model Hierarchy pane, select Base Workspace.
3 In the Model Explorer toolbar, click the arrow next to the Add Signal button and
select Customize class lists.
4 In the Customize class lists dialog box, under Signal classes, select the check box
next to myPackage.Signal and click OK.
5 In the Model Explorer, click the arrow next to Add Signal again and select
myPackage Signal. A myPackage.Signal object appears in the base workspace.
6 Delete the myPackage.Signal object from the base workspace. Now, when you use
the Model Data Editor to apply storage classes to signals, you can choose storage
classes from the myPackage package.
7 In the model, navigate into the BasicRollMode subsystem.
8 Underneath the block diagram, select the Model Data Editor > Signals tab.
9 In the model, select the three Gain blocks.
10 In the Model Data Editor, in the data table, for any of the highlighted rows, set
Storage Class to myCSC.
11 Generate code from the model.
30-8
Control Data and Function Placement in Memory by Inserting Pragmas
12 Inspect the generated file mySigs.c. The file defines the global variables that
correspond to the Gain block outputs in the model. The pragma applies to the
definitions.
real32_T DispGain;
#pragma SEC_MYALGORITHM_DATA("IntGain")
real32_T IntGain;
#pragma SEC_MYALGORITHM_DATA("RateGain")
real32_T RateGain;
Now, two definitions of the MYALGORITHM_DATA memory section exist: One in the
Embedded Coder Dictionary and one in myPackage. When you make changes to the
memory section, make the same changes for each definition.
30-9
30 Memory Sections in Embedded Coder
• If you need to use the memory section only in the Code Mapping Editor, define the
memory section in an Embedded Coder Dictionary.
• If you need to use the memory section outside of the Code Mapping Editor, for
example, in the Model Data Editor, define the memory section in a package.
Optionally, you can enable use of the package memory section in the Code Mapping
Editor by loading the package into an Embedded Coder Dictionary (see “Refer to Code
Generation Definitions in a Package”). However, if you create storage classes in the
dictionary, you cannot apply the package memory section to them. To associate a
memory section with storage classes that you define in an Embedded Coder Dictionary
and with other storage classes that you define in a package, maintain two definitions
of the memory section: one in the dictionary and one in the package.
30-10
Control Data and Function Placement in Memory by Inserting Pragmas
A new reference with a default name and properties appears below the previously
selected definition. The new reference is selected, and a Reference tab appears that
shows the reference's initial properties.
6 Use the Name field to enter a name for the new reference. The name must be unique
in the importing package, but can duplicate the name in the source package.
7 Set Refer to memory section in package to specify the package that contains the
memory section that you want to reference.
8 Set Memory section to reference to specify the memory section to be referenced.
9 Click OK or Apply to save the changes to memory. To save the changes permanently,
click Save.
30-11
30 Memory Sections in Embedded Coder
You can prevent changes to the memory section definitions of an entire package by
converting the csc_registration.m file from a MATLAB file to a P-file. Use the pcode
function.
• To use different memory sections to override the model-level defaults that you set in
the Code Mapping Editor, see “Override Memory Section for Atomic Subsystem” on
page 30-12.
• To specify that a subsystem use no memory section (in other words, to prevent the
subsystem from inheriting the model-level defaults), see “Specify That Atomic
Subsystem Use No Memory Section” on page 30-13.
The memory sections that you specify for a subsystem override the model-level defaults
that you set in the Code Mapping Editor. Use this technique to aggregate the data and
instruction code for subroutines or subcomponents (represented by subsystems) into
different regions of memory. To apply a memory section directly to an atomic subsystem:
1 Define the memory sections in a package. You cannot use a memory section that you
define in an Embedded Coder Dictionary.
2 In the target model, set Configuration Parameters > Code Generation >
Advanced parameters > Memory Sections > Package to the name of the
package. If the package does not appear in the list, click Refresh package list.
30-12
Control Data and Function Placement in Memory by Inserting Pragmas
3 Configure the Embedded Coder Dictionary of the model to load the target package as
described in “Refer to Code Generation Definitions in a Package”.
4 Configure the target subsystem to use the memory section. In the subsystem
parameters dialog box, on the Code Generation tab:
By default, subsystem functions and data inherit the model-level memory sections that
you specify for relevant function and data categories in the Code Mapping Editor. For
example, if you specify a function customization template for the Execution category, and
that template carries a memory section, the memory section applies to subsystem
execution functions as well as model entry-point execution functions.
1 In the target model, set Configuration Parameters > Code Generation >
Advanced parameters > Memory Sections > Package to one of these values:
• If the Embedded Coder Dictionary of the model does not refer to code generation
definitions in a package (see “Refer to Code Generation Definitions in a Package”),
set Package to Simulink.
• If the Embedded Coder Dictionary of the model refers to a package, set Package
to that package.
2 In the target subsystem, on the Code Generation tab, set parameters such as
Memory section for initialize/terminate functions to Default. With this setting,
the subsystem does not use a memory section for the data or functions that each
parameter represents.
30-13
30 Memory Sections in Embedded Coder
• The settings that you specify for an atomic, nonreusable subsystem with separate data
apply only to the data and functions of that subsystem, not to data in similarly
configured child subsystems. Atomic, nonreusable child subsystems with separate data
can inherit memory sections from the containing model, not from the parent
subsystem.
• If you use Build This Subsystem or Build Selected Subsystem to generate code for
an atomic subsystem that specifies memory sections, the code generator ignores the
subsystem-level specifications and uses the model-level specifications instead. For
information about building subsystems, see “Generate Code and Executables for
Individual Subsystems” (Simulink Coder).
Limitations
• The code generator does not apply memory sections to data that uses these built-in
storage classes:
• ExportedGlobal
• ImportedExtern
• ImportedExternPointer
• In the Custom Storage Class Designer, the storage type qualifier that you specify for a
memory section by using the Qualifier text box affects only data items that use a
storage class setting other than these built-in storage classes:
• ExportedGlobal
30-14
Control Data and Function Placement in Memory by Inserting Pragmas
• ImportedExtern
• ImportedExternPointer
The code generator omits the qualifier from other data categories.
• When you create a subsystem in a custom block library, you cannot specify memory
sections for the subsystem definition in the library. Instead, specify memory sections
for the subsystem instances that you place in your models.
Instructions
1 Learn about memory sections by clicking the documentation link in the model.
2 View the memory sections in the ECoderDemos package by clicking the button in the
model and then selecting the Memory Sections tab.
30-15
30 Memory Sections in Embedded Coder
3 View the memory sections selected for this model by clicking the button in the model.
The model-level settings are also the default settings for atomic subsystems.
4 Open the SubSystem Parameters dialog for the subsystems to see the memory section
settings for each of the atomic subsystems in the model.
5 Generate code by clicking the button in the model. An HTML report is displayed
automatically. Inspect the data and function definitions in the .c files and observe
how the generated pragmas correspond to the specified memory sections.
See Also
Related Examples
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
• “Define Storage Classes, Memory Sections, and Function Templates for Software
Architecture” on page 20-2
• “Create Custom Storage Classes by Using the Custom Storage Class Designer” on
page 26-26
• “Protect Global Data with const and volatile Keywords” on page 30-17
• “Standard Data Structures in the Generated Code” (Simulink Coder)
30-16
Protect Global Data with const and volatile Keywords
If the built-in custom storage classes do not meet your requirements, you can create
your own custom storage class. To make your custom storage class apply the
qualifiers, in the Custom Storage Class Designer, set Memory section to the
appropriate built-in memory section or to a memory section that you create. For more
information, see “Create Custom Storage Classes by Using the Custom Storage Class
Designer” on page 26-26.
• You can apply the qualifiers to a category of model data by default, such as parameters
or states. As you add blocks to a model, new data items in these categories carry the
qualifiers that you specify. For more information, see “Configure Default Code
Generation for Data” on page 21-8.
If the built-in storage classes do not meet your requirements, you can create your own
by using an Embedded Coder Dictionary. In the Dictionary, for your new storage class,
select the appropriate check boxes under Qualifiers. For more information, see
“Create Code Definitions for Use as Default Code Generation Settings” on page 20-2.
30-17
30 Memory Sections in Embedded Coder
• To configure function prototype control for a Simulink Function block, see “Customize
Generated Function Interfaces for Simulink Function and Function Caller Blocks” on
page 29-24.
When the generated code defines a function that has an argument (formal parameter),
the function definition does not apply volatile to the argument. Therefore, when other
generated code or your external code calls the function and passes a volatile variable as
the value of the argument, the called function implicitly casts away the volatility.
If your application executes the called function while the value of the volatile data
changes, the function can yield incorrect results or undefined behavior. In particular, for
lookup table data that you prepare for calibration by applying const and volatile,
make sure that you do not calibrate the data while your application executes the lookup
utilities.
See Also
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
30-18
See Also
30-19
Code Generation
21
31
The model configuration parameters for code generation are in the Code Generation
and Optimization panes in the Configuration Parameters dialog box. The content of the
Code Generation pane and its subpanes can change depending on the target that you
specify. Some configuration options are available only with the Embedded Coder product.
The Optimization pane includes code generation parameters that help to improve the
performance of the generated code.
Your application objectives can include a combination of these code generation objectives:
debugging, traceability, execution efficiency, and safety precaution. There are tradeoffs
associated with these configuration choices, such as execution speed and memory usage.
To help configure a model to achieve your application objectives, use the Model Advisor
and the Code Generation Advisor.
• To open the Configuration Parameters dialog box, click the model configuration
parameters icon.
31-2
Code Generation Configuration
(active). Click elements in the middle pane to display the corresponding parameters
in the right pane.
Note In a Configuration Parameters dialog box, when you change the value of a check
box, menu selection, or edit field, the white background of the element changes color to
indicate that you made an unsaved change. When you click OK, Cancel, or Apply, the
background resets to white.
Configuration Tools
To help you configure your model for code generation and to check your configuration
against your code generation objectives, Simulink Coder and Embedded Coder provide
several tools.
31-3
31 Configuration for Simulink Coder
See Also
Related Examples
• “Configuration Reuse” (Simulink)
• “Configure Code Generation Parameters for Model Programmatically” (Simulink
Coder)
• “Application Objectives Using Code Generation Advisor” on page 31-18
31-4
Configure Code Generation Parameters for Model Programmatically
31-5
31 Configuration for Simulink Coder
saveAs(cs,'Exec_Efficiency_cs');
dbtype Exec_Efficiency_cs 1:50
See Also
More About
• “Code Generation Configuration” on page 31-2
• “Application Objectives Using Code Generation Advisor” on page 31-18
31-6
Use Configuration Reference to Select Code Generation Target
open_system('slexConfigSetRefExample');
To open the active configuration set for the model slexConfigSetRefExample, from
the model editor menu, select Simulation > Model Configuration Parameters.
31-7
31 Configuration for Simulink Coder
The dialog box indicates that the model is using a referenced configuration set,
Reference, located in the data dictionary, slexConfigSetRefData.sldd.
open_system('slexConfigSetRefExample/Amplifier');
31-8
Use Configuration Reference to Select Code Generation Target
Open the active configuration set for this model. The name and location for the
referenced configuration is the same as in slexConfigSetRefExample.
31-9
31 Configuration for Simulink Coder
To open the referenced configuration set, click the Open button in either of the
Configuration Reference dialog boxes. The Model Explorer opens and displays the
referenced configuration set.
31-10
Use Configuration Reference to Select Code Generation Target
31-11
31 Configuration for Simulink Coder
The referenced configuration set is customized for ERT code generation. To generate
code, press Ctrl+B.
rtwbuild('slexConfigSetRefExample');
31-12
Use Configuration Reference to Select Code Generation Target
In the middle pane of the Model Explorer, there is another configuration set,
Configuration_AUTOSAR, that is customized for AUTOSAR code generation. In the right
panel, in the Name drop-down list, select Configuration_AUTOSAR.
slexConfigSetREfExample and its referenced model, slexConfigSetMdlRef, now
both use the configuration set, Configuration_AUTOSAR.
Because you edited the configuration reference, the data dictionary has unsaved changes.
The configurations are stored outside of the models so the models do not have unsaved
changes.
31-13
31 Configuration for Simulink Coder
If you have downloaded the AUTOSAR package, you can now generate code for an
AUTOSAR target. In the model editor window, press Ctrl+B.
31-14
Check Model and Configuration for Code Generation
31-15
31 Configuration for Simulink Coder
If the Code Generation Advisor issues failures or warnings, and you specified:
Note When you specify an efficiency or Safety precaution objective, the Code
Generation Advisor includes additional checks. When you make changes to one of
these additional checks, previous check results can potentially become invalid and
need to be rerun.
For more information, see “Set Objectives — Code Generation Advisor Dialog Box”
(Simulink Coder)
31-16
See Also
See Also
Related Examples
• “Select and Run Model Advisor Checks” (Simulink)
• “Application Objectives Using Code Generation Advisor” on page 31-18
31-17
31 Configuration for Simulink Coder
In this section...
“High-Level Code Generation Objectives” on page 31-19
“Configure Model for Code Generation Objectives Using Code Generation Advisor” on
page 31-19
“Configure Model for Code Generation Objectives by Using Configuration Parameters
Dialog Box” on page 31-21
Consider how your application objectives, such as efficiency, traceability, and safety, map
to code generation options in a model configuration set. Parameters that you set in the
Solver, Data Import/Export, Diagnostics, and Code Generation panes in the
Configuration Parameters dialog box specify the behavior of a model in simulation and the
code generated for the model.
Before generating code, or as part of the code generation process, you can use the Code
Generation Advisor to review a model. When you choose to review a model before
generating code, you specify which model, subsystem, or referenced model the Code
Generation Advisor reviews. When you choose to review a model as part of the code
generation process, the Code Generation Advisor reviews the entire system. The Code
Generation Advisor uses the information presented in “Recommended Settings Summary
for Model Configuration Parameters” to determine the parameter values that meet your
objectives. When there is a conflict between multiple objectives, the higher-priority
objective takes precedence.
Setting code generation objectives, and then running the Code Generation Advisor
provides information on how to meet code generation objectives for your model. The Code
Generation Advisor does not alter the generated code. You can use the Code Generation
Advisor to make the suggested changes to your model. The generated code is changed
only after you modify your model and regenerate code. When you use the Code
Generation Advisor to set code generation objectives and check your model, the
generated code includes comments identifying which objectives you specified, the checks
the Code Generation Advisor ran on the model, and the results of running the checks.
If a model uses a configuration reference (Simulink), you can run the Code Generation
Advisor to review your configuration parameter settings. However, the Code Generation
Advisor cannot modify the configuration parameter settings.
31-18
Application Objectives Using Code Generation Advisor
• Execution efficiency (all targets) — Configure code generation settings to achieve fast
execution time.
• ROM efficiency (ERT-based targets) — Configure code generation settings to reduce
ROM usage.
• RAM efficiency (ERT-based targets) — Configure code generation settings to reduce
RAM usage.
• Traceability (ERT-based targets) — Configure code generation settings to provide
mapping between model elements and code.
• Safety precaution (ERT-based targets) — Configure code generation settings to
increase clarity, determinism, robustness, and verifiability of the code.
• Debugging (all targets) — Configure code generation settings to debug the code
generation build process.
• MISRA C:2012 guidelines (ERT-based targets) — Configure code generation settings to
increase compliance with MISRA C:2012 guidelines.
• Polyspace (ERT-based targets) — Configure code generation settings to prepare the
code for Polyspace analysis.
If you select the MISRA C:2012 guidelines code generation objective, the Code
Generation Advisor:
• Checks the model configuration settings for compliance with the MISRA C:2012
configuration setting recommendations.
• Checks for blocks that are not supported or recommended for MISRA C:2012
compliant code generation.
31-19
31 Configuration for Simulink Coder
1 On the menu bar, select Code > C/C++ Code > Code Generation Advisor.
2 In the System Selector window, select the model or subsystem that you want to
review, and then click OK.
3 In the Code Generation Advisor, on the Code Generation Objectives pane, select
the code generation objectives from the drop-down list (GRT-based targets). As you
select objectives, on the left pane, the Code Generation Advisor updates the list of
checks it will run on your model. If your model is configured with an ERT-based
target, more objectives are available.
4 Click Run Selected Checks to run the checks listed in the left pane of the Code
Generation Advisor.
5 In the Code Generation Advisor window, review the results for Check model
configuration settings against code generation objectives by selecting it from
the left pane. The results for that check are displayed in the right pane.
• Parameters are set to values other than the value recommended for the specified
code generation objectives.
• Selected code generation objectives differ from the objectives set in the model.
When you specify an efficiency or Safety precaution objective, the Code Generation
Advisor includes additional checks. When you make changes to one of these additional
checks, previous check results can potentially become invalid and need to be rerun.
31-20
Application Objectives Using Code Generation Advisor
1 Open the Configuration Parameters dialog box and select Code Generation.
2 Select or confirm selection of a System target file.
3 Specify the objectives using the Select objectives drop-down list (GRT-based
targets) or clicking Set Objectives button (ERT-based targets). Clicking Set
Objectives opens the “Set Objectives — Code Generation Advisor Dialog Box”
(Simulink Coder) dialog box.
4 Click Check Model to run the model checks. The Code Generation Advisor dialog
box opens. The Code Generation Advisor uses the code generation objectives to
determine which model checks to run.
5 On the left pane, the Code Generation Advisor lists the checks run on the model and
the results. Click each warning to see the suggestions for changes that you can make
to your model to pass the check.
6 Determine which changes to make to your model. On the right pane of the Code
Generation Advisor, follow the instructions listed for each check to modify the model.
31-21
31 Configuration for Simulink Coder
• To start the Model Advisor, in the model window, select Analysis > Model Advisor >
Model Advisor.
• In the Model Advisor window, expand the By Task folder. The folder contains Model
Advisor checks that you can run to help accomplish the task.
For more information about the Model Advisor, see “Run Model Checks” (Simulink).
The table summarizes the Simulink Coder Model Advisor checks that are available in the
By Task folders.
See Also
Related Examples
• “Select and Run Model Advisor Checks” (Simulink)
• “Embedded Coder Model Advisor Checks for Standards, Guidelines, and Code
Efficiency” on page 32-12
31-22
See Also
31-23
31 Configuration for Simulink Coder
Goal Action
Include comments in Include comments (Simulink Coder). Selecting this parameter allows you
generated code to select one or more autogenerated comment types to be placed in the
code.
Include comments that Simulink block comments (Simulink Coder). Selecting this parameter
describe a Simulink includes the comments before the Simulink block’s code in the generated
block's code code. In Embedded Coder, use Trace to model using (Simulink Coder) to
select Block path or Simulink identifier as the comment format.
Include comments that Stateflow object comments (Simulink Coder). Selecting this parameter
describe Stateflow includes the comments describing Stateflowobjects in the generated code.
objects In Embedded Coder, use Trace to model using (Simulink Coder) to select
Block path or Simulink identifier as the comment format.
Include MATLAB MATLAB source code as comments (Simulink Coder). Selecting this
source code as parameter inserts these comments preceding the associated generated
comments code. The function signature is included in the function banner.
Include comments for Show eliminated blocks (Simulink Coder). Selecting this parameter
eliminated blocks includes comments for blocks that were eliminated as the result of
optimizations, such as inlining parameters.
Include parameter Verbose comments for SimulinkGlobal storage class (Simulink Coder).
comments regardless Selecting this parameter includes comments for parameter variable names
of the number of and names of source blocks in the model parameter structure declaration
parameters in model_prm.h.
31-24
Configure Code Comments
Note When you configure the code generator to produce code that includes comments,
the code generator includes text for model parameters, block names, signal names, and
Stateflow object names in the generated code comments. If the text includes characters
that are unrepresented in the character set encoding for the model, the code generator
replaces the characters with XML escape sequences. For example, the code generator
replaces the Japanese full-width Katakana letter ア with the escape sequence ア.
For more information, see “Internationalization and Code Generation” (Simulink Coder).
31-25
31 Configuration for Simulink Coder
The code generator conditionally generates the name-mangling text to resolve potential
conflicts with other generated identifiers.
To configure how the code generator names identifiers and objects, see:
The code generator reserves certain words for its own use as keywords of the generated
code language. For more information, see “Reserved Keywords” on page 31-30.
With an Embedded Coder license, you can specify parameters to control identifier
formats, mangle length, scalar inlined parameters, and Simulink data object naming
rules. For more information, see “Customize Generated Identifier Naming Rules” on page
39-14.
31-26
Identifier Name Collisions and Mangling
When a name conflict occurs between an identifier within the scope of a higher-level
model and an identifier within the scope of a referenced model, the identifier from the
referenced model is preserved. Name mangling is performed on the identifier from the
higher-level model.
31-27
31 Configuration for Simulink Coder
When there is a potential name collision between two identifiers, name-mangling text is
generated. The text has the minimum number of characters required to avoid the
collision. The other symbol components are then inserted. If Maximum identifier length
is not large enough to accommodate full expansions of the other components, they are
truncated. To avoid this outcome, it is good practice to:
• Avoid name collisions by not using default block names (for example, Gain1,
Gain2...) when the model includes multiple blocks of the same type.
• For subsystems, make them atomic and reusable.
• Increase the Maximum identifier length parameter to accommodate the length of
the identifier you expect to generate.
31-28
Specify Reserved Names for Generated Identifiers
If your model contains MATLAB Function or Stateflow blocks, the code generation
process can use the reserved names specified for those blocks if you select Use the same
reserved names as Simulation Target (Simulink Coder) on the Code Generation >
Symbols pane.
31-29
31 Configuration for Simulink Coder
Reserved Keywords
In this section...
“C Reserved Keywords” on page 31-30
“C++ Reserved Keywords” on page 31-31
“Reserved Keywords for Code Generation” on page 31-31
“Code Generation Code Replacement Library Keywords” on page 31-32
Generator keywords are reserved for internal use. Do not use them in models as
identifiers or function names. Also avoid using C reserved keywords in models as
identifiers or function names. If your model contains reserved keywords, code generation
does not complete and an error message appears. To address the error, modify your
model to use identifiers or names that are not reserved.
If you use the code generator to produce C++ code, your model must not contain the
“Reserved Keywords for Code Generation” on page 31-31 nor the “C++ Reserved
Keywords” on page 31-31.
Note You can register additional reserved identifiers in the Simulink environment. For
more information, see “Specify Reserved Names for Generated Identifiers” on page 31-29.
C Reserved Keywords
auto double int struct
break else long switch
case enum register typedef
char extern return union
const float short unsigned
continue for signed void
default goto sizeof volatile
do if static while
31-30
Reserved Keywords
31-31
31 Configuration for Simulink Coder
This function returns an array of library keywords. Specifying the input argument is
optional.
Note To list the libraries currently registered in your environment, use the MATLAB
command crviewer.
To generate a list of reserved keywords for a specific library that you are using to
generate code, call the function passing the name of the library as displayed in the Code
replacement library menu on the Code Generation > Interface pane of the
Configuration Parameters dialog box. For example,
lib_ids = RTW.TargetRegistry.getInstance.getTflReservedIdentifiers('GNU C99 Extensions')
lib_ids =
'exp10'
'exp10f'
31-32
Reserved Keywords
'acosf'
'acoshf'
'asinf'
'asinhf'
'atanf'
'atanhf'
...
'rt_lu_cplx'
'rt_lu_cplx_sgl'
'rt_lu_real'
'rt_lu_real_sgl'
'rt_mod_boolean'
'rt_rem_boolean'
'strcpy'
'utAssert'
Note Some of the returned keywords appear with the suffix $N, for example,
'rt_atan2$N'. $N expands into the suffix _snf only if nonfinite numbers are supported.
For example, 'rt_atan2$N' represents 'rt_atan2_snf' if nonfinite numbers are
supported and 'rt_atan2' if nonfinite numbers are not supported. As a precaution, you
should treat both forms of the keyword as reserved.
31-33
31 Configuration for Simulink Coder
Debug
In the Configuration Parameters dialog box, use parameters on the Diagnostics pane and
debugging parameters to configure a model such that the generated code and the build
process are set for debugging. You can set parameters that apply to the model
compilation phase, the target language code generation phase, or both.
Parameters in the following table will be helpful if you are writing TLC code for
customizing targets, integrating legacy code, or developing new blocks.
To... Select...
Display progress “Verbose build” (Simulink Coder).Compiler output also
information during code displays.
generation in the
MATLAB Command
Window
Prevent the build “Retain .rtw file” (Simulink Coder). This parameter is useful if
process from deleting you are modifying the target files, in which case you need to
the model.rtw file look at the model.rtw file.
from the build folder at
the end of the build
Instruct the TLC “Profile TLC” (Simulink Coder). The report is in HTML format
profiler to analyze the and can be read in your web browser.
performance of TLC
code executed during
code generation and
generate a report
Start the TLC debugger “Start TLC debugger when generating code” (Simulink Coder).
during code generation Alternatively, enter the argument -dc for the “System target
file” (Simulink Coder) parameter on the Code Generation
pane. To start the debugger and run a debugger script, enter -
df filename for System target file.
31-34
Debug
To... Select...
Generate a report “Start TLC coverage when generating code” (Simulink Coder).
containing statistics Alternatively, enter the argument -dg for the System Target
indicating how many File parameter on the Code Generation pane.
times the code
generator reads each
line of TLC code during
code generation
Halt a build if a user- “Enable TLC assertion” (Simulink Coder). Alternatively, you can
supplied TLC file use MATLAB commands to control TLC assertion handling.
contains an %assert
directive that evaluates To set the flag on or off, use the set_param command. The
to FALSE default is off.
get_param(model, 'TLCAssertion')
Detect loss of tunability “Detect loss of tunability” (Simulink) on the Diagnostics >
Data Validity pane. You can use this parameter to report loss
of tunability when an expression is reduced to a numeric
expression. This can occur if a tunable workspace variable is
modified by Mask Initialization code, or is used in an arithmetic
expression with unsupported operators or functions. Possible
values are:
31-35
31 Configuration for Simulink Coder
To... Select...
Enable model “Model Verification block enabling” (Simulink). Use this
verification (assertion) parameter to enable or disable model verification blocks such
blocks as Assert, Check Static Gap, and related range check blocks.
The diagnostic applies to generated code and simulation
behavior. For example, simulation and code generation ignore
this parameter when model verification blocks are inside an S-
function. Possible values are:
utAssert(input_signal);
utAssert(input_signal != 0.0);
utAssert(input_signal != 0);
make_rtw OPTS="-DDOASSERTS"
31-36
See Also
To... Select...
External Code by Using Model Configuration Parameters”
(Simulink Coder).
For more information about the TLC debugging options, see Debugging on “Target
Language Compiler” (Simulink Coder). Also, consider using the Model Advisor as a tool
for troubleshooting model builds.
See Also
More About
• “Tunable Expression Limitations” (Simulink Coder)
• “Integrate External Code by Using Model Configuration Parameters” (Simulink
Coder)
• “Target Language Compiler” (Simulink Coder)
31-37
32
• “Configure Model for Code Generation Objectives by Using Code Generation Advisor”
on page 32-2
• “Configure Code Generation Objectives Programmatically” on page 32-9
• “Check Model and Configuration for Code Generation” on page 32-10
• “Embedded Coder Model Advisor Checks for Standards, Guidelines, and Code
Efficiency” on page 32-12
• “Create Custom Code Generation Objectives” on page 32-16
• “Configuration Variations” on page 32-22
• “Configure and Optimize Model with Configuration Wizard Blocks” on page 32-23
• “Create a Model Configured for Code Generation Using Model Templates”
on page 32-32
32 Configuration in Embedded Coder
Consider how your application objectives, such as efficiency, traceability, and safety, map
to code generation parameters in a model configuration set. Parameters that you set in
the Solver, Data Import/Export, Diagnostics, and Code Generation panes in the
Configuration Parameters dialog box specify the behavior of a model in simulation and the
code generated for the model.
Before generating code, or as part of the code generation process, you can use the Code
Generation Advisor to review a model. When you choose to review a model before
generating code, you specify which model, subsystem, or referenced model the Code
Generation Advisor reviews. When you choose to review a model as part of the code
generation process, the Code Generation Advisor reviews the entire system. The Code
Generation Advisor uses the information presented in “Recommended Settings Summary
for Model Configuration Parameters” to determine the parameter values that meet your
objectives. When there is a conflict between multiple objectives, the higher-priority
objective takes precedence.
Setting code generation objectives, and then running the Code Generation Advisor
provides information on how to meet code generation objectives for your model. The Code
Generation Advisor does not alter the generated code. You can use the Code Generation
Advisor to make the suggested changes to your model. The generated code is changed
only after you modify your model and regenerate code. When you use the Code
Generation Advisor to set code generation objectives and check your model, the
generated code includes comments identifying which objectives you specified, the checks
that the Code Generation Advisor ran on the model, and the results of running the checks.
If a model uses a configuration reference (Simulink), you can run the Code Generation
Advisor to review your configuration parameter settings. but the Code Generation Advisor
cannot modify the configuration parameter settings.
32-2
Configure Model for Code Generation Objectives by Using Code Generation Advisor
• Execution efficiency (all targets) — Configure code generation settings to achieve fast
execution time.
• ROM efficiency (ERT-based targets) — Configure code generation settings to reduce
ROM usage.
• RAM efficiency (ERT-based targets) — Configure code generation settings to reduce
RAM usage.
• Traceability (ERT-based targets) — Configure code generation settings to provide
mapping between model elements and code.
• Safety precaution (ERT-based targets) — Configure code generation settings to
increase clarity, determinism, robustness, and verifiability of the code.
• Debugging (all targets) — Configure code generation settings to debug the code
generation build process.
• MISRA C:2012 guidelines (ERT-based targets) — Configure code generation settings to
increase compliance with MISRA C:2012 guidelines.
• Polyspace (ERT-based targets) — Configure code generation settings to prepare the
code for Polyspace analysis.
If you select the MISRA C:2012 guidelines code generation objective, the Code
Generation Advisor:
• Checks the model configuration settings for compliance with the MISRA C:2012
configuration setting recommendations.
• Checks for blocks that are not supported or recommended for MISRA C:2012
compliant code generation.
32-3
32 Configuration in Embedded Coder
To specify different objectives for the top model and each referenced model, review the
models separately without generating code.
1 On the menu bar, select Code > C/C++ Code > Code Generation Advisor.
2 In the System Selector window, select the model or subsystem that you want to
review, and then click OK.
3 In the Code Generation Advisor, on the Code Generation Objectives pane, select
the code generation objectives. As you select objectives, on the left pane, the Code
Generation Advisor updates the list of checks it runs on your model. If your model is
configured with an ERT-based target, more objectives are available. For this example,
the model is configured with an ERT-based target. If your objectives are execution
efficiency and traceability, in that priority, do the following:
4 To run the checks listed in the left pane of the Code Generation Advisor, click Run
Selected Checks.
5 In the Code Generation Advisor window, review the results for Check model
configuration settings against code generation objectives by selecting it from
the left pane. The results for that check are displayed in the right pane.
32-4
Configure Model for Code Generation Objectives by Using Code Generation Advisor
• Parameters are set to values other than the value recommended for the specified
code generation objectives.
• Selected code generation objectives differ from the objectives set in the model.
6 In the Code Generation Advisor window, review the results for the remaining checks
by selecting them from the left pane. The results for the checks display in the right
pane.
7 After reviewing the check results, you can choose to fix warnings and failures, as
described in “Fix a Model Check Warning or Failure” (Simulink).
32-5
32 Configuration in Embedded Coder
When you specify an efficiency or Safety precaution objective, the Code Generation
Advisor includes additional checks. When you make changes to one of these additional
checks, previous check results can potentially become invalid and need to be rerun.
c To accept the objectives, click OK. In the Configuration Parameters dialog box,
Code Generation > General > Prioritized objectives is updated.
5 On the Configuration Parameters > Code Generation > General pane, click
Check Model.
32-6
Configure Model for Code Generation Objectives by Using Code Generation Advisor
6 In the System Selector window, select the model or subsystem that you want to
review, and then click OK. The Code Generation Advisor opens and reviews the
model or subsystem that you specified.
7 In the Code Generation Advisor window, review the results by selecting a check from
the left pane. The results for that check display in the right pane.
8 After reviewing the check results, you can choose to fix warnings and failures, as
described in “Fix a Model Check Warning or Failure” (Simulink).
When you specify an efficiency or Safety precaution objective, the Code Generation
Advisor includes additional checks. When you make changes to one of these additional
checks, previous check results can potentially become invalid and need to be rerun.
For more information, see “Set Objectives — Code Generation Advisor Dialog Box”
(Simulink Coder)
32-7
32 Configuration in Embedded Coder
See Also
Related Examples
• “Configure Code Generation Objectives Programmatically” on page 32-9
• “Recommended Settings Summary for Model Configuration Parameters”
• “Recommended Model Configuration Parameters for Polyspace Analysis” (Polyspace
Bug Finder)
• “Code Generation Advisor Checks” (Simulink Coder)
32-8
Configure Code Generation Objectives Programmatically
1 Specify a system target file. If you specify an ERT-based target, more objectives are
available. For this example, specify ert.tlc. model_name is the name or handle to
the model.
set_param(model_name, 'ObjectivePriorities',...
{'Execution efficiency', 'Traceability'});
3 Execute the Code Generation Advisor, by using either the Code Generation Advisor or
in the Configuration Parameters dialog box. For more information, see “Configure
Model for Code Generation Objectives by Using Code Generation Advisor” on page
32-2.
When you specify a GRT-based system target file, you can specify an objective at the
command line. If you specify ROM efficiency, RAM efficiency, Traceability,
MISRA C:2012 guidelines, Polyspace, or Safety precaution, the build process
changes the objective to Unspecified because you have specified a value that is invalid
when using a GRT-based target.
See Also
Related Examples
• “Configure Model for Code Generation Objectives by Using Code Generation
Advisor” on page 32-2
• “Create Custom Code Generation Objectives” on page 32-16
• “Recommended Settings Summary for Model Configuration Parameters”
• “Code Generation Advisor Checks” (Simulink Coder)
32-9
32 Configuration in Embedded Coder
To check model rtwdemo_throttlecntrl for code efficiency, use the Model Advisor.
32-10
Check Model and Configuration for Code Generation
If the Code Generation Advisor issues failures or warnings, and you specified:
Note When you specify an efficiency or Safety precaution objective, the Code
Generation Advisor includes additional checks. When you make changes to one of
these additional checks, previous check results can potentially become invalid and
need to be rerun.
For more information, see “Set Objectives — Code Generation Advisor Dialog Box”
(Simulink Coder)
32-11
32 Configuration in Embedded Coder
• To start the Model Advisor, in the model window, select Analysis > Model Advisor >
Model Advisor.
• In the Model Advisor window, expand the By Task folder. The folder contains Model
Advisor checks that you can run to help accomplish the task.
For more information about the Model Advisor, see “Run Model Checks” (Simulink).
The table summarizes the Embedded Coder Model Advisor checks that are available in
the By Task folders.
32-12
Embedded Coder Model Advisor Checks for Standards, Guidelines, and Code Efficiency
32-13
32 Configuration in Embedded Coder
See Also
Related Examples
• “Select and Run Model Advisor Checks” (Simulink)
• “Simulink Coder Model Advisor Checks for Standards and Code Efficiency”
(Simulink Coder)
32-14
See Also
32-15
32 Configuration in Embedded Coder
In this section...
“Specify Parameters in Custom Objectives” on page 32-16
“Specify Checks in Custom Objectives” on page 32-17
“Determine Checks and Parameters in Existing Objectives” on page 32-17
“Steps to Create Custom Objectives” on page 32-18
The Code Generation Advisor reviews your model based on objectives that you specify. If
the predefined efficiency, traceability, Safety precaution, and debugging objectives do not
meet your requirements, you can create custom objectives.
• Create an objective and add parameters and checks to this new objective.
• Create an objective based on an existing objective, then add, modify, and remove the
parameters and checks within that new objective.
• addParam — Add parameters and specify the values that the Code Generation Advisor
reviews in Check model configuration settings against code generation
objectives.
• modifyInheritedParam — Modify inherited parameter values that the Code
Generation Advisor reviews in Check model configuration settings against code
generation objectives.
• removeInheritedParam — Remove inherited parameters from a new objective that
is based on an existing objective. When you select multiple objectives, if another
selected objective includes this parameter, the Code Generation Advisor reviews the
parameter value in Check model configuration settings against code generation
objectives.
32-16
Create Custom Code Generation Objectives
• addCheck — Add checks to the Code Generation Advisor. When you select the custom
objective, the Code Generation Advisor displays the check, unless you specify an
additional objective with a higher priority that excludes the check.
For example, add a check to the Code Generation Advisor to include a custom check in
the automatic model checking process.
• excludeCheck — Exclude checks from the Code Generation Advisor. When you select
multiple objectives, if you specify an additional objective that includes this check as a
higher priority objective, the Code Generation Advisor displays this check.
For example, exclude a check from the Code Generation Advisor when a check takes a
long time to process.
• removeInheritedCheck — Remove inherited checks from a new objective that is
based on an existing objective. When you select multiple objectives, if another selected
objective includes this check, the Code Generation Advisor displays the check.
For example, remove an inherited check, rather than exclude the check, when the
check takes a long time to process, but the check is important for another objective.
For example, the Efficiency objective includes checks that you can see in the Code
Generation Advisor.
1 Open the rtwdemo_rtwecintro model.
2 Specify an ERT-based target.
3 On the model toolbar, select Code > C/C++ Code > Code Generation Advisor.
4 In the System Selector window, select the model or subsystem that you want to
review, and then click OK.
32-17
32 Configuration in Embedded Coder
5 In the Code Generation Advisor, on the Code Generation Objectives pane, select
the code generation objectives. As you select objectives, on the left pane, the Code
Generation Advisor updates the list of checks it runs on your model. For this example,
select Execution efficiency. In Available objectives, double-click Execution
efficiency. Execution efficiency is added to Selected objectives -
prioritized.
In the left pane, the Code Generation Advisor lists the checks for the Execution
efficiency objective. The first check, Check model configuration settings against
code generation objectives, lists parameters and values specified by the objective. For
example, the Code Generation Advisor displays the list of parameters and the
recommended values in the Execution efficiency objective. To see the list of
parameters and values:
1 Run Check model configuration settings against code generation objectives.
2 Click Modify Parameters.
3 Rerun the check.
In the check results, the Code Generation Advisor displays the list of parameters and
recommended values for the Execution efficiency objective.
32-18
Create Custom Code Generation Objectives
For example:
function sl_customization(cm)
%SL_CUSTOMIZATION objective customization callback
objCustomizer = cm.ObjectiveCustomizer;
index = objCustomizer.addCallbackObjFcn(@addObjectives);
objCustomizer.callbackFcn{index}();
end
3 Create a MATLAB callback function that:
The following example shows how to create an objective Reduce RAM Example.
Reduce RAM Example includes five parameters and three checks that the Code
Generation Advisor reviews.
function addObjectives
32-19
32 Configuration in Embedded Coder
end
end
4 If you previously opened the Code Generation Advisor, close the model from which
you opened the Code Generation Advisor.
5 Refresh the customization manager. At the MATLAB command line, enter
sl_refresh_customizations.
6 Open your model and review the new objectives.
32-20
See Also
See Also
Related Examples
• “Configure Model for Code Generation Objectives by Using Code Generation
Advisor” on page 32-2
• “Configure Code Generation Objectives Programmatically” on page 32-9
• “Recommended Settings Summary for Model Configuration Parameters”
• “Code Generation Advisor Checks” (Simulink Coder)
32-21
32 Configuration in Embedded Coder
Configuration Variations
Every model contains one or more named configuration sets that specify model
parameters such as solver options, code generation options, and other choices. A model
can contain multiple configuration sets, but only one configuration set is active at a time.
For more information on configuration sets and how to view and edit them in the
Configuration Parameters dialog box, see “About Model Configurations” (Simulink).
A configuration set includes parameters that specify code generation in general. For more
information, see “Configure a Model for Code Generation” (Simulink Coder). With
Embedded Coder and an ERT system target file, more parameters are available for fine-
tuning to optimize and customize the appearance of the generated code.
See Also
Related Examples
• “About Model Configurations” (Simulink)
• “Configure a Model for Code Generation” (Simulink Coder)
32-22
Configure and Optimize Model with Configuration Wizard Blocks
In this section...
“Configuration Wizard Block Library” on page 32-23
“Add a Configuration Wizard Block” on page 32-24
“Use Configuration Wizard Blocks to Configure Your Model” on page 32-25
“Create a Custom Configuration Wizard Block” on page 32-26
Block Description
Custom MATLAB file Update active configuration parameters of
parent model by using a custom file
ERT (optimized for fixed-point) Update active configuration parameters of
parent model for ERT fixed-point code
generation
ERT (optimized for floating-point) Update active configuration parameters of
parent model for ERT floating-point code
generation
GRT (debug for fixed/floating-point) Update active configuration parameters of
parent model for GRT fixed- or floating-
point code generation with debugging
enabled
GRT (optimized for fixed/floating-point) Update active configuration parameters of
parent model for GRT fixed- or floating-
point code generation
32-23
32 Configuration in Embedded Coder
When you add one of the preset Configuration Wizard blocks to your model and double-
click it, a predefined MATLAB file script configures parameters of the active configuration
set without manual intervention. The preset blocks optimally configure the parameters for
one of the following cases:
The Custom block provides an example MATLAB file script that you can adapt to your
requirements.
You can also set up the Configuration Wizard blocks to invoke the build process after
configuring the model.
32-24
Configure and Optimize Model with Configuration Wizard Blocks
2 Open the Embedded Coder block library by typing the command rtweclib.
3 Double-click the Configuration Wizards icon. The Configuration Wizards sublibrary
opens.
4 Select the Configuration Wizard block that you want to use and drag it into your
model. This model contains the ERT (optimized for fixed-point)
Configuration Wizard block.
5 If you want the Configuration Wizard block to invoke the build process after
configuration, right-click the Configuration Wizard block in your model, and select
Mask > Mask Parameters from the context menu. Then, select the Invoke build
process after configuration parameter. Do not change the Configure the model
for block parameter, unless you want to create a custom block and script. In that
case, see “Create a Custom Configuration Wizard Block” on page 32-26.
6 Click Apply and close the Mask Parameters dialog box.
7 Save the model.
32-25
32 Configuration in Embedded Coder
If you selected the Invoke build process after configuration block parameter, the
script also initiates the code generation and build process.
Note To provide a quick way to switch between configurations, you can add more than
one Configuration Wizard block to your model.
Set up a custom Configuration Wizard block and link it to a script. If you want to use the
block in more than one mode, it is advisable to create a Simulink library to contain the
block.
1 To store your custom script, create a folder. This folder must not be anywhere inside
the MATLAB folder structure (that is, it must not be under matlabroot).
This statement is used later as a test to see that your custom block has executed the
script.
5 Save your script and close the MATLAB editor.
The next task is to create a Simulink library and add a custom block to it.
32-26
Configure and Optimize Model with Configuration Wizard Blocks
1 Open the Embedded Coder block library and the Configuration Wizards sublibrary, as
described in “Add a Configuration Wizard Block” on page 32-24.
2 Select New > Library from the File menu of the Configuration Wizards sublibrary
window. An empty library window opens.
3 Select the Custom MATLAB file block from the Configuration Wizards sublibrary and
drag it into the empty library window.
4 To distinguish your custom block from the original, edit the Custom MATLAB file
label under the block.
5 Select Save as from the File menu of the new library window. Save the library to
the /my_wizards folder, under your library name of choice. In this figure, the
library is saved as ex_custom_button and the block is labeled my_wizard
MATLAB-file.
The next task is to link the custom block to the custom script:
1 Right-click the block in your model and select Mask > Mask Parameters from the
context menu. The Configure the model for menu is set to Custom. When Custom
is selected, the Configuration function edit field is enabled so that you can enter
the name of a custom script.
2 In the Configuration function field, enter the name of your custom script . (Do not
enter the .m file name extension, which is implicit.)
32-27
32 Configuration in Embedded Coder
3 By default, the Invoke build process after configuration parameter is cleared. You
can change the default for your custom block by selecting this option. For now, leave
this parameter cleared.
4 Click Apply and close the Mask Parameters dialog box.
5 Save the library.
6 Close the Embedded Coder block library and the Configuration Wizards sublibrary.
Leave your custom library open for use in the next task.
vdp
2 Open the Configuration Parameters dialog box and view the parameters by clicking
Code Generation in the list in the left pane of the dialog box.
3 Observe that vdp is configured, by default, for the GRT target. Close the
Configuration Parameters dialog box.
4 Select your custom block from your custom library. Drag the block into the vdp
model.
5 In the vdp model, double-click your custom block.
6 In the MATLAB window, you see the test message that you previously added to your
script:
The test message indicates that the custom block executed the script.
7 Reopen the Configuration Parameters dialog box and view the Code Generation
pane again. The model is now configured for the ERT target.
Before applying further edits to your custom script, proceed to the next section to learn
about the operation and conventions of Configuration Wizard scripts.
Create your custom Configuration Wizard script by copying and modifying the example
script, rtwsampleconfig.m.
32-28
Configure and Optimize Model with Configuration Wizard Blocks
The example script implements a single function without a return value. The function
takes a single argument cs:
function rtwsampleconfig(cs)
The argument cs is a handle to a proprietary object that contains information about the
active configuration set. The Simulink software obtains this handle and passes it in to the
configuration function when you double-click a Configuration Wizard block.
Your custom script must conform to this prototype. Your code must use cs as a “black-
box” object that transmits information to and from the active configuration set.
To set parameters or obtain parameter values, use the Simulink set_param and
get_param functions.
To obtain the current setting of an option in the active configuration set, call get_param.
Pass in the cs object as the first argument, followed by the internal option name. For
example, the following code excerpt tests the setting of the Create code generation
report option:
To set an option in the active configuration set, call set_param. Pass in the cs object as
the first argument, followed by one or more parameter/value pairs that specify the
internal option name and its value. For example, the following code excerpt turns off the
Support absolute time option:
set_param(cs,'SupportAbsoluteTime','off');
32-29
32 Configuration in Embedded Coder
Select a Target
A Configuration Wizard script must select a target configuration. The example script uses
the ERT target as a default. The script first stores character vector variables that
correspond to the required System target file, Template makefile, and Make
command settings:
stf = 'ert.tlc';
tmf = 'ert_default_tmf';
mc = 'make_rtw';
You select the system target file by passing the cs object and the stf character vector to
the switchTarget function:
switchTarget(cs,stf,[]);
Set the template makefile and make command options by using set_param calls:
set_param(cs,'TemplateMakefile',tmf);
set_param(cs,'MakeCommand',mc);
To select a target, your custom script must set up the character vector variables stf,
tmf, and mc and pass them to the calls.
Obtain Target and Configuration Set Information
The following utility functions and properties are provided so that your code can obtain
information about the current target and configuration set with the cs object:
You can use this information to determine whether the script must configure ERT-specific
parameters, for example:
if isERT
set_param(cs,'ZeroExternalMemoryAtStartup','off');
32-30
See Also
set_param(cs,'ZeroInternalMemoryAtStartup','off');
set_param(cs,'InitFltsAndDblsToZero','off');
set_param(cs,'InlinedParameterPlacement',...
'NonHierarchical');
set_param(cs,'NoFixptDivByZeroProtection','on')
end
Configuration Wizard scripts can be run from the MATLAB command line.
Before invoking the script, you must open a model and instantiate a cs object to pass in
as an argument to the script. After running the script, you can invoke the build process
with the rtwbuild command. The following example opens, configures, and builds a
model.
open my_model;
cs = getActiveConfigSet ('my_model');
rtwsampleconfig(cs);
rtwbuild('my_model');
See Also
Related Examples
• “Generate Code by Using the Quick Start Tool” on page 37-10
• “Generate Code and Simulate Models in a Simulink Project”
• “Generate Code and Simulate Models with Simulink Project API”
32-31
32 Configuration in Embedded Coder
• Code Generation System. Create a model to get started with code generation.
• Exported functions. Create a model for generating code from function-call subsystems.
• Fixed-step, multirate. Create a fixed-step model with multiple rates for production
code generation.
• Fixed-step, single-rate. Create a fixed-step model with a single rate for production
code generation.
In the templates, traceability and reporting are turned on so that you can easily evaluate
your generated code. The model has System target file set to ert.tlc and is configured
to meet code generation objectives prioritized in the following order:
1 Execution efficiency
2 Traceability
For more information, for example to create and use a template as a reference design, see
“Create a Template from a Model” (Simulink).
32-32
33
After selecting a system target file, you can modify model configuration parameter
settings.
You can switch between different system target files in a single workflow for different
code generation purposes (for example, rapid prototyping versus production code
deployment). To switch, set up different configuration sets for the same model and switch
the active configuration set for the current operation. For more information on how to set
up configuration sets and change the active configuration set, see “Manage a
Configuration Set” (Simulink).
In this section...
“Select a Solver That Supports Code Generation” on page 33-2
“Select a System Target File from STF Browser” on page 33-3
“Select a System Target File Programmatically” on page 33-4
“Develop Custom System Target Files” on page 33-5
• Use Configuration Parameters > Solver > Type and select Fixed-step for GRT,
ERT, and ERT-based system target files.
33-2
Configure a System Target File
• Use Configuration Parameters > Solver > Type and select Fixed-step or
Variable-step for Rapid Simulation (Rsim) or S-Function (rtwsfcn) system target
files.
For more information about the requirement that you use a fixed-step solver to generate
code for a realtime system target file, see “Time-Based Scheduling and Code Generation”
on page 17-2.
When you try to build models with a nonzero start time using a system target file does not
support a nonzero start time, the code generator does not produce code. The build
process displays an error message. The Rapid Simulation (RSim) system target file
supports a nonzero start time when Configuration Parameters > RSim Target >
Solver selection is set to Use Simulink solver module. Other system target files do
not support a nonzero start time.
If you use a system target file that does not appear in the System Target File Browser,
enter the name of your system target file in the System target file field.
You also can select a system target file programmatically from MATLAB code, as
described in “Select a System Target File Programmatically” on page 33-4.
After selecting a system target file, you can modify model configuration parameter
settings. Selecting a system target file for your model selects either the toolchain
approach or template makefile approach for build process control. For more information
about these approaches, see “Choose Build Approach and Configure Build Process” on
page 43-14.
If you want to switch between different system target files in a single workflow for
different code generation purposes, set up different configuration sets for the same
model. Switch the active configuration set for the current operation. This approach is
useful for switching between rapid prototyping and production code deployment. For
more information on how to set up configuration sets and change the active configuration
set, see “Manage a Configuration Set” (Simulink).
33-3
33 System Target File Configuration
To select a system target file using the System Target File Browser,
1 Open the Code Generation pane of the Configuration Parameters dialog box.
2 Click the Browse button next to the System target file field. This button opens the
System Target File Browser. The browser displays a list of currently available system
target files, including customizations. When you select a system target file, the code
generator automatically chooses the system target file, toolchain or template
makefile, and/or make command for that configuration.
The next step shows the System Target File Browser with the GRT system target file
selected.
3 Click the desired entry in the list of available configurations. The background of the
list box turns yellow to indicate that an unapplied choice has been made. To apply it,
click Apply or OK.
When you choose a system target file, the code generator selects the toolchain or
template makefile and/or make command for that configuration and displays them in
the System target file field. The description of the system target file from the
browser is placed below its name in the Code Generation pane. For information
each system target file, see “Compare System Target File Support” on page 33-21.
33-4
Configure a System Target File
structure of a particular system target file and the current values of relevant options.
Simulink loads some of this information from the system target file that you specify. You
can configure models to generate alternative code by copying and modifying old or
adding new configuration sets and browsing to select a new system target file. Then, you
can interactively select an active configuration from among these sets (only one
configuration set can be active at a given time).
Scripts that automate system target file selection must emulate this process.
For example:
cs = getActiveConfigSet(model);
stf = 'ert.tlc';
tmf = 'ert_default_tmf';
mc = 'make_rtw';
switchTarget(cs,stf,[]);
set_param(cs,'TemplateMakefile',tmf);
set_param(cs,'MakeCommand',mc);
For more information about selecting system target files programmatically, see
switchTarget.
33-5
33 System Target File Configuration
For more information on how to make custom system target files appear in the System
Target File Browser and display relevant controls, see “About Embedded Target
Development” (Simulink Coder) and the topics it references.
See Also
getActiveConfigSet | switchTarget
More About
• “Configure STF-Related Code Generation Parameters” on page 33-7
• “Configure a Code Replacement Library” on page 33-17
• “Configure Standard Math Library for Target System” on page 33-18
• “Compare System Target File Support” on page 33-21
• “About Embedded Target Development” (Simulink Coder)
33-6
Configure STF-Related Code Generation Parameters
In this section...
“Specify Generated Code Interfaces” on page 33-7
“Configure Numeric Data Support” on page 33-12
“Configure Time Value Support” on page 33-12
“Configure Noninlined S-Function Support” on page 33-13
“Configure Model Function Generation and Argument Passing” on page 33-13
“Configure Code Reuse Support” on page 33-15
33-7
33 System Target File Configuration
• When the model contains Model blocks, places utility code within
the slprj/target/_sharedutils folder.
• When the model does not contain Model blocks, places utility code
in the build folder (generally, in model.c or model.cpp).
Specify text to be added to Enter a prefix or suffix, such as rt_ or _rt, for the MAT-file variable
the variable names used name modifier parameter. The code generator prefixes or appends
when logging data to MAT- the text to the variable names for system outputs, states, and
files and to distinguish simulation time specified in the Data Import/Export pane. See “Log
logging data from code Program Execution Results” on page 45-2 for information on MAT-
generation and simulation file data logging.
applications.
33-8
Configure STF-Related Code Generation Parameters
Note Before setting Standard math library or Code replacement library, verify that
your compiler supports the library you want to use. If you select a parameter value that
your toolchain does not support, compiler errors can occur. For example, if you select
standard math library C99 (ISO) and your compiler does not support the ISO C math
extensions, compile-time errors could occur.
When the Embedded Coder product is installed on your system, the Code Generation >
Interface pane expands to include several additional options. For descriptions of Code
Generation > Interface pane parameters, see “Model Configuration Parameters: Code
Generation Interface” (Simulink Coder).
33-9
33 System Target File Configuration
Interface Dependencies
33-10
Configure STF-Related Code Generation Parameters
33-11
33 System Target File Configuration
For more information, see “Model Configuration Parameters: Code Generation Interface”
(Simulink Coder).
To... Select...
Generate code that creates Support absolute time. For further information on the allocation
and maintains integer and operation of absolute and elapsed timers, see “Absolute and
counters for blocks that use Elapsed Time Computation” (Simulink Coder). If you do not select
absolute or elapsed time this parameter and the model includes a block that uses absolute or
values (default). elapsed time values, the build process generates an error.
Generate code for blocks that Support continuous time. If you do not select this parameter and
rely on continuous time. the model includes continuous-time blocks, the build process
generates an error.
For more information, see “Model Configuration Parameters: Code Generation Interface”
(Simulink Coder).
33-12
Configure STF-Related Code Generation Parameters
When you select Support non-finite numbers and the model includes a C MEX S-
function that does not have a corresponding TLC implementation (for inlining code
generation), the build process generates an error.
When generating code for a model that contains noninlined S-functions with an ERT
system target file, there could be a mismatch between the simulation and code generation
results when either of the following is true:
To... Do...
Generate model function calls Select Classic call interface and MAT-file logging. In
that are compatible with the main addition, clearing Remove error status field in real-time
program module of the pre- model data structure. Classic call interface provides a quick
R2012a GRT system target file way to use code generated in R2012a or higher with a pre-
(grt_main.c or .cpp). R2012a GRT-based custom system target file by generating
wrapper function calls that interface to the generated code.
33-13
33 System Target File Configuration
To... Do...
Reduce overhead and use more Select Single output/update function
local variables by combining the
output and update functions in a Errors or unexpected behavior can occur if a Model block is
single model_step function. part of a cycle and the model configuration enables “Single
output/update function” (Simulink Coder) (the default). For
more information about direct feed through, see “Algebraic
Loops” (Simulink).
Generate a model_terminate Select Terminate function required (Simulink Coder). For
function for a model not designed more information, see the description of model_terminate.
to run indefinitely.
Generate reusable, reentrant Select Generate reusable code. See “Configure Code Reuse
code from a model or subsystem. Support” on page 33-15 for details.
Statically allocate model data Clear Generate reusable code. The generated code is not
structures and access them reusable or reentrant. See “Configure Code Generation for
directly in the model code. Model Entry-Point Functions” (Simulink Coder) for information
on the calling interface generated for model functions in this
case.
Suppress the generation of an Select Remove error status field in real-time model data
error status field in the real-time structure. Selecting this parameter can also cause the code
model data structure, rtModel, generator to omit the rtModel structure from the generated
for example, if you do not require code.
to log or monitor error messages.
When generating code for multiple integrated models, set this
parameter the same for all of the models. Otherwise, the
integrated application could exhibit unexpected behavior. For
example, if you select the option in one model but not in
another, it is possible that the integrated application could not
register the error status.
33-14
Configure STF-Related Code Generation Parameters
To... Do...
Open the Model Step Functions Click Configure Step Function. Based on the Function
dialog box preview and modify specification value you select for your model_step function
the model_step function (supported values include Default model-step function
prototype (see “Configure Code and Model specific C prototype), you can preview and
Generation for Model Entry-Point modify the function prototype. Once you validate and apply your
Functions” (Simulink Coder)). changes, you can generate code based on your function
prototype modifications. For more information about using the
Configure Step Function button and the Model Step
Functions dialog box, see “Customize Generated C Function
Interfaces” on page 29-2.
For more information, see “Model Configuration Parameters: Code Generation Interface”
(Simulink Coder).
The Configuration Parameters > Code Generation > Pass root-level I/O as
parameter provides options that control how model inputs and outputs at the root level of
the model are passed to the model_step function.
To... Select...
Pass each root-level model input and output Code interface packaging > Reusable
argument to the model_step function function and Pass root-level I/O as >
individually (the default) Individual arguments.
Pack root-level input arguments and root-level Code interface packaging > Reusable
output arguments into separate structures that function and Pass root-level I/O as >
are then passed to the model_step function Structure reference.
Pack root-level input arguments and root-level Code interface packaging > Reusable
output arguments into the model data structure function and Pass root-level I/O as > Part
to support reentrant multi-instance code from a of model data structure.
model for ERT system target file
If using the Code interface packaging > Reusable function selection, consider
using the Use dynamic memory allocation for model initialization option to control
33-15
33 System Target File Configuration
whether an allocation function is generated. This option applies for ERT system target
files.
Sometimes, the code generator is unable to generate valid and compilable code. For
example, if the model contains one of the following, the generated code is invalid.
For more information, see “Generate Reentrant Code from Top-Level Models” on page 37-
21 and “Model Configuration Parameters: Code Generation Interface” (Simulink Coder).
See Also
More About
• “Configure a System Target File” on page 33-2
• “Configure a Code Replacement Library” on page 33-17
• “Configure Standard Math Library for Target System” on page 33-18
• “Compare System Target File Support” on page 33-21
33-16
Configure a Code Replacement Library
For more information about replacing code, using code replacement libraries that
MathWorks provides, see “What Is Code Replacement?” on page 41-2 and “Code
Replacement Libraries” (Simulink Coder). For information about developing code
replacement libraries, see “What Is Code Replacement Customization?” on page 54-3.
See Also
More About
• “Configure a System Target File” on page 33-2
• “Configure STF-Related Code Generation Parameters” on page 33-7
• “Configure Standard Math Library for Target System” on page 33-18
• “Compare System Target File Support” on page 33-21
• “Specify Generated Code Interfaces” on page 33-7
33-17
33 System Target File Configuration
The C99 library leverages the performance that a compiler offers over standard ANSI C.
When using the C99 library, the code generator produces calls to ISO C functions when
possible. For example, the generated code calls the function sqrtf(), which operates on
single-precision data, instead of sqrt().
33-18
Configure Standard Math Library for Target System
2. Generate code.
3. Examine the code in the generated file rtwdemo_clibsup.c. Note that the code calls
the sqrt function.
33-19
33 System Target File Configuration
1. Change the setting of Standard math library to C99 (ISO). Alternatively, at the
command line, set TargetLangStandard to C99 (ISO).
3. Reexamine the code in the generated file rtwdemo_clibsup.c. Now the generated
code calls the function sqrtf instead of sqrt.
Related Information
33-20
Compare System Target File Support
In this section...
“Evaluate Product System Target Files” on page 33-23
“Compare Code Styles and STF Support” on page 33-25
“Compare Generated Code Features by Product” on page 33-26
“Compare Generated Code Features by STF” on page 33-29
The code generator uses the system target file to produce code intended for execution on
certain target hardware or operating system. The system target file invokes other run-
time environment-specific files. For more information on configuring model code
generation parameters for target hardware, see “Configure Run-Time Environment
Options” (Simulink Coder).
Different types of system target files support a selection of generated code features. In
the system target file, the value of the CodeFormat TLC variable and corresponding
rtwgensettings.DerivedFrom field value identify the system target file type and
generated code features. These selections control decisions made at several points in the
code generation process. These decisions include whether and how the model build
generates:
• If the system target file does not include a value for the CodeFormat TLC variable, the
default value is RealTime for generic real-time target (GRT). The corresponding
rtwgensettings.DerivedFrom field value is grt.tlc (default value).
• If you are developing a custom system target file and you have a license for Embedded
Coder software, consider setting the CodeFormat TLC variable value to Embedded-C
for embedded real-time target (ERT). The corresponding
rtwgensettings.DerivedFrom field value is ert.tlc. The ERT system target file
supports more generated code features than the GRT system target file.
33-21
33 System Target File Configuration
The following example shows how the value for the CodeFormat TLC variable and
corresponding rtwgensettings.DerivedFrom field value are set in ert.tlc.
/%
BEGIN_RTW_OPTIONS
rtwgensettings.DerivedFrom = 'ert.tlc';
END_RTW_OPTIONS
%/
Warning You must use the value for the CodeFormat TLC variable with its
corresponding rtwgensettings.DerivedFrom field value to generated code for the
model. If none are explicitly selected, the default values correspond. For more
information, see “System Target File Structure” (Simulink Coder).
For a description of the optimized call interface generated by default for both the GRT
and ERT system target files, see “Configure Code Generation for Model Entry-Point
Functions” (Simulink Coder).
For a description of the rtModeldata structure, see “Use the Real-Time Model Data
Structure” (Simulink Coder).
The following topics provide more information about generated code features:
In this section...
“Evaluate Product System Target Files” on page 33-23
“Compare Code Styles and STF Support” on page 33-25
“Compare Generated Code Features by Product” on page 33-26
33-22
Compare System Target File Support
In this section...
“Compare Generated Code Features by STF” on page 33-29
Note You can select from a range of system target files by using the System Target File
Browser. This selection lets you experiment with configuration options and save your
model with different configurations. However, you cannot build or generate code for non-
GRT system target files, unless you have the required license on your system. For
example, you require Embedded Coder for ERT system target files, require Simulink
Desktop Real-Time for SLDRT system target files, and so on.
Selecting a system target file for your model selects either the toolchain approach or
template makefile approach for build process control. For more information about these
approaches, see “Choose Build Approach and Configure Build Process” on page 43-14.
33-23
33 System Target File Configuration
33-24
Compare System Target File Support
33-25
33 System Target File Configuration
embedded applications. The following table maps system target files to corresponding
code styles.
Third-party vendors supply additional system target files for the code generator. For more
information about third-party products, see the MathWorks Connections program web
page: https://www.mathworks.com/products/connections.
33-26
Compare System Target File Support
Compare Code Generation Features for Simulink Coder Versus Embedded Coder
33-27
33 System Target File Configuration
33-28
Compare System Target File Support
The following table summarizes how different system target files support applications:
The following table summarizes the various options available for each System target file
selection, with the exceptions noted.
33-29
33 System Target File Configuration
Static X X X X X
memory
allocation
Dynamic X4, 5 X4, 5 X X X
memory
allocation
Continuous X X X X X X
time
C/C++ MEX X X X X X X
S-functions
(noninlined)
S-function X X X X X X X
(inlined)
Minimize X X2 X
RAM/ROM
usage
Supports X X X X X
external
mode
Rapid X X X X
prototyping
Production X X2 X3
code
Batch X X
parameter
tuning and
Monte Carlo
methods
System-level X
Simulator
33-30
Compare System Target File Support
Executes in X3 X3 X X X5
hard real
time
Non-real- X X X
time
executable
included
Multiple X4, 5 X4, 5 X4 X4, 5 X4, 5
instances of
model
Supports X X
variable-step
solvers
Supports X X
SIL/PIL
1
System Target Files: grt.tlc - generic real-time target, ert.tlc - embedded real-time
target, ert_shrlib.tlc - embedded real-time target shared library), rtwsfcn.tlc - S-
Function, rsim.tlc - rapid simulation, sldrt.tlc - Simulink Desktop Real-Time, slrt.tlc -
Simulink Real-Time, and Other - The embedded real-time capabilities in Simulink Coder
support other system target files.
2
Does not apply to GRT-based system target files. Applies only to an ERT-based system
target files.
3
The default GRT and ERT rt_main files emulate execution of hard real time, and when
explicitly connected to a real-time clock execute in hard real time.
4
You can generate code for multiple instances of a Stateflow chart or subsystem
containing a chart, except when the chart contains exported graphical functions or the
Stateflow model contains machine parented events.
5
You must select the value Reusable function for Code interface packaging
(Simulink Coder) in the Code Generation > Interface pane of the Configuration
Parameters dialog box.
33-31
33 System Target File Configuration
See Also
More About
• “Configure a System Target File” on page 33-2
• “Configure STF-Related Code Generation Parameters” on page 33-7
• “Configure a Code Replacement Library” on page 33-17
• “Configure Standard Math Library for Target System” on page 33-18
33-32
34
Internationalization Support in
Simulink Coder
34 Internationalization Support in Simulink Coder
In this section...
“Locale Settings” on page 34-2
“Prepare to Generate Code for Mixed Languages and Locales” on page 34-2
“Character Set Limitations” on page 34-3
“XML Escape Sequence Replacements” on page 34-3
“Generate and Review Code with Mixed Languages and Mixed Locales” on page 34-3
Locale Settings
On a computer, a locale setting defines the language (character set encoding) for the user
interface and the display formats for information such as time, date, and currency. The
encoding dictates the number of characters that a locale can render. For example, the US-
ASCII coded character set (codeset) defines 128 characters. A Unicode® codeset, such as
UTF-8, defines more than 1,100,000 characters.
For code generation, the locale setting determines the character set encoding of
generated file content. To avoid garbled text or incorrectly displayed characters, the
locale setting for your MATLAB session must be compatible with the setting for your
compiler and operating system. For information on finding and changing the operating
system setting, see “Internationalization” (MATLAB) or see the operating system
documentation.
To check a model for characters that cannot be represented in the locale setting of your
current MATLAB session, use the Simulink Model Advisor check “Check model for foreign
characters” (Simulink).
34-2
Internationalization and Code Generation
Before using this example, see “Internationalization and Code Generation” (Simulink
Coder) or “Internationalization and Code Generation” on page 35-2.
The rtwdemo_unicode model configuration uses the Embedded Coder (R) ert.tlc
system target file. To see internationalization and localization support with Simulink
Coder®, configure the model to use the grt.tlc system target file. The example
indicates the support that is specific to Embedded Coder® (for example, code generation
templates).
34-3
34 Internationalization Support in Simulink Coder
The model configuration specifies files and settings that control how the code generator
handles localization for:
Labels in the model appear in multiple languages (Arabic, Chinese, English, German, and
Japanese) and various Unicode symbols.
model = 'rtwdemo_unicode';
open_system(model);
Verify that the locale setting for your MATLAB® software is compatible with your
compiler. See the documentation for your operating system or the following MATLAB
documentation:
34-4
Internationalization and Code Generation
to verify the model for characters that the code generator cannot represent in the model's
current character set encoding, use the Simulink® Model Advisor check Check model
for foreign characters.
1. Open the Model Advisor in Simulink®. Select Analysis > Model Advisor > Model
Advisor. Or, in the Command Window, type:
modeladvisor('rtwdemo_unicode')
2. Expand By Product.
3. Expand Simulink.
6. Review the results. Several warnings appear. Verify that the characters in the model
can be represented in the current character set encoding.
To use a code generation template file with unicode characters when generating code,
complete these steps (requires Embedded Coder®). Otherwise, go to the next section.
2. Navigate to the Code Generation > Template pane. The model is configured to use
the code generation template file rtwdemo_unicode.cgt. That file adds comments to
the top of generated code files. For the code generator to apply escape sequence
replacements for the .cgt file, enable replacements by specifying:
<encodingIn = "encoding-name">
edit rtwdemo_unicode.cgt
4. Find the line of code that enables escape sequence replacements for the character set
encoding UTF-8.
34-5
34 Internationalization Support in Simulink Coder
<encodingIn = "UTF-8">
To use file customization templates with unicode characters when generating code,
complete these steps (requires Embedded Coder®). Otherwise, go to the next section.
You can specify customizations to generated code files by using TLC code. TLC files
support user default encoding only. To produce international custom generated code that
is portable, use the 7-bit ASCII character set.
2. Navigate to the Code Generation > Template pane. The model is configured to use
the code customization file example_file_process.tlc. That file customizes the
generated code just before the code generator writes the code files. For example, the file
adds a C source file, corresponding include file, and #define and #include statements.
edit example_file_process.tlc
Generate C Code
For characters that are not in the current MATLAB® character set encoding, the code
generator uses escape sequence replacements to render characters correctly in the code
generation report.
1. If the code generation report for model rtwdemo_unicode is not open, in the
Command Window, type:
34-6
Internationalization and Code Generation
coder.report.open('rtwdemo_unicode')
3. Open the Traceability Report. The report maintains traceability information, even when
the name contains characters that are not represented in the current encoding. Names of
model elements appear in the report as replacement names in the local language.
4. Scroll down to and click the code location link for the first Chart (State
'Selection' <S2>:23). The report view changes to show the corresponding code in
rtwdemo_unicode.c.
5. In the code comment, click the <S2>:23 link. The model window shows the chart in a
new tab.
6. In the model window, right-click that chart. Select C/C++ Code > Navigate to C/C++
Code. The report view changes to show the named constant section of code for that
chart.
7. Close the code generation report, Model Advisor, and model. In the Command Window,
type:
coder.report.close();
bdclose('all');
model = 'rtwdemo_unicode';
open_system(model);
34-7
34 Internationalization Support in Simulink Coder
2. Change Configuration Parameters > Code Generation > Language to C++. Or, in
the Command Window, type:
set_param('rtwdemo_unicode','TargetLang','C++');
3. Change Configuration Parameters > Code Generation > Interface > Code
interface packaging to C++ class. Or, in the Command Window, type:
set_param('rtwdemo_unicode','CodeInterfacePackaging','C++ class');
evalc('rtwrebuild(''rtwdemo_unicode'')');
5. To see internationalization and localization support, review the generated code. See
Review the Generated Code.
6. Close the code generation report and model. In the Command Window, type:
coder.report.close();
bdclose('all');
See Also
More About
• “Locale Settings for MATLAB Process” (MATLAB)
34-8
35
Internationalization Support in
Embedded Coder
35 Internationalization Support in Embedded Coder
In this section...
“Locale Settings” on page 35-2
“Prepare to Generate Code for Mixed Languages and Locales” on page 35-3
“Character Set Limitations” on page 35-3
“XML Escape Sequence Replacements” on page 35-3
“CGT Files and XML Escape Sequence Replacements” on page 35-3
“Generate and Review Code with Mixed Languages and Mixed Locales” on page 35-4
Locale Settings
On a computer, a locale setting defines the language (character set encoding) for the user
interface and the display formats for information such as time, date, and currency. The
encoding dictates the number of characters that a locale can render. For example, the US-
ASCII coded character set (codeset) defines 128 characters. A Unicode codeset, such as
UTF-8, defines more than 1,100,000 characters.
For code generation, the locale setting determines the character set encoding of
generated file content. To avoid garbled text or incorrectly displayed characters, the
locale setting for your MATLAB session must be compatible with the setting for your
compiler and operating system. For information on finding and changing the operating
system setting, see “Internationalization” (MATLAB) or see the operating system
documentation.
To check a model for characters that cannot be represented in the locale setting of your
current MATLAB session, use the Simulink Model Advisor check “Check model for foreign
characters” (Simulink).
35-2
Internationalization and Code Generation
By default, code generation template files do not contain character set encoding
information. The operating system reads the files, using its current encoding, regardless
of the encoding that you use to write the file. You can enable escape sequence
replacements by adding the following token at the top of the template file:
35-3
35 Internationalization Support in Embedded Coder
<encodingIn = "encoding">
Replace encoding with a string that names a standard character encoding scheme, such
as UTF-8, ISO-8859–1, or windows-1251.
This example shows content from the file rtwdemo_unicode.cgt in a MATLAB session for
windows-1251. The example uses the encodingIn token to set the encoding to UTF–8,
which is the correct value for code generation.
Before using this example, see “Internationalization and Code Generation” (Simulink
Coder) or “Internationalization and Code Generation” on page 35-2.
The rtwdemo_unicode model configuration uses the Embedded Coder (R) ert.tlc
system target file. To see internationalization and localization support with Simulink
Coder®, configure the model to use the grt.tlc system target file. The example
indicates the support that is specific to Embedded Coder® (for example, code generation
templates).
The model configuration specifies files and settings that control how the code generator
handles localization for:
35-4
Internationalization and Code Generation
Labels in the model appear in multiple languages (Arabic, Chinese, English, German, and
Japanese) and various Unicode symbols.
model = 'rtwdemo_unicode';
open_system(model);
Verify that the locale setting for your MATLAB® software is compatible with your
compiler. See the documentation for your operating system or the following MATLAB
documentation:
35-5
35 Internationalization Support in Embedded Coder
to verify the model for characters that the code generator cannot represent in the model's
current character set encoding, use the Simulink® Model Advisor check Check model
for foreign characters.
1. Open the Model Advisor in Simulink®. Select Analysis > Model Advisor > Model
Advisor. Or, in the Command Window, type:
modeladvisor('rtwdemo_unicode')
2. Expand By Product.
3. Expand Simulink.
6. Review the results. Several warnings appear. Verify that the characters in the model
can be represented in the current character set encoding.
To use a code generation template file with unicode characters when generating code,
complete these steps (requires Embedded Coder®). Otherwise, go to the next section.
2. Navigate to the Code Generation > Template pane. The model is configured to use
the code generation template file rtwdemo_unicode.cgt. That file adds comments to
the top of generated code files. For the code generator to apply escape sequence
replacements for the .cgt file, enable replacements by specifying:
<encodingIn = "encoding-name">
edit rtwdemo_unicode.cgt
4. Find the line of code that enables escape sequence replacements for the character set
encoding UTF-8.
35-6
Internationalization and Code Generation
<encodingIn = "UTF-8">
To use file customization templates with unicode characters when generating code,
complete these steps (requires Embedded Coder®). Otherwise, go to the next section.
You can specify customizations to generated code files by using TLC code. TLC files
support user default encoding only. To produce international custom generated code that
is portable, use the 7-bit ASCII character set.
2. Navigate to the Code Generation > Template pane. The model is configured to use
the code customization file example_file_process.tlc. That file customizes the
generated code just before the code generator writes the code files. For example, the file
adds a C source file, corresponding include file, and #define and #include statements.
edit example_file_process.tlc
Generate C Code
For characters that are not in the current MATLAB® character set encoding, the code
generator uses escape sequence replacements to render characters correctly in the code
generation report.
1. If the code generation report for model rtwdemo_unicode is not open, in the
Command Window, type:
35-7
35 Internationalization Support in Embedded Coder
coder.report.open('rtwdemo_unicode')
3. Open the Traceability Report. The report maintains traceability information, even when
the name contains characters that are not represented in the current encoding. Names of
model elements appear in the report as replacement names in the local language.
4. Scroll down to and click the code location link for the first Chart (State
'Selection' <S2>:23). The report view changes to show the corresponding code in
rtwdemo_unicode.c.
5. In the code comment, click the <S2>:23 link. The model window shows the chart in a
new tab.
6. In the model window, right-click that chart. Select C/C++ Code > Navigate to C/C++
Code. The report view changes to show the named constant section of code for that
chart.
7. Close the code generation report, Model Advisor, and model. In the Command Window,
type:
coder.report.close();
bdclose('all');
model = 'rtwdemo_unicode';
open_system(model);
35-8
See Also
2. Change Configuration Parameters > Code Generation > Language to C++. Or, in
the Command Window, type:
set_param('rtwdemo_unicode','TargetLang','C++');
3. Change Configuration Parameters > Code Generation > Interface > Code
interface packaging to C++ class. Or, in the Command Window, type:
set_param('rtwdemo_unicode','CodeInterfacePackaging','C++ class');
evalc('rtwrebuild(''rtwdemo_unicode'')');
5. To see internationalization and localization support, review the generated code. See
Review the Generated Code.
6. Close the code generation report and model. In the Command Window, type:
coder.report.close();
bdclose('all');
See Also
More About
• “Locale Settings for MATLAB Process” (MATLAB)
35-9
36
In this section...
“About This Example” on page 36-2
“Functional Design of the Model” on page 36-3
“View the Top Model” on page 36-3
“View the Subsystems” on page 36-4
“Simulation Test Environment” on page 36-5
“Run Simulation Tests” on page 36-10
“Key Points” on page 36-11
“Learn More” on page 36-12
Prerequisites
Required Files
Before you use each example model file, place a copy in a writable location and add it to
your MATLAB path.
36-2
Configure Model, Generate Code, and Simulate
Subsystems PI_ctrl_1
PI_ctrl_2
Define_Throt_Param
Pos_Command_Arbitration
Top-level input pos_rqst
fbk_1
fbk_2
36-3
36 Source Code Generation in Simulink Coder
36-4
Configure Model, Generate Code, and Simulate
The PI controllers in the model are from a library, a group of related blocks or models
for reuse. Libraries provide one of two methods for including and reusing models.
The second method, model referencing, is described in “Simulation Test
Environment” on page 36-5. You cannot edit a block that you add to a model from a
library. Edit the block in the library so that instances of the block in different models
remain consistent.
3 Open the Pos_Command_Arbitration subsystem. This Stateflow chart performs
basic error checking on the two command signals. If the command signals are too far
apart, the Stateflow diagram sets the output to a fail_safe position.
4 Close throttlecntrl.
The test harness model for this example implements a common simulation testing
environment consisting of the following parts:
36-5
36 Source Code Generation in Simulink Coder
2 Set up your throttlecntrl model as the control algorithm of the test harness.
36-6
Configure Model, Generate Code, and Simulate
The control algorithm is the unit under test, as indicated by the name of the Model
block, Unit_Under_Test.
The Model block provides a method for reusing components. From the top model, it
allows you to reference other models (directly or indirectly) as compiled functions. By
default, Simulink software recompiles the model when the referenced models change.
Compiled functions have the following advantages over libraries:
36-7
36 Source Code Generation in Simulink Coder
The subsystem uses a Signal Builder block for the test vector source. The block has
data that drives the simulation (PosRequest) and provides the expected results used
by the Verification subsystem. This example test harness uses only one set of test
data. Typically, create a test suite that fully exercises the system.
4 Open the evaluation and logging subsystem, implemented in this test harness as
subsystem Verification.
A test harness compares control algorithm simulation results against golden data —
test results that exhibit the desired behavior for the control algorithm as certified by
an expert. In the Verification subsystem, an Assertion block compares the
simulated throttle value position from the plant against the golden value from the test
harness. If the difference between the two signals is greater than 5%, the test fails
and the Assertion block stops the simulation.
36-8
Configure Model, Generate Code, and Simulate
Alternatively, you can evaluate the simulation data after the simulation completes
execution. Perform the evaluation with either MATLAB scripts or third-party tools.
Post-execution evaluation provides greater flexibility in the analysis of data. However,
it requires waiting until execution is complete. Combining the two methods can
provide a highly flexible and efficient test environment.
5 Open the plant or feedback system, implemented in this test harness as the Plant
subsystem.
The Plant subsystem models the throttle dynamics with a transfer function in
canonical form. You can create plant models to varying levels of fidelity. It is common
to use different plant models at different stages of testing.
6 Open the input and output scaling subsystems, implemented in this test harness as
Input_Signal_Scaling and Output_Signal_Scaling.
36-9
36 Source Code Generation in Simulink Coder
The subsystems that scale input and output perform the following primary functions:
36-10
Configure Model, Generate Code, and Simulate
The lower-right hand plot shows the difference between the expected (golden)
throttle position and the throttle position that the plant calculates. If the difference
between the two values is greater than ±0.05, the simulation stops.
4 Save and close throttle controller and test harness models.
Key Points
• A basic model architecture separates calculations from signal routing and partitions
the model into subsystems
• Two options for model reuse include block libraries and model referencing.
• If you represent your control algorithm in a test harness as a Model block, specify the
name of the control algorithm model in the Model Reference Parameters dialog box.
36-11
36 Source Code Generation in Simulink Coder
Learn More
• “Support Model Referencing” (Simulink Coder)
• “Code Generation” (Simulink Coder)
• “Signal Groups” (Simulink)
36-12
Configure Model and Generate Code
Prerequisites
Required Files
36-13
36 Source Code Generation in Simulink Coder
3 Open the Code Generation > General pane and note that the System target file is
set to grt.tlc.
Note The GRT (Generic Real-Time Target) configuration requires a fixed-step solver.
However, the rsim.tlc system target file supports variable step code generation.
36-14
Configure Model and Generate Code
The system target file (STF) defines an environment for generating and building code
for execution on a certain hardware or operating system platform. For example, one
property of a system target file is the value for the CodeFormat TLC variable. The
GRT configuration requires a fixed step solver and the rsim.tlc supports variable step
code generation.
4 Open the Code Generation > Custom Code pane and under Include list of
additional, select Include directories. The following path appears in the text field:
"$matlabroot$\toolbox\rtw\rtwdemos\EmbeddedCoderOverview\"
This folder includes files that are required to build an executable for the model.
5 Close the dialog box.
thcntrlAcs = getActiveConfigSet('throttlecntrl');
thcntrlAcs.saveAs('throttlecntrlModelConfig');
You can then use the resulting function (for example, throttlecntrlModelConfig) to:
For example, you can set the configuration of model myModel to match the configuration
of the throttle controller model by opening myModel and entering:
myModelAcs = throttlecntrlModelConfig;
attachConfigSet('myModel', myModelAcs, true);
setActiveConfigSet('myModel', myModelAcs.Name);
For more information, see “Save a Configuration Set” (Simulink) and “Load a Saved
Configuration Set” (Simulink).
36-15
36 Source Code Generation in Simulink Coder
Watch the messages that appear in the MATLAB Command Window. The code
generator produces standard C and header files, and an HTML code generation
36-16
Configure Model and Generate Code
report. The code generator places the files in a build folder, a subfolder named
throttlecntrl_grt_rtw under your current working folder.
Consider examining the following files. In the HTML report Contents pane, click the
links. Or, in your working folder, explore the generated code subfolder.
File Description
throttlecntrl.c C file that contains the scheduler,
controller, initialization, and interface code
throttlecntrl_data.c C file that assigns values to generated data
structures
throttlecntrl.h Header file that defines data structures
throttlecntrl_private.h Header file that defines data used only by
the generated code
throttlecntrl_types.h Header file that defines the model data
structure
36-17
36 Source Code Generation in Simulink Coder
For more information, see “Manage Build Process File Dependencies” (Simulink Coder).
At this point, consider logging data to a MAT-file. For an example, see “Log Data for
Analysis” (Simulink Coder).
Generate an Executable
1 Open throttlecntrl.
2 In the Configuration Parameters dialog box, clear the Code Generation > Generate
code only check box and click Apply.
3 Press Ctrl+B. Watch the messages in the MATLAB Command Window. The code
generator uses a template make file associated with your system target file selection
to create an executable file. You can run this program on your workstation,
independent of external timing and events.
4 Check your working folder for the filethrottlecntrl.exe.
5 Run the executable. In the Command Window, enter !throttlecntrl. The !
character passes the command that follows it to the operating system, which runs the
standalone program.
At this point, consider logging data to a MAT-file. For an example, see “Log Data for
Analysis” (Simulink Coder).
Tip For UNIX platforms, run the executable in the Command Window with the syntax !./
executable_name. If preferred, run the executable from an OS shell with the syntax ./
executable_name. For more information, see “Run External Commands, Scripts, and
Programs” (MATLAB).
Key Points
• To generate code, change the model configuration to specify a fixed-step solver then
select a system target file. Using the grt.tlc file requires a fixed-step solver. If the
model contains continuous time blocks, you can use a variable-step solver with the
rsim.tlc system target file.
36-18
See Also
See Also
More About
• “Code Generation” (Simulink Coder)
• “Configuration Reuse” (Simulink)
• “Run Model Checks” (Simulink)
36-19
36 Source Code Generation in Simulink Coder
Prerequisites
Required File
Declare Data
Most programming languages require that you declare data before using it. The
declaration specifies the following information:
36-20
Configure Data Interface
A storage class is the scope and duration of a data item. For more information about
storage classes, see “Apply Storage Classes to Individual Signal, State, and Parameter
Data Elements” on page 22-81.
In the MATLAB and Simulink environment, you can use data objects in various ways. This
example focuses on the following types of data objects:
• Signal
• Parameter
• Bus
To configure the data interface for your model using the data object method, in the
MATLAB base workspace, you define data objects. Then, associate them with your
Simulink model or embedded Stateflow chart. When you build your model, the build
process uses the associated base workspace data objects in the generated code.
You can set the values of the data object properties, which include:
36-21
36 Source Code Generation in Simulink Coder
• Data type
• Storage class
• Value (parameters)
• Initial value (signals)
• Alias (define a different name in the generated code)
• Dimension (typically inherited for parameters)
• Complexity (inherited for parameters)
• Unit (physical measurement unit)
• Minimum value
• Maximum value
• Description (used to document your data objects — does not affect simulation or code
generation)
You can create and inspect base workspace data objects by entering commands in the
MATLAB Command Window or by using Model Explorer. To explore base workspace
signal data objects, use these steps:
36-22
Configure Data Interface
You can also view the definition of a signal object. In the MATLAB Command Window,
enter pos_cmd_one:
pos_cmd_one =
36-23
36 Source Code Generation in Simulink Coder
You can use a bus definition (ThrottleCommands) to instantiate multiple instances of the
structure. In a model diagram, a bus object appears as a wide line with central dashes, as
shown.
To find constructs for which you can create data objects, use the Data Object Wizard. This
tool finds the constructs and then creates the objects for you. The model includes two
signals that are not associated with data objects: fbk_1 and pos_cmd_two.
36-24
Configure Data Interface
a In the model window, right-click the pos_cmd_one signal line and select
Properties. A Signal Properties dialog box opens.
b Make sure that you select the Signal name must resolve to Simulink signal
object parameter.
2 Enable signal object resolution for the signals in the model. In the MATLAB
Command Window, enter:
disableimplicitsignalresolution('throttlecntrl_datainterface')
3 Save and close throttlecntrl_datainterface.
36-25
36 Source Code Generation in Simulink Coder
1 Open throttlecntrl_datainterface.
2 Open your copy of test harness, throttlecntrl_testharness.
3 Right-click the Unit_Under_Test Model block and select Block Parameters
(ModelReference).
4 Set Model name to throttlecntrl_datainterface. Click OK.
5 Update the test harness model diagram.
6 Simulate the test harness.
The resulting plot shows that the difference between the golden and simulated
versions of the model remains zero.
36-26
Configure Data Interface
Manage Data
Data objects exist in a separate file from the model in the base workspace. To save the
data manually, in the MATLAB Command Window, enter save.
The separation of data from the model provides the following benefits:
36-27
36 Source Code Generation in Simulink Coder
• Use of different parameter values to change the behavior of the control algorithm
(for example, for reusable components with different calibration values)
• Use of different data types to change targeted hardware (for example, for floating-
point and fixed-point targeted hardware)
• Multiple models, one data set:
Key Points
• You can declare data in Simulink models and Stateflow charts by using data objects or
direct specification.
• From the Model Explorer or from the command line in the MATLAB Command
Window, manage (create, view, configure, and so on) base workspace data.
• The Data Object Wizard provides a quick way to create data objects for constructs
such as signals, buses, and parameters.
• Configure data objects explicitly to appear by name in generated code.
• Separation of data from model provides several benefits.
See Also
More About
• “Load Signal Data for Simulation” (Simulink)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
• “Control Placement of Global Data Definitions and Declarations in Generated Files”
on page 23-2
36-28
Call External C Functions
In this section...
“About This Example” on page 36-29
“Include External C Functions in a Model” on page 36-30
“Create a Block That Calls a C Function” on page 36-30
“Validate External Code in the Simulink Environment” on page 36-32
“Validate C Code as Part of a Model” on page 36-33
“Call a C Function from Generated Code” on page 36-35
“Key Points” on page 36-35
Prerequisites
Required Files
36-29
36 Source Code Generation in Simulink Coder
This example shows you how to create a custom block that calls an external C function.
When the block is part of the model, you can take advantage of the simulation
environment to test the system further.
The data structure def defines the function interface to the external C code.
def =
SFunctionName: ''
InitializeConditionsFcnSpec: ''
OutputFcnSpec: ''
StartFcnSpec: ''
TerminateFcnSpec: ''
HeaderFiles: {}
SourceFiles: {}
HostLibFiles: {}
36-30
Call External C Functions
TargetLibFiles: {}
IncPaths: {}
SrcPaths: {}
LibPaths: {}
SampleTime: 'inherited'
Options: [1x1 struct]
b Populate the function interface definition structure by entering the following
commands:
def.OutputFcnSpec=['double y1 = SimpleTable(double u1,',...
'double p1[], double p2[], int16 p3)'];
def.HeaderFiles = {'SimpleTable.h'};
def.SourceFiles = {'SimpleTable.c'};
def.SFunctionName = 'SimpTableWrap';
c Create the S-function:
legacy_code('sfcn_cmex_generate', def)
d Compile the S-function:
legacy_code('compile', def)
e Create the S-Function block:
legacy_code('slblock_generate', def)
Tip Creating the S-Function block is a one-time task. Once the block exists, you
can reuse it in multiple models.
3 Save the model to your working folder as: s_func_simptablewrap.
4 Create a Target Language Compiler (TLC) file for the S-Function block:
legacy_code('sfcn_tlc_generate', def)
The TLC file is the component of an S-function that specifies how the code generator
produces the code for a block.
36-31
36 Source Code Generation in Simulink Coder
• The Sine Wave block produces output values from [-2 : 2].
• The input range of the lookup table is from [-1 : 1].
• The output from the lookup table is the absolute value of the input.
• The lookup table output clips the output at the input limits.
2 Simulate the model.
3 View the validation results by opening the Validation subsystem and, in that
subsystem, clicking the Scope block.
The following figure shows the validation results. The external C code and the
Simulink Lookup table block provide the same output values.
36-32
Call External C Functions
36-33
36 Source Code Generation in Simulink Coder
36-34
See Also
1 Open throttlecntrl_extfunccall.
2 Generate code for the model.
3 Examine the generated code in the filethrottlecntrl_extfunccall.c.
4 Close throttlecntrl_extfunccall and throttlecntrl_testharness.
Key Points
• You can easily integrate external functions into a model and generated code by using
the Legacy Code Tool.
• Validate the functionality of external C function code which you integrate into a model
as a standalone component.
• After you validate the functionality of external C function code as a standalone
component, validate the S-function in the model.
See Also
More About
• “Integrate C Functions Using Legacy Code Tool” (Simulink)
• “S-Functions and Code Generation” (Simulink Coder)
36-35
36 Source Code Generation in Simulink Coder
1 Click the Code for model node in the Model Hierarchy pane.
2 In the Code pane, click the Refresh link.
The code generator reloads the code for the model from the build folder.
See Also
More About
• “Rebuild a Model” (Simulink Coder)
• “Control Regeneration of Top Model Code” (Simulink Coder)
36-36
Manage Build Process Folders
• Your company does not use the current working folder as the location for the code
generation folder or the simulation cache folder.
• You place the code generation folder under version control, but do not place the
simulation cache folder under version control.
36-37
36 Source Code Generation in Simulink Coder
36-38
Manage Build Process Folders
36-39
36 Source Code Generation in Simulink Coder
36-40
See Also
If the system target file is ERT-based, then these configuration parameters also control
the location of shared utility code:
You can use RTW.getBuildDir to display build folder information for the model.
See Also
RTW.getBuildDir | Simulink.fileGenControl
More About
• “Manage Build Process Files” (Simulink Coder)
• “Manage Build Process File Dependencies” (Simulink Coder)
• “Add Build Process Dependencies” (Simulink Coder)
• “Enable Build Process for Folder Names with Spaces” (Simulink Coder)
36-41
36 Source Code Generation in Simulink Coder
36-42
Manage Build Process Files
The code generator creates model.* files during the code generation and build process.
You can customize the file names for generated header, source, and data files. For more
information, see “Customize Generated File Names” on page 39-70. The code generator
creates additional folders and dependency files to support shared utilities and model
references. For more information about the folders that the build process creates, see
“Manage Build Process Folders” (Simulink Coder). For an example that shows how to use
Simulink project to manage build process folders, see “Generate Code and Simulate
Models in a Simulink Project” (Simulink Coder).
Depending on model architectures and code generation options, the build process for a
GRT-based system target file can produce files that the build process does not generate
for an ERT-based system target file. Also, for ERT-based system target files, the build
process packages generated files differently than for GRT-based system target files. See
“Manage File Packaging of Generated Code Modules” on page 37-14.
Note By default, the build process deletes foreign (not generated) source files in the
build folder. It is possible to preserve foreign source files in the build folder by following
the guidelines in “Preserve External Code Files in Build Folder” (Simulink Coder).
The table describes the principal generated files. Within the generated file names shown
in the table, the model represents the name of the model for which you are generating
code. The subsystem represents the name of a subsystem within the model. When you
select the Create code generation report parameter, the code generator produces a set
of HTML files. There is one HTML file for each source file plus a model_contents.html
index file in the html subfolder within your build folder. The source and header files in
the table have dependency relationships. For descriptions of other file dependencies, see
“Manage Build Process File Dependencies” (Simulink Coder) and “Add Build Process
Dependencies” (Simulink Coder).
36-43
36 Source Code Generation in Simulink Coder
File Description
builtin_typeid_types.h Defines an enumerated type corresponding to built-in data types.
For more information about using this file, see “model.bat” on page
36-49.
model.c Corresponds to the model file.
model.cpp The Target Language Compiler generates this C or C++ source code
file. The file contains:
36-44
Manage Build Process Files
File Description
model.h Defines model data structures and a public interface to the model
entry points and data structures. Provides an interface to the real-
time model data structure (model_rtM) via access macros.
By default, the build process deletes this ASCII file when the build
process is complete. You can choose to retain the file for inspection.
model_capi.h (optional files) Contain data structures that describe the model
signals, states, and parameters without using external mode.
model_capi.c
For more information, see “Exchange Data Between Generated and
External Code Using C API” (Simulink Coder).
36-45
36 Source Code Generation in Simulink Coder
File Description
model_data.c Contains (if conditionally generated) declarations for the parameters
data structure and the constant block I/O data structure, and zero
representations for structure data types that the model uses.
A model build generates this file when the model uses these data
structures. The extern declarations for structures appear in
model.h. When present, this file contains:
The generated source files from the model build include this file.
When you interface external code with generated code from a model,
include model_private.h. The file contains:
36-46
Manage Build Process Files
File Description
model_targ_data_map.m (optional file) Contains MATLAB language commands that external
mode uses to initialize the external mode connection.
model_types.h Provides forward declarations for the real-time model data structure
and the parameters data structure.
The generated header files from the model build include this file.
Function declarations of reusable functions can use these structures.
multiword_types.h Contains type definitions for multiple-word wide data types and their
word-size chunks. If your code uses multiword data types, include
this header file.
The build process does not create these modules at code generation
time. The modules include rt_model.h to access model-specific
data structures and entry points. If you create your own main
program module, make sure to include rtmodel.h.
36-47
36 Source Code Generation in Simulink Coder
File Description
rtwtypes.h Provides the essential type definitions, #define statements, and
enumerations.
sl_proj.tmw The build process generates these files to help the make utility
determine when to recompile and link the generated code.
rt_defines.h Contains type definitions for special mathematical constants (such as
π and e) and defines the UNUSED_PARAMETER macro.
A model build generates this file when the generated code requires a
mathematical constant definition or when the function body does not
access a required model function argument.
rt_sfcn_helper.h (optional files) Provide functions that the noninlined S-functions use
in a model.
rt_sfcn_helper.c
The noninlined S-functions use functions rt_CallSys,
rt_enableSys, and rt_DisableSys to call downstream function-
call subsystems.
subsystem.c (optional file) Contains C source code for each noninlined nonvirtual
subsystem or copy the code when the subsystem is configured to
place code in a separate file.
subsystem.h (optional file) Contains exported symbols for noninlined nonvirtual
subsystems.
36-48
Manage Build Process Files
model.bat
This file contains Windows batch file commands that set the compiler environment and
invoke the make utility.
If you are using the toolchain approach for the build process, you also can use this batch
file to extract information from the generated makefile, model.mk. The information
includes macro definitions and values that appear in the makefile, such as CFLAGS (C
compiler flags) and CPP_FLAGS (C++ compiler flags). With the folder containing
model.bat selected as the current working folder, in the Command Window, type:
On UNIX and Macintosh platforms, the code generator does not create the model.bat
file. To extract information for toolchain approach builds from the generated makefile on
these systems, in the Command Window, type:
model.h
The header file model.h declares model data structures and a public interface to the
model entry points and data structures. This header file also provides an interface to the
real-time model data structure (model_M) by using access macros. If your code interfaces
to model functions or model data structures, include model.h:
#ifndef rtmGetSampleTime
# define rtmGetSampleTime(rtm, idx)
((rtm)->Timing.sampleTimes[idx])
#endif
• Model entry point functions (ERT example)
36-49
36 Source Code Generation in Simulink Coder
The main.c (or .cpp) file includes model.h. If the model build generates the main.c
(or .cpp) file from a TLC script, the TLC source can include model.h.
#include "%<CompiledModel.Name>.h"
If main.c is a static source file, you can use the fixed header file name rtmodel.h. This
file includes the model.h header file:
#include "model.h" /* If main.c is generated */
or
#include "rtmodel.h" /* If static main.c is used */
Other external source files can require to include model.h to interface to model data, for
example exported global parameters or signals. The model.h file itself can have
additional header dependencies due to requirements of generated code. See “System
Header Files” (Simulink Coder) and “Code Generator Header Files” (Simulink Coder).
To reduce dependencies and reduce the number of included header files, see “Manage
Build Process File Dependencies” (Simulink Coder).
rtwtypes.h
The header file rtwtypes.h defines data types, structures, and macros required by the
generated code. You include rtwtypes.h for GRT and ERT system target files, instead of
including tmwtypes.h or simstruc_types.h.
Often, the generated code requires that integer operations overflow or underflow at
specific values. For example, when the code expects a 16-bit integer, the code does not
accept an 8-bit or a 32-bit integer type. The C language does not set a standard for the
number of bits in types such as char, int, and others. So, there is no universally
accepted data type in C to use for sized-integers.
To accommodate this feature of the C language, the generated code uses sized integer
types, such as int8_T, uint32_T, and others, which are not standard C types. In
rtwtypes.h, the generated code maps these sized-integer types to the corresponding C
keyword base type using information in the Hardware Implementation pane of the
configuration parameters.
36-50
Manage Build Process Files
The code generator produces the optimized version of rtwtypes.h for ERT-based system
target files when these conditions exist:
• The model has a cleared the Configuration Parameters > Code Generation >
Interface > Advanced parameters > Classic call interface option.
• The model does not contain noninlined S-functions.
Include rtwtypes.h. If you include it for GRT system target files, for example, it is easier
to use your code with ERT-based system target files.
For GRT and ERT system target files, the location of rtwtypes.h depends on whether
the build process uses the shared utilities location. If it uses a shared location, the code
generator places rtwtypes.h in slprj/target/_sharedutils; otherwise, it places
rtwtypes.h in the build folder (model_target_rtw). See “Specify Generated Code
Interfaces” (Simulink Coder).
Source files include the rtwtypes.h header file when the source files use code generator
type names or other code generator definitions. A typical example is for files that declare
variables by using a code generator data type, for example, uint32_T myvar.
A source file that the code generator and an S-function use can use the preprocessor
macro MATLAB_MEX_FILE. The macro definition comes from the mex function:
#ifdef MATLAB_MEX_FILE
#include "tmwtypes.h"
#else
#include "rtwtypes.h"
#endif
A source file for the code generator main.c (or .cpp) file includes rtwtypes.h without
preprocessor checks.
#include "rtwtypes.h"
Custom source files that the Target Language Compiler generates can also emit these
include statements into their generated file.
See “Control Placement of rtwtypes.h for Shared Utility Code” (Simulink Coder).
36-51
36 Source Code Generation in Simulink Coder
See Also
More About
• “Manage Build Process Folders” (Simulink Coder)
• “Manage Build Process File Dependencies” (Simulink Coder)
• “Add Build Process Dependencies” (Simulink Coder)
• “Enable Build Process for Folder Names with Spaces” (Simulink Coder)
• “Build Process Workflow for Real-Time Systems” (Simulink Coder)
• “Generate Code and Simulate Models in a Simulink Project” (Simulink Coder)
• “Generate Code and Simulate Models with Simulink Project API” (Simulink Coder)
36-52
Manage Build Process File Dependencies
The dependency relationships among generated source and header files appear in the
figure. Arrows coming from a file point to files it includes. Other dependencies exist, for
example, on Simulink header files tmwtypes.h and simstruc_types.h, plus C or C++
library files. The figure maps inclusion relations between only those files that are
generated in the build folder. These files can reference utility and model reference code
located in a code generation folder. For more information about the folders and files that
the build process creates, see “Manage Build Process Folders” (Simulink Coder) and
“Manage Build Process Files” (Simulink Coder).
The two tables identify the conditions that control creation of dependency files for GRT
and ERT targets. To manage build-related dependencies, consider how these conditions
apply to your model and code generation process. Then, configure model parameters and
code generation options to manage build process file dependencies.
Due to differences in file packaging options for code generated with ERT-based system
target files, the file dependencies differ slightly from file packaging for code generated
with GRT-based system target files. See “Manage File Packaging of Generated Code
Modules” on page 37-14.
The parent system header files (model.h) include child subsystem header files
(subsystem.h). In more layered models, subsystems similarly include their children's
header files in the model hierarchy. As a consequence, subsystems are able to view
recursively into their descendant subsystems and view into the root system because every
subsystem.c or subsystem.cpp includes model.h and model_private.h.
36-53
36 Source Code Generation in Simulink Coder
rtmodel.h is a place
holder include file
for code generated
with the GRT system
target file
For information about file dependencies in header files, see the following:
In this section...
“System Header Files” on page 36-54
“Code Generator Header Files” on page 36-57
The code generator includes some system header files for broadly defined cases. For
example, generated code includes <stddef.h> when the model contains a utility
function that requires this header file. This approach helps identify header file
dependencies:
36-54
Manage Build Process File Dependencies
1 Set the Shared code placement parameter to 'Shared location' and build the
model. The code generator places the utility functions in __sharedutils folder.
2 Use a find-in-file utility (for example, grep utility) to search the .c and .h files in the
__sharedutils folder for #include. The search results list the utilities with
header file dependencies.
3 Use this information to identify utilities to remove from the model and reduce header
file dependencies in the generated code.
For more information, see “Generate Shared Utility Code for Fixed-Point Functions”
(Simulink Coder).
System Header File Description and Inclusion Conditions for GRT or ERT System
Target Files
<math.h> Defines math constants
ERT—Generated code includes this file when the code honors your
model configuration for solver Stop time and either:
GRT and ERT—Generated code includes this file when your model
contains a utility function that requires this file.
36-55
36 Source Code Generation in Simulink Coder
System Header File Description and Inclusion Conditions for GRT or ERT System
Target Files
<stdio.h> Provides file I/O functions
36-56
Manage Build Process File Dependencies
System Header File Description and Inclusion Conditions for GRT or ERT System
Target Files
<string.h> Provides memory functions such as memset() and memcpy()
showblockdatatypetable
Look for blocks with the N2 note. To omit calls to memset() from
model initialization code, select the Remove root level I/O zero
initialization and Remove internal data zero initialization
optimization configuration parameters.
Header File Description and Inclusion Conditions for GRT or ERT System
Target Files
builtin_typeid_types.h Defines an enumerated type corresponding to built-in data types
GRT and ERT—Generated code includes this file when one or more of
these conditions apply:
36-57
36 Source Code Generation in Simulink Coder
Header File Description and Inclusion Conditions for GRT or ERT System
Target Files
dt_info.h Defines data structures for external mode
GRT and ERT—Generated code includes this file when your model
configuration enables external mode.
ext_work.h Defines external mode functions
GRT and ERT—Generated code includes this file when your model
configuration enables external mode.
fixedpoint.h Provides fixed-point support for noninlined S-functions
GRT and ERT—Generated code includes this file when one or more of
these conditions apply:
36-58
Manage Build Process File Dependencies
Header File Description and Inclusion Conditions for GRT or ERT System
Target Files
rtGetInf.h Support nonfinite numbers
rtGetNaN.h GRT—Generated code includes this file when one or more of these
conditions apply:
rt_nonfinite.h
• Your model contains S-functions.
• The generated code requires nonfinite numbers.
• Your model configuration enables MAT-file logging. See “MAT-
file logging” (Simulink Coder).
• Your model configuration selects the Classic call interface.
36-59
36 Source Code Generation in Simulink Coder
Header File Description and Inclusion Conditions for GRT or ERT System
Target Files
rt_logging.h Supports MAT-file logging and includes:
rtwtypes.h
builtin_typeid_types.h
multiword_types.h
rt_mxclassid.h
rtw_matlogging.h
GRT and ERT—Generated code includes this file when the code
includes rt_logging.c.
rtw_continuous.h Supports continuous time
36-60
Manage Build Process File Dependencies
Header File Description and Inclusion Conditions for GRT or ERT System
Target Files
rtw_matlogging.h Supports MAT-file logging
36-61
36 Source Code Generation in Simulink Coder
Header File Description and Inclusion Conditions for GRT or ERT System
Target Files
simstruc.h Supports calling noninlined S-functions that use the Simstruct
definition; also includes:
limits.h
string.h
tmwtypes.h
simstruc_types.h
rtw_matlogging.h
rtw_extmode.h
rtw_continuous.h
rtw_solver.h
sysran_types.h
36-62
See Also
Header File Description and Inclusion Conditions for GRT or ERT System
Target Files
zero_crossing_types.h Contains zero-crossing definitions for models with triggered
subsystems where the trigger is rising, falling, or either. File is
generated only if required by the model as determined by the data
type of the trigger signal. For example, if the data type of the trigger
signal is Boolean, zero-crossing detection not needed.
GRT—Generated code does not include this file for GRT code
generation targets.
See Also
More About
• “Manage Build Process Folders” (Simulink Coder)
• “Manage Build Process Files” (Simulink Coder)
• “Add Build Process Dependencies” (Simulink Coder)
• “Enable Build Process for Folder Names with Spaces” (Simulink Coder)
• “Build Process Workflow for Real-Time Systems” (Simulink Coder)
36-63
36 Source Code Generation in Simulink Coder
The generated code for a model consists of a small set of files. (See “Manage Build
Process Files” (Simulink Coder).) These files have dependencies on other files, which
occur due to:
• Blocks in a model generate code that makes function calls. These calls can occur in
several forms:
• Included source files (not generated) declare the called functions. In cases such as
a blockset, manage these source file dependencies by compiling them into a library
file.
• The generated code makes calls to functions in the run-time library provided by the
compiler.
• Some function dependencies also are generated files, which are referred to as
shared utilities. Some examples are fixed-point utilities and non-finite support
functions. These dependencies are referred to as shared utilities. The generated
functions can appear in files in the build folder for standalone models or in the
_sharedutils folder under the slprj folder for builds that involve model
reference.
• Models with continuous time require solver source code files.
• Code generator options such as external mode, C API, and MAT-file logging.
36-64
Add Build Process Dependencies
For information about adding file dependencies in information for the build process, see
the following:
In this section...
“File Dependency Information for the Build Process” on page 36-65
“Folder Dependency Information for the Build Process” on page 36-68
• Add folders that contain S-function MEX-files that the model uses to the header
include path.
• Create makefile rules for these folders to allow for finding source code.
• Specify additional source file names with the S-Function block parameter
SFunctionModules.
• Specify additional dependencies with the rtwmakecfg.m mechanism. See “Use
rtwmakecfg.m API to Customize Generated Makefiles” (Simulink Coder).
For model- or system target file-based dependencies, such as external header files,
consider using:
• The Code Generation > Custom Code pane in the Configuration Parameters dialog
box. You can specify additional libraries, source files, and include folders.
36-65
36 Source Code Generation in Simulink Coder
For toolchain approach or template makefile (TMF) approach build processes, the code
generator generates a makefile. For TMFs, the generated makefile provides token
expansion in which the build process expands different tokens in the makefile to include
the additional dependency information. The resulting makefile contains the complete
dependency information. See “Customize Template Makefiles” (Simulink Coder).
A property of make utilities is that you do not have to specify the specific location for a
given source C or C++ file. If a rule exists for that folder and the source file name is a
prerequisite in the makefile, the make utility can find the source file and compile it. The C
or C++ compiler (preprocessor) does not require absolute paths to the headers. The
compiler finds header file with the name of the header file by using an #include
directive and an include path. The generated C or C++ source code depends on this
standard compiler capability.
Libraries are created and linked against, but occlude the specific functions that the
program calls.
These properties can make it difficult to determine the minimum list of file dependencies
manually. You can use the makefile as a starting point to determine the dependencies in
the generated code. For an example that shows how to identify dependencies, see
“Relocate Code to Another Development Environment with packNGo” (Simulink Coder).
36-66
Add Build Process Dependencies
of code generator and blockset source and header files to help in locating the
dependencies.
Several locations in the MATLAB folder tree contain static file dependencies specific to
the code generator:
• matlabroot/rtw/c/src (open)
This folder has subfolders and contains additional files must be compiled. Examples
include solver functions (for continuous time support), external mode support files, C
API support files, and S-function support files. Include source files in this folder into
the build process with the SRC variables of the makefile.
• Header files in the folder matlabroot/rtw/extern/include
• Header files in the folder matlabroot/simulink/include
Note For ERT-based system target files, you can avoid several header dependencies.
ERT-based system target files generate the minimum set of type definitions, macros,
and so on, in the file rtwtypes.h.
Blockset products with S-function code apply the rtwmakecfg.m mechanism to provide
the code generator with dependency information. The rtwmakecfg.m file from the
blockset contains the list of include path and source path dependencies for the blockset.
Typically, blocksets create a library from the source files to which the generated model
code can link. The libraries are created and identified when you use the rtwmakecfg.m
mechanism.
To locate the rtwmakecfg.m files for blocksets in your MATLAB installed tree, use the
following command:
>> which -all rtwmakecfg.m
If the model that you are compiling uses one or more of the blocksets listed by the which
command, you can determine folder and file dependency information from the respective
rtwmakecfg.m file.
36-67
36 Source Code Generation in Simulink Coder
Usage scenarios for the generated code include, but are not limited to, the following:
In this scenario, the build process invokes the code generator when you select the
Generate code only check box. Consider using fully qualified paths, relative paths, or
just the header file names in the #include statements. Use include paths.
• The build process compiles the generated code.
In this case, you can specify compiler include paths (-I) for the build process in
several ways:
• Specify additional include paths on the Code Generation > Custom Code pane in
the Configuration Parameters dialog box. The code generator propagates the
include paths into the generated makefile.
• The rtwmakecfg.m mechanism allows S-functions to introduce additional include
paths into the build process. The code generator propagates the include paths into
the generated makefile.
• When building a model that uses a custom system target file and is makefile-based,
you can directly add the include paths into the template makefile that the system
target file uses.
• Use the make command to specify a USER_INCLUDES make variable that defines a
folder in which the build process searches for included files. For example:
make_rtw USER_INCLUDES=-Id:\work\feature1
The build process passes the custom includes to the command-line invocation of
the make utility, which adds them to the overall flags passed to the compiler.
36-68
Add Build Process Dependencies
Consider the following approaches for using #include statements and include paths with
the build process to generate code that remains portable and minimizes compatibility
problems with future versions.
• An approach is to include in the #include statements only the file name, such as:
#include "foo.h"
#include "bar.h"
Then, the include path passed to the compiler contains folders in which the headers
files exist:
cc -Ic:\work\feature1 -Ic:\work\feature2 ...
Then, specify the anchor folder (for example \work) to the compiler:
cc -Ic:\work ...
When using the build process, avoid dependencies on folders in the build process “Code
generation folder” (Simulink), such as the model_ert_rtw folder or the slprj folder. Do
not use paths in #include statements that are relative to the location of the generated
source file. For example, if your MATLAB code generation folder is c:\work, the build
process generates the model.c source file into a subfolder such as:
c:\work\model_ert_rtw\model.c
It is preferable to use one of the other suggested approaches because the relative path
creates a dependency on the code generator folder structure.
36-69
36 Source Code Generation in Simulink Coder
See Also
More About
• “Manage Build Process Folders” (Simulink Coder)
• “Manage Build Process Files” (Simulink Coder)
• “Manage Build Process File Dependencies” (Simulink Coder)
• “Enable Build Process for Folder Names with Spaces” (Simulink Coder)
• “Build Process Workflow for Real-Time Systems” (Simulink Coder)
36-70
Enable Build Process for Folder Names with Spaces
The build process provides similar support for other build-related folders. For a summary
of support and limitations, see “Build Process Folder Support on Windows” (Simulink
Coder).
If your work environment includes one or more of the preceding scenarios, use the
following support mechanisms for the build process:
• If you are using the toolchain approach to build generated code, the system support
for spaces in folder names influences toolchain operation:
• For UNIX systems and Windows systems with 8.3 name creation enabled, the
toolchain manages spaces in folder names by using alternate names from the
platform. The toolchain uses the TransformPathsWithSpaces attribute to
manage these names.
36-71
36 Source Code Generation in Simulink Coder
When developing a toolchain for a Windows system, set both attributes. For more
information about the toolchain attributes, see addAttribute.
• If you are using the template makefile approach to build generated code, the template
makefile (.tmf) requires code to manage spaces in folder names. When the alternate
folder names (Windows short names) differ from the file system folder names
(Windows long names), add this code to the makefile.
ALT_MATLAB_ROOT = |>ALT_MATLAB_ROOT<|
ALT_MATLAB_BIN = |>ALT_MATLAB_BIN<|
!if "$(MATLAB_ROOT)" != "$(ALT_MATLAB_ROOT)"
MATLAB_ROOT = $(ALT_MATLAB_ROOT)
!endif
!if "$(MATLAB_BIN)" != "$(ALT_MATLAB_BIN)"
MATLAB_BIN = $(ALT_MATLAB_BIN)
!endif
When the values of the location tokens are not equal, this code replaces MATLAB_ROOT
with ALT_MATLAB_ROOT. The replacement indicates that the path to your MATLAB
installation folder includes spaces. This code applies the same type of replacement for
MATLAB_BIN with ALT_MATLAB_BIN. The preceding code is specific to nmake. For
platform-specific examples, see the supplied template makefiles.
With either build approach, when there is an issue with support for creation of alternate
names (short names), build errors can occur on Windows. If a build generates an error
message similar to the following message, see “Troubleshooting Errors When Folder
Names Have Spaces” (Simulink Coder).
NMAKE : fatal error U1073: don't know how to make ' ...
When using operating system commands, such as system or dos, enclose paths that
specify executable files or command parameters in double quotes (" "). For example:
system('dir "D:\Applications\Common Files"')
36-72
Enable Build Process for Folder Names with Spaces
Code generation For UNC locations, build process Build process folder support is
folder temporarily maps a drive by using available independent of file
the shell commands pushd and system (NTFS or ReFS) or file
Simulation popd. system configuration for short
cache folder path name support.
Custom code
source file
locations—
among others,
36-73
36 Source Code Generation in Simulink Coder
Build Process Approach for Paths with UNC or Support for Windows Platform
Folders Spaces
these locations For paths with spaces, build Build process folder support
include folders process uses the Windows short depends on NTFS file system and
specified by: path name (8.3) by using the requires Windows default support.
Windows API: Registry sets value of 2 or 0 for:
• rtwmakecfg
.m getShortPathName() NtfsDisable8dot3NameCreation
This message can occur if a space in the folder name (C:\Work\My Models) prevents
the build process from finding the model or a file to build. For descriptions of the build-
related folders that are sensitive to a space in the folder name or path, see “Build Process
Folder Support on Windows” (Simulink Coder).
To avoid issues from folder names with spaces when Windows short file name support for
file names is disabled, do not use paths with spaces. For example, install third-party
software to paths without spaces. Do not use paths with spaces for folders containing
your models, source files, or libraries.
36-74
Enable Build Process for Folder Names with Spaces
An issue can occur with builds that use folder names with spaces, because it is possible to
disable Windows alternate name support. The build process uses this alternate name
support on Windows systems. There are many terms for this file, folder, and path
alternate name support:
• 8.3 name
• DOS path
• short file name (SFN, ShortFileName)
• long name alias
• Windows path alias
Verify the type of file system that the drive uses. In Windows Explorer, right-click the
drive icon and select properties.
• If the file system is ReFS (Resilient File System), it is an issue. The ReFS does not
provide short file name support. Except for the MATLAB installation folder, the build
process does not support folder names with spaces for the ReFS file system. If your
work environment requires short file name support for the build folder or for
additional external code folders, do not use ReFS.
• If the file system is NTFS (New Technology File System), it is possible that the build
error is related to a registry setting incompatibility. Continue with troubleshooting
steps.
The error could stem from an issue with short file name support on a system using NTFS.
Check the Windows registry setting that enables the creation of short names for files,
folders, and paths.
1 Open the Windows command prompt, running as administrator. For example, from
the Windows Start menu, type cmd, right-click the cmd.exe icon, and select Run as
administrator.
2 Change to the windows\system32 folder and query the
NtfsDisable8dot3NameCreation status by typing:
> fsutil 8dot3name query
3 If the registry state of NtfsDisable8dot3NameCreation is not 2, the default
(Volume level setting), change the value to 2 by typing:
> fsutil 8dot3name set 2
For more information about enabling creation of short names. See http://
technet.microsoft.com/en-us/library/ff621566.aspx.
36-75
36 Source Code Generation in Simulink Coder
Changing the registry setting enables creation of short names only for files and
folders that are created after the change.
4 To create short names for files created while short name creation was disabled, at the
Windows command line, use the fsutil utility.
For example, to create the short name PROGRA~1 for the long name C:\Program
Files, type:
> fsutil file setshortname "C:\Program Files" PROGRA~1
See Also
addAttribute
More About
• “Manage Build Process Folders” (Simulink Coder)
• “Manage Build Process Files” (Simulink Coder)
• “Manage Build Process File Dependencies” (Simulink Coder)
• “Add Build Process Dependencies” (Simulink Coder)
• “Build Process Workflow for Real-Time Systems” (Simulink Coder)
External Websites
• MATLAB Answers: “Why is the build process failing ...?”
• http://technet.microsoft.com/en-us/library/cc788058.aspx
• http://technet.microsoft.com/en-us/library/cc788058.aspx
36-76
Code Generation of Matrices and Arrays
MATLAB, Simulink, and the code generator store matrix data and arrays (1–D, 2–D, ...) in
column-major format as a vector. Column-major format orders elements in a matrix
starting from the first column, top to bottom, and then moving on to the next column. For
example, the following 3x3 matrix:
A =
1 2 3
4 5 6
7 8 9
A(1) = A(1,1) = 1;
A(2) = A(2,1) = 4;
A(3) = A(3,1) = 7;
A(4) = A(1,2) = 2;
A(5) = A(2,2) = 5;
and so on.
For more information on the internal representation of MATLAB data, see “MATLAB
Data” (MATLAB) in the MATLAB External Interfaces document.
• The world of signal and array processing is largely column major: MATLAB, LAPack,
Fortran90, DSP libraries.
36-77
36 Source Code Generation in Simulink Coder
C typically uses row-major format. MATLAB and Simulink use column-major format. You
cannot configure the code generation software to generate code with row-major ordering.
If you are integrating external C code with the generated code, consider the following:
To Consider
Integrate row-major data in • Transposing the row-major data in your external C code
external C code with into column-major format as a 1–D array.
Simulink generated • Using “Access Data Through Functions with Custom
functions. Storage Class GetSet” on page 26-42. The GetSet
custom storage class replaces get (read from) and set
(write to) with user-specified GetSet functions. The
user-specified GetSet function has a single index
argument, requiring the function to process the
argument and access the targeted row and column data
element. Using the GetSet function impacts code
efficiency.
Integrate external C code Using the Legacy Code Tool option
functions requiring row- convert2DMatrixToRowMajor to create an S-function
major data with Simulink that integrates external code functions with Simulink
generated data. generated data. See legacy_code. The generated code
stores the data as a 1–D array. Using
convert2DMatrixToRowMajor impacts code efficiency.
36-78
Code Generation of Matrices and Arrays
The code generator declares Simulink block matrix parameters as scalar or 1-D array
variables
real_T scalar;
real_T mat[ nRows * nCols ];
real_T can be a data type supported by Simulink. It matches the variable type given in
the model file.
For example, the 3-by-3 matrix in the 2–D Look-Up Table block
1 2 3
4 5 6
7 8 9
is stored in model.rtw as
Parameter {
Name "OutputValues"
Value Matrix(3,3)
[[1.0, 2.0, 3.0]; [4.0, 5.0, 6.0]; [7.0, 8.0, 9.0];]
String "t"
StringType "Variable"
ASTNode {
IsNonTerminal 0
Op SL_NOT_INLINED
ModelParameterIdx 3
}
}
36-79
36 Source Code Generation in Simulink Coder
} Parameters;
The model.h file declares the actual storage for the matrix parameter. You can see that
the format is column-major.
1 2 3
4 5 6
7 8 9
Parameters model_P = {
/* 3 x 3 matrix s1_Look_Up_Table_2_D_Table */
{ 1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0 },
[ ... other parameter declarations ...]
};
36-80
See Also
See Also
More About
• “MATLAB Data” (MATLAB)
• “Mapping MATLAB Types to Types in Generated Code” (MATLAB Coder)
36-81
36 Source Code Generation in Simulink Coder
When you generate code for a model, the code generator by default creates shared utility
files that the model requires. When you generate code with different releases, the code
generators can produce functionally identical shared files that contain some
nonfunctional differences. For example, different comments and different coding style.
When you use the same release to generate code for different models in different folders,
you can also produce shared files with nonfunctional differences. For example, if you
specify different ParenthesesLevel or ExpressionFolding values for the models, the
code generator can produce shared files that contain different comments or different
coding styles.
If you have an Embedded Coder license, you can avoid these issues by specifying the
reuse of shared code from an existing folder, for example, a read-only library of verified
code. In this case, the code generator does not create new shared utility files. The build
process uses external code or previously generated shared utility code from the folder. An
administrator maintains and updates the read-only library.
36-82
Cross-Release Shared Utility Code Reuse
5 If files are missing from the existing shared code folder, you see an error. To continue
code generation with a locally generated version of the missing shared utility files:
If you require reuse of shared code for a component exported from a previous
release, provide the administrator with information about the exported artifacts
location. The administrator can use sharedCodeUpdate to copy the shared code
for your component to the existing shared code folder.
d When the files are available in the existing shared code folder, repeat steps 1–4.
If the shared utility code is generated from library subsystems that are shared across
models (Simulink Coder), you cannot reuse the code across releases because the
code is release-specific—the symbol name and file name mangling includes the
release number. The administrator must add the shared utility code generated for
each release to the shared code folder.
The sharedCodeUpdate function can add files to the shared code folder that have
identical content but different file and function names. This behavior is useful when
you have different model components that require their own shared utility functions.
Although some code is duplicated, the different model components can access the
shared utility functions with which they were verified. To force model components to
have their own versions of shared utility functions, configure naming rules to insert
the model name into shared utility identifiers (Simulink Coder).
36-83
36 Source Code Generation in Simulink Coder
For each R2010a version of rtwtypes.h that you want to include in your integration,
copy the corresponding #define statement into your master copy of rtwtypes.h.
• In R2015a, the zero-crossing definitions moved from rtwtypes.h into
zero_crossing_types.h. To create an rtwtypes.h file that is compatible with
generated model code from different releases, in your master copy of rtwtypes.h,
insert this statement.
#include "zero_crossing_types.h"
See Also
crossReleaseImport | crossReleaseExport | sharedCodeUpdate
Related Examples
• “Cross-Release Code Integration” on page 36-85
More About
• “Generate Shared Utility Code” (Simulink Coder)
• “Generate Shared Utility Code for Fixed-Point Functions” (Simulink Coder)
• “Generate Shared Utility Code for Custom Data Types” (Simulink Coder)
36-84
Cross-Release Code Integration
If you have an Embedded Coder license, you can integrate generated C code from
previous releases (R2010a and later) with generated code from the current release when
the source models are single-rate and the generated C code is from:
• Top-model or subsystem build processes that use the nonreusable function code
interface.
• Single or multiple instance model reference build processes that suppress error status
monitoring (SuppressErrorStatus is on).
If you can reuse existing code without modification, you can reduce the cost of
reverification.
Workflow
Consider this control system model.
36-85
36 Source Code Generation in Simulink Coder
The Controller Model block references a model that consists of three components:
• P1 is a Model block, which references a model developed with a previous release, for
example, R2015b. The generated model code, with the standalone code interface, is in
the folder P1_ert_rtw.
• C1 is a Model block, which references a model that you are developing in the current
release.
• P2 is a subsystem block developed with a previous release, for example, R2016a. The
generated subsystem code is in the folder P2_ert_rtw.
36-86
Cross-Release Code Integration
• P3 is a Model block, which references a model developed with a previous release, for
example, R2016b. The generated model code, with the model reference code interface,
is in the folder slprj/ert/P3.
To integrate code from previous releases with generated code from the current release,
use this workflow:
The crossReleaseExport function starts the required previous release and creates
a folder that contains export artifacts, for example, P1_R2015b.
3 Specify an existing shared code folder
You can specify the reuse of shared code (Simulink Coder) from an existing folder, for
example, a library of verified code that an administrator maintains and updates.
Specify the shared code folder for model components that require code generation in
the current release, for example, Controller and C1.
In the Configuration Parameters > Code Generation > Interface > Advanced
parameters > Existing shared code field, enter the full path to the shared code
folder.
4 Import components into current release
From the current release, using export artifacts created in step 2, import generated
component code from previous releases as software-in-the-loop (SIL) blocks or
processor-in-the-loop (PIL) blocks. For example:
crossReleaseImport(P1ArtifactsLocation,'Controller', ...
'SimulationMode','SIL');
crossReleaseImport(P2ArtifactsLocation,'Controller', ...
'SimulationMode','SIL');
crossReleaseImport(P3ArtifactsLocation,'Controller', ...
'SimulationMode','SIL');
36-87
36 Source Code Generation in Simulink Coder
In the current working folder, the crossReleaseImport function creates the xrel
subfolder that contains software-in-the-loop (SIL) blocks and subfolders:
To replace components with SIL or PIL blocks, use the Simulink Editor or the
pil_block_replace command. For example, replace:
• P1 with P1_R2015b_sil.
• P2 with P2_R2016a_sil.
• P3 with P3_R2016b_sil.
When you run a model simulation, the simulation runs the previous release code
through the SIL or PIL blocks.
The Simulink Code Inspector supports call-site validation for a cross-release SIL or
PIL block. The block provides a specification of the expected function call, which is
derived from the exported generated code and associated artifacts. During analysis,
the Simulink Code Inspector compares the expected function call with the block
behavior. For information about analysis limitations, see “S-Function” (Simulink Code
Inspector).
Limitations
The cross-release code integration workflow does not support:
36-88
Cross-Release Code Integration
At the end of the model build process, the code generation report displays shared files
that are directly used by the integration model, for example, Controller. The report
does not display shared files used by the components of the model, for example, P1 and
P2.
• A cross-release SIL or PIL block, you cannot run rapid accelerator mode simulations.
• A Model block that references a model containing a cross-release SIL or PIL block, you
cannot run accelerator mode or rapid accelerator mode simulations.
• Top-model SIL simulations of models that contain cross-release SIL or PIL blocks. The
models must not contain cross-release AUTOSAR Model blocks.
• Model block SIL simulations of referenced models that contain cross-release SIL or
PIL blocks. The referenced models must not contain cross-release AUTOSAR Model
blocks.
For information about other cross-release AUTOSAR code integration limitations, see
“Import AUTOSAR Code from Previous Releases” on page 36-100.
Simulink.Bus Support
To use a bus object as a data type in cross-release ERT code integration, use one of these
approaches.
36-89
36 Source Code Generation in Simulink Coder
36-90
Cross-Release Code Integration
36-91
36 Source Code Generation in Simulink Coder
If the integration model signal does not map to a generated code variable that has the
same name as the signal in the imported code, the generated code:
If the integration model signal maps to a variable with the same name as the signal in the
imported code, the variable used by the imported code is also used by the code generated
from the integration model. You must use a compatible storage class for the signal.
36-92
Cross-Release Code Integration
36-93
36 Source Code Generation in Simulink Coder
• Type – Unstructured
• Data access – Direct
• Data scope – Exported
• Owner – Non-empty value that is
not the name of the integration
model. For example, the value can
be the name of the imported
component.
• For signals in the integration model that
are not connected to root-level I/O ports,
use a custom storage class with these
property values:
36-94
Cross-Release Code Integration
Export Configuration
Before generating code in the old release, for the model component that you want to
export, configure data store memory to use a storage class that imports external code.
If a top-model or subsystem build process generates the code, set the Storage class
property of the Simulink.Signal objects to one of these classes:
• ImportedExtern
• ImportedExternPointer
• ImportFromFile custom storage class
If a model reference build process generates the code, you can also use these classes:
• ExportedGlobal
• ExportToFile custom storage class
When you run crossReleaseExport, the function identifies data store memories in the
codeInfo.mat file and places required information in the crossReleaseInfo.m
artifact.
Import Configuration
36-95
36 Source Code Generation in Simulink Coder
• ImportedExtern
• ExportedGlobal
• ImportFromFile or ExportToFile custom storage class.
For more information, see “Data Stores in Generated Code” (Simulink Coder).
Parameter Tuning
The cross-release ERT code integration workflow supports parameter tuning in an
integration model that contains component code with tunable parameters from previous
releases.
In the current release, before you run crossReleaseImport, for each tunable
parameter of the component that you want to import:
Support of the GetSet custom storage class from a previous release applies only for
R2011a and later releases.
36-96
Cross-Release Code Integration
custToolChainOpts = get_param(model,'CustomToolchainOptions');
custToolChainOpts{2} = ...
strrep(custToolChainOpts{2}, c_standard_opts_id, optionsToKeep);
set_param(model, 'CustomToolchainOptions',custToolChainOpts);
36-97
36 Source Code Generation in Simulink Coder
artifactLocation = crossReleaseExport(reusableReferencedModelcodeLocation)
2 Update existing shared code folder.
sharedCodeUpdate(sourceFolder,destinationFolder)
3 Import the code into the current release as a parameterized cross-release block, for
example, a SIL block.
open_system(integrationModel);
blockInstanceName1 = 'refModelInstanceName1';
blockinstanceName2 = 'refModelInstanceName2';
SILBlockFullName = getfullname(handleSILBlock);
replace_block(integrationModel, 'Name', blockInstanceName1, ...
SILBlockFullName, 'noprompt');
replace_block(integrationModel, 'Name', blockInstanceName2, ...
SILBlockFullName, 'noprompt');
5 Suppose the reusable referenced model has model arguments paramA and paramB,
and the values for the referenced model instances, refModelInstanceName1 and
refModelInstanceName2, are workspace variables. In this case, you can specify
argument values for the cross-release block instances that are workspace variables.
36-98
Cross-Release Code Integration
To test the numerical equivalence between the model component and the generated code
from the previous release, use Simulink Test. With the Test Manager (Simulink Test), you
can perform back-to-back tests and output comparisons:
1 Bring the model component into the current release as a Model block with the
Simulation mode block parameter set to Normal.
2 With the Model block, create a top model that specifies test input data.
3 Import the code generated in the previous release into the current release as a SIL
block.
4 With the SIL block, create another top model that specifies the same the test input
data.
5 In the Test Manager, create an equivalence test case that runs simulations of the top
models and compares outputs.
6 Run the test case and review results.
For more information, see Test Manager examples in “Simulink Test Examples” (Simulink
Test).
Note If you want to compare the behavior of generated code from the current and
previous release, in step 1, specify these Model block parameters:
36-99
36 Source Code Generation in Simulink Coder
When you run crossReleaseImport, the function imports the AUTOSAR code as a
cross-release Model block instead of a SIL or PIL block. The Simulation mode
parameter of the Model block is set to Software-in-the-loop (SIL) or Processor-
in-the-loop (PIL). Incorporate the Model block into the current release model.
• The cross-release workflow does not support per-instance memory that accesses
NVRAM.
• Tunable parameters must use AUTOSAR CalPrm or InternalCalPrm custom storage
classes.
• If the original model uses variants or symbolic dimensions (dimension variants), the
imported model can use only the same variant and symbolic dimension configuration
that was used when generating the code in the previous release.
See Also
crossReleaseImport | crossReleaseExport | sharedCodeMATLABVersions |
sharedCodeUpdate
More About
• “Cross-Release Shared Utility Code Reuse” on page 36-82
• “Generate Shared Utility Code” (Simulink Coder)
• “Generate Shared Utility Code for Fixed-Point Functions” (Simulink Coder)
• “Generate Shared Utility Code for Custom Data Types” (Simulink Coder)
• “Integrate Generated Code Using Cross-Release Workflow”
36-100
Generate Code Using Simulink® Coder™
The model represents an 8-bit counter that feeds a triggered subsystem that is
parameterized by constant blocks INC, LIMIT, and RESET. Input and Output represent
I/O for the model. The Amplifier subsystem amplifies the input signal by gain factor K,
which updates when signal equal_to_count is true.
1. Open the model. For example, type the following commands at the MATLAB®
command prompt.
model='rtwdemo_rtwintro';
open_system(model)
36-101
36 Source Code Generation in Simulink Coder
2. Open the Configuration Parameters dialog box from the model editor by clicking
Simulation > Configuration Parameters.
cs = getActiveConfigSet(model);
openDialog(cs);
You can generate code for a particular target environment or purpose. Some built-in
targeting options are provided using system target files, which control the code
generation process for a target.
36-102
Generate Code Using Simulink® Coder™
Optionally, in the Code Generation Advisor pane set the Select objective field to
Execution efficiency or Debugging. Then click Check model... to identify and
systematically change parameters to meet your objectives.
6. In the model window, initiate code generation and the build process for the model by
using any of the following options:
36-103
36 Source Code Generation in Simulink Coder
The report includes links to model files such as rtwdemo_rtwintro.c and associated
utility and header files.
36-104
Generate Code Using Simulink® Coder™
36-105
36 Source Code Generation in Simulink Coder
36-106
Generate Code Using Simulink® Coder™
bdclose(model)
rtwdemoclean;
Related Topics
36-107
37
The model represents an 8-bit counter that feeds a triggered subsystem that is
parameterized by constant blocks INC, LIMIT, and RESET. Input and Output represent
I/O for the model. The Amplifier subsystem amplifies the input signal by gain factor K,
which updates when signal equal_to_count is true.
2. Open the Configuration Parameters dialog box from the model editor by clicking
Simulation > Model Configuration Parameters.
37-2
Generate Code Using Embedded Coder®
cs = getActiveConfigSet(model);
openDialog(cs);
You can generate code for a particular target environment or purpose. Some built-in
targeting options are provided using system target files, which control the code
generation process for a target.
37-3
37 Source Code Generation in Embedded Coder
37-4
Generate Code Using Embedded Coder®
The ERT target includes a utility to specify and prioritize code generation settings based
on your application objectives.
37-5
37 Source Code Generation in Embedded Coder
You can set and prioritize objectives for the generated code. For example, while code
traceability might be a very important criterion for your application, you might not want
to prioritize it at the cost of code execution efficiency.
7. In the Set Objectives pane, select Execution efficiency and Traceability. Click OK.
You can select and prioritize a combination of objectives before generating code.
8. In the model window, initiate code generation and the build process for the model by
using any of the following options:
The report includes rtwdemo_rtwecintro.c, associated utility and header files, and
traceability and validation reports.
37-6
Generate Code Using Embedded Coder®
37-7
37 Source Code Generation in Embedded Coder
37-8
See Also
bdclose(model)
rtwdemoclean;
Related Topics
See Also
More About
• “Generate Code by Using the Quick Start Tool” on page 37-10
37-9
37 Source Code Generation in Embedded Coder
After you start the tool, you must answer these questions about the code that you want to
generate:
The tool validates your choices against the model and presents the parameter changes
required to generate code. If you choose to generate code, the tool applies the changes to
your configuration set and generates the code. After code generation, you can view the
code generation report and find information on building, customizing, optimizing, and
packaging the code. To further customize your generated code, click Finish and you are
immediately brought into the Code Perspective environment in the editor window. The
Code Perspective provides the tools to control the names and representation of the model
data and functions in the generated code. For more information, see “Environment for
Configuring Model Data and Functions for Code Generation” on page 21-2.
The Quick Start tool evaluates your model to determine the number of periodic sample
rates in your system.
37-10
Generate Code by Using the Quick Start Tool
Single rate Your model has only one periodic sample rate. The generated code has a single-
entry point function that runs at the time interval of the sample rate.
Multirate Your model has more than one periodic sample rate. It is possible that the
generated code does not execute at the same time intervals. After the analysis
step, you can choose to generate a single-entry point function for each of the
sample rates or generate a different entry point function for each sample rate.
For more information about sample rates, see “Time-Based Scheduling and Code
Generation” (Simulink Coder).
The Quick Start tool evaluates your model for continuous blocks to determine the correct
solver to use.
No If your system does not contain continuous states, the Quick Start tool configures
your model to use a fixed-step discrete solver for code generation if you have not
selected one.
Yes If your system does contain continuous states, the Quick Start tool configures
your model to use a fixed-step continuous solver for code generation if you have
not selected one. The tool also selects the SupportContinuous configuration
parameter.
The Quick Start tool evaluates your model to see if scheduler code must be generated.
37-11
37 Source Code Generation in Embedded Coder
No If you did not configure your system for export function calls, the generated code
includes code for the system algorithm and the scheduler code.
Yes If you configured your system for export function calls, the generated code
includes code for the system algorithm. You can manually write the scheduler
code or generate it from other models.
The Quick Start tool evaluates your model to see if it depends on code from other models.
No If your system does not contain referenced models, the generated code does not
depend on code from other models.
Yes If your system contains referenced models, the generated code for your model
depends on other modules generated from referenced models. The code generator
can optimize the generated code because it is aware of the relationship between
your model and the referenced models.
For more information, see “Code Generation of Referenced Models” (Simulink Coder).
37-12
Generate Code by Using the Quick Start Tool
Note If the Quick Start tool creates the configuration set object in the MATLAB
workspace, you must save it to preserve the configuration set after the MATLAB session
ends. For more information, see “Save a Configuration Set” (Simulink).
Next Steps
After you have generated code by using Quick Start, possible next steps are:
To control the names and representation of the model data and functions in the generated
code, use the Code Perspective in the Simulink Editor. When you are done with Quick
Start and you click Finish, you are immediately brought into the Code Perspective
environment in the editor window. To enter the perspective from outside of the Quick
Start tool, in the model window, select Code > C/C++ Code > Configure Model in
Code Perspective. For more information, see “Environment for Configuring Model Data
and Functions for Code Generation” on page 21-2.
37-13
37 Source Code Generation in Embedded Coder
To locate and examine the generated code files, use the HTML code generation report.
The code generation report provides hyperlinks in the comments that you click to view
the generated code in the MATLAB Help browser. For more information, see “Traceability
in Code Generation Report” on page 64-3.
In this section...
“Generated Code Modules” on page 37-14
“User-Written Code Modules” on page 37-18
“Customize Generated Code Modules” on page 37-18
Code Modules and Header Files Affected by File Packaging summarizes the structure of
source code that the code generator produces.
• File packaging formats: Manage the number of source files generated for your model.
In the Configuration Parameter dialog box, on the Code Generation > Code
Placement pane, specify the File packaging format parameter. For more
information, see “Customize Generated Code Modules” on page 37-18.
37-14
Manage File Packaging of Generated Code Modules
information, see “Apply Custom Storage Classes to Individual Signal, State, and
Parameter Data Elements” on page 26-19.
• Module Packaging Features (MPF): Direct the generated code into a required set of .c
or .cpp and .h files, and control the internal organization of the generated files. For
details, see “Data, Function, and File Definition”.
37-15
37 Source Code Generation in Embedded Coder
File Description
model.c or .cpp Contains entry points for code implementing the model algorithm
(for example, model_step, model_initialize, and
model_terminate).
model_private.h Contains local macros and local data that the model and subsystems
require. This file is included in the model.c file as a #include
statement. You do not need to include model_private.h when
interfacing handwritten code to the generated code of a model.
model.h Declares model data structures and a public interface to the model
entry-points and data structures. Provides an interface to the real-
time model data structure (model_M) with accessor macros.
37-16
Manage File Packaging of Generated Code Modules
File Description
multiword_types.h Contains type definitions for wide data types and their chunks. File is
generated when multiword data types are used or when you select
one or more of these configuration parameters:
• MAT-file logging
• Code Generation > Interface > External mode
model_reference_types. Contains type definitions for timing bridges. File is generated for a
h model reference target or a model containing model reference
blocks.
builtin_typeid_types.h Defines an enumerated type corresponding to built-in data types. File
is generated when your model contains a Stateflow chart that uses
messages or when you select one or more of these configuration
parameters:
• MAT-file logging
• Any C API option at Code Generation > Interface
zero_crossing_types.h Contains zero-crossing definitions for models with triggered
subsystems where the trigger is rising, falling, or either. File
is generated only if required by the model.
ert_main.c or .cpp (optional file) If the Generate an example main program option is
on (default), this file is generated. For more information, see
“Generate an example main program”.
rtmodel.h (optional file) If the Generate an example main program option is
off, this file is generated. For more information, see “Generate an
example main program”.
37-17
37 Source Code Generation in Embedded Coder
File Description
model_capi.c or .cpp (optional file) Provides data structures that enable a running
program to access model signals, states, and parameters without
model_capi.h external mode. To learn how to generate and use the model_capi.c
or .cpp and .h files, see “Exchange Data Between Generated and
External Code Using C API” (Simulink Coder).
For information on how to customize your ERT-based system target file for your
production requirements, see “Target Development” (Simulink Coder).
37-18
Manage File Packaging of Generated Code Modules
subsystem files
(optional)
model.h
model_types.h
model_private.h
model_data.c
(conditional)
Compact (with separate model.c model_private.h
data file)
model.h model_types.h (conditional,
see Removed Files According to
model_data.c File Packaging Format)
(conditional)
Compact model.c model_data.c
model.h model_private.h
model_types.h (conditional,
see Removed Files According to
File Packaging Format)
You can specify a different file packaging format for each referenced model.
37-19
37 Source Code Generation in Embedded Coder
The Configuration Parameter > Code Generation > Interface > Shared code
placement selection interacts with file packaging operations. If you specify Shared code
placement as Shared location, the code generator generates separate files for utility
code in a shared location, regardless of the file packaging format. If you specify the
Shared code placement as Auto, the code generator generates code for utilities
according to the file packaging format selection.
File packaging formats Compact and Compact (with separate data file)
generate model_types.h for models containing:
File packaging formats Compact and Compact (with separate data file) are not
compatible with:
See Also
More About
• “Manage Build Process Folders” on page 36-37
• “Manage Build Process Files” on page 36-43
• “Manage Build Process File Dependencies” on page 36-53
• “Control Placement of Global Data Definitions and Declarations in Generated Files”
on page 23-2
37-20
Generate Reentrant Code from Top-Level Models
• By default, the generated model.c source file does not contain an allocation function
that dynamically allocates model data for each instance of the model. Use the Use
dynamic memory allocation for model initialization option to control whether an
allocation function is generated.
• The generated code passes the real-time model data structure in, by reference, as an
argument to model_step and the other model entry point functions.
• The real-time model data structure is exported with the model.h header file.
• By default, root-level input and output arguments are passed to the reusable model
entry-point functions as individual arguments. Use the Pass root-level I/O as
parameter to control whether root-level input and output arguments are passed. This
selection chooses whether this I/O is included in the real-time model data structure
that is passed to the functions, passed as individual arguments, or passed as
references to an input structure and an output structure.
Configure Model
To configure an ERT-based model to generate reusable, reentrant code:
1 In the Code Generation > Interface pane of the Configuration Parameters dialog
box, set Code interface packaging (Simulink Coder) to the value Reusable
function. This action enables the parameters Multi-instance code error
diagnostic, Pass root-level I/O as, and Use dynamic memory allocation for
model initialization.
2 Examine the setting of Multi-instance code error diagnostic (Simulink Coder).
Leave the parameter at its default value Error unless you have a specific need to
alter the severity level for diagnostics displayed when a model violates requirements
for generating multi-instance code.
37-21
37 Source Code Generation in Embedded Coder
3 Configure Pass root-level I/O as (Simulink Coder) to control how root-level model
input and output are passed to model_step and the other generated model entry-
point functions.
When you set Code interface packaging to Reusable function, model data
(such as block I/O, DWork, and parameters) is packaged into the real-time model data
structure, and the model structure is passed to the model entry-point functions. If you
set Pass root-level I/O as to Part of model data structure, the root-level
model input and output also are packaged into the real-time model data structure.
4 If you want the generated model code to contain a function that dynamically allocates
memory for model instance data, select the option Use dynamic memory allocation
for model initialization (Simulink Coder). If you do not select this option, the
generated code statically allocates memory for model data structures.
5 Generate model code.
6 Examine the model entry-point function interfaces in the generated files and the
HTML code generation report. For more information about generating and calling
model entry-point functions, see “Configure Code Generation for Model Entry-Point
Functions” (Simulink Coder).
For an example of a model configured to generate reusable, reentrant code, open the
example model rtwdemo_reusable. Click the button View Interface Configuration
and examine the Code interface parameters on the Code Generation > Interface
pane.
37-22
See Also
• 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, and apply a storage class other than Auto or, if you set the
default storage class for the corresponding category of parameter data to Default
(the default setting) in the Code Mapping Editor, Model 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 “Apply Storage Classes to
Individual Signal, State, and Parameter Data Elements” on page 22-81.
• 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 the Share across model instances
parameter. For more information, see “Model Global Data by Creating Data Stores”
(Simulink) and Data Store Memory.
See Also
More About
• “Configure Code Generation for Model Entry-Point Functions” (Simulink Coder)
37-23
38
The code generator software produces an HTML code generation report so that you can
view and analyze the generated code. When your model is built, the code generation
process produces an HTML file that is displayed in an HTML browser or in the Model
Explorer. The code generation report includes:
• The Summary section that contains model and code information, including Author,
Tasking Mode, System Target File, Hardware Device Type, and code generation
objectives information. The Configuration settings at the time of code generation
link opens a noneditable view of the Configuration Parameters dialog box. The dialog
box shows the Simulink model settings at the time of code generation, including TLC
options.
• The Subsystem Report section that contains information on nonvirtual subsystems in
the model.
• In the Generated Files section on the Contents pane, you can click the names of
source code files generated from your model to view their contents in a MATLAB Web
browser window. In the displayed source code, global variables are hypertext that
links to their definitions.
If you have a Simulink Report Generator license, you can document your code generation
project in multiple formats, including HTML, PDF, RTF, Microsoft Word, and XML. For an
example of how to create a Microsoft Word report, see “Document Generated Code with
Simulink Report Generator” on page 38-50.
38-2
Reports for Code Generation
information on the location of the build folder, see “Manage Build Process Folders”
(Simulink Coder).
• From the top-model code generation report, you can access the referenced model code
generation report by clicking a link under Referenced Models in the left navigation
pane. Clicking a link opens the code generation report for the referenced model in the
browser. To navigate back to the top model code generation report, use the Back
button at the top of the left navigation pane.
• From the referenced model diagram window, select Code > C/C++ Code > Code
Generation Report > Open Model Report.
For more information, see “Generate Code for Referenced Models” (Simulink Coder)
• The Code Interface Report section provides information about the generated code
interface, including model entry-point functions and input/output data. For more
information, see “Analyze the Generated Code Interface” on page 38-19.
• The Traceability Report section allows you to account for Eliminated / Virtual
Blocks that are untraceable versus the listed Traceable Simulink Blocks /
Stateflow Objects / MATLAB Scripts. This provides a complete mapping between
model elements and code. For more information, see “Customize Traceability Reports”
on page 64-36.
• The Static Code Metrics Report section provides statistics of the generated code.
Metrics are estimated from static analysis of the generated code. For more
information, see “Static Code Metrics” on page 38-33.
• The Code Replacements Report section allows you to account for code replacement
library (CRL) functions that were used during code generation, providing a mapping
between each replacement instance and the Simulink block that triggered the
38-3
38 Report Generation in Embedded Coder
On the Contents pane, in the Generated Files section, you can click the names of
source code files generated from your model to view their contents in a MATLAB Web
browser window. In the displayed source code:
• If you enable code-to-model traceability, hyperlinks within the displayed source code
navigate to the blocks or subsystems from which the code is generated. For more
information, see “Code-to-Model Traceability” on page 64-8.
• If you enable model-to-code traceability, you can navigate to the generated code for a
block in the model. For more information, see “Model-to-Code Traceability” on page
64-10.
• If you set the Code coverage tool parameter on the Code Generation >
Verification pane, you can view the code coverage data and annotations. For more
information, see “Configure Code Coverage with Third-Party Tools” on page 70-11.
• If you select the Static code metrics check box on the Code Generation > Report
pane, you can view code metrics information and navigate to code definitions and
declarations in the generated code. For more information, see “View Static Code
Metrics and Definitions Within the Generated Code” on page 38-35.
See Also
Related Examples
• “Verify Generated Code by Using Code Tracing” on page 64-2
38-4
Generate a Code Generation Report
1 In the Simulink Editor, select Code > C/C++ Code > Code Generation Report >
Options. The Configuration Parameters dialog box opens with the Code Generation
> Report pane visible.
2 Select the Create code generation report (Simulink Coder) parameter.
3 If you want the code generation report to automatically open after generating code,
select the Open report automatically (Simulink Coder) parameter (which is
enabled by selecting Create code generation report).
4 Generate code.
The build process writes the code generation report files to the html subfolder of the
build folder (see “HTML Code Generation Report Location” on page 38-2). Next, the build
process automatically opens a MATLAB Web browser window and displays the code
generation report.
To open an HTML code generation report at any time after a build, see “Open Code
Generation Report” on page 38-8 and “Generate Code Generation Report After Build
Process” on page 38-6.
38-5
38 Report Generation in Embedded Coder
1 In the model diagram window, select Code > C/C++ Code > Code Generation
Report > Open Model Report.
2 If your current working folder contains the code generation files the following dialog
opens.
Enter the full path of the build folder for your model, ../model_target_rtw and
click Open Report.
38-6
Generate Code Generation Report After Build Process
Note An alternative method for generating the report after the build process is complete
is to configure your model to generate a report and build your model. In this case, the
software generates the report without regenerating the code.
38-7
38 Report Generation in Embedded Coder
If your current working folder does not contain the code generation files and the code
generation report, the following dialog box opens:
Enter the full path of the build folder for your model, ../model_target_rtw and click
Open Report.
Limitation
After building your model or generating the code generation report, if you modify legacy
or custom code, you must rebuild your model or regenerate the report for the code
generation report to include the updated legacy source files. For example, if you modify
your legacy code, and then use the Code > C/C++ Code > Code Generation Report >
38-8
Open Code Generation Report
Open Model Report menu to open an existing report, the software does not check if the
legacy source file is out of date compared to the generated code. Therefore, the code
generation report is not regenerated and the report includes the out-of-date legacy code.
This issue also occurs if you open a code generation report using the
coder.report.open function.
38-9
38 Report Generation in Embedded Coder
38-10
View Code Generation Report in Model Explorer
When you generate code, or open a model that has generated code for its current target
configuration in your working folder, the Hierarchy (left) pane of Model Explorer
contains a node named Code for model. Under that node are other nodes, typically
called This Model and Shared Code. Clicking This Model displays in the Contents
(middle) pane a list of generated source code files in the build folder of that model. The
next figure shows code for the rtwdemo_counter model.
The views in the Document (right) pane are read only. The code listings there contain
hyperlinks to functions and macros in the generated code. Clicking the file hyperlink
opens that source file in a text editing window where you can modify its contents.
If an open model contains Model blocks, and if generated code for these models exists in
the current slprj folder, nodes for the referenced models appear in the Hierarchy pane
38-11
38 Report Generation in Embedded Coder
one level below the node for the top model. Such referenced models do not need to be
open for you to browse and read their generated source files.
If the code generator produces shared utility code for a model, a node named Shared
Code appears directly under the This Model node. It collects source files that exist in
the ./slprj/target/_sharedutils subfolder.
Note You cannot use the Search tool built into Model Explorer toolbar to search
generated code displayed in the Code Viewer. On PCs, typing Ctrl+F when focused on the
Document pane opens a Find dialog box that you can use to search for text in the
currently displayed file. You can also search for text in the HTML report window, and you
can open the files in the editor.
38-12
Package and Share the Code Generation Report
• /slprj
• html subfolder of the build folder, model_target_rtw, for example
rtwdemo_counter_grt_rtw/html
• /slprj
• Build folder: model_target_rtw
2 Right-click to open the context menu.
3 In the context menu, select Create Zip File. A file appears in the Current Folder
browser.
4 Name the zip file.
Alternatively, you can use the MATLAB zip command to zip the code generation report
files:
zip('myzip',{'slprj','rtwdemo_counter_grt_rtw'})
Note If you need to relocate the static and generated code files for a model to another
development environment, such as a system or an integrated development environment
(IDE) that does not include MATLAB and Simulink products, use the code generator pack-
and-go utility. For more information, see “Relocate Code to Another Development
Environment” (Simulink Coder).
38-13
38 Report Generation in Embedded Coder
38-14
Web View of Model in Code Generation Report
In this section...
“About Model Web View” on page 38-15
“Generate HTML Code Generation Report with Model Web View” on page 38-15
“Model Web View Limitations” on page 38-18
A Simulink Report Generator license is required to include a Web view (Simulink Report
Generator) of the model in the code generation report.
Web view requires a Web browser that supports Scalable Vector Graphics (SVG). Web
view uses SVG to render and navigate models.
• Mozilla Firefox Version 1.5 or later, which has native support for SVG. To download the
Firefox browser, go to www.mozilla.com/.
• The Microsoft Internet Explorer® Web browser with the Adobe® SVG Viewer plug-in.
To download the Adobe SVG Viewer plug-in, go to www.adobe.com/svg/.
• Apple Safari Web browser
38-15
38 Report Generation in Embedded Coder
Note These settings specify only the top model, not referenced models.
7 Open the Configuration Parameters for the referenced model, rtwdemo_mdlrefbot
and perform steps 3–6.
8 Save the models, rtwdemo_mdlreftop and rtwdemo_mdlrefbot.
9 From the top model diagram, press Ctrl+B. After building the model and generating
code, the code generation report for the top model opens in a MATLAB Web browser.
10 In the left navigation pane, select a source code file. The corresponding source code
is displayed in the right pane and includes hyperlinks.
38-16
Web View of Model in Code Generation Report
11 Click a link in the code. The model Web view displays and highlights the
corresponding block in the model.
12 To highlight the generated code for a referenced model block in your model, click
CounterB. The corresponding code is highlighted in the source code pane.
Note You cannot open the referenced model diagram in the Web view by double-
clicking the referenced model block in the top model.
13 To open the code generation report for a referenced model, in the left navigation
pane, below Referenced Models, click the link, rtwdemo_mdlrefbot. The source
files for the referenced model are displayed along with the Web view of the
referenced model.
38-17
38 Report Generation in Embedded Coder
14 To go back to the code generation report for the top model, at the top of the left
navigation pane, click the Back button until the top model’s report is displayed.
For more information about exploring a model in a Web view, see “Navigate the Web
View” (Simulink Report Generator).
For more information about navigating between the generated code and the model
diagram, see “Trace Simulink Model Elements in Generated Code” on page 64-8.
• Code is not generated for virtual blocks. In the model Web view of the code generation
report, when tracing between the model and the code, when you click a virtual block,
it is highlighted yellow.
• In the model Web view, you cannot open a referenced model diagram by double-
clicking the referenced model block in the top model. Instead, open the code
generation report for the referenced model by clicking a link under Referenced
Models in the left navigation pane.
• Stateflow truth tables, events, and links to library charts are not supported in the
model Web view.
• Searching in the code generation report does not find or highlight text in the model
Web view.
• If you navigate from the actual model diagram (not the model Web view in the report),
to the source code in the HTML code generation report, the model Web view is
disabled and not visible. To enable the model Web view, open the report again, see
“Open Code Generation Report” (Simulink Coder).
• For a subsystem build, the traceability hyperlinks of the root level inport and outport
blocks are disabled.
• “Traceability Limitations” on page 64-6 that apply to tracing between the code and
the actual model diagram.
38-18
Analyze the Generated Code Interface
For limitations that apply to code interface reports, see “Code Interface Report
Limitations” on page 38-31.
38-19
38 Report Generation in Embedded Coder
1 Open your model, go to the Code Generation pane of the Configuration Parameters
dialog box, and select ert.tlc or an ERT-based System target file, if one is not
already selected.
2 Go to the Code Generation > Report pane of the Configuration Parameters dialog
box and select the option Create code generation report, if it is not already
selected. The rtwdemo_basicsc, rtwdemo_mrmtbb, and rtwdemo_fcnprotoctrl
models used in this section select multiple Report pane options by default. But
selecting only Create code generation report, generates a Code Interface Report
section in the HTML report.
Alternatively, you can programmatically select the option by issuing the following
MATLAB command:
38-20
Analyze the Generated Code Interface
38-21
38 Report Generation in Embedded Coder
For help navigating the content of the code interface report subsections, see “Navigating
Code Interface Report Subsections” on page 38-22. For help interpreting the content of
the code interface report subsections, see the sections beginning with “Interpreting the
Entry-Point Functions Subsection” on page 38-23.
• For a large subsection, the report provides [-] and [+] symbols that allow you to
collapse or expand that section. In the example in the previous section, the symbols
are provided for the Inports and Interface Parameters sections.
• Several forms of hyperlink navigation are provided in the code interface report. For
example:
• The Table of Contents located at the top of the code interface report provides
links to each subsection.
• You can click each function name to go to its definition in model.c.
• You can click each function's header file name to go to the header file source
listing.
• If you selected the Code-to-model parameter for your model, to go to the
corresponding location in the model display, you can click hyperlinks for any of the
following:
• Function argument
• Function return value
• Inport
• Outport
• Interface parameter (if the parameter source is a block)
• Data store (if the data store source is a Data Store Memory block)
For backward and forward navigation within the HTML code generation report, use the
Back and Forward buttons above the Contents section in the upper-left corner of the
report.
38-22
Analyze the Generated Code Interface
Field Description
Function: Lists the function name. You can click the function name to go to
its definition in model.c.
Prototype Displays the function prototype, including the function return
value, name, and arguments.
Description Provides a text description of the function's purpose in the
application.
Timing Describes the timing characteristics of the function, such as how
many times the function is called, or if it is called periodically, and
at what time interval. For a multirate timing example, see the
following rtwdemo_mrmtbb report excerpt.
Arguments If the function has arguments, displays the number, name, data
type, and Simulink description for each argument. If you select
the Code-to-model parameter for your model, you can click the
hyperlink in the description to go to the block corresponding to
the argument in the model display. For argument examples, see
the rtwdemo_fcnprotoctrl report excerpt below.
Return value If the function has a return value, this field displays the return
value data type and Simulink description. If you selected the
Code-to-model parameter for your model, you can click the
hyperlink in the description to go to the block corresponding to
the return value in the model display. For a return value example,
see the following rtwdemo_fcnprotoctrl report excerpt.
Header file Lists the name of the header file for the function. You can click the
header file name to go to the header file source listing.
For example, here is the Entry-Point Functions subsection for the model
rtwdemo_basicsc.
38-23
38 Report Generation in Embedded Coder
To illustrate how timing information might be listed for a multirate model, here are the
Entry-Point Functions and Inports subsections for the model rtwdemo_mrmtbb. This
multirate, discrete-time, multitasking model contains Inport blocks 1 and 2, which specify
1-second and 2-second sample times, respectively. The sample times are constrained to
the specified times by the Periodic sample time constraint option on the Solver pane
of the Configuration Parameters dialog box.
38-24
Analyze the Generated Code Interface
To illustrate how function arguments and return values are displayed in the report, here
is the entry-point function description of the model step function for model
rtwdemo_fcnprotoctrl.
38-25
38 Report Generation in Embedded Coder
Field Description
Block Name Displays the Simulink block name of the inport or outport. If you
selected the Code-to-model parameter for your model, you can
click on each inport or outport Block Name value to go to its
location in the model display.
38-26
Analyze the Generated Code Interface
Field Description
Code Identifier Lists the identifier associated with the inport or outport data in
the generated code, as follows:
For example, here are the Inports and Outports subsections for the model
rtwdemo_basicsc.
38-27
38 Report Generation in Embedded Coder
Field Description
Parameter Source Lists the source of the parameter value, as follows:
38-28
Analyze the Generated Code Interface
Field Description
Code Identifier Lists the identifier associated with the tunable parameter data in
the generated code, as follows:
For example, here is the Interface Parameters subsection for the model
rtwdemo_basicsc (with the ExportedGlobal Storage Class button selected in the
model window).
38-29
38 Report Generation in Embedded Coder
Field Description
Data Store Source Lists the source of the data store memory, as follows:
38-30
Analyze the Generated Code Interface
Field Description
Code Identifier Lists the identifier associated with the data store data in the
generated code, as follows:
For example, here is the Data Stores subsection for the model rtwdemo_basicsc (with
the ExportedGlobal Storage Class button selected in the model window).
38-31
38 Report Generation in Embedded Coder
• The code interface report does not support the GRT interface with an ERT target or C
++ class code interface packaging. For these configurations, the code interface report
is not generated and does not appear in the HTML code generation report Contents
pane.
• The code interface report supports data resolved with most custom storage classes
(CSCs), except when the CSC properties are set in any of the following ways:
• The CSC property Type is set to FlatStructure. For example, the BitField and
Struct CSCs in the Simulink package have Type set to FlatStructure.
• The CSC property Type is set to Other. For example, the GetSet CSC in the
Simulink package has Type set to Other.
• The CSC property Data access is set to Pointer, indicating that imported
symbols are declared as pointer variables rather than simple variables. This
property is accessible only when the CSC property Data scope is set to Imported
or Instance-specific.
In these cases, the report displays empty Data Type and Dimension fields.
• For outports, the code interface report cannot describe the associated memory (data
type and dimensions) if the memory is optimized. In these cases, the report displays
empty Data Type and Dimension fields.
• The code interface report does not support data type replacement using the Code
Generation > Data Type Replacement pane of the Configuration Parameters dialog
box. The data types listed in the report will link to built-in data types rather than their
specified replacement data types.
See Also
Related Examples
• “How Generated Code Exchanges Data with an Environment” on page 22-33
38-32
Static Code Metrics
In this section...
“About Static Code Metrics” on page 38-33
“Static Code Metrics Analysis” on page 38-34
“View Static Code Metrics and Definitions Within the Generated Code” on page 38-35
• “Generate Static Code Metrics Report for Simulink Model” on page 38-37
• “Generate a Static Code Metrics Report for MATLAB Code” on page 38-42
38-33
38 Report Generation in Embedded Coder
• Uses the specified C data types. For Simulink models, you specify these data types in
the Hardware Implementation > Production hardware pane of the Configuration
Parameters dialog box. For code generation from MATLAB code, you specify them in
the Hardware tab of the MATLAB Coder project settings dialog box or using a code
generation configuration object. Actual object code metrics might differ due to target-
specific compiler and platform settings.
• Includes custom code only if you specify it. For Simulink models, you specify custom
code on the Code Generation > Custom Code pane in the model configuration. For
code generation from MATLAB code, you specify it on the Debugging tab of the
MATLAB Coder project settings dialog box or using a code generation configuration
object. An error report is generated if the generated code includes platform-specific
files not contained in the standard C run-time library.
• For Simulink models, includes the generated code from referenced models.
• Uses 1-byte alignment for all members of a structure for estimating global and local
data structure sizes. The size of a structure is calculated by summing the sizes of all of
its fields. This estimation represents the smallest possible size for a structure.
• Calculates the self stack size of a function as the size of local data within a function,
excluding input arguments. The accumulated stack size of a function is the self stack
size plus the maximum of the accumulated stack sizes of its called functions. For
example, if the accumulated stacks sizes for the called functions are represented as
accum_size1...accum_sizeN, then the accumulated stack size for a function is
accumulated_stack_size = self_stack_size + max(accum_size1,...,accum_sizeN)
• When estimating the stack size of a function, static analysis stops at the first instance
of a recursive call. The Function Information table indicates when recursion occurs
in a function call path. Code generation generates only recursive code for Stateflow
event broadcasting and for graphical functions if it is written as a recursive function.
• Calculates the cyclomatic complexity of a function as the number of decisions plus
one:
CC = Number of decisions + 1
38-34
Static Code Metrics
• If statement
• Else-If statement
• Switch statement (1 decision for each case branch)
• Loop statements: While, For, Do-while
Note Boolean operators in the above constructs do not add extra decisions.
• Does not include ert_main.c, because you have the option to provide your own
main.c.
• On the Code Generation > Report pane, if you select the Static code metrics
check box you can hover your cursor over global variables and functions in the code
window to see code metrics information.
• In the code window, if you click linked variables or functions, the code inspect window
is displayed. The window provides links to definitions for the variables or functions. On
the Code Generation > Report pane, if you selected the Static code metrics check
box, you can also see code metrics information for the variable or function.
38-35
38 Report Generation in Embedded Coder
38-36
Generate Static Code Metrics Report for Simulink Model
1 Before generating the HTML Code Generation Report, open the Configuration
Parameters dialog box for your model. On the Code Generation > Report pane,
select the “Static code metrics” (Simulink Coder) check box.
If your model includes referenced models, select the Static code metrics check box
in each referenced model’s configuration set. Otherwise, you cannot view a separate
static code metrics report for a referenced model.
2 Press Ctrl+B to build your model and generate the HTML code generation report.
For more information, see “Generate a Code Generation Report” on page 38-5.
3 If the HTML Code Generation Report is not already open, open the report. On the left
navigation pane, in the Contents section, select Static Code Metrics Report.
4 To see the generated files and how many lines of code are generated per file, look at
the File Information section.
38-37
38 Report Generation in Embedded Coder
5 Hover your cursor over column titles and some column values to see a description of
the corresponding data.
6 If your model includes referenced models, the File information section includes a
Referenced Model column. In this column, click the referenced model name to open
its static code metrics report. If the static code metrics report is not available for a
referenced model, specify the Static code metrics parameter in the referenced
model’s configuration set and rebuild your model.
7 To view the global variables in the generated code, their size, and the number of
accesses, see the Global Variables section.
The Reads/Writes column displays the total number of read and write accesses to
the global variable. The Reads/Writes in a Function column displays the maximum
38-38
Generate Static Code Metrics Report for Simulink Model
number of read and write accesses to the global variable within a function. You use
this information is to estimate the benefit of turning on optimizations, which reduce
the number of global references. For more information, see “Optimize Global Variable
Usage” on page 58-2.
8 To navigate from the report to the source code, click a global variable or function
name. These names are hyperlinks to their definitions.
9 To view the function call tree of the generated code, in the Function Information
section, click Call Tree at the top of the table.
38-39
38 Report Generation in Embedded Coder
ert_main.c is not included in the code metrics analysis, therefore it is not shown in
the call tree format. The Complexity column includes the cyclomatic complexity of
each function.
10 To view the functions in a table format, click Table.
The second column, Called By, lists functions that call the function listed in the first
column, using the following criteria:
38-40
Generate Static Code Metrics Report for Simulink Model
38-41
38 Report Generation in Embedded Coder
By default, if you have an Embedded Coder license, when you use MATLAB Coder to
generate standalone C/C++ code, the code generation report includes a static code
metrics report. The static code metrics report is not available for generated MEX
functions.
In the same local, writable folder, create a test file, moving_average_test.m, that
contains:
function moving_average_test( )
z = zeros(10,1);
for i = 1:10
[avg, z] = moving_average(i,z);
end
disp(avg)
end
1 To open the MATLAB Coder app and set up a project, at the command line, enter:
38-42
Generate a Static Code Metrics Report for MATLAB Code
1 To automatically define the input types, select or enter the test file
moving_average_test.m. Click Autodefine Input Types.
The Check for Run-Time Issues step generates a MEX file from your entry-point
functions, runs the MEX function, and reports issues. This step is optional. However,
it is a best practice to perform this step. You can detect and fix run-time errors that
are harder to diagnose in the generated C code.
1 To open the Check for Run-Time Issues dialog box, click the Check for Issues
arrow .
The app populates the test file field with moving_average_test.m, the test file that
you used to define input types.
2 Click Check for Issues.
1 On the Generate Code page, to open the Generate dialog box, click the Generate
arrow .
2 Set Build type to Static library.
38-43
38 Report Generation in Embedded Coder
Generate C Code
MATLAB Coder generates a C static library and supporting files in the default folder,
codegen/lib/moving_average.
2 Click Next to go to the Finish Workflow step.
1 To open the code generation report, under Generated Output, click Code
Generation Report.
2 In the code generation report, on the Summary tab, next to Reports, click Code
Metrics .
3 To see the generated files and the number of lines of code per file, click File
Information.
38-44
Generate a Static Code Metrics Report for MATLAB Code
4 To see the global variables in the generated code, go to the Global Variables
section.
To navigate from the report to the source code, click a global variable name.
5 To view the function call tree of the generated code, in the Function Information
section, click Call Tree.
To navigate from the report to the function code, click a function name.
6 To view the functions in a table format, click Table.
38-45
38 Report Generation in Embedded Coder
The second column, Called By, lists functions that call the function listed in the first
column. If multiple functions call the function, all functions are listed. If no functions
call the function, this column is empty.
1 Create a code generation configuration object for standalone code generation. For
example, to generate a static library, use:
1 Create a code generation configuration object for standalone code generation. For
example, to generate a static library:
38-46
See Also
cfg.GenerateReport = true;
cfg.GenerateCodeMetricsReport = true;
3 Generate code, passing the configuration object as a parameter. For example:
See Also
More About
• “Code Generation Reports” (MATLAB Coder)
38-47
38 Report Generation in Embedded Coder
The figure below shows a Code Replacements Report generated for the CRL model
rtwdemo_crladdsub. Each replacement function used is listed with a link to the block
that triggered the replacement.
38-48
Analyze Code Replacements in Generated Code
If you click a block path in the report, the block that triggered the replacement is
highlighted in the model diagram. If the replacement was triggered by a Stateflow chart
or a MATLAB function, a window opens to display the chart or function.
For more information, see Trace Code Replacements Generated Using Your Code
Replacement Library on page 54-85.
38-49
38 Report Generation in Embedded Coder
The Simulink Report Generator software creates documentation from your model in
multiple formats, including HTML, PDF, RTF, Microsoft Word, and XML. This example
shows one way to document a code generation project in Microsoft Word. The generated
report includes:
To adjust Simulink Report Generator settings to include custom code and then generate a
report for a model, complete the following tasks:
38-50
Document Generated Code with Simulink Report Generator
A Simulink Report Generator license is required for the following report formats: PDF,
RTF, Microsoft Word, and XML. For more information on generating reports in these
formats, see the Simulink Report Generator documentation.
38-51
38 Report Generation in Embedded Coder
3
Double-click codegen.rpt or select it and click the Open report button . The
Report Explorer displays the structure of the setup file in the outline pane (left).
38-52
Document Generated Code with Simulink Report Generator
1 In the properties pane, under Report Options, review the options listed.
38-53
38 Report Generation in Embedded Coder
1 In the outline pane (left), select Model Loop. Report Generator displays Model Loop
component options in the properties pane.
2 If not already selected, select Current block diagram for the Model name
option.
38-54
Document Generated Code with Simulink Report Generator
1 In the outline pane (left), expand the node Chapter - Generated Code. By default,
the report includes two sections, each containing one of two report components.
2 Expand the node Section 1 — Code Generation Summary.
3 Select Code Generation Summary. Options for the component are displayed in the
properties pane.
4 Click Help to review the report customizations that you can make with the Code
Generation Summary component. For this example, do not customize the component.
5 In the Report Explorer window, expand the node Section 1 — Generated Code
Listing.
6 Select Import Generated Code. Options for the component are displayed in the
properties pane.
7 Click Help to review the report customizations that you can make with the Import
Generated Code component.
38-55
38 Report Generation in Embedded Coder
When the report is complete, open the report, MyModelCGReport.rtf in the folder
report_ex (in this example).
38-56
Get Code Description of Generated Code
You can use the code descriptor API once the code is generated. Use the code descriptor
API to describe these items in the generated code:
rtwbuild('rtwdemo_comments')
38-57
38 Report Generation in Embedded Coder
codeDescriptor = coder.getCodeDescriptor('rtwdemo_comments')
3 To obtain a list of all the data interface types in the generated code, call the
getDataInterfaceTypes method.
dataInterfaceTypes = codeDescriptor.getDataInterfaceTypes()
{'Inports' }
{'Outports' }
{'Parameters' }
{'GlobalParameters'}
38-58
Get Code Description of Generated Code
dataInterface = codeDescriptor.getDataInterfaces('Inports')
This call returns properties of the Inport blocks in the generated code.
5 Because this model has four inports, dataInterface is an array of
coder.descriptor.DataInterface objects. Obtain the details of the first Inport
of the model by accessing the first location in the array.
dataInterface(1)
rtwbuild('rtwdemo_roll')
38-59
38 Report Generation in Embedded Coder
codeDescriptor = coder.getCodeDescriptor('rtwdemo_roll')
3 To obtain a list of all the function interface types in the generated code, call the
getFunctionInterfaceTypes method.
functionInterfaceTypes = codeDescriptor.getFunctionInterfaceTypes()
{'Initialize'}
{'Output' }
{'Terminate' }
functionInterface = codeDescriptor.getFunctionInterfaces('Initialize')
This call returns properties of a specified function interface in the generated code.
38-60
Get Code Description of Generated Code
functionInterface.Prototype
Name: 'rtwdemo_roll_initialize'
Return: [0×0 coder.descriptor.types.Argument]
HeaderFile: 'rtwdemo_roll.h'
SourceFile: 'rtwdemo_roll.c'
Arguments: [1x0 coder.descriptor.types.Argument List]
rtwbuild('rtwdemo_async_mdlreftop')
38-61
38 Report Generation in Embedded Coder
codeDescriptor = coder.getCodeDescriptor('rtwdemo_async_mdlreftop')
3 Get a list of all the referenced models by calling the getReferencedModelNames
method.
refModels = codeDescriptor.getReferencedModelNames()
{'rtwdemo_async_mdlrefbot'}
38-62
See Also
You can now use the refCodeDescriptor object to obtain more information about
the referenced model by calling all the available methods in the Code Descriptor API.
See Also
Related Examples
• “Analyze the Generated Code Interface” on page 38-19
• coder.codedescriptor.CodeDescriptor
38-63
39
39-2
Add Custom Comments to Generated Code
Goal Specify
Include the text specified in the Description Simulink block descriptions
field of a block's Block Properties dialog box as
comments in the code generated for each block.
Add a comment that includes the block name at Simulink block descriptions
the start of the code for each block.
Include the text specified in the Description Simulink data object descriptions
field of a Simulink data object (such as a signal,
parameter, data type, or bus) in the Simulink
Model Explorer as comments in the code
generated for each object.
Include comments just above signals and Custom comments (MPT objects only)
parameter identifiers in the generated code as
specified in the MATLAB or TLC function.
Include the text specified in the Description Stateflow object descriptions
field in the Properties dialog box for a Stateflow
object as comments just above the code
generated for each object.
Include requirements assigned to Simulink Requirements in block comments
blocks in the generated code comments (for
more information, see “Generate Code for
Models with Requirements Links” (Simulink
Requirements)).
Include MATLAB function description comments MATLAB user comments
and other user comments in the generated code.
39-3
39 Code Appearance in Embedded Coder
• The code generator includes strings for model parameters, block names, signal names,
and Stateflow object names in the generated code comments. If those strings are
unrepresented in the character set encoding for the model, the code generator
replaces the strings with XML escape sequences. For example, the code generator
replaces the Japanese full-width Katakana letter ア with the escape sequence
ア. For more information, see “Internationalization and Code Generation”
(Simulink Coder).
• The code generation software automatically inserts comments into the generated code
for custom blocks. Therefore, you do not need to include block comments in the
associated TLC file for a custom block.
Note If you have existing TLC files with manually inserted comments for block
descriptions, the code generation process emits these comments instead of the
automatically generated comments. Consider removing existing block comments from
your TLC files. Manually inserted comments might be poorly formatted in the
generated code and code-to-model traceability might not work.
• For virtual blocks or blocks that have been removed due to block reduction, comments
are not generated.
39-4
Add Custom Comments for Variables in the Generated Code
For more information about data objects, see “Data Objects” (Simulink).
In this section...
“Embed Handwritten Comments for Signals or Parameters” on page 39-5
“Generate Dynamic Comments Based on Data Properties” on page 39-6
1 Create a data object to represent a signal, state, or parameter. You can use a data
object from any package. For example, use a data object of the classes
Simulink.Signal or Simulink.Parameter, which are defined in the package
Simulink.
myParam = Simulink.Parameter(15.23);
2 Set the storage class of the data object so that optimizations do not eliminate the
signal or parameter from the generated code. For example, use the storage class
ExportedGlobal.
myParam.StorageClass = 'ExportedGlobal';
3 Set the Description property of the object. The description that you specify
appears in the generated code as lines of comments.
39-5
39 Code Appearance in Embedded Coder
To generate comments from data object descriptions, you must use an ERT-based
target.
5 Select Configuration Parameters > Code Generation > Comments > Simulink
data object descriptions.
6 Generate code from the model. In the code, the data object description appears near
the definition of the corresponding variable.
/* Unit: psi */
/* Owner: */
/* DefinitionFile: specialDef */
real_T MAP = 0.0;
1 Create a data object from the package mpt and apply a custom storage class to the
object. The default storage class for objects that you create from the package mpt is
the custom storage class Global (Custom).
MAP = mpt.Signal;
To generate dynamic comments, you must use a data object from the package mpt,
and you must apply a custom storage class to the object.
2 Write a MATLAB or TLC function that generates the comment text. For an example
MATLAB function, see the function matlabroot/toolbox/rtw/rtwdemos/
rtwdemo_comments_mptfun.m.
The function must accept three input arguments that correspond to objectName,
modelName, and request. If you write a TLC file, you can use the library function
LibGetSLDataObjectInfo to get the property values of the data object.
39-6
See Also
3 Save the function as a MATLAB file or a TLC file, and place the file in a folder that is
on your MATLAB path.
4 In the model, select Configuration Parameters > Code Generation > Comments
> Custom comments (MPT objects only).
5 Set Custom comments function to the name of the MATLAB file or TLC file that
you created.
6 Generate code from the model. The comments that your function generates appear
near the code that represents each data object.
Limitations
• To generate comments by using the Custom comments (MPT objects only) and
Custom comments function options, you must create data objects from the package
mpt. The data objects must use a custom storage class.
• Only the custom storage classes from the mpt package that create unstructured
variables support a custom comments function.
See Also
Related Examples
• “Add Custom Comments to Generated Code” on page 39-3
• “Apply Custom Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 26-19
More About
• “Data Objects” (Simulink)
• “MPT Data Object Properties” on page 25-2
39-7
39 Code Appearance in Embedded Coder
The following examples show how to add a global comment to a Simulink model so that
the comment text appears in the generated file or files where you want. Specify a
template symbol name with a Simulink DocBlock, a Simulink annotation, or a Stateflow
note. You can also use a sorted-notes capability that works with Simulink annotations or
Stateflow notes (but not DocBlocks). For more information about template symbols, see
“Template Symbols and Rules” on page 39-97.
Note Template symbol names Description and ModifiedHistory also are fields in
the Model Properties dialog box. If you use one of these symbol names for global
comment text, and its Model Properties field also has text in it, both names appear in the
generated files.
• Abstract
• Description
• History
• ModifiedHistory
39-8
Add Global Comments
• Notes
If you are using a DocBlock to add comments to your code, set the Document type
to Text. If you set Document type to RTF or HTML, your comments will not appear
in the code.
6 In the Block Properties dialog box, on the Block Annotation tab, select
%<ECoderFlag> and click OK. The symbol name that you typed in the previous step
now appears under the DocBlock in the model.
39-9
39 Code Appearance in Embedded Coder
7 Save the model. After you generate code, the code generator places the comment in
each generated file whose template has the symbol name that you typed. The code
generator places the comment in the generated file at the location that corresponds
to where the symbol name is located in the template file.
8 To add more comments to the generated files, repeat steps 1–7.
39-10
Add Global Comments
• Abstract
• Description
• History
• ModifiedHistory
• Notes
• Abstract
39-11
39 Code Appearance in Embedded Coder
• Description
• History
• ModifiedHistory
• Notes
You can use sorted notes with a Simulink annotation or a Stateflow note, but not with a
DocBlock.
• In the Simulink annotation or the Stateflow note, type <S:NoteY> followed by the first
comment. Y is a number or a letter.
• Repeat for as many additional comments you want. Replace Y with a subsequent
number or letter.
The figure illustrates sorted notes on a model, and where the code generator places each
note in a generated file.
39-12
Add Global Comments
The relevant fragment from the generated file for this model is:
** NOTES
**
39-13
39 Code Appearance in Embedded Coder
For GRT and RSim targets, the code generator constructs identifiers for variables and
functions in the generated code. For ERT targets, you can customize the naming of
identifiers in the generated code by specifying parameters on the Code Generation >
Symbols pane in the Configuration Parameters dialog box. You can also specify
parameters that control identifiers generated from Simulink data objects. For detailed
information about these parameters, see “Model Configuration Parameters: Code
Generation Symbols” (Simulink Coder).
39-14
Customize Generated Identifier Naming Rules
Goal Specify
Define a macro that specifies certain text A macro for the Identifier format control
included within generated identifiers for: parameters. For more information, see
“Identifier Format Control” on page 39-22. See
• Global variables also “Exceptions to Identifier Formatting
• Global types Conventions” on page 39-35 and “Identifier
Format Control Parameters Limitations” on page
• Field names of global types
39-36.
• Subsystem methods
• Subsystem method arguments
• Local temporary variables
• Local block output variables
• Constant macros
• Shared utilities identifier format
Set the minimum number of characters that the An integer value for the “Minimum mangle
code generator uses for the mangling text. length” (Simulink Coder) parameter. For more
information, see “Control Name Mangling in
Generated Identifiers” on page 39-30
Control whether the software uses shortened Shortened for the “System-generated
names for system-generated identifiers. identifiers” (Simulink Coder) parameter. This
setting:
39-15
39 Code Appearance in Embedded Coder
Goal Specify
Control whether the generated code expresses The value Literals or Macros for the
scalar inlined parameter values as literal values “Generate scalar inlined parameters as”
or as macros. (Simulink Coder) parameter.
You can control these identifiers by specifying naming rules that are specific to Simulink
data objects. On the Code Generation > Symbols pane of the Configuration Parameters
dialog box, adjust the settings in the Simulink data object naming rules section.
When you specify naming rules for generated code, follow ANSI C5/C++ rules for naming
identifiers.
This example shows how to customize identifiers in generated code by defining a MATLAB
function.
1 Write a MATLAB function that returns an identifier by modifying a data object name,
and save the function in your working folder. For example, the following function
returns an identifier name by appending the text _param to a data object name.
function revisedName = append_text(name, object)
% APPEND_TEXT: Returns an identifier for generated
% code by appending text to a data object name.
%
39-16
Customize Generated Identifier Naming Rules
% Input arguments:
% name: data object name as spelled in model
% object: target data object
%
% Output arguments:
% revisedName: altered identifier returned for use in
% generated code.
%
%
text = '_param';
revisedName = [name,text];
2 Open the model rtwdemo_namerules.
3 Double-click the yellow box labeled View Symbols Configuration to open the Code
Generation > Symbols pane in the Configuration Parameters dialog box.
4 From the Parameter naming (Simulink Coder) drop-down list, select Custom M-
function.
5 In the M-function field, type the name of the file that defines the MATLAB function,
append_text.m.
6 Click Apply.
7 Generate code for the model.
8 Inspect the code generation report to confirm the parameter object naming rule. For
example, the generated file rtwdemo_namerules.h represents the parameter
objects G1, G2, and G3 with the variables G1_param, G2_param, and G3_param.
You can specify a naming rule that applies only to Simulink data objects whose storage
class you set to Define. For these data objects, the specified naming rule overrides the
other parameter and signal object naming rules. On the Code Generation > Symbols
pane in the Configuration Parameters dialog box, adjust the #define naming (Simulink
Coder) setting.
39-17
39 Code Appearance in Embedded Coder
This example shows how to override a data object naming rule for a single data object.
You can override data object naming rules by specifying the Alias property of an
individual Simulink data object. Generated code uses the text that you specify as the
identifier to represent the data object, regardless of naming rules.
39-18
Customize Generated Identifier Naming Rules
This example shows how to apply uniform naming rules for Simulink® data objects,
including signals, parameters, and data store memory variables.
model='rtwdemo_namerules';
open_system(model)
39-19
39 Code Appearance in Embedded Coder
39-20
See Also
% Cleanup
rtwdemoclean;
close_system(model,0)
See Also
“Signal naming” (Simulink Coder)
39-21
39 Code Appearance in Embedded Coder
• Valid tokens, which are listed in Identifier Format Tokens. You can use or omit tokens
depending on what you want to include in the identifier name. The Shared utilities
identifier format parameter requires you to specify the checksum token, $C. The
other parameters require the mangling token, $M. For more information, see “Control
Name Mangling in Generated Identifiers” on page 39-30. The mangling token is
subject to the use and ordering restrictions noted in Identifier Format Control
Parameter Values.
• Token decorators, which are listed in “Control Case with Token Decorators” on page
39-27. You can use token decorators to control the case of generated identifiers for
each token.
• Valid C or C++ language identifier characters (a-z, A-Z, _ , 0-9).
The build process generates each identifier by expanding tokens and inserting the
resultant text into the identifier. The tokens are expanded in the order listed in Identifier
Format Tokens. Groups of characters are inserted in the positions that you specify around
tokens directly into the identifier. Contiguous token expansions are separated by the
underscore (_) character.
39-22
Identifier Format Control
Token Description
$C This token is required for Shared utilities identifier format. If the
identifier exceeds the Maximum identifier length, the code generator
inserts an 8-character checksum to avoid naming collisions. The position of
the $C token in the Identifier format control parameter specification
determines the position of the checksum in the generated identifier. For
example, if you use the specification $N$C, the checksum is appended to
the end of the identifier. This token is available only for shared utilities.
$M This token is required. If necessary, the code generator inserts name-
mangling text to avoid naming collisions. Modify checksum character
length by using Shared checksum length parameter. The position of the
$M token in the Identifier format control parameter specification
determines the position of the name-mangling text in the generated
identifier. For example, if you use the specification $R$N$M, the name-
mangling text is appended (if required) to the end of the identifier. For
more information, see “Control Name Mangling in Generated Identifiers”
on page 39-30.
$U Insert text that you specify for the $U token. Use the Custom token text
parameter to specify this text.
$F Insert method name (for example, _Update for update method). This token
is available only for subsystem methods.
$N Insert name of object (block, signal or signal object, state, parameter,
shared utility function or parameter object) for which identifier is being
generated.
$R Insert root model name into identifier, replacing unsupported characters
with the underscore (_) character. When you use referenced models, this
token is required in addition to $M (see “Avoid Identifier Name Collisions
with Referenced Models” on page 39-32).
Note: This token replaces the Prefix model name to global identifiers
option in previous releases.
39-23
39 Code Appearance in Embedded Coder
Token Description
$H Insert tag indicating system hierarchy level. For root-level blocks, the tag is
the text root_. For blocks at the subsystem level, the tag is of the form
sN_. N is a unique system number assigned by the Simulink software. This
token is available only for subsystem methods and field names of global
types.
Note: This token replaces the Include data type acronym in identifier
option in previous releases.
$I • Insert u if the argument is an input.
• Insert y if the argument is an output.
• Insert uy if the argument is an input and output.
For example, rtu_ for an input argument, rty_ for an output argument,
and rtuy_ for an input and output argument. This token is available only
for subsystem method arguments.
$G Insert the name of a storage class that is associated with the data item.
This token is also available in the naming rule that you specify for the
Header File for a storage class in the Embedded Coder Dictionary.
$E Insert the file type. $E represents these instances of file types:
• capi
• capi_host
• dt
• testinterface
• private
• types
39-24
Identifier Format Control
Identifier Format Control Parameter Values lists the default macro value, the supported
tokens, and the applicable restrictions for each Identifier format control parameter.
39-25
39 Code Appearance in Embedded Coder
39-26
Identifier Format Control
Non-ERT-based targets (such as the GRT target) implicitly use a default $R$N$M
specification. This default specification consists of the root model name, followed by the
name of the generating object (signal, parameter, state, and so on), followed by name-
mangling text.
For limitations that apply to Identifier format control parameters, see “Exceptions to
Identifier Formatting Conventions” on page 39-35 and “Identifier Format Control
Parameters Limitations” on page 39-36.
The table shows how to manipulate the expansion of the $R token for a model whose
name is modelName.
39-27
39 Code Appearance in Embedded Coder
When you use a decorator, the code generator removes the underscore character (_) that
appears between tokens by default. However, you can append each decorator with an
underscore: $R[U_]$N. For example, if you set the Global variables parameter to
$R[u_]$N[uL]$M for a model named modelName and a DWork structure represented by
DW, the result is ModelName_Dw.
model='rtwdemo_symbols';
open_system(model)
39-28
Identifier Format Control
% Cleanup
rtwdemoclean;
close_system(model,0)
39-29
39 Code Appearance in Embedded Coder
The length of the name-mangling text is specified by the Minimum mangle length
(Simulink Coder) parameter. The default value is 1, but this automatically increases
during code generation as a function of the number of collisions. To minimize disturbance
to the generated code during development, specify a larger Minimum mangle length. A
Minimum mangle length of 4 is a conservative value. A value of 4 allows for over 1.5
million collisions for a particular identifier before the mangle length is increased.
• Avoid name collisions. One way to avoid name collisions is to not use default block
names (for example, Gain1, Gain2...) when there are many blocks of the same type
in the model.
39-30
Control Name Mangling in Generated Identifiers
• Where possible, increase the Maximum identifier length to accommodate the length
of the identifiers that you expect to generate.
• Set the Maximum identifier length parameter to reserve at least three characters
for the name-mangling text. The length of the name-mangling text increases as the
number of name collisions increases.
If changes to the model create more or fewer collisions, existing name-mangling text
increases or decreases in length. If the length of the name-mangling text increases,
additional characters are appended to the existing text. For example, the mangling
text 'xyz' can change to 'xyzQ'. For fewer collisions, the name-mangling text
'xyz' changes to 'xy'.
39-31
39 Code Appearance in Embedded Coder
• You must include the $R token in the Identifier format control parameter
specifications (in addition to the $M token).
• The Maximum identifier length must be large enough to accommodate full
expansions of the $R and $M tokens. If Maximum identifier length is too small, a
code generation error occurs.
When a name conflict occurs between an identifier within the scope of a higher-level
model and an identifier within the scope of a referenced model, the identifier from the
referenced model is preserved. Name mangling is performed on the identifier from the
higher-level model.
If your model contains two referenced models with the same input or output port names,
and one of the referenced models contains an atomic subsystem with “Function
packaging” (Simulink) set to Nonreuseable function, a name conflict can occur and
the build process produces an error.
• Global variables
• Global types
• Subsystem methods
• Constant macros
You can use the Model Advisor to identify referenced models in a model referencing
hierarchy for which code generation changes these configuration parameter settings.
39-32
Avoid Identifier Name Collisions with Referenced Models
2 Select By Task.
3 Run the Check code generation identifier formats used for model reference
check.
39-33
39 Code Appearance in Embedded Coder
• Choose unique names for Simulink objects (blocks, signals, states, and so on) as much
as possible.
• Use name mangling when conflicts cannot be avoided.
The position of the name-mangling text is specified by the placement of the $M token in
the Identifier format control parameters. Mangle characters consist of alphanumeric
characters that are unique to each object. For more information, see “Control Name
Mangling in Generated Identifiers” on page 39-30.
39-34
Exceptions to Identifier Formatting Conventions
• Type name generation: name mangling conventions do not apply to type names (that
is, typedef statements) generated for global data types. If the $R token is included in
the Identifier format control parameter specification, the model name is included in
the typedef. When generating type definitions, the Maximum identifier length
parameter is not respected.
• Non-Auto storage classes: the Identifier format control parameters specification
does not affect objects (such as signals and parameters) that have a storage class
other than Auto (such as ImportedExtern or ExportedGlobal).
• For shared utilities, code generation inserts the checksum specified by $C to prevent
name collisions in the following situations:
39-35
39 Code Appearance in Embedded Coder
• The following autogenerated identifiers currently do not fully comply with the setting
of the Maximum identifier length parameter on the Code Generation > Symbols
pane of the Configuration Parameters dialog box.
• Model methods
• Most are within the default Maximum identifier length of 31, but some
exceed the limit. Examples are
RTMSpecAccsGetStopRequestedValStoredAsPtr,
RTMSpecAccsGetErrorStatusPointer, and
RTMSpecAccsGetErrorStatusPointerPointer.
• Define protection guard macros
• Model methods
• Reentrant model function arguments
39-36
Identifier Format Control Parameters Limitations
39-37
39 Code Appearance in Embedded Coder
You can change the code style, cast expressions, and indentation of your generated code
to conform to certain coding standards. Modify style options by setting parameters on the
Code Generation > Code Style pane.
Goal Action
Specify parenthesization style for generated See “Control Parentheses in Generated Code” on
code page 39-39.
Specify whether to preserve order of operands in See “Optimize Code by Reordering Commutable
expressions Operands” on page 39-41.
Specify whether to preserve empty primary See “Preserve condition expression in if
condition expressions in if statements statement”.
Specify whether to generate code for if- See “Convert if-elseif-else patterns to switch-
elseif-else decision logic as switch-case case statements”.
statements
Specify whether to include the extern keyword See “Preserve extern keyword in function
in function declarations in the generated code declarations”.
Specify whether to include the static keyword See “Preserve static keyword in function
in function declarations in the generated code declarations”.
Specify whether to generate default cases for See “Suppress Generation of Default Cases for
switch-case statements in the code for Unreachable Stateflow Switch Statements” on
Stateflow charts page 39-42.
39-38
Control Code Style
Goal Action
Specify whether to replace multiplications by See “Replace Multiplication by Powers of Two
powers of two with signed bitwise shifts with Signed Bitwise Shifts” on page 39-45.
Specify whether to allow signed right bitwise See “Generate Code with Right Shifts on Signed
shifts in the generated C/C++ code Integers” on page 39-47.
Specify how the code generator casts data types See “Control Cast Expressions in Generated
for variables Code” on page 39-50.
Specify indent style for the generated code See “Control Indentation Style in Generated
Code” on page 39-48.
Specify the newline character in the generated See “Control Newline Style in Generated Code”
code on page 39-54.
This example shows that Embedded Coder® provides three levels of control for
parentheses in the generated code.
39-39
39 Code Appearance in Embedded Coder
model='rtwdemo_parentheses';
open_system(model)
39-40
Control Code Style
rtwdemoclean;
close_system(model,0)
Example Model
Generate Code
1 Open the Model Configuration Parameters dialog box. On the Code Style tab, select
the Preserve operand order in expression parameter.
2 Generate code for the model.
39-41
39 Code Appearance in Embedded Coder
The code generator preserves the specified expression order in the model. Preserving the
specified expression order increases the readability of the code for code traceability
purposes.
1 Open the Model Configuration Parameters dialog box. On the Code Style tab, clear
the Preserve operand order in expression parameter.
2 Generate code for the model.
The code generator optimizes the code by reordering the commutable operands to make
the expression left-recursive. Left-recursive expressions improve code efficiency.
For more information on the Preserve operand order in expression parameter, see
“Preserve operand order in expression”.
Some coding standards, such as MISRA, require the default case for switch-case
statements. If you want to increase your chances of producing MISRA C compliant code,
generate default cases for unreachable Stateflow switch statements.
Example
39-42
Control Code Style
39-43
39 Code Appearance in Embedded Coder
Generate Code with Default Cases for Unreachable Stateflow Switch Statements
rtwdemo_fuelsys
2 Open the Model Configuration parameters dialog box. On the Code Generation >
Code Style tab, clear the Suppress generation of default cases for Stateflow
statements if unreachable parameter.
3 In the MATLAB Command Window, to build the model, enter:
rtwbuild('sldemo_fuelsys/fuel_rate_control');
39-44
Control Code Style
For the different operation modes, the fuel_rate_control.c file contains default cases
for unreachable switch statements. For example, for the Shutdown operation mode, the
generated code contains this default statement:
default:
/* Unreachable state, for coverage only */
rtDWork.bitsForTID0.is_Fuel_Disabled = IN_NO_ACTIVE_CHILD;
break;
For the Warmup operation mode, the generated code contains this default statement:
default:
/* Unreachable state, for coverage only */
rtDWork.bitsForTID0.is_Low_Emissions = IN_NO_ACTIVE_CHILD;
break;
1 Open the Configuration Parameters dialog box. On the Code Generation > Code
Style tab, select the Suppress generation of default cases for Stateflow
statements if unreachable parameter.
2 Build the model.
Read through the fuel_rate_control.c file. The default cases for unreachable switch
statements are not in the generated code.
For more information on the Suppress generation of default cases for Stateflow
statements if unreachable parameter, see “Suppress generation of default cases for
Stateflow switch statements if unreachable”.
Some coding standards, such as MISRA, do not allow bitwise operations on signed
integers. If you want to increase your chances of producing MISRA C compliant code, do
not replace multiplication by powers of two with bitwise shifts.
39-45
39 Code Appearance in Embedded Coder
Example
To replace multiplication by powers of two with bitwise shifts, create the following model.
In this model, a signal of Data type int16 feeds into a Shift Arithmetic block. In the Shift
Arithmetic Block Parameters dialog box, the Bits to shift > Direction parameter is set
to Left. The Bits to shift > Number parameter is set to 3. This parameter corresponds
to a value of 8, or raising 2 to the power of 3.
39-46
Control Code Style
For more information on the Replace multiplications by powers of two with signed
bitwise shifts parameter, see “Replace multiplications by powers of two with signed
bitwise shifts”.
Some coding standards, such as MISRA, do not allow right shifts on signed integers
because different hardware can store negative integers differently. For negative integers,
you can get different answers depending on the hardware. If you want to increase your
chances of producing MISRA C compliant code, do not allow right shifts on signed
integers.
Example Model
To generate code with right shifts on signed integers, create the following model. In this
model, a signal of Data type int16 feeds into a Shift Arithmetic block. In the Shift
Arithmetic Block Parameters dialog box, the Bits to shift > Direction parameter is set
to Right. The Bits to shift > Number parameter is set to 3.
1 Open the Model Configuration Parameters dialog box and select the Code Style tab.
The Allow right shifts on signed integers parameter is on by default.
2 Generate code for the model.
39-47
39 Code Appearance in Embedded Coder
Generate Code That Does Not Allow Right Shifts on Signed Integers
1 Open the Model Configuration Parameters dialog box and select the Code Style tab.
Clear the Allow right shifts on signed integers parameter.
2 Generate code for the model.
When you clear the Allow right shifts on signed integers parameter, the generated
code contains a function call instead of a right shift on a signed integer. The function
asr_s32 contains this code:
int32_T asr_s32(int32_T u, uint32_T n)
{
int32_T y;
if (u >= 0) {
y = (int32_T)((uint32_T)u >> n);
} else {
y = -(int32_T)((uint32_T)-(u + 1) >> n) - 1;
}
return y;
}
The asr_s32 function casts a signed integer to an unsigned integer, and then right shifts
the unsigned integer.
For more information on the Allow right shifts on signed integers parameter, see
“Allow right shifts on signed integers”.
39-48
Control Code Style
K&R
K&R stands for Kernighan and Ritchie. Each function has the opening and closing brace
on its own line at the same level of indentation as the function header. Code within the
function is indented according to the Indent size.
For blocks within a function, opening braces are on the same line as the control
statement. Closing braces are on a new line at the same level of indentation as the control
statement. Code within the block is indented according to the Indent size.
For example, here is generated code with the Indent style set to K&R with an Indent
size of 2:
void rt_OneStep(void)
{
static boolean_T OverrunFlag = 0;
if (OverrunFlag) {
rtmSetErrorStatus(rtwdemo_counter_M, "Overrun");
return;
}
OverrunFlag = TRUE;
rtwdemo_counter_step();
OverrunFlag = FALSE;
}
Allman
Each function has the opening and closing brace on its own line at the same level of
indentation as the function header. Code within the function is indented according to the
Indent size.
For blocks within a function, opening and closing braces for control statements are on a
new line at the same level of indentation as the control statement. This is the key
difference between K&R and Allman styles. Code within the block is indented according
to the Indent size.
For example, here is generated code with the Indent style set to Allman with an Indent
size of 4:
void rt_OneStep(void)
{
static boolean_T OverrunFlag = 0;
39-49
39 Code Appearance in Embedded Coder
if (OverrunFlag)
{
rtmSetErrorStatus(rtwdemo_counter_M, "Overrun");
return;
}
OverrunFlag = TRUE;
rtwdemo_counter_step();
OverrunFlag = FALSE;
}
• Nominal instructs the code generator to generate code that has minimal data type
casting. When you do not have special data type information requirements, choose
Nominal.
• Standards Compliant instructs the code generator to cast data types to conform to
MISRA standards when it generates code. The MISRA data type casting eliminates
common MISRA standard violations, including address arithmetic and assignment. It
reduces 10.1, 10.2, 10.3, and 10.4 violations.
39-50
Control Code Style
When you choose Nominal casting mode, the code generator does not create data type
casts for variables in the generated code.
1 On the Code Generation > Code Style pane, from the Casting modes drop-down
list, select Nominal.
2 On the Code Generation > Report pane, select Create code generation report.
3 On the Code Generation pane, select Generate code only.
4 Click Apply.
5 In the model window, press Ctrl+B to generate code.
6 In the Code Generation report left pane, click rtwdemo_rtwecintro.c to see the
code.
/* Model step function */
void rtwdemo_rtwecintro_step(void)
{
boolean_T rtb_equal_to_count;
39-51
39 Code Appearance in Embedded Coder
*/
if (rtb_equal_to_count && (rtPrevZCSigState.Amplifier_Trig_ZCE != POS_ZCSIG))
{
/* Outport: 'XRootX/Output' incorporates:
* Gain: 'XS1X/Gain'
* Inport: 'XRootX/Input'
*/
rtY.Output = rtU.Input << 1;
}
/* Switch: 'XRootX/Switch' */
if (!rtb_equal_to_count) {
/* Update for UnitDelay: 'XRootX/X' incorporates:
* Constant: 'XRootX/RESET'
*/
rtDWork.X = 0U;
}
When you choose Standards Compliant casting mode, the code generator creates
MISRA standards compliant data type casts for variables in the generated code.
1 On the Code Style pane, from the Casting modes drop-down list, select Standards
Compliant.
2 On the Code Generation pane, click Apply.
3 In the model window, press Ctrl+B to generate code.
4 In the Code Generation report left pane, click rtwdemo_rtwecintro.c to see the
code.
void rtwdemo_rtwecintro_step(void)
{
boolean_T rtb_equal_to_count;
39-52
Control Code Style
*/
if (((int32_T)rtb_equal_to_count) && (rtPrevZCSigState.Amplifier_Trig_ZCE !=
POS_ZCSIG)) {
/* Outport: '<Root>/Output' incorporates:
* Gain: '<S1>/Gain'
* Inport: '<Root>/Input'
*/
rtY.Output = (int32_T)(uint32_T)((uint32_T)rtU.Input << (uint32_T)(int8_T)1);
}
rtPrevZCSigState.Amplifier_Trig_ZCE = (uint8_T)(int32_T)(rtb_equal_to_count ?
(int32_T)(uint8_T)POS_ZCSIG : (int32_T)(uint8_T)ZERO_ZCSIG);
/* Switch: '<Root>/Switch' */
if (!rtb_equal_to_count) {
/* Update for UnitDelay: '<Root>/X' incorporates:
* Constant: '<Root>/RESET'
*/
rtDWork.X = 0U;
}
When you choose Explicit casting mode, the code generator creates explicit data type
casts for variables in the generated code.
1 On the Code Style pane, from the Casting modes drop-down list, select Explicit.
2 On the Code Generation pane, click Apply.
3 In the model window, press Ctrl+B to generate code.
4 In the Code Generation report left pane, click rtwdemo_rtwecintro.c to see the
code.
/* Model step function */
void rtwdemo_rtwecintro_step(void)
{
boolean_T rtb_equal_to_count;
39-53
39 Code Appearance in Embedded Coder
/* Switch: '<Root>/Switch' */
if (!(int32_T)rtb_equal_to_count) {
/* Update for UnitDelay: '<Root>/X' incorporates:
* Constant: '<Root>/RESET'
*/
rtDWork.X = 0U;
}
Default
This option is the default selected option. When you select this option, it generates the
newline character based on the operating system that the code is generated on. For
example, if the code is generated on a Windows machine, the newline character inserted
by default is "\r\n". If the code is generated on a UNIX machine, the newline character
inserted by default is "\n".
LF (Linefeed)
This option enables you to add the Line Feed (LF) character. "\n" is inserted as the
newline character.
39-54
See Also
This option enables you to add the Carriage Return + Line Feed (CR+LF) character. "\r
\n" is inserted as the newline character.
See Also
Related Examples
• “Replace and Rename Data Types to Conform to Coding Standards” on page 24-27
More About
• “Model Configuration Parameters: Code Generation Code Style”
39-55
39 Code Appearance in Embedded Coder
Custom file processing (CFP) tools allow you to customize the organization and
formatting of generated code. With these tools, you can:
• Generate a source (.c or .cpp) or header (.h) file. If you configure the Code
interface packaging for a model to be Reusable function or Nonreuseable
function (not C++ class), you can use a custom file processing template to control
how the code generator:
• Code generation template (CGT) files: a CGT file defines the top-level organization and
formatting of generated code. See “Code Generation Template (CGT) Files” on page
39-60.
• The code template API: a high-level Target Language Compiler (TLC) API that provides
functions with which you can organize code into named sections and subsections of
39-56
Customize Code Organization and Format
generated source and header files. The code template API also provides utilities that
return information about generated files, generate standard model calls, and perform
other functions. See “Code Template API Summary” on page 39-85.
• Custom file processing (CFP) templates: a CFP template is a TLC file that manages the
process of custom code generation. A CFP template assembles code to be generated
into buffers. A CFP template also calls the code template API to emit the buffered code
into specified sections of generated source and header files. A CFP template interacts
with a CGT file, which defines the ordering of major sections of the generated code.
See “Custom File Processing (CFP) Templates” on page 39-66.
To use CFP templates, you must understand TLC programming, for more information, see
“Target Language Compiler” (Simulink Coder).
Goal Action
Specify a template that defines the Enter a code generation template (CGT) file for the Source file
top-level organization and (*.c) template parameter.
formatting of generated source
code (.c or .cpp) files
Specify a template that defines the Enter a CGT file for the Header file (*.h) template
top-level organization and parameter. This template file can be the same template file that
formatting of generated header (.h) you specify for Source file (.c) template. If you use the same
files template file, source and header files contain identical
banners. The default template is matlabroot/toolbox/rtw/
targets/ecoder/ert_code_template.cgt.
Specify a template that organizes Enter a custom file processing (CFP) template file for the “File
generated code into sections (such customization template” parameter. A CFP template can emit
as includes, typedefs, functions, code, directives, or comments into each section. For more
and more) information, see “Custom File Processing (CFP) Templates” on
page 39-66.
Generate a model-specific example Select Generate an example main program. For more
main program module information, see “Generate a Standalone Program” on page 52-
2.
39-57
39 Code Appearance in Embedded Coder
Note Place the template files that you specify on the MATLAB path.
39-58
Specify Templates For Code Generation
Select and edit CGT files and CFP templates, and specify their use in the code generation
process in the Code Generation > Templates pane of a model configuration set. The
following figure shows options configured for their defaults.
• The Source file (.c) template field in the Code templates and Data templates
sections. This field specifies the name of a CGT file to use when generating source (.c
or .cpp) files. You must place this file on the MATLAB path.
• The Header file (.h) template field in the Code templates and Data templates
sections. This field specifies the name of a CGT file to use when generating header
(.h) files. You must place this file on the MATLAB path.
By default, the template for both source and header files is matlabroot/
toolbox/rtw/targets/ecoder/ert_code_template.cgt.
• The File customization template edit field in the Custom templates section. This
field specifies the name of a CFP template file to use when generating code files. You
must place this file on the MATLAB path. The default CFP template is matlabroot/
toolbox/rtw/targets/ecoder/example_file_process.tlc.
In each of these fields, click Browse to navigate to and select an existing CFP template or
CGT file. Click Edit to open the specified file into the MATLAB editor where you can
customize it.
39-59
39 Code Appearance in Embedded Coder
(Required) This section contains tokens that define an ordered partitioning of the
generated code into a number of sections (such as Includes and Defines sections).
Tokens have the form of:
%<SectionName>
For example,
%<Includes>
The code generation software defines a minimal set of required tokens. These tokens
generate C or C++ source or header code. They are built-in tokens (see “Built-In Tokens
and Sections” on page 39-61). You can also define custom tokens on page 39-80 and
custom sections on page 39-78.
Each token functions as a placeholder for a corresponding section of generated code. The
ordering of the tokens defines the order in which the corresponding sections appear in
39-60
Code Generation Template (CGT) Files
the generated code. If you do not include a token, then the corresponding section is not
generated. To generate code into a given section, explicitly call the code template API
from a CFP template, as described in “Custom File Processing (CFP) Templates” on page
39-66.
The CGT tokens define the high-level organization of generated code. Using the code
template API, you can partition each code section into named subsections, as described in
“Subsections” on page 39-63.
In the code insertion section, you can also insert C or C++ comments between tokens.
Such comments emit directly into the generated code.
(Optional) This section contains comments and tokens you use in generating a custom file
banner.
(Optional) This section contains comments and tokens for use in generating a custom
function banner.
(Optional) This section contains comments and tokens for use in generating a custom
shared utility function banner.
(Optional) This section contains comments for use in generating a custom trailer banner.
For more information on these sections, see “Generate Custom File and Function
Banners” on page 39-89.
39-61
39 Code Appearance in Embedded Coder
%%
%<Includes>
%<Defines>
%<Types>
%<Enums>
%<Definitions>
%<Declarations>
%<Functions>
Note If you modify a CGT file and then rebuild your model, the code generation process
does not force a top model build. To regenerate the code, see “Force Regeneration of Top
Model Code” (Simulink Coder).
The following table summarizes the built-in tokens and corresponding section names, and
describes the code sections.
39-62
Code Generation Template (CGT) Files
Subsections
You can define one or more named subsections for any section. Some of the built-in
sections have predefined subsections summarized in table Subsections Defined for Built-
In Sections.
Note Sections and subsections emit to the source or header file in the order listed in the
CGT file.
Using the custom section feature, you can define additional sections. See “Generate a
Custom Section” on page 39-78.
39-63
39 Code Appearance in Embedded Coder
model='rtwdemo_codetemplate';
open_system(model)
39-64
Code Generation Template (CGT) Files
rtwdemoclean;
close_system(model,0)
39-65
39 Code Appearance in Embedded Coder
Once you have created a CFP template, you must integrate it into the code generation
process, using the File customization template edit field. See “Specify Templates For
Code Generation” on page 39-59.
Code for each section is assembled in buffers and then emitted, in the order listed, to the
file being generated.
To generate a file section, your CFP template must first assemble the code to be
generated into a buffer. Then, to emit the section, your template calls the TLC function
where
39-66
Custom File Processing (CFP) Templates
• section is the code section or subsection to which code is to be emitted. section must
be one of the section or subsection names listed in Subsections Defined for Built-In
Sections.
• If Subsections Defined for Built-In Sections does not define subsections for a given
section, use the section name as the section argument.
• If Subsections Defined for Built-In Sections defines one or more subsections for a
given section, you can use either the section name or a subsection name as the
section argument.
• If you have defined a custom token denoting a custom section, do not call
LibSetSourceFileSection. Special API calls are provided for custom sections
(see “Generate a Custom Section” on page 39-78).
• tmpBuf is the buffer containing the code to be emitted.
There is no requirement to generate all of the available sections. Your template need only
generate the sections you require in a particular file.
Note that legality or syntax checking is not performed on the custom code within each
section.
See “Generate Source and Header Files with a Custom File Processing (CFP) Template”
on page 39-73, for typical usage examples.
39-67
39 Code Appearance in Embedded Coder
The following fragment shows the rtwdemo_basicsc.c file header that is generated
using this default template:
/*
* File: rtwdemo_basicsc.c
*
* Code generated for Simulink model 'rtwdemo_basicsc'.
*
* Model version : 1.299
* Simulink Coder version : 8.11 (R2017a) 01-Aug-2016
* C/C++ source code generated on : Fri Aug 19 12:45:59 2016
*
* Target selection: ert.tlc
* Embedded hardware selection: Intel->x86-64 (Windows64)
* Code generation objectives: Unspecified
* Validation result: Not run
*/
You can change the organization of generated files using code templates and data
templates. Code templates organize the files that contain functions, primarily. Data
templates organize the files that contain identifiers. In this procedure, you organize the
generated files, using the supplied code and data templates:
1 Display the active Templates configuration parameters.
2 In the Code templates section of the Templates pane, type
code_c_template.cgt into the Source file (*.c) templates text box.
3 Type code_h_template.cgt into the Header file (*.h) templates text box.
4 In the Data templates section, type data_c_template.cgt into the Source file
(*.c) templates text box.
5 Type data_h_template.cgt into the Header file (*.h) templates text box, and
click Apply.
6 In the model window, press Ctrl+B. Now the files are organized using the templates
you specified. For example, the rtwdemo_basicsc.c file header now is organized
like this:
39-68
Change the Organization of a Generated File
/**
*******************************************************************************
** FILE INFORMATION:
** Filename: rtwdemo_basicsc.c
** File Creation Date: 19-Aug-2016
**
** ABSTRACT:
**
**
** NOTES:
**
**
** MODEL INFORMATION:
** Model Name: rtwdemo_basicsc
** Model Description: Specifying Storage Class Within a Diagram
39-69
39 Code Appearance in Embedded Coder
In the Configuration Parameters dialog box, on the Code Generation > Code
Placement pane, use the Auto-generated file naming rules group to customize the
names of generated files. When you use Modular or Compact(with separate date
file) file packaging, you can specify custom names for generated header, source, and
data files. When you use Compact file packaging, you can specify custom names for
generated header and source files.
$E is mandatory for Header files and Source files. $E represents these instances of
file types:
• capi
• capi_host
• dt
• testinterface
• private
• types
4 To build the model, press Ctrl + B. In the code generation report, the generated files
are listed on the left pane under Model files and Data files section.
39-70
Customize Generated File Names
In this example, $E resolves to private and types. The generated header files
resolve to the model name with the value for $E and custom text header. The
generated source files resolve to the model name with custom text source. The
generated data file resolves to the model name with custom text data. Here is a
summary of naming rules applied and the corresponding generated files:
39-71
39 Code Appearance in Embedded Coder
See Also
Related Examples
• “Model Configuration Parameters: Code Generation Code Placement”
39-72
Generate Source and Header Files with a Custom File Processing (CFP) Template
This example shows you the process of generating a simple source (.c or .cpp) and
header (.h) file using the example CFP template. Then, it examines the template and the
code generated by the template.
Follow the steps below to become acquainted with the use of CFP templates:
39-73
39 Code Appearance in Embedded Coder
It now reads:
Notice that the Generated Code list contains the following files:
39-74
Generate Source and Header Files with a Custom File Processing (CFP) Template
The files were generated by the CFP template. The next section examines the
template to learn how this was done.
13 Keep the model, the code generation report, and the
test_example_file_process.tlc file open so you can refer to them in the next
section.
Source (.c or .cpp) and header (.h) files are created by calling
LibCreateSourceFile, as in the following excerpts:
%assign cFile = LibCreateSourceFile("Source", "Custom", "timestwo")
...
%assign hFile = LibCreateSourceFile("Header", "Custom", "timestwo")
Subsequent code refers to the files by the file reference returned from
LibCreateSourceFile.
The code template API lets you partition the code generated to each file into sections,
tagged as Definitions, Includes, Functions, Banner, and so on. You can append
code to each section as many times as required. This technique gives you a great deal of
flexibility in the formatting of your custom code files.
Subsections Defined for Built-In Sections describes the available file sections and their
order in the generated file.
For each section of a generated file, use %openfile and %closefile to store the text
for that section in temporary buffers. Then, to write (append) the buffer contents to a file
section, call LibSetSourceFileSection, passing in the desired section tag and file
reference. For example, the following code uses two buffers (typesBuf and tmpBuf) to
generate two sections (tagged "Includes" and "Functions") of the source file
timestwo.c or .cpp (referenced as cFile):
%openfile typesBuf
39-75
39 Code Appearance in Embedded Coder
#include "rtwtypes.h"
%closefile typesBuf
%<LibSetSourceFileSection(cFile,"Includes",typesBuf)>
%openfile tmpBuf
%closefile tmpBuf
%<LibSetSourceFileSection(cFile,"Functions",tmpBuf)>
#include "rtwtypes.h"
The timestwo.c or .cpp file generated in the previous example was independent of the
standard code files generated from a model (for example, model.c or .cpp, model.h,
and so on). You can use similar techniques to generate custom code within the model
files. The code template API includes functions to obtain the names of the standard
models files and other model-related information. The following excerpt calls
LibGetMdlPubHdrBaseName to obtain the name for the model.h file. It then obtains a
file reference and generates a definition in the Defines section of model.h:
%% Add a #define to the model's public header file model.h
%openfile tmpBuf
39-76
Generate Source and Header Files with a Custom File Processing (CFP) Template
%closefile tmpBuf
%<LibSetSourceFileSection(modelH,"Defines",tmpBuf)>
Examine the generated rtwdemo_udt.h file to see the generated #define directive.
Normally, the ERT target determines whether and how to generate an ert_main.c
or .cpp module based on the settings of the Generate an example main program and
Target operating system options on the Templates pane of the Configuration
Parameters dialog box. You can use a CFP template to override the normal behavior and
generate a main program module customized for your target environment.
To support generation of main program modules, two TLC files are provided:
When generating your own main program module, you disable the default generation of
ert_main.c or .cpp. The TLC variable GenerateSampleERTMain controls generation
of ert_main.c or .cpp. You can directly force this variable to TLC_FALSE. The examples
bareboard_mrmain.tlc and bareboard_srmain.tlc use this technique, as shown in
the following excerpt from bareboard_srmain.tlc.
39-77
39 Code Appearance in Embedded Coder
%if GenerateSampleERTMain
%assign CompiledModel.GenerateSampleERTMain = TLC_FALSE
%warning Overriding example ert_main.c!
%endif
See the “rtwgensettings Structure” (Simulink Coder) section for information on creating a
SelectCallback function.
The following code illustrates how to deselect and disable the Generate an example
main program option in the context of a SelectCallback function.
Note Creation of a main program for your target environment requires some
customization; for example, in a bareboard environment you need to attach rt_OneStep
to a timer interrupt. It is expected that you will customize either the generated code, the
generating TLC code, or both. See “Guidelines for Modifying the Main Program” on page
52-4 and “Guidelines for Modifying rt_OneStep” on page 52-9 for further
information.
• Add a custom token to the code insertion section of your CGT file.
• In your CFP file:
39-78
Generate Source and Header Files with a Custom File Processing (CFP) Template
The following code examples illustrate the addition of a custom token, Myincludes, to a
CGT file, and the subsequent association of the custom section Myincludes with the
built-in section Includes in a CFP file.
Note If you have not already created custom CGT and CFP files for your model, copy the
default template files matlabroot/toolbox/rtw/targets/ecoder/
ert_code_template.cgt and matlabroot/toolbox/rtw/targets/ecoder/
example_file_process.tlc to a work folder that is outside the MATLAB folder
structure but on the MATLAB or TLC path, rename them (for example, add the prefix
test_ to each file), and update the Templates pane of the Configuration Parameters
dialog box to reference them.
First, add the token Myincludes to the code insertion section of your CGT file. For
example:
%<Includes>
%<Myincludes>
%<Defines>
%<Types>
%<Enums>
%<Definitions>
%<Declarations>
%<Functions>
Next, in the CFP file, add code to generate include directives into a buffer. For example,
in your copy of the example CFP file, you could insert the following section between the
Includes section and the Create a simple main section:
%openfile tmpBuf
#include "moretables1.h"
#include "moretables2.h"
%closefile tmpBuf
39-79
39 Code Appearance in Embedded Coder
%<LibAddSourceFileCustomSection(modelC,"Includes","Myincludes")>
%<LibSetSourceFileCustomSection(modelC,"Myincludes",tmpBuf)>
In the generated code, the include directives generated to the custom section appear
after other code directed to Includes.
#include "rtwdemo_udt.h"
#include "rtwdemo_udt_private.h"
/* #include "mytables.h" */
#include "moretables1.h"
#include "moretables2.h"
Note The placement of the custom token in this example CGT file is arbitrary. By locating
%<Myincludes> after %<Includes>, the CGT file specifies only that the Myincludes
code appears after Includes code.
Custom Tokens
Custom tokens are automatically translated to TLC syntax as a part of the build process.
To escape a token, that is to prepare it for normal TLC expansion, use the '!' character.
For example, the token %<!TokenName> is expanded to %<TokenName> by the template
conversion program. You can specify valid TLC code, including TLC function calls: %<!
MyTLCFcn()>.
39-80
Comparison of a Template and Its Generated File
• Define what code the code generation software should add to the generated file
• Control the location of code in the file
• Optionally insert comments in the generated file
Notice %<Includes>, for example, on the template. The term Includes is a symbol
name. A percent sign and brackets (%< >) must enclose every symbol name. You can add
the desired symbol name (within the %< > delimiter) at a particular location in the
template. This is how you control where the code generator places an item in the
generated file.
39-81
39 Code Appearance in Embedded Coder
39-82
Comparison of a Template and Its Generated File
39-83
39 Code Appearance in Embedded Coder
For a list of template symbols and the rules for using them, see “Template Symbol
Groups” on page 39-98, “Template Symbols” on page 39-101, and “Rules for Modifying
or Creating a Template” on page 39-104. To set comment options, from the Simulation
menu, select Model Configuration Parameters. On the Configuration Parameters
dialog box, select the Code Generation > Comments pane. For details, see “Configure
Code Comments” (Simulink Coder).
39-84
Code Template API Summary
39-85
39 Code Appearance in Embedded Coder
Function Description
LibClearFileSectionContents Clears a file section with custom values
before writing file to disk.
LibGetNumSourceFiles Returns the number of created source files
(.c or .cpp and .h).
LibGetSourceFileTag Returns <filename>_h and <filename>_c
for header and source files, respectively,
where filename is the name of the model
file.
LibCreateSourceFile Creates a new C or C++ file and returns its
reference. If the file already exists, simply
returns its reference.
LibGetFileRecordName Returns a model file name (including the
path) without the extension.
LibGetSourceFileFromIdx Returns a model file reference based on its
index. This is useful for a common operation
on all files, such as to set the leading file
banner of all files.
LibSetSourceFileSection Adds to the contents of a specified section
within a specified file (see also “Custom File
Processing (CFP) Template Structure” on
page 39-66).
LibIndentSourceFile Indents a file (from within the TLC
environment).
LibCallModelInitialize Returns code for calling the model's
model_initialize function (valid for ERT
only).
LibCallModelStep Returns code for calling the model's
model_step function (valid for ERT only).
LibCallModelTerminate Returns code for calling the model's
model_terminate function (valid for ERT
only).
39-86
Code Template API Summary
Function Description
LibCallSetEventForThisBaseStep Returns code for calling the model's set
events function (valid for ERT only).
LibWriteModelData Returns data for the model (valid for ERT
only).
LibSetRTModelErrorStatus Returns the code to set the model error
status.
LibGetRTModelErrorStatus Returns the code to get the model error
status.
LibIsSingleRateModel Returns true if model is single rate and false
otherwise.
LibGetModelName Returns name of the model (without an
extension).
LibGetMdlSrcBaseName Returns the name of model's main source file
(for example, model.c or .cpp).
LibGetMdlPubHdrBaseName Returns the name of model's public header
file (for example, model.h).
LibGetMdlPrvHdrBaseName Returns the name of the model's private
header file (for example,
model_private.h).
LibIsSingleTasking Returns true if the model is configured for
single-tasking execution.
LibWriteModelInput Returns the code to write to a particular root
input (that is, a model inport block). (valid
for ERT only).
LibWriteModelOutput Returns the code to write to a particular root
output (that is, a model outport block). (valid
for ERT only).
LibWriteModelInputs Returns the code to write to root inputs (that
is, all model inport blocks). (valid for ERT
only)
LibWriteModelOutputs Returns the code to write to root outputs
(that is, all model outport blocks). (valid for
ERT only).
39-87
39 Code Appearance in Embedded Coder
Function Description
LibNumDiscreteSampleTimes Returns the number of discrete sample times
in the model.
LibSetSourceFileCodeTemplate Set the code template to be used for
generating a specified source file.
LibSetSourceFileOutputDirectory Set the folder into which a specified source
file is to be generated.
LibAddSourceFileCustomSection Add a custom section to a source file. The
custom section must be associated with one
of the built-in (required) sections:
Includes, Defines, Types, Enums,
Definitions, Declarations, or
Functions.
LibSetSourceFileCustomSection Adds to the contents of a specified custom
section within a specified file. The custom
section must have been previously created
with LibAddSourceFileCustomSection.
39-88
Generate Custom File and Function Banners
To specify banners, create a custom CGT file with customized banner sections. The build
process creates an executable TLC file from the CGT file. The code generation process
then invokes the TLC file.
You do not need to be familiar with TLC programming to generate custom banners. You
can modify example files that are supplied with the ERT target.
Note Prior releases supported direct use of customized TLC files as banner templates.
You specified these with the Source file (.c) banner template and Header file (.h)
banner template options of the ERT target. You can still use a custom TLC file banner
template, however, you can now use CGT files instead.
ERT template options on the Code Generation > Templates pane of a configuration set,
in the Code templates section, support banner generation.
• “Code templates: Source file (*.c) template”: CGT file to use when generating source
(.c or .cpp) files. Place this file on the MATLAB path.
• “Code templates: Header file (*.h) template”: CGT file to use when generating header
(.h) files. You must place this file on the MATLAB path. This file can be the same
template specified in the Code templates: Source file (*.c) template field, in which
case identical banners are generated in source and header files.
By default, the template for both source and header files is matlabroot/
toolbox/rtw/targets/ecoder/ert_code_template.cgt.
• In each of these fields, click Browse to navigate to and select an existing CGT file for
use as a template. Click Edit to open the specified file into the MATLAB editor, where
you can customize it.
39-89
39 Code Appearance in Embedded Coder
39-90
Generate Custom File and Function Banners
Components of the File and Function Banner Sections in the CGT file
In a CGT file, you can modify the following sections: file banner, function banner, shared
utility function banner, and file trailer. Each section is defined by open and close tags. The
tags specific to each section are shown in the following table.
You can customize your banners by including tokens and comments between the open and
close tag for each section. Tokens are typically TLC variables, for example
<ModelVersion>, which are replaced with values in the generated code.
Note Including C comment indicators, '/*' or a '*/', in the contents of your banner might
introduce an error in the generated code.
An open tag includes tag attributes. Enclose the value of the attribute in double quotes.
The attributes available for an open tag are:
• width: specifies the width of the file or function banner comments in the generated
code. The default value is 80.
• style: specifies the boundary for the file or function banner comments in the
generated code.
39-91
39 Code Appearance in Embedded Coder
Note If the Configuration Parameters > Code Generation > Language parameter is
set to C++, to select a comment style that uses C comment notation (/*...*/), you must
also set the Configuration Parameters > Comments > Comment style parameter to
Multi-line.
• classic
/**********************************************************/
/* banner contents */
/**********************************************************/
• box_cpp
////////////////////////////////////////////////////////////
// banner contents //
////////////////////////////////////////////////////////////
• open_box
/**********************************************************
* banner contents
**********************************************************/
• open_box_cpp
39-92
Generate Custom File and Function Banners
////////////////////////////////////////////////////////////
// banner contents
////////////////////////////////////////////////////////////
• doxygen
/**
* multiple line comments
* second line
*/
• doxygen_cpp
///
/// multiple line comments
/// second line
///
• doxygen_qt
/*!
* multiple line comments
* second line
*/
• doxygen_qt_cpp
//!
//! multiple line comments
//! second line
//!
File Banner
This section contains comments and tokens for use in generating a custom file banner.
The file banner precedes C or C++ code generated by the model. If you omit the file
banner section from the CGT file, then no file banner emits to the generated code.
39-93
39 Code Appearance in Embedded Coder
Note If you customize your file banner, the software does not emit the customized banner
for the file const_params.c.
The following section is the file banner section provided with the default CGT file,
matlabroot/toolbox/rtw/targets/ecoder/ert_code_template.cgt.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Custom file banner section (optional)
%%
<FileBanner style="classic">
File: %<FileName>
39-94
Generate Custom File and Function Banners
Function Banner
This section contains comments and tokens for use in generating a custom function
banner. The function banner precedes C or C++ function generated during the build
process. If you omit the function banner section from the CGT file, the default function
banner emits to the generated code. The following section is the default function banner
section provided with the default CGT file, matlabroot/toolbox/rtw/targets/
ecoder/ert_code_template.cgt.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Custom function banner section (optional)
%% Customize function banners by using the following predefined tokens:
%% %<ModelName>, %<FunctionName>, %<FunctionDescription>, %<Arguments>,
%% %<ReturnType>, %<GeneratedFor>, %<BlockDescription>.
%%
<FunctionBanner style="classic">
%<FunctionDescription>
%<BlockDescription>
</FunctionBanner>
The shared utility function banner section contains comments and tokens for use in
generating a custom shared utility function banner. The shared utility function banner
39-95
39 Code Appearance in Embedded Coder
precedes C or C++ shared utility function generated during the build process. If you omit
the shared utility function banner section from the CGT file, the default shared utility
function banner emits to the generated code. The following section is the default shared
utility function banner section provided with the default CGT file, matlabroot/
toolbox/rtw/targets/ecoder/ert_code_template.cgt.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Custom shared utility function banner section (optional)
%% Customize banners for functions generated in shared location by using the
%% following predefined tokens: %<FunctionName>, %<FunctionDescription>,
%% %<Arguments>, %<ReturnType>.
%%
<SharedUtilityBanner style="classic">
%<FunctionDescription>
</SharedUtilityBanner>
File Trailer
The file trailer section contains comments for generating a custom file trailer. The file
trailer follows C or C++ code generated from the model. If you omit the file trailer
section from the CGT file, no file trailer emits to the generated code. The following
section is the default file trailer provided in the default CGT file.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Custom file trailer section (optional)
%%
<FileTrailer style="classic">
File trailer for generated code.
[EOF]
</FileTrailer>
Tokens available for the file banner are available for the file trailer. See Summary of
Tokens for File Banner Generation.
39-96
Template Symbols and Rules
Introduction
“Template Symbol Groups” on page 39-98 and “Template Symbols” on page 39-101
describe custom file processing (CFP) template symbols and rules for using them. The
location of a symbol in one of the supplied template files (code_c_template.cgt,
code_h_template.cgt, data_c_template.cgt, or data_h_template.cgt)
determines where the items associated with that symbol are located in the corresponding
generated file. “Template Symbol Groups” on page 39-98 identifies the symbol groups,
starting with the parent (“Base”) group, followed by the children of each parent.
“Template Symbols” on page 39-101 lists the symbols alphabetically.
Note If you are using custom CGT sections, for files generated to the _sharedutils
folder, you can only use symbol names in the Base symbol group.
39-97
39 Code Appearance in Embedded Coder
Defines
Definitions
Documentation
Enums
Functions
Includes
Types
Declarations ExternalCalibrationLookup1D
ExternalCalibrationLookup2D
ExternalCalibrationScalar
ExternalVariableScalar
Defines LocalDefines
LocalMacros
39-98
Template Symbols and Rules
FilescopeCalibrationLookup2D
FilescopeCalibrationScalar
FilescopeVariableScalar
GlobalCalibrationLookup1D
GlobalCalibrationLookup2D
GlobalCalibrationScalar
GlobalVariableScalar
39-99
39 Code Appearance in Embedded Coder
Banner
Created
Creator
Date
Description
FileName
History
LastModifiedDate
LastModifiedBy
ModelName
ModelVersion
ModifiedBy
ModifiedComment
ModifiedHistory
Notes
ToolVersion
Functions CFunctionCode
Types This parent has no children.
39-100
Template Symbols and Rules
Template Symbols
Symbol Name* Symbol Group Symbol Symbol Description (What
Scope the symbol puts in the
generated file)
Abstract Documentation N/A User-supplied description of the
model or file. Placed in the
generated file based on the
Stateflow note, Simulink
annotation, or DocBlock on the
model.**
Banner Documentation N/A Comments located near top of
the file. Contains information
that includes model and
software versions, and date file
was generated.
CFunctionCode Functions File C/C++ functions. Must be at
the bottom of the template.
Created Documentation N/A Date when model was created.
From Created on field on
Model Properties dialog box.
Creator Documentation N/A User who created model. From
Created by field on Model
Properties dialog box.
Date Documentation N/A Date file was generated. Taken
from computer clock.
Declarations Base Data declaration of a signal or
parameter. For example,
extern real_T globalvar;.
Defines Base File Required #defines of .h files.
Definitions Base File Data definitions of signals or
parameters.
Description Documentation N/A Description of model. From
Model description field on
Model Properties dialog box.**
39-101
39 Code Appearance in Embedded Coder
39-102
Template Symbols and Rules
39-103
39 Code Appearance in Embedded Coder
* Symbol names must be enclosed between %< >. For example, %<Functions>.
** This symbol can be used to add a comment to the generated files. See “Add Global
Comments” on page 39-8. The code generator places the comment in each generated file
whose template has this symbol name. The code generator places the comment at the
location that corresponds to where the symbol name is located in the template file.
*** The description can be deduced from the symbol name. For example,
GlobalCalibrationScalar is a symbol that identifies a scalar. It contains data of
global scope that you can calibrate.
1 Place a symbol on a template within the %< > delimiter. For example, the symbol
named Includes should look like this on a template: %<Includes>. Note that
symbol names are case-sensitive.
2 Place a symbol on a template where desired. Its location on the template determines
where the item associated with this symbol is located in the generated file. If no item
is associated with it, the symbol is ignored.
3 Place a C/C++ statement outside of the %< > delimiter, and on a different line than a
%< > delimiter, for that statement to appear in the generated file. For example,
#pragma message ("my text") in the template results in #pragma message
("my text") at the corresponding location in the generated file. Note that the
statement must be compatible with your C/C++ compiler.
4 Use the .cgt extension for every template filename. ("cgt" stands for code
generation template.)
39-104
Template Symbols and Rules
39-105
39 Code Appearance in Embedded Coder
Polyspace might highlight overflows for certain operations that are legitimate because of
the way the code generator implements these operations. Consider the following model
and the corresponding generated code.
The code generator recognizes that the largest built-in data type is 32-bit. It is not
possible to saturate the results of the additions and subtractions using MIN_INT32 and
MAX_INT32 and a bigger single-word integer data type. Instead the software detects the
results overflow and the direction of the overflow, and saturates the result.
If you do not provide justification for the addition operator on line 36, Polyspace
verification generates an orange check that indicates a potential overflow. The verification
does not take into account the saturation function of lines 37 to 43. In addition, the trace-
back functionality of Polyspace Code Prover does not identify the reason for the orange
check.
39-106
See Also
The code generator annotates generated code with comments for Polyspace. For example:
When you run a verification using Polyspace Code Prover, the Polyspace software uses the
annotations to justify the operator-related orange checks and assigns the Not a defect
classification to the checks.
See Also
Related Examples
• “Run Polyspace Analysis on Code Generated with Embedded Coder” (Polyspace Bug
Finder)
39-107
39 Code Appearance in Embedded Coder
39-108
Enhance Readability of Code for Flow Charts
if (modelname_U.In1 == 1.0) {
/* Transition: '<S1>:11' */
/* Transition: '<S1>:12' */
modelname_Y.Out1 = 10.0;
/* Transition: '<S1>:15' */
/* Transition: '<S1>:16' */
} else {
/* Transition: '<S1>:10' */
if (modelname_U.In1 == 2.0) {
/* Transition: '<S1>:13' */
/* Transition: '<S1>:14' */
modelname_Y.Out1 = 20.0;
/* Transition: '<S1>:16' */
} else {
/* Transition: '<S1>:17' */
modelname_Y.Out1 = 30.0;
}
}
39-109
39 Code Appearance in Embedded Coder
/* Transition: '<S1>:39' */
}
39-110
Enhance Readability of Code for Flow Charts
if (modelname_U.In1 == 1.0) {
/* Transition: '<S1>:149' */
/* Transition: '<S1>:150' */
modelname_Y.Out1 = 1.0;
/* Transition: '<S1>:151' */
/* Transition: '<S1>:152' */
/* Transition: '<S1>:158' */
/* Transition: '<S1>:159' */
} else {
/* Transition: '<S1>:156' */
if (modelname_U.In1 == 2.0) {
/* Transition: '<S1>:153' */
/* Transition: '<S1>:154' */
modelname_Y.Out1 = 2.0;
/* Transition: '<S1>:155' */
/* Transition: '<S1>:158' */
/* Transition: '<S1>:159' */
} else {
/* Transition: '<S1>:161' */
modelname_Y.Out1 = 3.0;
}
}
The following procedure describes how to convert generated code for the flow chart from
if-elseif-else to switch-case statements.
39-111
39 Code Appearance in Embedded Coder
Rules of Conversion
For the conversion to occur, the following rules must hold. LHS and RHS refer to the left-
hand side and right-hand side of a condition, respectively.
39-112
Enhance Readability of Code for Flow Charts
For example, the LHS can read from but not write to global variables.
Each RHS Must be a constant or a parameter.
Must have an integer or enumerated data type.
If a flow chart has duplicate conditions, the conversion preserves only the first condition.
The code discards the other instances of duplicate conditions.
After removal of duplicates, two or more unique conditions must exist. If not, the
conversion does not occur and the code contains all duplicate conditions.
39-113
39 Code Appearance in Embedded Coder
The MATLAB functions in the chart contain the code in the following table. In each case,
the Function Inline Option is Auto. For more information about function inlining, see
“Specify Graphical Function Properties” (Stateflow).
39-114
Enhance Readability of Code for Flow Charts
traffic_speed = 0;
slowdown function slowdown
%#codegen
coder.extrinsic('disp')
disp('Slowing down.')
traffic_speed = 1;
accelerate function accelerate
%#codegen
coder.extrinsic('disp');
disp('Moving along.')
traffic_speed = 2;
light function color = light(x)
%#codegen
if (x < 20)
color = TrafficLights.GREEN;
elseif (x >= 20 && x < 25)
color = TrafficLights.YELLOW;
else
color = TrafficLights.RED;
end
The output color of the function light uses the enumerated type TrafficLights. The
enumerated type definition in TrafficLights.m is:
39-115
39 Code Appearance in Embedded Coder
Check that the flow chart in your chart follows the rules in “Rules of Conversion” on page
39-112.
• [light(intersection) == RED]
• [light(intersection) == YELLOW]
Each condition Each condition:
• Tests equality
• Uses the same function call light(intersection) for the LHS
Each LHS Each LHS:
39-116
Enhance Readability of Code for Flow Charts
Tip This conversion works on a per-model basis. If you select this check box, the
conversion applies to:
In the model, select Code > C/C++ Code > Build Model to generate source code from
the model.
The generated code for the flow chart appears something like this:
if (sf_color == RED) {
/* Transition: '<S1>:11' */
/* Transition: '<S1>:12' */
/* MATLAB Function 'stop': '<S1>:23' */
/* '<S1>:23:6' */
rtb_traffic_speed = 0;
/* Transition: '<S1>:15' */
/* Transition: '<S1>:16' */
} else {
/* Transition: '<S1>:10' */
/* MATLAB Function 'light': '<S1>:19' */
if (ifelse_using_enums_U.In1 < 20.0) {
/* '<S1>:19:3' */
/* '<S1>:19:4' */
sf_color = GREEN;
} else if ((ifelse_using_enums_U.In1 >= 20.0) &&
(ifelse_using_enums_U.In1 < 25.0)) {
/* '<S1>:19:5' */
/* '<S1>:19:6' */
sf_color = YELLOW;
} else {
/* '<S1>:19:8' */
sf_color = RED;
}
if (sf_color == YELLOW) {
39-117
39 Code Appearance in Embedded Coder
/* Transition: '<S1>:13' */
/* Transition: '<S1>:14' */
/* MATLAB Function 'slowdown': '<S1>:24' */
/* '<S1>:24:6' */
rtb_traffic_speed = 1;
/* Transition: '<S1>:16' */
} else {
/* Transition: '<S1>:17' */
/* MATLAB Function 'accelerate': '<S1>:25' */
/* '<S1>:25:6' */
rtb_traffic_speed = 2;
}
}
Because the MATLAB function light appears inlined, inequality comparisons appear in
these lines of code:
Because inequalities appear in the body of the if-elseif-else code for the flow chart,
the conversion to switch-case statements does not occur. To prevent this behavior, do
one of the following:
• Specify that the function light does not appear inlined. See “Change the Inlining
Property for the Function” on page 39-118.
• Modify the flow chart. See “Modify the Flow Chart to Ensure Switch-Case Statements”
on page 39-120.
If you do not want to modify your flow chart, change the inlining property for the function
light:
39-118
Enhance Readability of Code for Flow Charts
Note You do not have to change the inlining property for the other three MATLAB
functions in the chart. Because the flow chart does not call those functions during
evaluation of conditions, the inlining property for those functions can remain Auto.
When you regenerate code for your model, the code for the flow chart now appears
something like this:
switch (ifelse_using_enums_light(ifelse_using_enums_U.In1)) {
case RED:
/* Transition: '<S1>:11' */
/* Transition: '<S1>:12' */
/* MATLAB Function 'stop': '<S1>:23' */
/* '<S1>:23:6' */
ifelse_using_enums_Y.Out1 = 0.0;
/* Transition: '<S1>:15' */
/* Transition: '<S1>:16' */
break;
case YELLOW:
/* Transition: '<S1>:10' */
/* Transition: '<S1>:13' */
/* Transition: '<S1>:14' */
/* MATLAB Function 'slowdown': '<S1>:24' */
/* '<S1>:24:6' */
ifelse_using_enums_Y.Out1 = 1.0;
/* Transition: '<S1>:16' */
break;
default:
/* Transition: '<S1>:17' */
/* MATLAB Function 'accelerate': '<S1>:25' */
/* '<S1>:25:6' */
ifelse_using_enums_Y.Out1 = 2.0;
break;
}
39-119
39 Code Appearance in Embedded Coder
Because the MATLAB function light no longer appears inlined, the conversion to
switch-case statements occurs. The switch-case statements provide the following
benefits to enhance readability:
If you do not want to change the inlining property for the function light, modify your
flow chart:
1 Add chart local data color_out with the enumerated type TrafficLights.
2 Replace each instance of light(intersection) with color_out.
3 Add the action {color_out = light(intersection)} to the default transition of
the flow chart.
39-120
Enhance Readability of Code for Flow Charts
When you regenerate code for your model, the code for the flow chart uses switch-case
statements.
39-121
39 Code Appearance in Embedded Coder
The Inline setting explicitly directs the code generator to inline the subsystem code
unconditionally.
The default Auto setting directs the code generator to generate the most efficient code
for the subsystem based on the type and number of instances of the subsystem that exist
in the model. When there is only one instance of a subsystem, the Auto setting inlines the
subsystem code. When there are multiple instances of a subsystem, that is not too
complex, the Auto setting inlines the code for each subsystem. Otherwise, the Auto
setting generates a single copy of the function (as a reusable function). For a function-call
subsystem with multiple callers, the Auto setting generates subsystem code that is
consistent with the Nonreusable function setting.
When you generate code from your model, the code generator inlines subsystem code
within model.c or model.cpp (or in its parent system's source file). You can identify this
code by system/block identification tags, such as:
/* Atomic SubSystem Block: <Root>/AtomicSubsys1 */
39-122
Generate Inlined Subsystem Code
Exceptions to Inlining
There are certain cases in which the code generator does not inline a nonvirtual
subsystem, even though you select the Inline setting.
See Also
• “Control Generation of Subsystem Functions” (Simulink Coder)
• “Generate Subsystem Code as Separate Function and Files” (Simulink Coder)
• “Generate Reentrant Code from Subsystems” (Simulink Coder)
39-123
40
• Optimization for a specific run-time environment, including, but not limited to, specific
target hardware.
• Integration with existing application code.
• Compliance with a standard, such as AUTOSAR.
• Modification of code behavior, such as enabling or disabling nonfinite or inline
support.
• Application- or project-specific code requirements, such as:
• Elimination of math.h.
• Elimination of system header files.
• Elimination of calls to memcpy or memset.
• Use of BLAS.
• Use of a specific BLAS.
To apply this technique, configure the code generator to apply a code replacement library
(CRL) during code generation. By default, the code generator does not apply a code
replacement library. You can choose from libraries that MathWorks provides and that you
create and register by using the Embedded Coder product. The list of available libraries
depends on:
Libraries that include GNU99 extensions are intended for use with the GCC compiler. If
you use one of those libraries with another compiler, generated code might not compile.
40-2
What Is Code Replacement?
a specific embedded processor specifies function and operator replacements that optimize
generated code for that processor.
A code replacement table contains one or more code replacement entries, with each entry
representing a potential replacement for a function or operator. Each entry maps a
conceptual representation of a function or operator to an implementation representation
and priority.
40-3
40 Code Replacement in Simulink Coder
When the code generator looks for a match in a code replacement library, it creates and
populates a call site object with the function or operator conceptual representation. If a
match exists, the code generator uses the matched code replacement entry populated
with the implementation representation and uses it to generate code.
The code generator searches the tables in a code replacement library for a match in the
order that the tables appear in the library. If the code generator finds multiple matches
within a table, the priority determines the match. The code generator uses a higher-
priority entry over a similar entry with a lower priority.
40-4
What Is Code Replacement?
Term Definition
Call site object Conceptual representation of a function or operator
that the code generator uses when it encounters a
call site for a function or operator. The code
generator uses the object to query the code
replacement library for a conceptual representation
match. If a match exists, the code generator returns
a code replacement object, fully populated with the
conceptual representation, implementation
representation, and priority, and uses that object to
generate replacement code.
Code replacement library One or more code replacement tables that specify
application-specific implementations of functions
and operators. When configured to use a code
replacement library, the code generator uses
criteria defined in the library to search for matches.
If a match is found, the code generator replaces
code that it generates by default with application-
specific code defined in the library.
Code replacement table One or more code replacement table entries.
Provides a way to group related or shared entries
for use in different libraries.
Code replacement entry Represents a potential replacement for a function
or operator. Maps a conceptual representation of a
function or operator to an implementation
representation and priority.
Conceptual argument Represents an input or output argument for a
function or operator being replaced. Conceptual
arguments observe naming conventions ('y1',
'u1', 'u2', ...) and data types familiar to the code
generator.
40-5
40 Code Replacement in Simulink Coder
Term Definition
Conceptual representation Represents match criteria that the code generator
uses to qualify functions and operators for
replacement. Consists of:
40-6
See Also
Term Definition
Priority Defines the match priority for a code replacement
entry relative to other entries, which have the same
name and conceptual argument list, within a code
replacement library. The priority can range from 0
to 100, with 0 being the highest priority. The default
is 100. If a library provides two implementations for
a function or operator, the implementation with the
higher priority shadows the one with the lower
priority.
Code replacement for matrices — Code replacement libraries do not support Dynamic and
Symbolic sized matrices.
See Also
Related Examples
• “Choose a Code Replacement Library” (Simulink Coder)
• “Replace Code Generated from Simulink Models” (Simulink Coder)
40-7
40 Code Replacement in Simulink Coder
1 Explore available libraries. Identify one that best meets your application needs.
• Consider the lists of application code replacement requirements and libraries that
MathWorks provides in “What Is Code Replacement?” on page 41-2.
• See “Explore Available Code Replacement Libraries” on page 40-8.
2 Explore the contents of the library. See “Explore Code Replacement Library
Contents” on page 40-8.
If you do not find a suitable library and you have an Embedded Coder license, you can
create a custom code replacement library.
40-8
See Also
>> crviewer
The viewer opens. To view the content of a specific library, specify the name of the
library as an argument in single quotes. For example:
>> crviewer('GNU C99 extensions')
2 In the left pane, select the name of a library. The viewer displays information about
the library in the right pane.
3 In the left pane, expand the library, explore the list of tables it contains, and select a
table from the list. In the middle pane, the viewer displays the function and operator
entries that are in that table, along with abbreviated information for each entry.
4 In the middle pane, select a function or operator. The viewer displays information
from the table entry in the right pane.
If you select an operator entry that specifies net slope fixed-point parameters
(instantiated from entry class RTW.TflCOperationEntryGenerator or
RTW.TflCOperationEntryGenerator_NetSlope), the viewer displays an
additional tab that shows fixed-point settings.
See Code Replacement Viewer for details on what the viewer displays.
See Also
Related Examples
• “What Is Code Replacement?” (Simulink Coder)
• “Replace Code Generated from Simulink Models” (Simulink Coder)
40-9
40 Code Replacement in Simulink Coder
1 Make sure that MATLAB, Simulink, Simulink Coder, and a C compiler are installed on
your system. Some code replacement libraries available in your development
environment can also require Embedded Coder.
If you are not sure which library to use, explore the available libraries.
1 Configure the code generator to apply a code replacement library during code
generation for the model. Do one of the following:
• In the Configuration Parameters dialog box, on the Code Generation pane, select
“Generate code only” (Simulink Coder).
• Set the GenCodeOnly parameter at the command line or programmatically.
40-10
See Also
If you have an Embedded Coder license, you can configure the code generator to include
a code replacement section in the code generation report. The additional information can
help you verify code replacements.
Generate C/C++ code from the model and, if you configured the code generator
accordingly, a code generation report. For example, in the model window, press Ctrl+B.
The code generator produces the code and displays the report.
Verify code replacements by examining the generated code. It is possible that code
replacement behaves differently than you expect. For example, data types that you
observe in the code generator input might not match what the code generator uses as
intermediate data types during an operation.
See Also
Related Examples
• “What Is Code Replacement?” (Simulink Coder)
• “Choose a Code Replacement Library” (Simulink Coder)
• “Code Generation Configuration” (Simulink Coder)
40-11
41
• Optimization for a specific run-time environment, including, but not limited to, specific
target hardware.
• Integration with existing application code.
• Compliance with a standard, such as AUTOSAR.
• Modification of code behavior, such as enabling or disabling nonfinite or inline
support.
• Application- or project-specific code requirements, such as:
• Elimination of math.h.
• Elimination of system header files.
• Elimination of calls to memcpy or memset.
• Use of BLAS.
• Use of a specific BLAS.
To apply this technique, configure the code generator to apply a code replacement library
(CRL) during code generation. By default, the code generator does not apply a code
replacement library. You can choose from libraries that MathWorks provides and that you
create and register by using the Embedded Coder product. The list of available libraries
depends on:
Libraries that include GNU99 extensions are intended for use with the GCC compiler. If
you use one of those libraries with another compiler, generated code might not compile.
41-2
What Is Code Replacement?
a specific embedded processor specifies function and operator replacements that optimize
generated code for that processor.
A code replacement table contains one or more code replacement entries, with each entry
representing a potential replacement for a function or operator. Each entry maps a
conceptual representation of a function or operator to an implementation representation
and priority.
41-3
41 Code Replacement for Simulink Models in Embedded Coder
When the code generator looks for a match in a code replacement library, it creates and
populates a call site object with the function or operator conceptual representation. If a
match exists, the code generator uses the matched code replacement entry populated
with the implementation representation and uses it to generate code.
The code generator searches the tables in a code replacement library for a match in the
order that the tables appear in the library. If the code generator finds multiple matches
within a table, the priority determines the match. The code generator uses a higher-
priority entry over a similar entry with a lower priority.
41-4
What Is Code Replacement?
Term Definition
Call site object Conceptual representation of a function or operator
that the code generator uses when it encounters a
call site for a function or operator. The code
generator uses the object to query the code
replacement library for a conceptual representation
match. If a match exists, the code generator returns
a code replacement object, fully populated with the
conceptual representation, implementation
representation, and priority, and uses that object to
generate replacement code.
Code replacement library One or more code replacement tables that specify
application-specific implementations of functions
and operators. When configured to use a code
replacement library, the code generator uses
criteria defined in the library to search for matches.
If a match is found, the code generator replaces
code that it generates by default with application-
specific code defined in the library.
Code replacement table One or more code replacement table entries.
Provides a way to group related or shared entries
for use in different libraries.
Code replacement entry Represents a potential replacement for a function
or operator. Maps a conceptual representation of a
function or operator to an implementation
representation and priority.
Conceptual argument Represents an input or output argument for a
function or operator being replaced. Conceptual
arguments observe naming conventions ('y1',
'u1', 'u2', ...) and data types familiar to the code
generator.
41-5
41 Code Replacement for Simulink Models in Embedded Coder
Term Definition
Conceptual representation Represents match criteria that the code generator
uses to qualify functions and operators for
replacement. Consists of:
41-6
See Also
Term Definition
Priority Defines the match priority for a code replacement
entry relative to other entries, which have the same
name and conceptual argument list, within a code
replacement library. The priority can range from 0
to 100, with 0 being the highest priority. The default
is 100. If a library provides two implementations for
a function or operator, the implementation with the
higher priority shadows the one with the lower
priority.
Code replacement for matrices — Code replacement libraries do not support Dynamic and
Symbolic sized matrices.
See Also
Related Examples
• “Choose a Code Replacement Library” on page 41-8
• “Replace Code Generated from Simulink Models” on page 41-10
41-7
41 Code Replacement for Simulink Models in Embedded Coder
1 Explore available libraries. Identify one that best meets your application needs.
• Consider the lists of application code replacement requirements and libraries that
MathWorks provides in “What Is Code Replacement?” on page 41-2.
• See “Explore Available Code Replacement Libraries” on page 41-8.
2 Explore the contents of the library. See “Explore Code Replacement Library
Contents” on page 41-8.
If you do not find a suitable library and you have an Embedded Coder license, you can
create a custom code replacement library.
41-8
See Also
>> crviewer
The viewer opens. To view the content of a specific library, specify the name of the
library as an argument in single quotes. For example:
>> crviewer('GNU C99 extensions')
2 In the left pane, select the name of a library. The viewer displays information about
the library in the right pane.
3 In the left pane, expand the library, explore the list of tables it contains, and select a
table from the list. In the middle pane, the viewer displays the function and operator
entries that are in that table, along with abbreviated information for each entry.
4 In the middle pane, select a function or operator. The viewer displays information
from the table entry in the right pane.
If you select an operator entry that specifies net slope fixed-point parameters
(instantiated from entry class RTW.TflCOperationEntryGenerator or
RTW.TflCOperationEntryGenerator_NetSlope), the viewer displays an
additional tab that shows fixed-point settings.
See Code Replacement Viewer for details on what the viewer displays.
See Also
Related Examples
• “What Is Code Replacement?” on page 41-2
• “Replace Code Generated from Simulink Models” on page 41-10
41-9
41 Code Replacement for Simulink Models in Embedded Coder
1 Make sure that MATLAB, Simulink, Simulink Coder, and a C compiler are installed on
your system. Some code replacement libraries available in your development
environment can also require Embedded Coder.
If you are not sure which library to use, explore the available libraries.
1 Configure the code generator to apply a code replacement library during code
generation for the model. Do one of the following:
• In the Configuration Parameters dialog box, on the Code Generation pane, select
“Generate code only” (Simulink Coder).
• Set the GenCodeOnly parameter at the command line or programmatically.
41-10
See Also
If you have an Embedded Coder license, you can configure the code generator to include
a code replacement section in the code generation report. The additional information can
help you verify code replacements.
Generate C/C++ code from the model and, if you configured the code generator
accordingly, a code generation report. For example, in the model window, press Ctrl+B.
The code generator produces the code and displays the report.
Verify code replacements by examining the generated code. It is possible that code
replacement behaves differently than you expect. For example, data types that you
observe in the code generator input might not match what the code generator uses as
intermediate data types during an operation.
See Also
Related Examples
• “What Is Code Replacement?” on page 41-2
• “Choose a Code Replacement Library” on page 41-8
• “Code Generation Configuration” (Simulink Coder)
41-11
Deployment
13
42
The code generator includes multiple approaches for integrating legacy or custom code
with generated code. Legacy code is existing handwritten code or code for environments
that you integrate with code produced by the code generator. Custom code is legacy code
or other user-specified lines of code that you include in the code generator build process.
Collectively, legacy and custom code are called external code.
You integrate external code by importing existing external code into code produced by the
code generator, exporting generated code into an existing external code base, or you can
do both. For example, you can import code by calling an external function, by using the
Legacy Code Tool, or place external code at specific locations in generated code by
including Custom Code blocks in a model. When you import external code, the resulting
generated code interfaces with generated scheduling code.
You can export generated code as a plug-in function for use in an external development
environment. When you export generated code, you intend to interface that code
manually with a scheduling mechanism in your application run-time environment.
42-2
What Is External Code Integration?
This figure shows an application that requires integration of existing driver code for
hardware devices. The core software algorithms and logic can be a combination of code
modules for external reusable algorithms integrated into the Simulink environment and
code generated as part of an overall model design.
Several workflows and tools are available for you to integrate external and generated
code. Each workflow identifies tooling for generating code that aligns interfaces, code
appearance, and other factors, such as optimization between external and generated
code.
See Also
More About
• “Choose an External Code Integration Workflow” on page 42-4
42-3
42 External Code Integration in Simulink Coder
Completing these tasks helps you choose external code integration workflows and tooling
that align with your project.
42-4
Choose an External Code Integration Workflow
Code Deployment” on page 1-2. The first question to answer concerns which of the two
frameworks applies to your project.
Generate one set of application code files from external code and code that the
Simulink C/C++ code generator produces. The generated code includes a scheduler.
In this case, you import code into the Simulink code generation environment.
Integrate C or C++ code that the code generator produces from model components
with external application code and an external scheduler. You export generated code
from the Simulink code generation environment.
42-5
42 External Code Integration in Simulink Coder
Importing calls to external device driver code into a model and generating code for that
model for export involves importing and exporting code.
• Call reusable external algorithm code for simulation and code generation.
• Place external C/C++ code in generated code.
• Call external device drivers.
• Apply function and operator code replacements.
• Interface with external timer interrupt or scheduler.
• Generate replacement code for specific run-time environment.
42-6
Choose an External Code Integration Workflow
42-7
42 External Code Integration in Simulink Coder
42-8
Choose an External Code Integration Workflow
42-9
42 External Code Integration in Simulink Coder
Choose a Workflow
To choose a workflow for each integration point, use the following flow diagram . The
gray boxes identify common workflows and provide links to more information. Click the
gray box that best addresses the requirements of an integration point.
42-10
Choose an External Code Integration Workflow
42-11
42 External Code Integration in Simulink Coder
See Also
More About
• “Call Reusable External Algorithm Code for Simulation and Code Generation” on
page 42-13
• “Place External C/C++ Code in Generated Code” on page 42-27
• “Call External Device Drivers” on page 42-39
• “Deploy Generated Standalone Executable Programs To Target Hardware” on page
52-2
• “Deploy Generated Component Software to Application Target Platforms” on page
52-31
• “Code Replacement”
• “Generate Component Source Code for Export to External Code Base” on page 42-
52
• “Generate Shared Library for Export to External Code Base” on page 42-73
42-12
Call Reusable External Algorithm Code for Simulation and Code Generation
• Modularizing an application
• Reusing an optimized algorithm
• Interfacing with a predefined dataset
• Developing application variants
• Utility functions
• Lookup tables
• Digital filters
• Specialized integrators
• Proportional-integral-derivative (PID) control modules
Workflow
To call reusable external algorithm code for simulation and code generation, iterate
through the tasks listed in this table.
42-13
42 External Code Integration in Simulink Coder
42-14
Call Reusable External Algorithm Code for Simulation and Code Generation
To choose an approach for a reusable algorithm, see the subsection that matches the
programming language of your external algorithm code.
Multiple approaches are available for integrating external MATLAB code into the
Simulink environment. The following diagram and table help you choose the best
integration approach for your application based on integration requirements.
42-15
42 External Code Integration in Simulink Coder
42-16
Call Reusable External Algorithm Code for Simulation and Code Generation
42-17
42 External Code Integration in Simulink Coder
To embed external MATLAB code in a MATLAB Function block or generate C or C++ code
from MATLAB code with the MATLAB Coder software, the MATLAB code must use
functions and classes supported for C/C++ code generation.
• “Functions and Objects Supported for C/C++ Code Generation — Alphabetical List”
(MATLAB Coder)
• “Functions and Objects Supported for C/C++ Code Generation — Category List”
(MATLAB Coder)
Under most circumstances, you can integrate external code written in C or C++ into the
Simulink environment by generating S-functions and TLC files with the Legacy Code Tool.
This tool uses specifications that you supply as MATLAB code to transform existing
MATLAB functions into C MEX S-functions that you can include in Simulink models and
call from generated code. For details, see “Legacy Code Integration” (Simulink) and
“Import Calls to External Code into Generated Code with Legacy Code Tool” on page 11-
7.
In comparison to alternative approaches, Legacy Code Tool is the easiest to use and
generates code optimized enough for embedded systems. Consider alternative
approaches if one or more of the following conditions exist:
42-18
Call Reusable External Algorithm Code for Simulation and Code Generation
This diagram and table help you choose the best integration approach based on your
integration requirements.
42-19
42 External Code Integration in Simulink Coder
42-20
Call Reusable External Algorithm Code for Simulation and Code Generation
42-21
42 External Code Integration in Simulink Coder
42-22
Call Reusable External Algorithm Code for Simulation and Code Generation
To integrate external C code with generated C++ code or conversely, modify the language
of the external code to match the programming language choice for the generated code.
Options for making the programming language match include:
• Writing or rewriting the external code in the language choice for the generated code.
• If you are generating C++ code and the external code is C code, for each C function,
create a header file that prototypes the function. Use this format:
#ifdef __cplusplus
extern "C" {
#endif
int my_c_function_wrapper();
#ifdef __cplusplus
}
#endif
The prototype serves as a function wrapper. If your compiler supports C++ code, the
value __cplusplus is defined. The linkage specification extern "C" specifies C
linkage without name mangling.
• If you are generating C code and the external code is C++ code, include an extern
"C" linkage specification in each .cpp file. For example, the following example shows
C++ code in the file my_func.cpp:
42-23
42 External Code Integration in Simulink Coder
extern "C" {
int my_cpp_function()
{
...
}
}
To integrate external Fortran code, write an S-function and corresponding TLC file.
To integrate external code that applies only to Stateflow library charts for code
generation, for each library model that contributes a chart to your main model, complete
these steps. Then, generate code.
1 In the Stateflow Editor, select Code > C/C++ Code > Code Generation Options.
2 In the Model Configuration Parameters dialog box, select Code Generation > Use
local custom code settings (do not inherit from main model).
42-24
Call Reusable External Algorithm Code for Simulation and Code Generation
The library model retains its own custom code settings during code generation.
3 Specify your custom code in the subpanes.
Follow the guidelines in “Specify Relative Paths for Custom Code” (Stateflow).
If you specified custom code settings for simulation, you can apply these settings to
code generation. To avoid entering the same information twice, select Use the same
custom code settings as Simulation Target.
4 Click OK.
After completing these steps for each library model, generate code.
To integrate external code that applies to all charts for code generation:
1 Specify custom code options for code generation of your main model.
a In the Model Configuration Parameters dialog box, select Code Generation >
Custom Code.
b In the custom code text fields, specify your custom code.
Follow the guidelines in “Specify Relative Paths for Custom Code” (Stateflow).
If you specified custom code settings for simulation, you can apply these settings
to code generation. To avoid entering the same information twice, select Use the
same custom code settings as Simulation Target.
2 Configure code generation for each library model that contributes a chart to your
main model.
a In the Stateflow Editor, select Code > C/C++ Code > Code Generation
Options.
b In the Code Generation pane, clear the Use local custom code settings (do
not inherit from main model) check box.
The library charts inherit the custom code settings of your main model.
c Click OK.
3 Generate code.
42-25
42 External Code Integration in Simulink Coder
See Also
More About
• “Integrate C Functions Using Legacy Code Tool” (Simulink)
• “Import Calls to External Code into Generated Code with Legacy Code Tool”
(Simulink Coder)
• “Custom Code Algorithm” (Stateflow)
• “Integrate C Code Using the MATLAB Function Block” (Simulink)
• “S-Function Basics” (Simulink)
• “S-Functions and Code Generation” on page 11-2
42-26
Place External C/C++ Code in Generated Code
You can customize code that the code generator produces for a model by specifying
external code with custom code blocks or model configuration parameters.
• Place code at the start and end of the generated code for the root model.
• Place declaration, body, and exit code in generated function code for blocks in the root
model or nonvirtual subsystems.
The functions that you can augment with external code depends on the functions that the
code generator produces for blocks that are in the model. For example, if a model or
atomic subsystem includes blocks that have states, you can specify code for a disable
function. Likewise, if you need the code for a block to save data, free memory, or reset
target hardware, specify code for a terminate function. For more information, see “Block
Target File Methods” (Simulink Coder).
Workflow
To place external C or C++ code at specific locations in code that the code generator
produces for root models and subsystems, iterate through the tasks listed in this table.
42-27
42 External Code Integration in Simulink Coder
• Add blocks from the Custom Code library to a root model or atomic subsystem.
• Set model configuration parameters on the Code Generation > Custom Code pane.
The following table compares the two approaches. Choose the approach that aligns best
with your integration requirements. For more information about how to apply each
42-28
Place External C/C++ Code in Generated Code
approach, see “Integrate External Code by Using Custom Code Blocks” on page 42-30
and “Integrate External Code by Using Model Configuration Parameters” on page 42-33.
42-29
42 External Code Integration in Simulink Coder
The Custom Code block library contains blocks that you can use to place external C or C+
+ code into specific locations and functions within code that the code generator produces.
The library consists of 10 blocks that add your code to the model header (model.h) and
source (model.c or model.cpp) files that the code generator produces.
The Model Header and Model Source blocks add external code at the top and bottom of
header and source files that the code generator produces for a root model. These blocks
display two text fields into which you can type or paste code. One field specifies code that
you want to place at the top of the generated header or source file. The second field
specifies code that you want to place at the bottom of the file.
The remaining blocks add external code to functions that the code generator produces for
the root model or atomic subsystem that contains the block. The blocks display text fields
into which you can type or paste code that customizes functions that the code generator
produces. The text fields correspond to the declaration, execution, and exit sections of
code for a given function.
The block and its location within a model determines where the code generator places the
external code. For example, if the System Outputs block is at the root model level, the
42-30
Place External C/C++ Code in Generated Code
code generator places the code in the model Outputs function. If the block resides in a
triggered or enabled subsystem, the code generator places the code in the subsystem
Outputs function.
If the code generator does not need to generate a function that corresponds to a Custom
Code block that you include in a model, the code generator does one of the following:
• Omits the external code that you specify in the Custom Code block.
• Returns an error, indicating that the model does not include a relevant block. In this
case, remove the Custom Code block from the model.
For more information, see “Block Target File Methods” (Simulink Coder).
1 In the Simulink Library Browser, open the Custom Code block library. You can gain
access to the library by:
You can use models that contain Custom Code blocks as referenced models. The code
generator ignores the blocks when producing code for a simulation target. When
producing code for a code generation target, the code generator includes and compiles
the custom code.
This example shows how to use the System Start block to place external C code in the
code that the code generator produces for a model that includes a discrete filter.
42-31
42 External Code Integration in Simulink Coder
/* Initialize hardware */
*ptr = 0;
6 Click OK.
7 Generate code and a code generation report.
8 View the generated model.c file. Search for the string start function. You
should find the following code, which includes the external code that you entered in
steps 4 and 5.
{
{
/* user code (Start function Header) */
/* System '<Root>' */
unsigned int *ptr = 0xFFEE;
For another example, see “Integrate External C Code Into Generated Code By Using
Custom Code Blocks and Model Configuration Parameters” on page 42-35.
42-32
Place External C/C++ Code in Generated Code
To Select
Insert external code Source file, and enter the external code to insert.
near the top of the
generated model.c or
model.cpp file Note If you generate subsystem code into separate files, that code does
not have access to external code that you specify with the Source file
parameter. For example, if you specify an include file as a Source file
setting, the code generator inserts the #include near the top of the
model.c or model.cpp file. The subsystem code that the code
generator places in a separate file does not have access to declarations
inside your included file. In this case, consider specifying your external
code with the Header file parameter.
Insert external code Header file, and enter the external code to insert.
near the top of the
generated model.h file
Insert external code Initialize function, and enter the external code to insert.
inside the model
initialize function in the
model.c or model.cpp
file
Insert external code Terminate function, and enter the external code to insert. Also select
inside the model the Terminate function required parameter on the Interface pane.
terminate function in the
model.c or model.cpp
file
Add preprocessor macro Defines, and enter a space-separated list of preprocessor macro
definitions definitions to add to the generated code. The list can include simple
definitions (for example, -DEF1) and definitions with a value (for
example, -DDEF2=1). Definitions can omit the -D (for example, -DFOO=1
and FOO=1 are equivalent). If a definition includes -D, the toolchain can
override the flag if the toolchain uses a different flag for defines.
42-33
42 External Code Integration in Simulink Coder
To Select
Use the same custom Use the same custom code settings as Simulation Target
code parameter settings
as the settings specified This parameter refers to the Simulation Target pane in the
for simulation of Configuration Parameters dialog box.
MATLAB Function
blocks, Stateflow charts,
and Truth Table blocks
Enable a library model Use local custom code settings (do not inherit from main model)
to use custom code
settings unique from the This parameter is available only for library models that contain MATLAB
parent model to which Function blocks, Stateflow charts, or Truth Table blocks.
the library is linked
To include a header file in an external header file, add #ifndef code. Using this code
avoids multiple inclusions. For example, in rtwtypes.h, the following #include guards
are added:
#ifndef RTW_HEADER_rtwtypes_h_
#define RTW_HEADER_rtwtypes_h_
...
#endif /* RTW_HEADER_rtwtypes_h_ */
For more information on how to add files names and locations of header, source, and
shared library files to the build process, see “Build Integrated Code Within the Simulink
Environment” on page 42-42.
Note The code generator includes external code that you include in a configuration set
when generating code for software-in-the-loop (SIL) and processor-in-the-loop (PIL)
simulations. However, the code generator ignores external code that you include in a
configuration set when producing code with the S-function, rapid simulation, or
simulation system target file.
For more information about Custom Code parameters, see “Model Configuration
Parameters: Code Generation Custom Code” (Simulink Coder). For an example, see
“Integrate External C Code Into Generated Code By Using Custom Code Blocks and
Model Configuration Parameters” on page 42-35.
42-34
Place External C/C++ Code in Generated Code
open_system('rtwdemo_slcustcode')
42-35
42 External Code Integration in Simulink Coder
2. Open the Model Configuration Parameters dialog box and navigate to the Custom
Code pane.
3. Examine the settings for parameters Source file and Initialize function.
42-36
Place External C/C++ Code in Generated Code
• Source file specifies a comment and sets the variable GLOBAL_INT2 to -1.
• Initialize function initializes the variable GLOBAL_INT2 to 1.
5. Double-click the Model Source block. The Top of Model Source field specifies that the
code generator declare the variable GLOBAL_INT1 and set it to 0 at the top of the
generated file rtwdemo_slcustcode.c.
6. Open the triggered subsystem Amplifier. The subsystem includes the System
Outputs block. The code generator places code that you specify in that block in the
generated code for the nearest parent atomic subsystem. In this case, the code generator
places the external code in the generated code for the Amplifier subsystem. The
external code:
• Declares the pointer variable *intPtr and initializes it with the value of variable
GLOBAL_INT1.
• Sets the pointer variable to -1 during execution.
• Resets the pointer variable to 0 before exiting.
8. Examine the code in the generated source file rtwdemo_slcustcode.c. At the top of
the file, after the #include statements, you find the following declaration code. The
example specifies the first declaration with the Source file configuration parameter and
the second declaration with the Model Source block.
int_T GLOBAL_INT1 = 0;
The Output function for the Amplifier subsystem includes the following code, which
shows the external code integrated with generated code that applies the gain. The
example specifies the three lines of code for the pointer variable with the System Outputs
block in the Amplifier subsystem.
*intPtr = -1;
42-37
42 External Code Integration in Simulink Coder
*intPtr = 0;
The following assignment appears in the model initialize entry-point function. The
example specifies this assignment with the Initialize function configuration parameter.
GLOBAL_INT2 = 1;
See Also
More About
• “Configure a Model for Code Generation” on page 2-2
42-38
Call External Device Drivers
To call external device driver code from the Simulink environment, iterate through the
tasks in this table.
42-39
42 External Code Integration in Simulink Coder
See Also
More About
• “Integrate C Functions Using Legacy Code Tool” (Simulink)
• “Import Calls to External Code into Generated Code with Legacy Code Tool”
(Simulink Coder)
• “About Embedded Target Development” (Simulink Coder)
42-40
Apply Function and Operator Code Replacements
See Also
More About
• “What Is Code Replacement?” on page 40-2
• “What Is Code Replacement Customization?” on page 54-3
• Code Replacement Viewer
• Code Replacement Tool
42-41
42 External Code Integration in Simulink Coder
Workflow
To build executable programs that integrate generated code and external C or C++ code,
iterate through the tasks in this table.
42-42
Build Integrated Code Within the Simulink Environment
To Select
Add include folders, Configuration Parameters > Code Generation > Custom
which contain header Code > Additional build information > Include
files, to the build process directories, and enter the absolute or relative paths to the
folders.
42-43
42 External Code Integration in Simulink Coder
To Select
Add source files to be Configuration Parameters > Code Generation > Custom
compiled and linked Code > Additional build information > Source files, and
enter the full paths or just the file names for the files.
Enter just the file name if the file is in the current MATLAB
folder or in one of the include folders. For each additional
source that you specify, the build process expands a generic
rule in the template makefile for the folder in which the
source file is located. For example, if a source file is located in
folder inc, the build process adds a rule similar to the
following:
%.obj: buildir\inc\%.c
$(CC) -c -Fo$(@F) $(CFLAGS) $<
The build process adds the rules in the order that you list the
source files.
Add libraries to be linked Configuration Parameters > Code Generation > Custom
Code > Additional build information > Libraries, and
enter the full paths or just the file names for the libraries.
Enter just the file name if the library is located in the current
MATLAB folder or in one of the include folders.
Use the same custom Configuration Parameters > Code Generation > Custom
code settings as those Code > Use the same custom code settings as
specified for simulation of Simulation Target
MATLAB Function blocks,
Stateflow charts, and
Truth Table blocks Note This parameter refers to the Simulation Target pane
in the Configuration Parameters dialog box.
Enable a library model to Configuration Parameters > Code Generation > Custom
use custom code settings Code > Use local custom code settings (do not inherit
unique from the parent from main model)
model to which the
library is linked
Note This parameter is available only for library models that
contain MATLAB Function blocks, Stateflow charts, or Truth
Table blocks.
42-44
Build Integrated Code Within the Simulink Environment
If you put a .c/.cpp or .h source file in a build folder, and you want to prevent the code
generator from deleting it during the TLC code generation process, insert the text
target specific file in the first line of the .c/.cpp or .h file. For example:
/* COMPANY-NAME target specific file
*
* This file is created for use with the
* COMPANY-NAME target.
* It is used for ...
*/
...
Make sure that you spell the text “target specific file” as shown in the preceding example,
and that the text is in the first line of the source file. Other text can appear before or after
this text.
Flagging user files in this manner prevents postprocessing these files to indent them with
generated source files. Auto-indenting occurred in previous releases to build folder files
with names having the pattern model_*.c/.cpp (where * was text). The indenting is
harmless, but can cause differences detected by source control software that can
potentially trigger unnecessary updates.
42-45
42 External Code Integration in Simulink Coder
S-functions also provide the most flexible and capable way of including build information
for legacy and custom code files in the build process.
When building models with S-functions, the build process adds rules, include paths, and
source file names to the generated makefile. The source files (.h, .c, and .cpp) for the S-
function must be in the same folder as the S-function MEX-file. Whether using the
toolchain approach or template makefile approach for builds, the build process
propagates this information through the toolchain or template makefile.
• If the file sfcnname.h exists in the same folder as the S-function MEX-file (for
example, sfcnname.mexext), the folder is added to the include path.
• If the file sfcnname.c or sfcnname.cpp exists in the same folder as the S-function
MEX-file, the build process adds a makefile rule for compiling files from that folder.
• When an S-function is not inlined with a TLC file, the build process must compile the
S-function source file. To determine the name of the source file to add to the list of
files to compile, the build process searches for sfcnname.cpp on the MATLAB path. If
the source file is found, the build process adds the source file name to the makefile. If
sfcnname.cpp is not found on the path, the build process adds the file name
sfcnname.c to the makefile, whether or not it is on the MATLAB path.
Note For the Simulink engine to find the MEX-file for simulation and code generation,
it must exist on the MATLAB path or exist in our current MATLAB working folder.
If your S-function has additional source file dependencies, you must add the names of the
additional modules to the build process. Specify the file names:
• In the S-function modules field in the S-Function block parameter dialog box
• With the SFunctionModules parameter in a call to the set_param function
For example, suppose you build your S-function with multiple modules.
mex sfun_main.c sfun_module1.c sfun_module2.c
You can then add the modules to the build process by doing one of the following:
42-46
Build Integrated Code Within the Simulink Environment
When you are ready to generate code, force the code generator to rebuild the top model,
as described in “Control Regeneration of Top Model Code” (Simulink Coder).
For more complicated S-function file dependencies, such as specifying source files in
other locations or specifying libraries or object files, use the rtwmakecfg.m API, as
described in “Use rtwmakecfg.m API to Customize Generated Makefiles” on page 73-26.
If you inline your S-function by writing a TLC file, you can add source file names to the
build process by using the TLC library function LibAddToModelSources. For details,
see “LibAddSourceFileCustomSection(file, builtInSection, newSection)” (Simulink Coder).
Note This function does not support complete source file path specifications. The
function assumes that the code generator can find the additional source files when
executing the makefile.
For more complicated S-function file dependencies, such as specifying source files in
other locations or specifying libraries or object files, use the rtwmakecfg.m API, as
described in “Use rtwmakecfg.m API to Customize Generated Makefiles” on page 73-26.
42-47
42 External Code Integration in Simulink Coder
You can precompile new or updated S-function libraries (MEX-files) for a model by using
the MATLAB language function rtw_precompile_libs. Using a specified model and a
library build specification, this function builds and places the libraries in a precompiled
library folder.
By precompiling S-function libraries, you can optimize system builds. Once your
precompiled libraries exist, the build process can omit library compilation from
subsequent builds. For models that use numerous libraries, the time savings for build
processing can be significant.
To use rtw_precompile_libs:
1 Set the library file suffix, including the file type extension, based on your system
platform.
Consider determining the type of platform, and then use the TargetLibSuffix
parameter to set the library suffix accordingly. For example, when applying a suffix
for a GRT target, you can set the suffix to _std.a for a UNIX platform and
_vcx64.lib for a Windows platform.
if isunix
suffix = '_std.a';
else
suffix = '_vcx64.lib';
end
set_param(my_model,'TargetLibSuffix', suffix);
There are a number of factors that influence the precompiled library suffix and
extension. The following table provides examples for typical selections of system
target file, the compiler toolchain, and other options that affect your choice of suffix
and extension. For more information, examine the template make files in the
matlab/rtw/c/grt folder or matlab/rtw/c/ert folder.
42-48
Build Integrated Code Within the Simulink Environment
Use one of the following methods to set the precompiled library folder:
The following command sets the precompiled library folder for model my_model to
folder lib under the current working folder.
set_param(my_model,'TargetPreCompLibLocation', fullfile(pwd,'lib'));
Note If you set both the target folder for the precompiled library files and a target
library file suffix, the build process detects whether any precompiled library files are
missing while processing builds.
3 Define a build specification.
42-49
42 External Code Integration in Simulink Coder
Set up a structure that defines a build specification. The following table describes
fields that you can define in the structure. These fields are optional, except for
rtwmakecfgDirs.
Field Description
rtwmakecfgDirs A cell array of character vectors that name the folders containing
rtwmakecfg files for libraries to be precompiled. The function uses
the Name and Location elements of makeInfo.library, as returned
by rtwmakecfg, to specify the name and location of the precompiled
libraries. If you set the TargetPreCompLibLocation parameter to
specify the library folder, that setting overrides the
makeInfo.library.Location setting.
Note: The specified model must contain blocks that use precompiled
libraries specified by the rtwmakecfg files because the TMF-to-
makefile conversion generates the library rules only if the build
process uses the libraries.
libSuffix A character vector that specifies the suffix, including the file type
extension, to be appended to the name of each library (for example, .a
or _vc.lib). The character vector must include a period (.). You must
set the suffix with either this field or the TargetLibSuffix
parameter. If you specify a suffix with both mechanisms, the
TargetLibSuffix setting overrides the setting of this field.
intOnlyBuild A Boolean flag. When set to true, the flag indicates the libraries are to
be optimized such that they are compiled from integer code only. This
field applies to ERT targets only.
makeOpts A character vector that specifies an option to be included in the
rtwMake command line.
addLibs A cell array of structures that specify libraries to be built that are not
specified by an rtwmakecfg function. Each structure must be defined
with two fields that are character arrays:
The target makefile (TMF) can specify other libraries and how those
libraries are built. Use this field to precompile those libraries.
42-50
See Also
The following commands set up build specification build_spec, which indicates that
the files to be compiled are in folder src under the current working folder.
build_spec = [];
build_spec.rtwmakecfgDirs = {fullfile(pwd,'src')};
4 Issue a call to rtw_precompile_libs.
The call must specify the model for which you want to build the precompiled libraries
and the build specification. For example:
rtw_precompile_libs(my_model,build_spec);
See Also
More About
• “Call Reusable External Algorithm Code for Simulation and Code Generation” on
page 42-13
• “Place External C/C++ Code in Generated Code” on page 42-27
• “Call External Device Drivers” on page 42-39
• “Deploy Generated Standalone Executable Programs To Target Hardware” on page
52-2
• “Deploy Generated Component Software to Application Target Platforms” on page
52-31
42-51
42 External Code Integration in Simulink Coder
If you have Embedded Coder software, you can generate function source code from
modeling components to use in an external code base. The generated code does not
include supporting scheduling code (for example, a step function). Controlling logic
outside of the Simulink environment invokes the generated function code.
Modeling Options
You can generate function code to export for these modeling components:
To export code that the code generator produces for these modeling components, the
modeling components must meet specific requirements on page 42-53.
For models designed in earlier releases, the code generator can export functions from
triggered subsystems. The requirements stated for export-function subsystems also apply
to exporting functions from triggered subsystems, with the following exceptions:
• Encapsulate triggered subsystems from which you intend to export functions in a top-
level virtual subsystem.
42-52
Generate Component Source Code for Export to External Code Base
• Triggered subsystems do not have to meet requirements and limitations identified for
virtual subsystems that contain function-call subsystem.
• “Export Functions That Use Absolute or Elapsed Time” on page 42-54 does not apply
to exporting functions from triggered subsystems.
Requirements
• Model solver must be a fixed-step discrete solver.
• You must configure each root-level Inport block that triggers a function-call subsystem
to output a function-call trigger. These Inport blocks cannot connect to an
Asynchronous Task Specification block.
• Model or subsystem, must contain only the following blocks at the root level:
42-53
42 External Code Integration in Simulink Coder
In addition, for export-function models, data logging and signal-viewer blocks, such as the
Scope block, are not allowed at the root level or within the function-call blocks.
If you want to export function code for a modeling component with blocks that use
absolute or elapsed time, those blocks must be inside a function-call subsystem that:
For more information, see “Absolute and Elapsed Time Computation” (Simulink Coder).
42-54
Generate Component Source Code for Export to External Code Base
• You can export function-call systems for the C++ class code interface packaging only
when its function specification is set to Default step method. See “Customize
Generated C++ Class Interfaces” on page 29-36. The exported function is compatible
with single-threaded execution. To avoid potential data race conditions for shared
signals, invoke all members for the class from the same execution thread.
• The code generator supports a SIL or PIL block in accelerator mode only if its
function-call initiator is noninlined in accelerator mode. Examples of noninlined
initiators include Stateflow charts.
• A Level-2 S-function initiator block, such as a Stateflow chart or the built-in Function-
Call Generator block, must drive a SIL block.
• You can export an asynchronous (sample-time) function-call system, but the software
does not support the SIL or PIL block for an asynchronous system.
• The software does not support MAT-file logging for export-function subsystems.
Specifications that enable MAT-file logging are ignored.
• The use of the TLC function LibIsFirstInit has been removed for export-function
subsystems.
Workflow
To generate code for an exported function, iterate through the tasks listed in this table.
42-55
42 External Code Integration in Simulink Coder
42-56
Generate Component Source Code for Export to External Code Base
how to create export-function models, see “Export-Function Models” (Simulink). For more
information on generating code for function call subsystems, see “Generate Component
Source Code for Export to External Code Base” on page 42-52.
42-57
42 External Code Integration in Simulink Coder
42-58
Generate Component Source Code for Export to External Code Base
The model with functions for export must satisfy architectural constraints at the model
root level. At the root level, valid blocks are:
• Inport
• Outport
• Function-Call Subsystem
• Simulink Function
• Goto
• From
• Merge
The code generator produces function code for Function-Call Subsystem and Simulink
Function blocks and Initialize and Reset Function blocks. For a Function-call Subsystem
block, you connect the block input ports to root Inport blocks that assert function-call
signals. The subsystem is executed based on the function-call signal that it receives. A
Simulink Function block is executed in response to the execution of a corresponding
Function Caller block or Stateflow chart. An Initialize Function block is executed on a
model initialize event and a Reset Function block is executed on a user-defined reset
event.
open_system('rtwdemo_functions')
42-59
42 External Code Integration in Simulink Coder
Use a Function Caller block to invoke a Simulink Function block. The Function Caller
block can be in the same model or in a different model as the Simulink Function block.
Multiple Function Caller blocks can invoke a Simulink Function block. You can place the
Function Caller block inside a function-call subsystem. During code generation, the code
generator exports a function from the function-call subsystem.
open_system('rtwdemo_caller')
42-60
Generate Component Source Code for Export to External Code Base
When you export functions, the generated code does not include a scheduler. Create a
test harness model to handle scheduling during simulation. Do not use the test harness
model to generate code that you deploy.
• Schedules the Simulink Function block with the Function Caller block in
rtwdemo_caller.
• Provides function-call signals to other models in this example to schedule the model
contents, including the model initialize and reset events.
open_system('rtwdemo_export_functions')
42-61
42 External Code Integration in Simulink Coder
Verify that the model containing the functions that you want to export is executed as you
expect by simulating the test harness model. For example, simulate
rtwdemo_export_functions.
sim('rtwdemo_export_functions')
Generate code and a code generation report for the functions that you want to export. For
example, generate code for rtwdemo_functions.
rtwbuild('rtwdemo_functions')
42-62
Generate Component Source Code for Export to External Code Base
• ert_main.c is an example main program (execution framework) for the model. This
code shows how to call the exported functions. The code also shows how to initialize
and execute the generated code.
• rtwdemo_functions.c calls the initialization function, including Initialize
Function, and exported functions for model components f1_alg, f2_alg, and f3.
• rtwdemo_functions.h declares model data structures and a public interface to the
exported entry-point functions and data structures.
• f3.h is a shared file that declares the call interface for the Simulink function f3.
• rtwtypes.h defines data types, structures, and macros that the generated code
requires.
Open and review the Code Interface Report. To write the interface code for your
execution framework, use the information in that report.
Input ports:
Entry-point functions:
42-63
42 External Code Integration in Simulink Coder
Output ports:
More About
• “Generate Component Source Code for Export to External Code Base” on page 42-52
• “Deploy Generated Standalone Executable Programs To Target Hardware” on page 52-
2
• “Customize Code Organization and Format” on page 39-56
• “Customize Generated C Function Interfaces” on page 29-2
• “Generate Code for a Simulink Function and Function Caller” (Simulink Coder)
bdclose('rtwdemo_export_functions')
bdclose('rtwdemo_functions')
bdclose('rtwdemo_caller')
42-64
Generate Component Source Code for Export to External Code Base
Create Model That Contains Functions and C++ Class Interface for Export
The model with functions for export with a C++ model class interface must satisfy
architectural constraints at the model root level. For C++ class generation, blocks that
are valid at the root level are:
• Inport
• Outport
• Function-Call Subsystem
• Goto
• From
• Merge
Note: Export Function-Call Subsystem with C++ class interface does not support
Simulink Function blocks.
The code generator produces function code for the Function-Call Subsystem block. For a
Function-call Subsystem block, you connect the block input ports to root Inport blocks
that assert function-call signals. The subsystem is executed based on the function-call
signal that it receives.
open_system('rtwdemo_cppclass_functions')
42-65
42 External Code Integration in Simulink Coder
When you export functions, the generated code does not include a scheduler. Create a
test harness model to handle scheduling during simulation. Do not use the test harness
model to generate code that you deploy.
open_system('rtwdemo_cppclass_export_functions')
42-66
Generate Component Source Code for Export to External Code Base
Verify that the model containing the functions that you want to export is executed as you
expect by simulating the test harness model. For example, simulate
rtwdemo_cppclass_export_functions.
sim('rtwdemo_cppclass_export_functions')
Generate code and a code generation report for the functions that you want to export. For
example, generate code for rtwdemo_cppclass_functions.
rtwbuild('rtwdemo_cppclass_functions')
42-67
42 External Code Integration in Simulink Coder
Open and review the Code Interface Report. To write the interface code for your
execution framework, use the information in that report.
Input ports:
Entry-point functions:
Output ports:
42-68
Generate Component Source Code for Export to External Code Base
More About
• “Generate Component Source Code for Export to External Code Base” on page 42-52
• “Deploy Generated Standalone Executable Programs To Target Hardware” on page 52-
2
• “Customize Code Organization and Format” on page 39-56
• “Customize Generated C++ Class Interfaces” on page 29-36
• “Generate Code for a Simulink Function and Function Caller” (Simulink Coder)
42-69
42 External Code Integration in Simulink Coder
The operation creates a new model, subsystem.slx, that contains the content of
the original subsystem and creates a ScratchModel that contains a Model block.
This block references the newly created subsystem.slx model.
The Build code for subsystem: Subsystem dialog box opens. This dialog box is not
specific to export-function subsystems. Generating code does not require entering
information in the dialog box.
4 Click Build to build the newly created subsystem.slx model.
The code generator produces code and places it in the working folder.
If you set Create block to SIL in step 2b, Simulink opens a new window that
contains an S-function block that represents the generated code. This block has the
same size, shape, and connectors as the original subsystem.
Code generation and optional block creation are now complete. You can test and use the
code and optional block as you do for generated ERT code and S-function block. For
optional workflow tasks, see “Specify a Custom Initialize Function Name” on page 42-70
and “Specify a Custom Description” on page 42-70.
You can specify a custom name for the initialize function of your exported function as an
argument to the rtwbuild command. The command takes the following form:
blockHandle = rtwbuild('subsystem', 'Mode', 'ExportFunctionCalls',..
'ExportFunctionInitializeFunctionName', 'fcnname')
fcnname specifies the function name. For example, if you specify the name
'myinitfcn', the build process emits code similar to:
You can enter a custom description for an exported function by using the Block Properties
dialog box of an Inport block.
1 Right-click the Inport block that drives the control port of the subsystem for which
you are exporting code.
42-70
See Also
2 Select Properties.
3 In the General tab, in the Description field, enter your descriptive text.
During function export, the text you enter is emitted to the generated code in the header
for the Inport block. For example, if you open the example program
rtwdemo_exporting_functions and enter a description in the Block Properties dialog
box for port t_1tic_A, the code generator produces code that is similar to:
/*
* Output and update for exported function: t_1tic_A
*
* My custom description of the exported function
*/
void t_1tic_A(void)
{
...
}
See Also
More About
• “Design Models for Generated Embedded Code Deployment” on page 1-2
• “Systems and Subsystems” (Simulink)
42-71
42 External Code Integration in Simulink Coder
42-72
Generate Shared Library for Export to External Code Base
Workflow
To generate a shared library from a model component and use the library, complete the
tasks listed in this table.
42-73
42 External Code Integration in Simulink Coder
42-74
Generate Shared Library for Export to External Code Base
2 Build the model. The code generator produces source code for the model and a
shared library version of the code. The code generator places the source code in the
code generation folder and the shared library (.dll, .so, or .dylib file) in your
current working folder. The code generator also produces and retains a .lib file to
support implicit linking.
1 Create an application header file that contains type declarations for model external
input and output. For example:
#ifndef _APP_MAIN_HEADER_
#define _APP_MAIN_HEADER_
typedef struct {
int32_T Input;
} ExternalInputs_rtwdemo_shrlib;
typedef struct {
int32_T Output;
} ExternalOutputs_rtwdemo_shrlib;
#endif /*_APP_MAIN_HEADER_*/
2 In the application C source code, dynamically load the shared library. Use
preprocessing conditional statements to invoke platform-specific commands. For
example:
#else /* UNIX */
#include <dlfcn.h>
#define GETSYMBOLADDR dlsym
#define LOADLIB dlopen
#define CLOSELIB dlclose
42-75
42 External Code Integration in Simulink Coder
#endif
int main()
{
void* handleLib;
...
#if defined(_WIN64)
handleLib = LOADLIB("./rtwdemo_shrlib_win64.dll");
#else #if defined(_WIN32)
handleLib = LOADLIB("./rtwdemo_shrlib_win32.dll");
#else /* UNIX */
handleLib = LOADLIB("./rtwdemo_shrlib.so", RTLD_LAZY);
#endif
#endif
...
return(CLOSELIB(handleLib));
}
3 From the application C source code, access exported data and functions generated
from the model. The code uses hooks to add user-defined initialization, step, and
termination code.
int32_T i;
...
void (*mdl_initialize)(boolean_T);
void (*mdl_step)(void);
void (*mdl_terminate)(void);
ExternalInputs_rtwdemo_shrlib (*mdl_Uptr);
ExternalOutputs_rtwdemo_shrlib (*mdl_Yptr);
uint8_T (*sum_outptr);
...
#if (defined(LCCDLL)||defined(BORLANDCDLL))
/* Exported symbols contain leading underscores
when DLL is linked with LCC or BORLANDC */
mdl_initialize =
(void(*)(boolean_T))GETSYMBOLADDR(handleLib ,
"_rtwdemo_shrlib_initialize");
mdl_step =
(void(*)(void))GETSYMBOLADDR(handleLib ,
"_rtwdemo_shrlib_step");
mdl_terminate =
(void(*)(void))GETSYMBOLADDR(handleLib ,
42-76
Generate Shared Library for Export to External Code Base
"_rtwdemo_shrlib_terminate");
mdl_Uptr =
(ExternalInputs_rtwdemo_shrlib*)GETSYMBOLADDR(handleLib ,
"_rtwdemo_shrlib_U");
mdl_Yptr =
(ExternalOutputs_rtwdemo_shrlib*)GETSYMBOLADDR(handleLib ,
"_rtwdemo_shrlib_Y");
sum_outptr =
(uint8_T*)GETSYMBOLADDR(handleLib , "_sum_out");
#else
mdl_initialize =
(void(*)(boolean_T))GETSYMBOLADDR(handleLib ,
"rtwdemo_shrlib_initialize");
mdl_step =
(void(*)(void))GETSYMBOLADDR(handleLib ,
"rtwdemo_shrlib_step");
mdl_terminate =
(void(*)(void))GETSYMBOLADDR(handleLib ,
"rtwdemo_shrlib_terminate");
mdl_Uptr =
(ExternalInputs_rtwdemo_shrlib*)GETSYMBOLADDR(handleLib ,
"rtwdemo_shrlib_U");
mdl_Yptr =
(ExternalOutputs_rtwdemo_shrlib*)GETSYMBOLADDR(handleLib ,
"rtwdemo_shrlib_Y");
sum_outptr =
(uint8_T*)GETSYMBOLADDR(handleLib , "sum_out");
#endif
if ((mdl_initialize &&
mdl_step &&
mdl_terminate &&
mdl_Uptr &&
mdl_Yptr &&
sum_outptr)) {
/* user application
initialization function */
mdl_initialize(1);
/* insert other user defined
application initialization code here */
/* user application
step function */
for(i=0;i<=12;i++){
42-77
42 External Code Integration in Simulink Coder
mdl_Uptr->Input = i;
mdl_step();
printf("Counter out(sum_out):
%d\tAmplifier in(Input):
%d\tout(Output):
%d\n", *sum_outptr, i,
mdl_Yptr->Output);
/* insert other user defined
application step function
code here */
}
/* user application
terminate function */
mdl_terminate();
/* insert other user defined
application termination
code here */
}
else {
printf("Cannot locate the specified
reference(s) in the shared library.\n");
return(-1);
}
Limitations
• Code generation for the ert_shrlib.tlc system target file exports the following as
data:
42-78
Generate Shared Library for Export to External Code Base
To build a shared library from the model and use the library in an application:
1. Develop your model. For this example, open the model rtwdemo_shrlib.
open_system('rtwdemo_shrlib');
42-79
42 External Code Integration in Simulink Coder
The model is a single-rate, discrete-time model. An 8-bit counter feeds the triggered
subsystem named Amplifier. Parameters INC, LIMIT, and RESET are set to constant
42-80
See Also
2. Configure the model for code generation, specifying ert_shrlib.tlc as the system
target file. Click the yellow button on the model to view the configuration settings on the
Code Generation pane in the Configuration Parameters dialog box.
3. Build the shared library file. The file that the code generator produces depends on your
development platform. For example, on a Windows system, the code generator produces
the library file rtwdemo_shrlib_win64.dll.
4. Create application code that uses the shared library. This example uses application
code that is available in the these files:
matlabroot\toolbox\rtw\rtwdemos\shrlib_demo\rtwdemo_shrlib_app.h
matlabroot\toolbox\rtw\rtwdemos\shrlib_demo\rtwdemo_shrlib_app.c
To view the source code in these files, in the model, click the white buttons for the .h
and .c files.
5. Compile and link the file application and shared library files to produce an executable
program. The following script compiles, builds, and runs the program.
matlabroot\toolbox\rtw\rtwdemos\shrlib_demo\rtwdemo_shrlib_app.m
To view the script code, in the model, click the white button for the .m file.
To build the model and run the application that uses the generated shared library, in the
model, double-click the blue button.
For more information about using a shared library, see “Package Generated Code as
Shared Libraries” on page 50-2.
See Also
More About
• “Design Models for Generated Embedded Code Deployment” on page 1-2
• “Configure a System Target File” on page 33-2
42-81
42 External Code Integration in Simulink Coder
42-82
Build Integrated Code Outside the Simulink Environment
For information about the example model and related examples, see “Generate C Code
from a Control Algorithm for an Embedded System”.
The code that Embedded Coder® generates requires support files that MathWorks®
provides. To relocate the generated code to another development environment, such as a
dedicated build system, you must relocate these support files. You can package these files
in a zip file by using the packNGo utility. This utility finds and packages the files that you
need to build an executable image. The utility uses tools for customizing the build process
after code generation, which include a buildinfo_data structure, and a packNGo
function. These files include external files that you identify in the Code Generation >
Custom Code pane in the Model Configuration Parameters dialog box. The utility saves
the buildinfo MAT-file in the model_ert_rtw folder.
The number of files in the zip file depends on the version of Embedded Coder® and on
the configuration of the model that you use. The compiler does not require all of the files
in the zip file. The compiled executable size (RAM/ROM) depends on the linking process.
The linker likely includes only the object files that are necessary.
42-83
42 External Code Integration in Simulink Coder
This example shows how to integrate the generated code into an existing code base. The
example uses the Eclipse™ IDE and the Cygwin™/gcc compiler. The required integration
tasks are common to all integration environments.
A full embedded controls system consists of multiple hardware and software components.
Control algorithms are just one type of component. Other components can be:
Typically, you do not use the generated code in these components. Instead, the generated
code includes interfaces that connect with these components. MathWorks® provides
hardware interface block libraries for many common embedded controllers. For examples,
see the Embedded Targets block library.
This example provides files to show how you can build a full system. The main file is
example_main.c, which contains a simple main function that performs only basic
actions to exercise the code.
View example_main.c.
42-84
Build Integrated Code Outside the Simulink Environment
The file:
The order of function execution matches the order of subsystem execution in the test
harness model and in rtwdemo_PCG_Eval_P5.h. If you change the order of execution in
example_main.c, results that the executable image produces differ from simulation
results.
42-85
42 External Code Integration in Simulink Coder
Integration requires matching the Data and Function interfaces of the generated code
and the existing system code. In this example, the example_main.c file imports and
exports the data through #include statements and extern declarations. The file also
calls the functions from the generated code.
The system has three input signals: pos_rqst, fbk_1, and fbk_2. The generated code
accesses the two feedback signals through direct reference to imported global variables
(storage class ImportedExtern). The code accesses the position signal through an
imported pointer (storage class ImportedExternPointer).
The handwritten file defineImportedData.c defines the variables and the pointer. The
generated code does not define the variables and the pointer because the handwritten
code defines them. Instead, the generated code declares the imported data (extern) in
the file rtwdemo_PCG_Eval_P5_Private.h. In a real system, the data typically comes
from other software components or from hardware devices.
View defineImportedData.c.
View rtwdemo_PCG_Eval_P5_Private.h.
42-86
Build Integrated Code Outside the Simulink Environment
In this example, you do not access the output data of the system. The example “Test
Generated Code” shows how you can save the output data to a standard log file. You can
access the output data by referring to the file rtwdemo_PCG_Eval_P5.h.
View rtwdemo_PCG_Eval_P5.h.
The generated code contains several structures that store commonly used data including:
The table lists the common data structures. Depending on the configuration of the model,
some or all of these structures appear in the generated code. The data is declared in the
file rtwdemo_PCG_Eval_P5.h, but in this example, you do not access this data.
Data Type Data Name Data Purpose
By default, functions that the code generator generates have a void Func(void)
interface. If you configure the model or atomic subsystem to generate reentrant code, the
42-87
42 External Code Integration in Simulink Coder
code generator creates a more complex function prototype. In this example, the
example_main function calls the generated functions with the correct input arguments.
This example uses the Eclipse™ IDE and the Cygwin™ GCC debugger to build the
embedded system. The example provides installation files for both programs. Software
components and versions numbers are:
To install and use Eclipse™ and GCC, see “Install and Use Cygwin and Eclipse”.
You can install the files for this example by clicking this hyperlink:
42-88
Build Integrated Code Outside the Simulink Environment
You can use the Eclipse™ debugger to step through and evaluate the execution behavior
of the generated C code. See the example “Install and Use Cygwin and Eclipse”.
To exercise the model with input data, see “Test Generated Code”.
Related Topics
• “Generate Component Source Code for Export to External Code Base” on page 42-52
• “Generate Shared Library for Export to External Code Base” on page 42-73
42-89
42 External Code Integration in Simulink Coder
Functions in C or C++ code, including your external functions, can exchange data with a
caller or a called function through:
In Simulink, you can organize and configure data so that a model uses these exchange
mechanisms to provide, extract, and share data with your code.
Before you attempt to match data interfaces, to choose an overall integration approach,
see “Choose an External Code Integration Workflow” on page 42-4.
• To exchange data through the arguments of your external function, construct and
configure your model to create and package the data according to the data types of
the arguments. Then, you connect and configure the block that calls or represents
your function to accept, produce, or refer to the data from the model.
For example, if you use the Legacy Code Tool to generate an S-Function block that
calls your function, the ports and parameters of the block correspond to the
42-90
Exchange Data Between External C/C++ Code and Simulink Model or Generated Code
arguments of the function. You connect the output signals of upstream blocks to the
input ports and set parameter values in the block mask. Then, you can create signal
lines from the output ports of the block and connect those signals to downstream
blocks.
• To exchange data through global variables that your external code already defines, a
best practice is to use a Stateflow chart to call your function and to access the
variables. You write algorithmic C code in the chart so that during simulation or
execution of the generated code, the model reads and writes to the variables.
To use such a global variable as an item of parameter data (not signal or state data)
elsewhere in a model, you can create a numeric MATLAB variable or
Simulink.Parameter object that represents the variable. If you change the value of
the C-code variable in between simulation runs, you must manually synchronize the
value of the Simulink variable or object. If your algorithmic code (function) changes
the value of the C-code variable during simulation, the corresponding Simulink
variable or object does not change.
If you choose to create a Simulink representation of the C-code variable, you can
configure the Simulink representation so that the generated code reads and writes to
the variable but does not duplicate the variable definition. Apply a storage class to the
Simulink representation.
42-91
42 External Code Integration in Simulink Coder
42-92
Exchange Data Between External C/C++ Code and Simulink Model or Generated Code
42-93
42 External Code Integration in Simulink Coder
42-94
Exchange Data Between External C/C++ Code and Simulink Model or Generated Code
42-95
42 External Code Integration in Simulink Coder
42-96
Exchange Data Between External C/C++ Code and Simulink Model or Generated Code
To package lookup
table data into a
structure,
Simulink.LookupT
able.
For general
information about
creating structures in
the generated code,
see “Organize Data
into Structures in
Generated Code”
(Simulink Coder).
42-97
42 External Code Integration in Simulink Coder
This technique
requires Embedded
Coder.
Storage type const myParam = 9.8; Apply the custom “Protect Global Data
qualifiers storage classes Const, with Keywords const
such as Volatile, and and volatile” (Simulink
const and ConstVolatile to Coder)
volatile data items.
42-98
Exchange Data Between External C/C++ Code and Simulink Model or Generated Code
These techniques
require Embedded
Coder.
Call to External code: Apply the custom “Access Data Through
custom storage class GetSet Functions with Custom
external /* Call this function to signals, states, and Storage Class GetSet”
function that to acquire the value of parameters. Each data on page 26-42
the signal. */
reads or item appears in the
double get_inSig(void)
writes to data { generated code as a
call to your custom
return myBigGlobalStruct.inSig;
} functions that read
and write to the target
Generated algorithmic code: data.
42-99
42 External Code Integration in Simulink Coder
• At the time that you begin an external mode simulation, the external
executable uses the value that your code uses to initialize the
parameter data. However, when you change the corresponding value
in Simulink during the simulation (for example by modifying the
Value property of the corresponding parameter object), Simulink
downloads the new value to the executable.
• SIL and PIL simulations do not import the parameter value from your
code. Instead, the simulations use the parameter value from Simulink.
If you include your external code in the Simulink Coder build process,
duplicate data definitions can prevent the generated code from
compiling.
For information about SIL and PIL, see “Choose a SIL or PIL Approach”
on page 67-12. For information about external mode simulation, see
“Host-Target Communication with External Mode Simulation” (Simulink
Coder).
Generate code comments Generating these comments can help you match data interfaces while
that describe attributes of handwriting integration code. See “Add Custom Comments for Variables
exported data including in the Generated Code” on page 39-5.
physical units, real-world
initial value, and data
type
See Also
Related Examples
• “How Generated Code Exchanges Data with an Environment” (Simulink Coder)
• “Generate Code That Matches Appearance of External Code” on page 42-106
42-100
See Also
• “Design Data Interface by Configuring Inport and Outport Blocks” on page 22-206
• “Configure Generated Code According to Interface Control Document Interactively”
on page 26-73
• “Generate Code That Dereferences Data from a Literal Memory Address” on page
52-21
42-101
42 External Code Integration in Simulink Coder
• You can generate reentrant code from a model. The generated entry-point functions
typically accept data through arguments. Your calling code passes data through these
arguments. You can call the functions multiple times in a single application—the
application can maintain multiple instances of the model. See “Data Exchange for
Reentrant Generated Code” (Simulink Coder).
• When you generate nonreentrant code, by default, the entry-point functions exchange
data between the generated code and your code through global variables. You can
generate variable definitions for your code to use or you can share and reuse existing
variables that your code already defines. See “Data Exchange for Nonreentrant
Generated Code” (Simulink Coder).
Alternatively, you can configure the entry-point functions to exchange system inputs
and outputs (root-level Inport and Outport blocks) through arguments instead of
global variables. Apply function prototype control to the model, which requires
Embedded Coder. For more information about function prototype control, see
“Customize Generated C Function Interfaces” on page 29-2.
For general information about exchanging data between generated and external code,
including how to match specific C code patterns, see “Exchange Data Between External
C/C++ Code and Simulink Model or Generated Code” (Simulink Coder).
For information about creating a separate set of data for each call site in your external
code, see “Modify Static Main to Allocate and Access Model Instance Data” on page 52-
14.
42-102
Exchange Data Between External Calling Code and Generated Code
When you generate code that defines (allocates memory for) global data, the generated
code exports that data. When your external code defines data, the generated code imports
that data. Typically, storage classes that import data have the word Import in the storage
class name, for example, ImportedExternPointer.
When you export data from the generated code by using storage classes or custom
storage classes, the code generator creates an extern declaration. By default, this
declaration typically appears in the generated header file model.h. You can include
(#include) this header file in your external code.
You can control the file placement of the declarations and definitions to:
• Create separate object files that store only global parameter data.
• Modularize the generated code by organizing declarations into separate files.
For more information about controlling file placement of declarations and definitions, see
“Control Placement of Global Data Definitions and Declarations in Generated Files” on
page 23-2. For an example, see “Definition, Initialization, and Declaration of Parameter
Data” on page 14-7.
When your external code defines global variables, you can generate code that interacts
with those variables. For example, use the custom storage class ImportFromFile (see
42-103
42 External Code Integration in Simulink Coder
“Choose a Storage Class for Controlling Data Representation in the Generated Code”
(Simulink Coder)).
For imported variables that represent signal or state data, the code generator can
produce initialization code as described in “Initialization of Signal, State, and Parameter
Data in the Generated Code” (Simulink Coder). If your code already initializes a variable,
consider preventing the generation of duplicate initialization code. Create your own
custom storage class and, for that storage class, set Data initialization to None. For
information about creating and applying your own custom storage class, see “Define
Storage Classes, Memory Sections, and Function Templates for Software Architecture” on
page 20-2.
When your external code and the generated code exchange data through global variables,
you can generate code that uses const and volatile to protect data integrity and
improve the safety of your application. For example:
You must have Embedded Coder. For more information, see “Protect Global Data with
const and volatile Keywords” on page 30-17.
See Also
Related Examples
• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” (Simulink Coder)
• “Control Data and Function Interface in Generated Code” (Simulink Coder)
• “Design Data Interface by Configuring Inport and Outport Blocks” (Simulink Coder)
42-104
See Also
• “Integrate External Application Code with Code Generated from PID Controller” on
page 26-62
42-105
42 External Code Integration in Simulink Coder
42-106
Generate Code That Matches Appearance of External Code
• Level of parenthesization
• Order of operations in expressions
• Empty primary condition expressions in
if statements
• if-elseif-else or switch-case
statements for decision logic
• Use of extern keyword in function
declarations
• Use of static keyword in function
declarations
• Use of default cases for switch-case
statements
• Use multiplications by powers of two or
signed bitwise shifts
• Cast expressions
• Indent style (Kernighan and Ritchie or
Allman) and size
• Newline style
Placement of data definitions and “Control Placement of Global Data Definitions and
declarations, including location of global Declarations in Generated Files” on page 23-2
identifiers and global data declarations
(extern)
Appearance of code for flow charts “Enhance Readability of Code for Flow Charts” on
page 39-108
42-107
42 External Code Integration in Simulink Coder
See Also
More About
• “Code Appearance”
• “Choose an External Code Integration Workflow” on page 42-4
42-108
43
1 From Configuration Parameters > Code Generation > Language, select C or C++
for the code generation language. Alternatively, set the TargetLang parameter at
the command line.
The code generator produces .c or .cpp files, depending on your selection, and
places the generated files in your build folder.
See Also
More About
• “Select and Configure C or C++ Compiler or IDE” (Simulink Coder)
• “Troubleshoot Compiler Issues” (Simulink Coder)
43-2
Select and Configure C or C++ Compiler or IDE
https://www.mathworks.com/support/compilers/current_release
When creating an executable program, the build process must be able to access a
supported compiler. The build process can find a compiler to use based on your default
MEX compiler.
The build process also requires the selection of a toolchain or template makefile. The
toolchain or template makefile determines which compiler runs, during the make phase of
the build. For more information, see “Choose Build Approach and Configure Build
Process” (Simulink Coder)
To determine which templates makefiles are available for your compiler and system target
file, see “Compare System Target File Support” (Simulink Coder).
For both generated files and user-supplied files, the file extension, .c or .cpp,
determines whether the build process uses a C or a C++ compiler. If the file extension
is .c, the build process uses C compiler to compile the file, and the symbols use the C
linkage convention. If the file extension is .cpp, the build process uses a C++ compiler to
compile the file, and the symbols use the C++ linkage specification.
In this section...
“Language Standards Compliance” on page 43-3
“Programming Language Considerations” on page 43-4
“C++ Language Support Limitations” on page 43-5
“Code Generator Assumes Wrap on Signed Integer Overflows” on page 43-6
“Choose and Configure Compiler” on page 43-6
“Include S-Function Source Code” on page 43-7
43-3
43 Program Building, Interaction, and Debugging in Simulink Coder
Code that the code generator produces from these sources is ANSI C/C++ compliant:
• Embedded system target files (for example, startup code, device driver blocks)
• Custom S-functions or TLC files
Note Coding standards for these two sources are beyond the control of the code
generator. These standards can be a source for compliance problems, such as code that
uses C99 features not supported in the ANSI C, C89/C90 subset.
• Does your project require you to configure the code generator to use a specific
compiler? C/C++ code generation on Windows requires this selection.
• Does your project require you to change the default language configuration setting for
the model? See “Select C or C++ Programming Language” on page 43-2.
• Does your project require you to integrate legacy or custom code with generated
code? For a summary of integration options, see “What Is External Code Integration?”
on page 42-3.
• Does your project require you to integrate C and C++ code? If so, see “What Is
External Code Integration?” on page 42-3.
43-4
Select and Configure C or C++ Compiler or IDE
Note You can mix C and C++ code when integrating generated code with custom
code. However, you must be aware of the differences between C and default C++
linkage conventions, and add the extern "C"' linkage specifier where required. For
the details of the differing linkage conventions and how to apply extern "C", refer to
a C++ programming language reference book.
• Does your project require code generation support from other products? See “C++
Language Support Limitations” on page 43-5.
For C++ code generation examples with Stateflow, see the sfcndemo_cppcount model
or sf_cpp model.
• The code generator does not support C++ code generation for the following:
Simscape Driveline
Simscape Multibody First Generation (Simscape Multibody Second Generation is
supported)
Simscape Power Systems
Simulink Real-Time
• For ERT and ERT-based system target files with Configuration Parameters > Data
Placement > Interface > Code interface packaging set to Nonreusable
function, the following fields currently do not accept the .cpp extension. If you
specify a file name with a .c extension or without an extension and specify C++ for
the code generation language, the code generator produces a .cpp file.
• Configuration Parameters > Code Placement > Data definition filename field
(available when Configuration Parameters > Code Placement > Data
definition is set to Data defined in a single separate source file)
• Definition file field for a data object in Model Explorer. Data objects are objects of
the class Simulink.Signal, Simulink.Parameter, and subclasses.
43-5
43 Program Building, Interaction, and Debugging in Simulink Coder
When you generate code, if you use a supported compiler with the default options
configured by the code generator, the compiler preserves the full wrap-on-overflow
behavior. If you change the compiler options or compile the code in another development
environment, it is possible that the compiler does not preserve the full wrap-on-overflow
behavior. In this case, the executable program can produce unpredictable results.
If this issue is a concern for your application, consider one or more of the following
actions:
mex -setup
43-6
Select and Configure C or C++ Compiler or IDE
On a Windows computer, you can install supported compilers and select a default
compiler.
On a UNIX platform, the default compiler is GNU gcc/g++ for GNU or Xcode for Mac.
Unless the build approach configuration selects a specific compiler, the code generator
uses the default compiler for the build process.
Primarily, the specified system target file determines the compiler that the code generator
requires:
• If you select a toolchain-based system target file such as grt.tlc (Generic Real-Time
Target), ert.tlc (Embedded Coder), or autosar.tlc (Embedded Coder for
AUTOSAR), the Build process subpane displays toolchain parameters for configuring
the build process. Use the Toolchain parameter to select a compiler and associated
tools for your model build. To validate the selected toolchain, click the Validate button
for the Configuration Parameters > Code Generation > Build process >
Toolchain settings box.
• If you select a template makefile (TMF) based system target file, such as rsim.tlc,
the Build process subpane displays template makefile parameters for configuring the
build process. The Template makefile parameter displays the default TMF file for the
selected system target file. If the system target file supports compiler-specific
template makefiles (for example, Rapid Simulation or S-Function system target files),
you can set Template makefile to a compiler-specific TMF, such as rsim_lcc.tmf or
rsim_unix.tmf. (See “Compare System Target File Support” (Simulink Coder) for
valid TMF names.)
Similarly, the code generator adds a rule for the folder when it finds a file sfncname.c
(or .cpp) in the same folder as the S-function MEX-file is in.
43-7
43 Program Building, Interaction, and Debugging in Simulink Coder
See Also
More About
• “Run-Time Environment Configuration” (Simulink Coder)
• “Compare System Target File Support” (Simulink Coder)
• “Select C or C++ Programming Language” (Simulink Coder)
• “Troubleshoot Compiler Issues” on page 43-9
External Websites
• https://www.mathworks.com/support/compilers/current_release
43-8
Troubleshoot Compiler Issues
Action
The program generated for the model produces different results from model simulation
results. The generated source code includes an arithmetic operation that produces a
signed integer overflow. It is possible that your compiler does not implement wrapping
behavior for signed integer overflow conditions. Or, if you are using a compiler that
supports wrapping, it is possible that you did not configure it to use the -fwrapv option.
For more information, see “Code Generator Relies on Undefined Behavior of C Language
for Integer Overflows.”
43-9
43 Program Building, Interaction, and Debugging in Simulink Coder
Action
• If your compiler can force wrapping behavior, turn it on. For example, for the gcc
compiler or a compiler based on gcc, such as MinGW, specify the compiler option -
fwrapv.
• Choose a compiler that checks for integer overflows.
• If you have Embedded Coder, develop and apply a code replacement library to replace
code generated for signed integers.
The build process generates expected source code, but the executable program produces
unexpected results. The generated source code appears as expected. However, the
executable program produces unexpected results.
Action
1 Select Custom for the Model Configuration parameter Code Generation >
Compiler optimization level.
2 In the Custom compiler optimization flags field, specify a lower optimization
level.
3 Rebuild the model.
• Disable compiler optimizations.
For more information, see “Control Compiler Optimizations” (Simulink Coder) and your
compiler documentation.
43-10
Troubleshoot Compiler Issues
Compile-Time Issues
Issue Action
Error is present in the compiler Make sure that MATLAB supports the
configuration. compiler and version that you want to use.
For a list of currently supported and
compatible compilers, see
www.mathworks.com/support/
compilers/current_release/. If
necessary, upgrade or change your
compiler (see “Choose and Configure
Compiler” on page 43-6 or “Choose and
Configure Compiler” on page 43-6).
Environment variables are incorrectly set Review the environment variable settings
up for your make utility, compiler, or linker. for your system by using the set command
For example, installation of Cygwin tools on on a Windows platform or setenv on a
a Windows platform affects environment UNIX platform. Make sure that the settings
variables used by other compilers. match what is required for the tools you are
using.
Error is present in custom code specified as To isolate the source of the problem,
an S-function block or in Configuration remove the custom code from the model,
Parameters > Code Generation > debug, and rebuild the model.
Custom Code. For example, the code
refers to a header file that the compiler
cannot find.
The model includes a block, such as a Remove the system target file-specific block
device driver block, which is not intended or configure the model for use with another
for use with the currently selected system system target file.
target file.
43-11
43 Program Building, Interaction, and Debugging in Simulink Coder
Issue Action
A linker error about an undefined reference To resolve the issue, choose one of these
to the data appears when the model build methods:
generates an executable from the model
reference hierarchy and all these conditions • In the data object, clear the Owner
are true: property. Alternatively, set the owner to
a model that directly accesses the data.
• You represent signal, state, or • Use a different toolchain, such as gcc,
parameter data by creating a data object instead of lcc.
such as Simulink.Signal. You use the
object in a model reference hierarchy.
• You use a custom storage class with the
data object. Custom storage classes
require Embedded Coder.
• You set the owner of the object to a
model that does not directly access the
data.
• You use the toolchain lcc-win64.
If you use the LCC compiler and your model folder path contains an ampersand (&), the
build process produces an error.
Action
Remove the ampersand from the model folder path. Then, rebuild the model.
43-12
See Also
If you are compiling Rapid Accelerator code, the LCC compiler might produce an error
related to line limits. Rapid Accelerator code can have longer line lengths due to
obfuscation.
Action
Compile your Rapid Accelerator code using a compiler that supports longer code lines.
See Also
More About
• “Choose and Configure Compiler” on page 43-6
• “Select C or C++ Programming Language” (Simulink Coder)
• “Troubleshoot Compiler Issues” on page 43-9
• “Choose Build Approach and Configure Build Process” on page 43-14
• “Build Process Workflow for Real-Time Systems” on page 43-32
• “Rebuild a Model” on page 43-41
• “Reduce Build Time for Referenced Models” on page 43-45
• “Control Regeneration of Top Model Code” on page 43-43
• “Relocate Code to Another Development Environment” on page 43-56
• “Profile Code Performance” on page 43-72
• “Control Compiler Optimizations” (Simulink Coder)
• “Select and Configure C or C++ Compiler or IDE” on page 43-3
• “Executable Program Generation” on page 43-69
External Websites
• www.mathworks.com/support/compilers/current_release/
43-13
43 Program Building, Interaction, and Debugging in Simulink Coder
• Toolchain — A build process that generates optimized makefiles and supports custom
toolchains. This approach:
• Provides control of your build process with toolchain information objects. You can
define these objects using MATLAB scripts.
• Supports model referencing, SIL, PIL, and Rapid Accelerator builds.
• Supports Simulink Coder, Embedded Coder, and MATLAB Coder.
• Template makefile — A build process that uses a template makefile with a toolchain
that you specify. This approach:
The “System target file” (Simulink Coder) parameter, located in the Configuration
Parameters > Code Generation pane, lets you select the build process for a model.
When you set the System target file to:
You can switch from the toolchain approach to the template makefile approach with this
command:
Toolchain Approach
Toolchain settings appear under Build process when you set System target file to:
43-14
Choose Build Approach and Configure Build Process
For more information about toolchain-compliant system target files, see “Support
Toolchain Approach with Custom Target” (Simulink Coder).
43-15
43 Program Building, Interaction, and Debugging in Simulink Coder
linker, archiver, and other prebuild or postbuild tools that download and run the
executable on the target hardware.
Click the Validate button for the Configuration Parameters > Code Generation >
Build process > Toolchain settings parameter to check that the toolchain is present
and validate that the code generator has the information required to use the toolchain.
The resulting Validation Report gives a pass/fail for the selected toolchain, and
identifies issues to resolve.
• The “Build configuration” (Simulink Coder) parameter lets you choose or customize
the optimization settings. By default, Build Configuration is set to Faster Builds.
You can also select Faster Runs, Debug, and Specify. When you select Specify
and click Apply, you can customize the toolchain options for each toolchain. These
custom toolchain settings only apply to the current model.
Note The following system target files, which use the template makefile approach, have
the same names but different descriptions from system target files that use the toolchain
approach:
To avoid confusion, click Browse to select the system target file and look at the
description of each file.
43-16
Choose Build Approach and Configure Build Process
Note To upgrade models using a custom system target file to use the toolchain approach,
see “Support Toolchain Approach with Custom Target” on page 74-82.
Some model configuration parameter values prevent the software from upgrading a
model to use toolchain settings. The following instructions show you ways to complete the
upgrade process.
Consider upgrading your models and use the toolchain build approach. Doing so is not
required. You can continue generating code from a model that has not been upgraded.
Note The software does not upgrade models that use the following system target files:
43-17
43 Program Building, Interaction, and Debugging in Simulink Coder
Start by creating a working copy of the model using File > Save As. This action
preserves the original model and configuration parameters for reference.
43-18
Choose Build Approach and Configure Build Process
When you cannot upgrade the model using Upgrade Advisor, one or more of the following
parameters is not set to its default value, shown here:
• If Generate makefile is disabled, this case cannot be upgradable. However, you can
try enabling it and try upgrading the model using Upgrade Advisor.
• If Compiler optimization level is set to Optimizations on (faster runs):
1 Set Compiler optimization level is to Optimizations off (faster
builds).
2 Upgrade the model using Upgrade Advisor.
3 Set Build configuration to Faster Runs.
• If Compiler optimization level is set to Custom:
1 Copy the Custom compiler optimization flags to a text file.
2 Set Compiler optimization level to Optimizations off (faster builds).
3 Upgrade the model using Upgrade Advisor.
4 Set Build configuration to Specify.
5 To perform the same optimizations, edit the compiler options.
• If Template makefile uses a customized template makefile, this case cannot be
upgradable. However, you can try the following:
1 Update Template makefile to use the default makefile for the system target file.
Note To get the default makefile name, change the System target file, click
Apply, change it back, and click Apply again.
2 Upgrade the model using Upgrade Advisor.
3 If the template makefile contains build tool options, such as compiler optimization
flags, set Build configuration to Specify and update the options.
43-19
43 Program Building, Interaction, and Debugging in Simulink Coder
4 If the template makefile uses custom build tools, create and register a custom
toolchain, as described in “Custom Toolchain Registration” (MATLAB Coder) .
Then, set the Toolchain parameter to use the custom toolchain.
Note After registering the custom toolchain, update Toolchain to use the custom
toolchain.
5 If the template makefile contains custom rules and logic, these customizations
cannot be applied to the upgraded model.
43-20
Choose Build Approach and Configure Build Process
The Generate makefile option specifies whether the build process is to generate a
makefile for a model. By default, the build process generates a makefile. Suppress
generation of a makefile, for example in support of custom build processing that is not
based on makefiles, by clearing Generate makefile. When you clear this parameter:
43-21
43 Program Building, Interaction, and Debugging in Simulink Coder
Each template makefile-based system target file has an associated make command. The
code generator uses this internal MATLAB command to control the build process. The
command appears in the Make command field and runs when you start a build.
Most system target files use the default command, make_rtw. Third-party system target
files could supply another make command. See the documentation from the vendor.
In addition to the name of the make command, you can supply makefile options in the
Make command field. These options could include compiler-specific options, include
paths, and other parameters. When the build process invokes the make utility, these
options are passed on the make command line, which adds them to the overall flags
passed to the compiler.
“Template Makefiles and Make Options” on page 43-26 lists the Make command
options you can use with each supported compiler.
• If you selected a system target file with the System Target File Browser, this field
displays the name of a MATLAB language file that selects a template makefile for your
development environment. For example, in “Model Configuration Parameters: Code
Generation” (Simulink Coder), the Template makefile field displays
grt_default_tmf, indicating that the build process invokes grt_default_tmf.m.
“Template Makefiles and Make Options” on page 43-26 gives a detailed description of
the logic by which the build process selects a template makefile.
• Alternatively, you can explicitly enter the name of a specific template makefile
(including the extension) or a MATLAB language file that returns a template makefile
in this field. Use this approach if you are using a system target file that does not
appear in the System Target File Browser. For example, use this approach if you have
written your own template makefile for a custom system target file.
If you specify your own template makefile, be sure to include the file name extension. If
you omit the extension, the build process attempts to find and execute a file with the
extension .m (that is, a MATLAB language file). The template make file (or a MATLAB
language file that returns a template make file) must be on the MATLAB path. To
determine whether the file is on the MATLAB path, enter the following command in the
MATLAB Command Window:
43-22
Choose Build Approach and Configure Build Process
which tmf_filename
Specify a toolchain for the template makefile build process. This example provides a
definition for a minimal toolchain and shows how you can associate the toolchain with a
template makefile that is a copy of ert_unix.tmf or ert_vcx64.tmf.
if ispc
objExt = '.obj';
else
objExt = '.o';
end
% Specify source file and object file extension used by the C compiler
tool = tc.getBuildTool('C Compiler');
tool.setFileExtension( 'Source', '.c');
tool.setFileExtension( 'Header', '.h');
tool.setFileExtension( 'Object', objExt);
% Specify source file and object file extension used by the C++ compiler
tool = tc.getBuildTool('C++ Compiler');
tool.setFileExtension( 'Source', '.cpp');
tool.setFileExtension( 'Header', '.hpp');
tool.setFileExtension( 'Object', objExt);
43-23
43 Program Building, Interaction, and Debugging in Simulink Coder
1 Run the toolchain definition file, which generates a ToolchainInfo object, tc.
tc = minimalToolchainForTMF;
2 Save the ToolchainInfo object to a MAT file.
save('tcMinimal','tc')
3 Register the toolchain in RTW.TargetRegistry.
function rtwTargetInfo(tr)
tr.registerTargetInfo(@loc_createToolchain);
end
RTW.TargetRegistry.getInstance('reset');
Associate the template makefile with your model and build the model.
43-24
See Also
TLC options that you specify for code generation appear in the summary section of the
generated HTML code generation report.
Note Specifying TLC command-line options does not add flags to the make command
line.
You can specify Target Language Compiler (TLC) command-line options and arguments
for code generation using the model parameter TLCOptions in a set_param function
call. For example,
>> set_param(gcs,'TLCOptions','-p0 -aWarnNonSaturatedBlocks=0')
See Also
More About
• “Support Toolchain Approach with Custom Target” on page 74-82
• “Build Process Workflow for Real-Time Systems” (Simulink Coder)
• “Custom Toolchain Registration” (MATLAB Coder)
• “Register and Use Toolchain To Build Executable” (Simulink Coder)
• “Template Makefiles and Make Options” on page 43-26
• “Target Language Compiler Overview” (Simulink Coder)
• “Executable Program Generation” on page 43-69
43-25
43 Program Building, Interaction, and Debugging in Simulink Coder
In this section...
“Types of Template Makefiles” on page 43-26
“Specify Template Makefile Options” on page 43-27
“Template Makefiles for UNIX Platforms” on page 43-27
“Template Makefiles for the Microsoft Visual C++ Compiler” on page 43-28
“Template Makefiles for the LCC Compiler” on page 43-30
43-26
Template Makefiles and Make Options
For details on the structure of template makefiles, see “Customize Template Makefiles” on
page 74-62. This section describes compiler-specific template makefiles and common
options you can use with each.
make_rtw OPTS="-DMYDEFINE=1"
The syntax for make command options differs slightly for different compilers.
Note To control compiler optimizations for a makefile build at the Simulink GUI level, use
the Configuration Parameters > Code Generation > Build process > Compiler
optimization level parameter. The Compiler optimization level parameter provides
If you specify compiler options for your makefile build using OPT_OPTS, MEX_OPTS
(except MEX_OPTS="-v"), or MEX_OPT_FILE, the value of Compiler optimization level
is ignored and a warning is issued about the ignored parameter.
• ert_unix.tmf
• grt_unix.tmf
8. IEEE is a registered trademark of The Institute of Electrical and Electronics Engineers, Inc.
43-27
43 Program Building, Interaction, and Debugging in Simulink Coder
• rsim_unix.tmf
• rtwsfcn_unix.tmf
You can supply options to makefiles using the Make command box in the Configuration
Parameters > Code Generation pane. Options specified in Make command are passed
to the command-line invocation of the make utility, which adds them to the overall flags
passed to the compiler. The following options can be used to modify the behavior of the
build:
OPTS="-DMYDEFINE=1"
• OPT_OPTS— Optimization options. Default is -O. To enable debugging, specify the
option as OPT_OPTS=-g. Because of optimization problems in IBM_RS, the default is
no optimization.
• CPP_OPTS — C++ compiler options.
• USER_SRCS — Additional user sources, such as files used by S-functions.
• USER_INCLUDES — Additional include paths, for example,
USER_INCLUDES="-Iwhere-ever -Iwhere-ever2"
• DEBUG_BUILD — Add debug information to generated code, for example,
DEBUG_BUILD=1
These options are also documented in the comments at the head of the respective
template makefiles.
To build an executable using the Visual C++ compiler within the build process, use one of
the target_vcx64.tmf template makefiles:
• ert_vcx64.tmf
• grt_vcx64.tmf
43-28
Template Makefiles and Make Options
• rsim_vcx64.tmf
• rtwsfcn_vcx64.tmf
You can supply options to makefiles using the Make command field in the
Configuration Parameters > Code Generation pane. Options specified in Make
command are passed to the command-line invocation of the make utility, which adds
them to the overall flags passed to the compiler. The following options can be used to
modify the behavior of the build:
USER_INCLUDES="-Iwhere-ever -Iwhere-ever2"
• DEBUG_BUILD — Add debug information to generated code, for example,
DEBUG_BUILD=1
These options are also documented in the comments at the head of the respective
template makefiles.
To create a Visual C++ project makefile (model.mak) without building an executable, use
one of the target_msvc.tmf template makefiles:
• ert_msvc.tmf
• grt_msvc.tmf
These template makefiles are for nmake, which is bundled with the Visual C++ compiler.
You can supply options to makefiles using the Make command field in the
Configuration Parameters > Code Generation pane. Options specified in Make
command are passed to the command-line invocation of the make utility, which adds
them to the overall flags passed to the compiler. The following options can be used to
modify the behavior of the build:
43-29
43 Program Building, Interaction, and Debugging in Simulink Coder
OPTS="/D MYDEFINE=1"
• USER_SRCS — Additional user sources, such as files used by S-functions.
• USER_INCLUDES — Additional include paths, for example,
USER_INCLUDES="-Iwhere-ever -Iwhere-ever2"
• DEBUG_BUILD — Add debug information to generated code, for example,
DEBUG_BUILD=1
These options are also documented in the comments at the head of the respective
template makefiles.
• ert_lcc.tmf
• grt_lcc.tmf
• rsim_lcc.tmf
• rtwsfcn_lcc.tmf
You can supply options to makefiles using the Make command field in the
Configuration Parameters > Code Generation pane. Options specified in Make
command are passed to the command-line invocation of the make utility, which adds
them to the overall flags passed to the compiler. The following options can be used to
modify the behavior of the build:
OPTS="-DMYDEFINE=1"
• OPT_OPTS — Optimization options. Default is no options. To enable debugging, specify
-g4:
OPT_OPTS="-g4"
• CPP_OPTS — C++ compiler options.
• USER_SRCS — Additional user sources, such as files used by S-functions.
43-30
See Also
USER_INCLUDES="-Iwhere-ever -Iwhere-ever2"
For lcc, use / as file separator before the file name instead of \, for example, d:
\work\proj1/myfile.c.
• DEBUG_BUILD — Add debug information to generated code, for example,
DEBUG_BUILD=1
These options are also documented in the comments at the head of the respective
template makefiles.
See Also
More About
• “Configure a System Target File” on page 33-2
• “Customize System Target Files” (Simulink Coder)
• “Associate the Template Makefile with a Toolchain” on page 43-23
43-31
43 Program Building, Interaction, and Debugging in Simulink Coder
Working Folder
This example uses a local copy of the slexAircraftExample model, stored in its own
folder, aircraftexample. Set up your working folder as follows:
1 In the MATLAB Current Folder browser, navigate to a folder to which you have write
access.
2 To create the working folder, enter the following MATLAB command:
mkdir aircraftexample
3 Make aircraftexample your working folder:
cd aircraftexample
4 Open the slexAircraftExample model:
slexAircraftExample
When a model contains Model blocks (references to other models), the model build
creates special subfolders in your “Code generation folder” (Simulink) to organize code
43-32
Build Process Workflow for Real-Time Systems
for the referenced models. These code generation folders exist alongside product build
folders and are named slprj. “Generate Code for Referenced Models” on page 4-4
describes navigating code generation folder structures in Model Explorer.
Under the slprj folder, a subfolder named _sharedutils contains generated code that
can be shared between models.
Note The code generator produces code for models, using variable-step solvers, for rapid
simulation (rsim) and S-function system target files only.
To set model configuration parameters by using the Configuration Parameters dialog box:
43-33
43 Program Building, Interaction, and Debugging in Simulink Coder
In these examples and in most applications, you do not need to specify these parameters
individually. The examples use the ready-to-run generic real-time target (GRT)
configuration. The GRT system target file builds a standalone executable program that
runs on your desktop computer.
To select the GRT system target file using the Configuration Parameters dialog box:
The Configuration Parameters > Code Generation pane displays selections for
the System target file (grt.tlc), Toolchain (Automatically locate an
installed toolchain), and Build Configuration (Faster Builds).
43-34
Build Process Workflow for Real-Time Systems
Note If you click Browse, a System Target File Browser opens and displays the
system target files on the MATLAB path. Some system target files require additional
products. For example, ert.tlc requires Embedded Coder.
4 Save the model.
43-35
43 Program Building, Interaction, and Debugging in Simulink Coder
1 Select Code Generation > Report > Create code generation report. This action
enables the software to create and display a code generation report for the
myAircraftExample model.
2 Use the default Code Generation > Commentssettings.
3 The Code Generation > Symbols options control the look and feel of generated
code. Use the default settings.
4 These Code Generation > Advanced parameters parameters control build
verbosity and debugging:
• For the Shared code placement parameter, select Shared location. The build
process places generated code for utilities in a subfolder within your “Code
generation folder” (Simulink).
• Clear the Advanced parameters > Classic call interfacecheck box.
6 Click Apply and save the model.
1 With the myAircraftExample model open, initiate code generation and the build
process for the model by using any of the following options:
43-36
Build Process Workflow for Real-Time Systems
Some messages concerning code generation and compilation appear in the Command
Window. The initial message is:
### Starting build procedure for model: myAircraftExample
The contents of many of the succeeding messages depends on your compiler and
operating system. The final messages include:
### Created executable myAircraftExample.exe
### Successful completion of build procedure for model: myAircraftExample
### Creating HTML report file myAircraftExample_codegen_rpt.html
Note After generating the code for the myAircraftExample model, the build
process displays a code generation report. See “Report Generation” (Simulink Coder)
for more information about how to create and use a code generation report.
2 To see the contents of the working folder after the build, enter the dir or ls
command:
>> dir
. myAircraftExample.slx slprj
.. myAircraftExample.slx.autosave
myAircraftExample.exe myAircraftExample_grt_rtw
3 To run the executable from the Command Window, type !myAircraftExample.
The ! character passes the command that follows it to the operating system, which
runs the standalone myAircraftExample program.
>> !myAircraftExample
43-37
43 Program Building, Interaction, and Debugging in Simulink Coder
. rt_main.obj myAircraftExample_data.c
.. rtmodel.h myAircraftExample_data.obj
buildInfo.mat rtw_proj.tmw myAircraftExample_private.h
codeInfo.mat myAircraftExample.bat myAircraftExample_ref.rsp
defines.txt myAircraftExample.c myAircraftExample_types.h
html myAircraftExample.h
modelsources.txt myAircraftExample.mk
rt_logging.obj myAircraftExample.obj
File Description
myAircraftExample.c Standalone C code that implements the model
myAircraftExample.h An include header file containing definitions of
parameters and state variables
myAircraftExample_private.h Header file containing common include
definitions
myAircraftExample_types.h Forward declarations of data types used in the
code
rtmodel.h Master header file for including generated code
in the static main program (its name does not
change, and it simply includes
myAircraftExample.h)
The code generation report that you created for the myAircraftExample model displays
a link for each of these files. You can click the link explore the file contents.
The build folder contains other files used in the build process. They include:
43-38
See Also
The build folder also contains a subfolder, html, which contains the files that make up the
code generation report. For more information, see “Reports for Code Generation”
(Simulink Coder).
• If you use the toolchain approach, the code generator creates model.mk based on the
model Toolchain settings. You can modify generation of the makefile through the
rtwmakecfg.m API.
• If you use the template makefile approach, the code generator creates model.mk from
a system template file, system.tmf (where system stands for the selected system
target file name). The system template makefile is designed for your system target file.
You can modify the template makefile to specify compilers, compiler options, and
additional information for the creation of the executable.
For more information, see “Choose Build Approach and Configure Build Process” on page
43-14.
See Also
More About
• “Choose Build Approach and Configure Build Process” on page 43-14
• “Manage Build Process Folders” (Simulink Coder)
43-39
43 Program Building, Interaction, and Debugging in Simulink Coder
43-40
Rebuild a Model
Rebuild a Model
If you update generated source code or makefiles manually to add customizations, you
can rebuild the files with the rtwrebuild command. This command recompiles the
modified files by invoking the generated makefile. Alternatively, you can use this
command from the Model Explorer:
1 Open the top model. To open the Model Explorer window, select View > Model
Explorer.
2 In the Model Hierarchy pane, expand the node for the model.
3 Click the Code for model node.
4 In the Code pane, next to Code Recompile Command, click rebuild generated
code.
43-41
43 Program Building, Interaction, and Debugging in Simulink Coder
See Also
More About
• rtwrebuild
• “Build Process Workflow for Real-Time Systems” (Simulink Coder)
43-42
Control Regeneration of Top Model Code
Whether the top model code is regenerated, the build process calls the build process
hooks and reruns the makefile. The hooks include the STF_make_rtw_hook functions
and the post code generation command. This process recompiles and links the external
dependencies.
System target file authors can perform actions related to code regeneration in the
STF_make_rtw_hook functions that the build process calls. These actions include forcing
or reacting to code regeneration. For more information, see “Control Code Regeneration
Using STF_make_rtw_hook.m” on page 73-34.
The build process omits regeneration of the top model code when the checks indicate
both:
43-43
43 Program Building, Interaction, and Debugging in Simulink Coder
With an Embedded Coder license, if you modify a code generation template (CGT) file
then rebuild your model, the code generation process does not force a top model build. In
this case, see “Force Regeneration of Top Model Code” on page 43-44.
• To ignore the checksum and force regeneration of the top model code:
• rtwbuild(model,'ForceTopModelBuild',true)
• slbuild(model,'StandaloneRTWTarget','ForceTopModelBuild',true)
• To clean the model build area enough to trigger regeneration of the top model code at
the next build (slbuild only):
slbuild(model,'CleanTopModel')
You can force regeneration of the top model code by deleting the slprj folder or the
generated model code folder from the “Code generation folder” (Simulink) .
See Also
More About
• rtwrebuild
• “Control Code Regeneration Using STF_make_rtw_hook.m” on page 73-34
• “Choose Build Approach and Configure Build Process” on page 43-14
• “Rebuild a Model” on page 43-41
• “Reduce Build Time for Referenced Models” on page 43-45
43-44
Reduce Build Time for Referenced Models
In this section...
“Parallel Building for Large Model Reference Hierarchies” on page 43-45
“Parallel Building Configuration Requirements” on page 43-46
“Build Models in a Parallel Computing Environment” on page 43-46
“Locate Parallel Build Logs” on page 43-48
“View Build Process Status” on page 43-50
“Apply Build Process Status to Improve Parallel Builds” on page 43-51
For configuration requirements that could apply to your parallel computing environment,
see “Parallel Building Configuration Requirements” on page 43-46.
For a description of the general workflow for building referenced models in parallel
whenever conditions allow, see “Build Models in a Parallel Computing Environment” on
page 43-46.
For information on how to configure a custom embedded system target file to support
parallel builds, see “Support Model Referencing” (Simulink Coder).
43-45
43 Program Building, Interaction, and Debugging in Simulink Coder
• For local pools, the host machine must have enough RAM to support the number of
local workers (MATLAB sessions) that you plan to use. For example, using
parpool(4) to create a parallel pool with four workers results in five MATLAB
sessions on your machine. Each pool uses the amount of memory required for MATLAB
and the code generator at startup. For memory requirements, see System
Requirements for MATLAB & Simulink.
• Remote MATLAB Distributed Computing Server workers participating in a parallel
build and the client machine must use a common platform and compiler.
• A consistent MATLAB environment must be set up in each MATLAB worker session as
in the MATLAB client session — for example, shared base workspace variables,
MATLAB path settings, and so forth. One approach is to use the PreLoadFcn callback
of the top model. If you configure your model to load the top model with each MATLAB
worker session, its preload function can be used for any MATLAB worker session
setup.
43-46
Reduce Build Time for Referenced Models
parallel model reference builds (Simulink) option. This selection enables the
parameter MATLAB worker initialization for builds (Simulink).
For MATLAB worker initialization for builds, select one of the following values:
• None if it is preferable that the software does not perform special worker
initialization. Specify this value if the child models in the model reference
hierarchy do not rely on anything in the base workspace beyond what they
explicitly set up. An example is a model load function.
• Copy base workspace if it is preferable that the software attempts to copy the
base workspace to each worker. Specify this value if you use a setup script to
prepare the base workspace for multiple models to use.
43-47
43 Program Building, Interaction, and Debugging in Simulink Coder
• Load top model if it is preferable that the software loads the top model on each
worker. Specify this value if the top model in the model reference hierarchy
handles the base workspace setup. An example is a model load function.
Note Only set Enable parallel model reference builds for the top model of the
model reference hierarchy to which it applies.
3 Optionally, turn on verbose messages for simulation builds, code generation builds, or
both. If you select verbose builds, the build messages report the progress of each
parallel build with the name of the model.
Verbose options control the build messages in the MATLAB Command Window and in
parallel build log files.
4 Optionally, inspect the model reference hierarchy to determine, based on model
dependencies, which models are built in parallel. For example, you can use the Model
Dependency Viewer from the Simulink Analysis > Model Dependencies menu.
5 Build your model. Messages in the MATLAB Command Window record when each
parallel or serial build starts and finishes. The order in which referenced models
build is nondeterministic. They could build in a different order each time the model is
built.
If you need more information about a parallel build, for example, if a build fails, see
“Locate Parallel Build Logs” on page 43-48.
43-48
Reduce Build Time for Referenced Models
To obtain more detailed information about a parallel build, you can examine the parallel
build log. For each referenced model built in parallel, the build process generates a file
named model_buildlog.txt, where model is the name of the referenced model. This
file contains the full build log for that model.
If a parallel build completes, you can find the build log file in the build subfolder
corresponding to the referenced model. For example, for a build of referenced model
bot_model004, look for the build log file bot_model004_buildlog.txt in a
referenced model subfolder such as build_folder/slprj/grt/bot_model004,
build_folder/slprj/ert/bot_model004, or build_folder/slprj/sim/
bot_model004. The build log (diagnostic viewer) provides a relative path to the location
of each build log file.
If a parallel builds fails, you could see output similar to the following:
### Initializing parallel workers for parallel model reference build.
### Parallel worker initialization complete.
...
### Starting parallel model reference RTW build for 'bot_model002'
### Starting parallel model reference RTW build for 'bot_model003'
### Finished parallel model reference RTW build for 'bot_model002'
### Finished parallel model reference RTW build for 'bot_model003'
### Starting parallel model reference RTW build for 'bot_model001'
### Starting parallel model reference RTW build for 'bot_model004'
### Finished parallel model reference RTW build for 'bot_model004'
### The following error occurred during the parallel model reference RTW build for
'bot_model001':
If a parallel build fails, you can find the build log file in a referenced model subfolder
under the build subfolder /par_mdl_ref/model. For example, for a failed parallel build
of model bot_model001, look for the build log file bot_model001_buildlog.txt in a
43-49
43 Program Building, Interaction, and Debugging in Simulink Coder
Note The Build Process Status window support parallel builds of referenced model
hierarchies. Do not use the Build Process Status window for sequential (non-parallel)
builds.
To open the Build Process Status window, use any of these options:
• To open the Build Process Status window for a model, in the command window,
type:
coder.buildstatus.open('model')
• To open the Build Process Status window for a model with the rtwbuild function,
in the command window, type:
rtwbuild('model', ...
'OpenBuildStatusAutomatically',true)
• To open the Build Process Status window for a model with the slbuild function, in
the command window, type:
slbuild('model','StandaloneRTWTarget', ...
'OpenBuildStatusAutomatically',true)
To cancel an in-progress model build, the Build Process Status window provides a
Cancel button. This button cancels the build after completion of the current model or
referenced model build. Using cancel to stop a build ends a build process without
creating out-dated build artifacts that require post-build clean up.
43-50
Reduce Build Time for Referenced Models
This example shows how apply build process status from parallel builds. The status
information can help you identify ways to improve parallel builds by modifying the
referenced model hierarchy.
parpool('local', 2)
2 Open the top-level model in a reference model hierarchy. The a_1 model refers to a
number of referenced models.
open_system('a_1')
43-51
43 Program Building, Interaction, and Debugging in Simulink Coder
43-52
Reduce Build Time for Referenced Models
3 View the model dependencies with Analysis > Model Dependencies > Model
Dependency Viewer > Models Only. This view displays the dependencies for the
referenced model hierarchy.
During the build process, the Build Process Status window displays the progress of
the code generator as it works its way up the referenced model hierarchy. The code
generator builds the referenced models in the order that they block building of
models further up the dependency tree.
4 Start a parallel build of the referenced model hierarchy and open the Build Process
Status window.
rtwbuild('a_1','OpenBuildStatusAutomatically',true)
5 As the build progresses, the Build Process Status window displays the status for each
referenced model.
43-53
43 Program Building, Interaction, and Debugging in Simulink Coder
43-54
See Also
The elapse time shows you where the build process spends time. Use the dependency tree
of the model hierarchy and the elapse time of reference model builds to identify locations
where the build process spends the most time and restricts the build progress. Some
options for reducing the parallel build time include:
• Restructure the referenced model hierarchy to reduce build time for individual
models.
• Provide sufficient parallel workers in the pool to match the number of referenced
model dependencies being built.
See Also
coder.buildstatus.close | coder.buildstatus.open | rtwbuild | slbuild
More About
• “Control Regeneration of Top Model Code” on page 43-43
• “Reduce Update Time for Referenced Models” (Simulink)
• “Build Process Workflow for Real-Time Systems” (Simulink Coder)
• “Profile Code Performance” on page 43-72
• “Support Model Referencing” on page 74-84
43-55
43 Program Building, Interaction, and Debugging in Simulink Coder
In this section...
“Code Relocation” on page 43-56
“Package Code Using the User Interface” on page 43-56
“Package Code Using the Command-Line Interface” on page 43-58
“Build Integrated Code Outside the Simulink Environment” on page 43-61
“packNGo Function Limitations” on page 43-67
Code Relocation
The pack-n-go utility uses the tools for customizing the build process after code
generation and a packNGo function to find and package files for building an executable
image. The files are packaged in a compressed file that you can relocate and unpack
using a standard zip utility.
• Use the model option Package code and artifacts (Simulink Coder) in the
Configuration Parameters > Code Generation pane. See “Package Code Using the
User Interface” on page 43-56.
• Use MATLAB commands to configure a PostCodeGenCommand parameter with a call
to the packNGo function. See “Package Code Using the Command-Line Interface” on
page 43-58. The command-line interface provides more control over the details of
code packaging.
43-56
Relocate Code to Another Development Environment
2 Select the option Package code and artifacts (Simulink Coder). This option
configures the build process to run the packNGo function after code generation to
package generated code and artifacts for relocation.
3 In the Zip file name (Simulink Coder) field, enter the name of the zip file in which
to package generated code and artifacts for relocation. You can specify the file name
with or without the .zip extension. If you specify no extension or an extension other
than .zip, the zip utility adds the.zip extension. If you do not specify a value, the
build process uses the name model.zip, where model is the name of the top model
for which code is being generated.
43-57
43 Program Building, Interaction, and Debugging in Simulink Coder
4 Apply changes and generate code for your model. To verify that it is ready for
relocation, inspect the resulting zip file. Depending on the zip tool that you use, you
could be able to open and inspect the file without unpacking it.
5 Relocate the zip file to the destination development environment and unpack the
file.
Before you generate and package the files for a model build, decide whether you want the
files to be packaged in a flat or hierarchical folder structure. By default, the packNGo
function packages the files in a single, flat folder structure.
If you use a hierarchical structure, the packNGo function creates two levels of zip files, a
primary zip file, which in turn contains the following secondary zip files:
43-58
Relocate Code to Another Development Environment
• sDirFiles.zip — files in and under your build folder where you initiated code
generation for the model
• otherFiles.zip — required files not in the matlabroot or start folder trees
Paths for the secondary zip files are relative to the root folder of the primary zip file,
maintaining the source development folder structure.
By default, the packNGo function names the primary zip file model. You have the option
of specifying a different name. If you specify a file name and omit the file type extension,
the function appends . to the name that you specify.
In this case, before generating the model code, use set_param to set the
configuration parameter PostCodeGenCommand to an explicit call to the packNGo
function. For example:
set_param(bdroot, 'PostCodeGenCommand', 'packNGo(buildInfo);');
After generating and writing the model code to disk and before generating a makefile,
this command instructs the build process to evaluate the call to packNGo. This
command uses the system generated build information object for the currently
selected model.
• A build information object that you construct programmatically.
In this case, you could use other build information functions to include paths and files
selectively in the build information object that you then specify with the packNGo
function. For example:
.
.
.
myModelBuildInfo = RTW.BuildInfo;
addSourceFiles(myModelBuildInfo, {'test1.c' 'test2.c' 'driver.c'});
.
.
43-59
43 Program Building, Interaction, and Debugging in Simulink Coder
.
packNGo(myModelBuildInfo);
The following examples show how you can change the default behavior of packNGo.
To... Specify...
Change the structure of the file packNGo(buildInfo, {'packType'
packaging to hierarchical 'hierarchical'});
Rename the primary zip file packNGo(buildInfo, {'fileName'
'zippedsrcs'});
Change the structure of the file packNGo(buildInfo, {'packType'
packaging to hierarchical and rename 'hierarchical'...
the primary zip file 'fileName' 'zippedsrcs'});
Include header files found on the packNGo(buildInfo, {'minimalHeaders' false});
include path in the zip file
Generate warnings for parse errors packNGo(buildInfo, {'ignoreParseError'
and missing files true...
'ignoreFileMissing' true});
Note The packNGo function can potentially modify the build information passed in the
first packNGo argument. As part of packaging model code, packNGo could find additional
files from source and include paths recorded in build information for the model and add
them to the build information.
To verify that it is ready for relocation, inspect the generated zip file. Depending on the
zip tool that you use, you could be able to open and inspect the file without unpacking it.
If unpacking the file and you packaged the model code files as a hierarchical structure,
unpacking requires you to unpack the primary and secondary zip files. When you unpack
the secondary zip files, relative paths of the files are preserved.
Relocate the generated zip file to the destination development environment and unpack
the file.
43-60
Relocate Code to Another Development Environment
This example shows how to package code files generated for the example model
rtwdemo_rtwintro using the command-line interface:
You must double the single-quotes due to the nesting of character arrays
'packType' and 'hierarchical' within the character array that specifies the call
to packNGo.
4 Generate code for the model.
5 Inspect the generated zip file, rtwdemo_rtwintro.zip. The zip file contains the
two secondary zip files, mlrFiles.zip and sDirFiles.zip.
6 Inspect the zip files mlrFiles.zip and sDirFiles.zip.
7 Relocate the zip file to a destination environment and unpack it.
For information about the example model and related examples, see “Generate C Code
from a Control Algorithm for an Embedded System”.
The code that Embedded Coder® generates requires support files that MathWorks®
provides. To relocate the generated code to another development environment, such as a
dedicated build system, you must relocate these support files. You can package these files
in a zip file by using the packNGo utility. This utility finds and packages the files that you
43-61
43 Program Building, Interaction, and Debugging in Simulink Coder
need to build an executable image. The utility uses tools for customizing the build process
after code generation, which include a buildinfo_data structure, and a packNGo
function. These files include external files that you identify in the Code Generation >
Custom Code pane in the Model Configuration Parameters dialog box. The utility saves
the buildinfo MAT-file in the model_ert_rtw folder.
The number of files in the zip file depends on the version of Embedded Coder® and on
the configuration of the model that you use. The compiler does not require all of the files
in the zip file. The compiled executable size (RAM/ROM) depends on the linking process.
The linker likely includes only the object files that are necessary.
This example shows how to integrate the generated code into an existing code base. The
example uses the Eclipse™ IDE and the Cygwin™/gcc compiler. The required integration
tasks are common to all integration environments.
A full embedded controls system consists of multiple hardware and software components.
Control algorithms are just one type of component. Other components can be:
Typically, you do not use the generated code in these components. Instead, the generated
code includes interfaces that connect with these components. MathWorks® provides
43-62
Relocate Code to Another Development Environment
hardware interface block libraries for many common embedded controllers. For examples,
see the Embedded Targets block library.
This example provides files to show how you can build a full system. The main file is
example_main.c, which contains a simple main function that performs only basic
actions to exercise the code.
View example_main.c.
The file:
43-63
43 Program Building, Interaction, and Debugging in Simulink Coder
The order of function execution matches the order of subsystem execution in the test
harness model and in rtwdemo_PCG_Eval_P5.h. If you change the order of execution in
example_main.c, results that the executable image produces differ from simulation
results.
Integration requires matching the Data and Function interfaces of the generated code
and the existing system code. In this example, the example_main.c file imports and
exports the data through #include statements and extern declarations. The file also
calls the functions from the generated code.
The system has three input signals: pos_rqst, fbk_1, and fbk_2. The generated code
accesses the two feedback signals through direct reference to imported global variables
(storage class ImportedExtern). The code accesses the position signal through an
imported pointer (storage class ImportedExternPointer).
The handwritten file defineImportedData.c defines the variables and the pointer. The
generated code does not define the variables and the pointer because the handwritten
code defines them. Instead, the generated code declares the imported data (extern) in
the file rtwdemo_PCG_Eval_P5_Private.h. In a real system, the data typically comes
from other software components or from hardware devices.
View defineImportedData.c.
43-64
Relocate Code to Another Development Environment
View rtwdemo_PCG_Eval_P5_Private.h.
In this example, you do not access the output data of the system. The example “Test
Generated Code” shows how you can save the output data to a standard log file. You can
access the output data by referring to the file rtwdemo_PCG_Eval_P5.h.
View rtwdemo_PCG_Eval_P5.h.
The generated code contains several structures that store commonly used data including:
43-65
43 Program Building, Interaction, and Debugging in Simulink Coder
The table lists the common data structures. Depending on the configuration of the model,
some or all of these structures appear in the generated code. The data is declared in the
file rtwdemo_PCG_Eval_P5.h, but in this example, you do not access this data.
By default, functions that the code generator generates have a void Func(void)
interface. If you configure the model or atomic subsystem to generate reentrant code, the
code generator creates a more complex function prototype. In this example, the
example_main function calls the generated functions with the correct input arguments.
This example uses the Eclipse™ IDE and the Cygwin™ GCC debugger to build the
embedded system. The example provides installation files for both programs. Software
components and versions numbers are:
43-66
Relocate Code to Another Development Environment
To install and use Eclipse™ and GCC, see “Install and Use Cygwin and Eclipse”.
You can install the files for this example by clicking this hyperlink:
You can use the Eclipse™ debugger to step through and evaluate the execution behavior
of the generated C code. See the example “Install and Use Cygwin and Eclipse”.
To exercise the model with input data, see “Test Generated Code”.
Related Topics
• “Generate Component Source Code for Export to External Code Base” on page 42-52
• “Generate Shared Library for Export to External Code Base” on page 42-73
• The function operates on source files, such as *.c, *.cpp, and *.h files, only. The
function does not support compile flags, defines, or makefiles.
• Unnecessary files could be included. The function could find additional files from
source and include paths recorded in build information for the model and include
them, even if they are not used.
43-67
43 Program Building, Interaction, and Debugging in Simulink Coder
See Also
More About
• packNGo
• “Choose Build Approach and Configure Build Process” on page 43-14
• “Build Process Workflow for Real-Time Systems” (Simulink Coder)
• “Executable Program Generation” on page 43-69
43-68
Executable Program Generation
Click Build
Button
Custom
Template Generate Makefile
Makefile Makefile
model.mk
Create No
Executable?
Yes
Invoke
make
Stop
During the final stage of processing, the build process invokes the generated makefile,
model.mk, which in turn compiles and links the generated code. On PC platforms, a
batch file is created to invoke the generated makefile. The batch file sets up the
environment for invoking the make utility and related compiler tools. To avoid recompiling
C files, the make utility performs date checking on the dependencies between the object
and C files; only out-of-date source files are compiled. Optionally, the makefile can
download the resulting executable image to your target hardware.
43-69
43 Program Building, Interaction, and Debugging in Simulink Coder
This stage is optional, as illustrated by the control logic in the preceding figure. You could
choose to omit this stage (for example, if you are targeting an embedded microcontroller
board).
To omit this stage of processing, select the Configuration Parameters > Code
Generation pane and select the Generate code only check box. You can then cross-
compile your code and download it to your target hardware.
If you select the Configuration Parameters > Code Generation > Report pane and
select Create code generation report, the code generator produces a navigable
summary of source files when the model is built. The report files occupy a folder called
html within the build folder. The following display shows an example of an HTML code
generation report for a generic real-time (GRT) system target file.
43-70
See Also
See Also
More About
• “Choose Build Approach and Configure Build Process” on page 43-14
• “Build Process Workflow for Real-Time Systems” (Simulink Coder)
• “Executable Program Generation” on page 43-69
43-71
43 Program Building, Interaction, and Debugging in Simulink Coder
Profiling can be especially important early in the development cycle for identifying
potential architectural issues that can be more expensive to address later in the process.
Profiling can also identify bottlenecks and procedural issues that indicate a need for
optimization, for example, with an inner loop or inline code.
Note If you have an Embedded Coder license, see “Code Execution Profiling” for an
alternative and simpler approach based on software-in-the-loop (SIL) or processor-in-the-
loop (PIL) simulations.
In this section...
“Use the Profile Hook Function Interface” on page 43-72
“Profile Hook Function Interface Limitation” on page 43-75
1 For your system target file, create a TLC file that defines the following hook
functions. Write the functions so that they specify profiling code. The code generator
adds the hook function code to code generated for atomic systems in the model.
43-72
Profile Code Performance
43-73
43 Program Building, Interaction, and Debugging in Simulink Coder
Define... To Be...
ProfileGenCode TLC_TRUE or 1 to turn on profiling (TLC_FALSE
or 0 to turn off profiling)
ProfilerTLC The name of the TLC file that you created in step
1
A quick way to define global variables is to define the parameters with the -a option.
You can apply this option by using the set_param command to set the model
configuration parameter TLCOptions. For example,
>> set_param(gcs,'TLCOptions', ...
'-aProfileGenCode=1 -aProfilerTLC="rtwdemo_profile_hook.tlc"')
3 Consider setting configuration parameters for generating a code generation report.
You can then examine the profiling code in the context of the code generated for the
model.
4 Build the model. The build process embeds the profiling code in the hook function
locations in the generated code for the model.
5 Run the generated executable file. In the MATLAB Command Window, enter !model-
name. You see the profiling report you programmed in the profiling TLC file that you
created. For example, a profile report could list the number of calls made to each
system in a model and the number of CPU cycles spent in each system.
For details on programming a .tlc file and defining TLC configuration variables, see
“Target Language Compiler” (Simulink Coder).
43-74
See Also
See Also
More About
• “Build Process Workflow for Real-Time Systems” (Simulink Coder)
• “Code Execution Profiling”
43-75
44
Host/Target Communication in
Simulink Coder
• Modify or tune block parameters in real time. When you change parameters in the
model, Simulink downloads the new values to the executing target application.
• Monitor and save signal data from the executing target application.
The low-level transport layer of the channel handles the physical transmission of
messages. Simulink and the generated model code are independent of this layer. The
transport layer and its interface code are isolated in separate modules that format,
transmit, and receive messages and data packets.
44-2
Host-Target Communication with External Mode Simulation
Simulink supports two communication mechanisms for external mode simulation. This
table can help you to decide which mechanism to use.
44-3
44 Host/Target Communication in Simulink Coder
44-4
Host-Target Communication with External Mode Simulation
This table summarises feature support for both forms of external mode simulations.
44-5
44 Host/Target Communication in Simulink Coder
See matlabroot/
simulink/include/
simstruc.h.
XY Graph Yes, provided signal Yes
logging is enabled
for block input.
Signal Viewing Subsystem on page 44-64 Yes, provided signal Yes
logging is enabled
for subsystem input.
44-6
See Also
See Also
More About
• “External Mode Simulation with XCP Communication” on page 44-8
• “Customize XCP Slave Software” on page 44-22
• “External Mode Simulation with TCP/IP or Serial Communication” on page 44-36
• “Create a Transport Layer for TCP/IP or Serial External Mode Communication” on
page 44-90
44-7
44 Host/Target Communication in Simulink Coder
• Monitor a signal with a Scope block, a Dashboard block, and the Simulation Data
Inspector.
• Tune a parameter with a Dashboard block.
Configure Signal Monitoring and Parameter Tuning for XCP External Mode
mkdir ext_mode_xcp_example
cd ext_mode_xcp_example
2 Open Simulink and create a simple model, xcpExample, which contains these blocks:
• Sine Wave
• Scope
• Half Gauge
• Knob
3 Double-click the Sine Wave block. Set Sample time to 0.1, and then click OK.
4 Connect the Sine Wave block to the Scope block, and name the connection, for
example, Test Signal.
5 Configure the signal for logging:
44-8
External Mode Simulation with XCP Communication
• Connect the block to the Amplitude parameter of the Sine Wave block.
• In the Minimum and Maximum fields, enter values, for example, 0.1 and 1
respectively.
d Click OK.
8 Save the model.
44-9
44 Host/Target Communication in Simulink Coder
• Select the Generate an example main program check box. The code generator
uses matlabroot\toolbox\coder\xcp\src\target\ext_mode\include
\ext_mode.h to produce an example main file, ert_main.c.
• Set Target operating system to BareBoardExample.
10 Click OK. Then save the model.
11 Press Ctrl+B. The build process generates source code and creates the executable
file.
44-10
External Mode Simulation with XCP Communication
In Linux, the build process places DWARF format debugging information in the created
ELF executable file, xcpExample.
1 Open a command window for your operating system and navigate to the
ext_mode_xcp_example folder.
2 In the command window, enter:
• -w (optional) specifies that the target application enters a wait state until it
receives a message from Simulink. The target application runs but does not yet
execute model code.
If you do not specify -w, the target application executes model code immediately.
The model code runs with parameter values from the time when you built the
model.
• -tf inf (optional) specifies that, when model code is executed, the model runs
indefinitely. Use this option to override the model parameter, StopTime.
3 Connect Simulink to the target application:
44-11
44 Host/Target Communication in Simulink Coder
To change the amplitude of the sine wave, rotate the pointer on the Knob block to the
required value.
You can also use these methods to tune tunable (Simulink) block parameters during a
simulation:
For more information about parameter tuning with generated code, see:
To stop the execution of generated model code (before StopTime is reached) and
disconnect the target application, on the Simulink Editor toolbar, click the Stop button.
If you want to disconnect the target application from Simulink without stopping code
Argument Description
-w Specify that the target application enters and stays in a
wait state until it receives a message from Simulink.
44-12
External Mode Simulation with XCP Communication
Argument Description
-tf time Override the model parameter, StopTime. -tf inf
specifies that the model runs indefinitely when model code
is executed.
For host-based external mode simulations, you can specify additional rtiostream on
page 67-48 arguments.
Argument Description
-verbose level Specify verbosity level:
• 0 –– No information
• 1 –– Detailed information
-port number For XCP on TCP/IP transport layer,
specify port number of TCP/IP server. An
integer value between 256 and 65535.
Default is 17725.
44-13
44 Host/Target Communication in Simulink Coder
This table gives the controls that you can use for an XCP external mode simulation.
44-14
External Mode Simulation with XCP Communication
44-15
44 Host/Target Communication in Simulink Coder
These commands assume that a Simulink model is open and a target application is
running:
44-16
External Mode Simulation with XCP Communication
set_param(gcs,'SimulationMode','external');
2 Connect Simulink to the target application.
set_param(gcs,'SimulationCommand','connect')
3 Run generated model code.
set_param(gcs,'SimulationCommand','start');
4 To tune a parameter, change its workspace variable value through a line command.
For example, if a block parameter value is specified as a Simulink.Parameter
object, assign the new value to the Value property.
myParamObj.Value = 5.23;
5 To download the new value to the target application, update the model.
set_param(gcs,'SimulationCommand','update');
6 Stop the target application and disconnect Simulink from the target environment.
set_param(gcs,'SimulationCommand','stop');
set_param(gcs,'SimulationCommand','disconnect');
44-17
44 Host/Target Communication in Simulink Coder
Feature Details
Parameter updates that change You cannot change, for example:
model structure
• The number of states, inputs, or outputs of a
block
• The sample time or the number of sample times
• The integration algorithm for continuous systems
• The name of the model or of a block
• The parameters to the Fcn block
44-18
External Mode Simulation with XCP Communication
Feature Details
referenced models. Use the updated block diagram
to rebuild the target application.
Signal value display The graphical display of signal values during a
simulation is not supported. For example, you cannot
use the Data Display in Simulation menu items
Show Value Labels When Hovering, Toggle
Value Labels When Clicked, and Show Value
Label of Selected Port. For more information, see
“Displaying Signal Values in Model Diagrams”
(Simulink).
Signal triggering and data The Signal & Triggering, Arm Trigger, Cancel
archiving Trigger, and Data Archiving features, which are
available on the External Mode Control Panel, are
not supported.
Signal streaming Dynamic selection of signals for streaming is not
supported. If want to select different signals for
streaming, you must rebuild the model.
Overriding signal logging settings Overriding signal logging settings with the Signal
Logging Selector is not supported.
Compiler debug symbol format Your toolchain must generate debug information in
one of these formats:
• DWARF
• PDB
Inlined parameters If you set DefaultParameterBehavior to
'Inlined', the code generator embeds numerical
model parameter values (instead of symbolic
parameter names) in the generated code. You can
use Simulink.Parameter objects to remove
parameters from inlining and declare the
parameters tunable. However, when you connect
Simulink to the target application, the numerical
values of the tunable parameters are not
automatically uploaded to the model. Simulink
produces a warning.
44-19
44 Host/Target Communication in Simulink Coder
Feature Details
Global variables Signals, parameters, and states must be specified as
global variables. The target memory addresses at
which the variables are stored must lie in the range
0 – 4294967295.
Stateflow animation As uploading of DWork data during the model
execution is not supported, you cannot run Stateflow
animation.
Parameter structures You cannot tune parameters that are structures.
Pure integer code Pure integer generated code is not supported.
Variable-size signals Uploading of variable-size signals is not supported.
Compiler support lcc-win64 is not supported.
Mac operating system As the default XCP slave platform abstraction layer
supports only Linux and Windows systems, you
cannot run host-based XCP external mode
simulations on a Mac system.
Endianess Target hardware that uses big endian architecture is
not supported.
Address granularity Target hardware that uses word addresses is not
supported.
Scope and Floating Scope blocks, Some signal data types are not supported. The
and Scope Viewer simulation produces a warning.
Scopes in referenced models In a model hierarchy, if the top model runs in
external mode and a referenced model runs in
normal or accelerator mode, scopes in the
referenced model are not displayed.
Non-zero simulation start time Non-zero simulation start times are not supported.
Use the default value for Solver > Start time, that
is, 0.0.
File-scoped data File-scoped data is not supported. For example, data
items to which you apply the built-in custom storage
class FileScope. The simulation produces a
warning.
44-20
See Also
Feature Details
Row-major code generation Code generated with the row-major format is not
supported.
Concurrent execution Concurrent execution is not supported. If System
target file is ert.tlc and Target operating
system is NativeThreadsExample, you cannot
build the target application.
VxWorks example If System target file is ert.tlc and Target
operating system is VxWorksExample, you cannot
build the target application.
See Also
More About
• “Host-Target Communication with External Mode Simulation” on page 44-2
• “Configure a Signal for Logging” (Simulink)
• “Customize XCP Slave Software” on page 44-22
External Websites
• https://www.asam.net/standards/detail/mcd-1-xcp/wiki/
44-21
44 Host/Target Communication in Simulink Coder
• On your development computer for code that is generated using ERT (ert.tlc) and
GRT (grt.tlc) system target files.
• For some support packages on page 44-2.
If your system target file for custom target hardware is derived from the ERT or GRT
system target files, you can use supplied APIs to provide XCP target connectivity. XCP
external mode limitations on page 44-17 apply.
44-22
Customize XCP Slave Software
matlabroot\toolbox\coder\xcp\src\target\ext_mode
44-23
44 Host/Target Communication in Simulink Coder
To communicate with Simulink, the target application uses services exposed by the
external mode abstraction layer. This flow chart shows the target application steps that
are required to establish communication with Simulink.
This tables gives the functions that your target application must invoke at each stage.
44-24
Customize XCP Slave Software
44-25
44 Host/Target Communication in Simulink Coder
The following pseudo-code example shows how you can implement the various stages in
your target application. During the RUN stage, the external mode run-time environment
requires at least two threads:
• A periodic thread that is responsible for the execution of the generated model code.
• A background thread that is responsible for running the external mode communication
stack and transmitting and receiving packets.
/* Initialize model */
modelName_initialize();
44-26
Customize XCP Slave Software
modelName_terminate();
To see code that invokes the functions, do the example in “External Mode Simulation with
XCP Communication” on page 44-8 with System target file set to ert.tlc. Then, from
the code generation folder, open ert_main.c.
matlabroot\toolbox\coder\xcp\src\target\slave\protocol\src
In an external mode simulation, the build process automatically adds the required files to
the build information object (Simulink Coder).
matlabroot\toolbox\coder\xcp\src\target\slave\transport\src
In an external mode simulation, the build process automatically adds the required files to
the build information object (Simulink Coder).
• An XCP driver on page 44-28 for sending and receiving raw data through the physical
communication interface.
44-27
44 Host/Target Communication in Simulink Coder
For a customization example, see “Create Custom Abstraction Layer” on page 44-33.
XCP Driver
The XCP driver sends and receives XCP messages through the communication channel. In
an external mode simulation, the build process automatically adds the driver files to the
build information object.
The XCP driver is based on the rtiostream on page 67-48 API. For example, host-
based external mode simulations use these rtiostream files:
• matlabroot\rtw\c\src\rtiostream\rtiostreamtcpip.c
• matlabroot\rtw\c\src\rtiostream\rtiostream_serial.c
For a custom platform abstraction layer, you must add your rtiostream files to the build
information object (Simulink Coder). For an example, see “Create Custom Abstraction
Layer” on page 44-33.
Memory Allocator
The XCP slave software requires the dynamic allocation of variable-size, contiguous
memory blocks to:
In an external mode simulation, the build process automatically adds memory allocator
files to the build information object.
The default memory allocator can allocate and deallocate up to 16 different sets of
memory blocks. For each set, you can override the default allocations during compilation.
You can specify:
44-28
Customize XCP Slave Software
For example, these preprocessor macros create 4 blocks of 64 bytes and 8 blocks of 256
bytes.
#define XCP_MEM_BLOCK_1_SIZE 64
#define XCP_MEM_BLOCK_1_NUMBER 4
#define XCP_MEM_BLOCK_2_SIZE 256
#define XCP_MEM_BLOCK_2_NUMBER 8
#define XCP_MEM_ALIGNMENT 8
This table describes the functionality that you must provide for the XCP slave software
that you deploy on your target hardware.
44-29
44 Host/Target Communication in Simulink Coder
Functionality Details
Mutual exclusion To access system data structures with mutual exclusion
support, the XCP driver depends on basic APIs for definition,
initialization, lock, and unlock.
#else
...
#include <pthread.h>
#define XCP_MUTEX_DEFINE(lock) pthread_mutex_t lock
#define XCP_MUTEX_INIT(lock) pthread_mutex_init(&(lock), NULL)
#define XCP_MUTEX_LOCK(lock) pthread_mutex_lock(&(lock))
#define XCP_MUTEX_UNLOCK(lock) pthread_mutex_unlock(&(lock))
...
#endif
44-30
Customize XCP Slave Software
Functionality Details
Sleep Provide a sleep API that makes the calling thread sleep until a
specified time has elapsed. The default implementation for
Linux and Windows systems is:
#else
...
#if _POSIX_C_SOURCE >= 199309L
#define XCP_SLEEP(seconds,microseconds) do {struct timespec t;\
t.tv_sec = seconds; t.tv_nsec = microseconds * 1000; nanosleep(&
#else
/* nanosleep is not available. Use select instead. */
#define XCP_SLEEP(seconds,microseconds) do {struct timeval t; t.
t.tv_usec = microseconds; select(0, NULL, NULL, NULL, &t);} whil
#endif /* _POSIX_C_SOURCE >= 199309L */
...
#endif
Logging To generate diagnostic messages, the XCP slave software
requires a custom print API that supports logging services
provided by the target hardware. If you do not define the
XCP_PRINTF preprocessor macro, the default implementation
is empty.
44-31
44 Host/Target Communication in Simulink Coder
Functionality Details
Address conversion The XCP standard expresses the address of a variable in
memory as a 32-bit address with an 8-bit extension.
44-32
Customize XCP Slave Software
Functionality Details
Set and copy memory You can specify an optimized version of copy memory and set
memory operations.
#ifndef XCP_MEMCPY
#define XCP_MEMCPY memcpy
#endif
#ifndef XCP_MEMSET
#define XCP_MEMSET memset
#endif
Parsing command line If your target hardware does not support the parsing of
arguments command line arguments, define the preprocessor macro
EXTMODE_DISABLE_ARGS_PROCESSING.
For the build process, you can define a post-code generation command that creates a
custom platform abstraction layer.
1 Specify the header file xcp_platform_custom.h. This Linux example defines the
required functions.
#ifndef XCP_PLATFORM_CUSTOM_H
#define XCP_PLATFORM_CUSTOM_H
/* XCP_ADDRESS_GET */
#include <stdint.h>
#define XCP_ADDRESS_GET(addressExtension, address) (uint8_T*) ((uintptr_t) address)
/* XCP_MUTEX */
44-33
44 Host/Target Communication in Simulink Coder
#include <pthread.h>
#define XCP_MUTEX_DEFINE(lock) pthread_mutex_t lock
#define XCP_MUTEX_INIT(lock) pthread_mutex_init(&(lock), NULL)
#define XCP_MUTEX_LOCK(lock) pthread_mutex_lock(&(lock))
#define XCP_MUTEX_UNLOCK(lock) pthread_mutex_unlock(&(lock))
/* XCP_SLEEP */
#include <sys/time.h> /* gettimeofday */
#if _POSIX_C_SOURCE >= 199309L
#include <time.h> /* for nanosleep */
#else
#include <stddef.h>
#include <sys/select.h> /* for select */
#endif
function myXCPTargetPostCodeGenCommand(buildInfo)
buildInfo.addDefines('-DXCP_CUSTOM_PLATFORM', 'OPTS');
% Add my rtiostream
buildInfo.addSourceFiles(customRtIOStreamFileName, customRtIOStreamSrcPath);
end
44-34
See Also
See Also
extmodeBackgroundRun | extmodeEvent | extmodeGetFinalSimulationTime |
extmodeInit | extmodeParseArgs | extmodeReset |
extmodeSetFinalSimulationTime | extmodeSimulationComplete |
extmodeStopRequested | extmodeWaitForHostRequest
More About
• “Host-Target Communication with External Mode Simulation” on page 44-2
• “External Mode Simulation with XCP Communication” on page 44-8
External Websites
• https://www.asam.net/standards/detail/mcd-1-xcp/wiki/
44-35
44 Host/Target Communication in Simulink Coder
The example, which uses the GRT target, does not require external hardware. The
generated executable file runs:
mkdir ext_mode_example
2 Make ext_mode_example your working folder:
cd ext_mode_example
3 Create a model in Simulink with a Sine Wave block for the input signal, two Gain
blocks in parallel, and two Scope blocks. Be sure to label the Gain and Scope blocks
as shown.
44-36
External Mode Simulation with TCP/IP or Serial Communication
A = 2;
B = 3;
5 Open Gain block A and set its Gain parameter to the variable A.
6 Open Gain block B and set its Gain parameter to the variable B.
When the target program is built and connected to Simulink in external mode, you
can download new gain values to the executing target program. To do this, you can
44-37
44 Host/Target Communication in Simulink Coder
assign new values to workspace variables A and B, or edit the values in the block
parameters dialog box. For more information, see “Tune Parameters” on page 44-44.
7 Verify operation of the model. Open the Scope blocks and run the model. When A =
2 and B = 3, the output appears as shown.
1 Open the Configuration Parameters dialog box by selecting Simulation > Model
Configuration Parameters.
2 Select the Solver pane.
3 In the Solver selection subpane:
44-38
External Mode Simulation with TCP/IP or Serial Communication
c Open Additional options. In the Fixed-step size field, specify 0.1. (Otherwise,
when you generate code, the Simulink Coder build process posts a warning and
supplies a value.)
Click Apply.
4 Select the Data Import/Export pane, and clear the Time and Output check boxes.
In this example, data is not logged to the workspace or to a MAT-file. Click Apply.
5 Select the Optimization pane. Make sure that Default parameter behavior is set
to Tunable. Inlined parameters are not part of this example. If you have made
changes, click Apply.
6 Select the Code Generation pane. By default, the generic real-time (GRT) target is
selected.
7 Select the Code Generation > Interface pane. In the Data exchange interface
section, select External mode. This selection enables generation of external mode
support code and displays additional external mode configuration parameters.
8 In the External mode configuration section, make sure that the default value
tcpip is selected for the Transport layer parameter.
External mode supports communication via TCP/IP, serial, and custom transport
protocols. The MEX-file name field specifies the name of a MEX-file that implements
host and target communication on the host side. The default for TCP/IP is ext_comm,
a MEX-file provided with the Simulink Coder software. You can override this default
by supplying other files. If you need to support other transport layers, see “Create a
Transport Layer for TCP/IP or Serial External Mode Communication” (Simulink
Coder).
The MEX-file arguments field lets you specify arguments, such as a TCP/IP server
port number, to be passed to the external interface program. These arguments are
44-39
44 Host/Target Communication in Simulink Coder
specific to the external interface that you are using. For information on setting these
arguments, see “MEX-File Optional Arguments for TCP/IP Transport” (Simulink
Coder) and “MEX-File Optional Arguments for Serial Transport” (Simulink Coder).
This example uses the default arguments. Leave the MEX-file arguments field
blank.
The Static memory allocation check box controls how memory is allocated for
external mode communication buffers in the target. For this example, do not select
the check box. For more information, see “Control Memory Allocation for
Communication Buffers in Target” on page 44-46.
9 Click Apply to save the external mode settings.
10 Save the model.
11 Select the Code Generation pane. Make sure that Generate code only is cleared,
and then, in the model window, press Ctrl+B to generate code and create the target
program. The software creates the ex_extModeExample target executable in your
working folder.
The External Signal & Triggering dialog box (accessed from the External Mode Control
Panel) displays a list of blocks in your model that support external mode signal monitoring
and logging. In the dialog box, you can configure the signals that are viewed, how they
are acquired, and how they are displayed.
In this example, you observe and use the default settings of the External Signal &
Triggering dialog box.
44-40
External Mode Simulation with TCP/IP or Serial Communication
1 From the Code menu of the model diagram, select External Mode Control Panel.
This control panel is where you configure signal monitoring and data archiving. You
can also connect to the target program, and start and stop execution of the model
code.
• After the target program starts, you use the top row of buttons.
• The Signal & Triggering button opens the External Signal & Triggering dialog
box. Use this dialog box to select the signals that are collected from the target
system and viewed in external mode. You can also select a signal that triggers
uploading of data when certain signal conditions are met, and define the
triggering conditions.
• The Data Archiving button opens the Enable Data Archiving dialog box. Use data
archiving to save data sets generated by the target program for future analysis.
This example does not use data archiving. See “Configure Host Archiving of
Target Program Signal Data” on page 44-60 .
44-41
44 Host/Target Communication in Simulink Coder
2 Click the Signal & Triggering button to open the External Signal & Triggering
dialog box. The default configuration selects all signals for monitoring and sets signal
monitoring to begin once the host and target programs are connected.
3 Make sure that the External Signal & Triggering dialog box options are set to these
defaults:
• Select all check box is selected. Signals in the Signal selection list are marked
with an X in the Selected column.
• Under Trigger options:
• Source: manual
• Mode: normal
44-42
External Mode Simulation with TCP/IP or Serial Communication
• Duration: 1000
• Delay: 0
• Arm when connecting to target: selected
To close the External Signal & Triggering dialog box, click OK. Then, close the
External Mode Control Panel.
For descriptions of the External Signal & Triggering dialog box parameters, see
“Configure Host Monitoring of Target Program Signal Data” on page 44-52.
4 To run the target program, open an operating system command window (on UNIX
systems, a terminal emulator window). At the command prompt, use cd to navigate to
the ext_mode_example folder to which you generated the target program
executable.
Note Alternatively, you can run the target program from the MATLAB Command
Window, using the following syntax.
The -tf switch overrides the stop time set for the model in Simulink. The inf value
directs the model to run indefinitely. The model code runs until the target program
receives a stop message from Simulink.
The -w switch instructs the target program to enter a wait state until it receives a
Start Real-Time Code message from the host. If you want to view data from time
step 0 of the target program execution, or if you want to modify parameters before
the target program begins execution of model code, this switch is required.
5 Open the Scope blocks in the model. Signals are not visible on the scopes. When you
connect Simulink to the target program and begin model execution, the signals
generated by the target program become visible on the scope displays.
44-43
44 Host/Target Communication in Simulink Coder
6 Before communication between the model and the target program can begin, the
model must be in external mode. To enable external mode, from the Simulation >
Mode menu, select External.
7 Reopen the External Mode Control Panel (found in the Code menu) and click
Connect. This action initiates a handshake between Simulink and the target
program. When Simulink and the target are connected, the Start Real-Time Code
button becomes enabled, and the label of the Connect button changes to
Disconnect.
8 Click Start Real-Time Code. The outputs of Gain blocks A and B are displayed on
the two scopes in your model.
You have established communication between Simulink and the running target program.
You can now tune block parameters in Simulink and observe the effects the parameter
changes have on the target program.
Tune Parameters
You can change the gain factor of either Gain block by assigning a new value to the
variable A or B in the MATLAB workspace. When you change block parameter values in
the workspace during a simulation, you must explicitly update the block diagram with
these changes. When you update the block diagram, the new values are downloaded to
the target program.
Under certain conditions, you can also tune the expressions that you use to specify block
parameter values. To change an expression during simulation, open the block dialog box.
1 At the command prompt, assign new values to both variables, for example:
A = 0.5;
B = 3.5;
2 Open the ex_extModeExample model window. From the Simulation menu, select
Update Diagram. As soon as Simulink has updated the block parameters, the new
gain values are downloaded to the target program, and the scopes are changed
because of the gain change.
3 In the Sine Wave block dialog box, set Amplitude to 0.5. Click Apply or OK.
When you click Apply or OK, the simulation downloads the new block parameter
value to the target program. The Scope block displays the change to reflect the new
amplitude value.
44-44
External Mode Simulation with TCP/IP or Serial Communication
You cannot change the sample time of the Sine Wave block during simulation. Block
sample times are part of the structural definition of the model and are part of the
generated code. Therefore, if you want to change a block sample time, you must stop the
external mode simulation, reset the sample time of the block, and rebuild the executable.
Block parameter tunability during external mode simulation depends on the way that the
generated code represents block parameters.
For example, in the Gain A block dialog box, you cannot change the expression A in the
Gain parameter during simulation. Instead, you must change the value of the variable A
in the base workspace. You cannot change the expression because the generated code
does not allocate storage in memory for the Gain parameter. Instead, the code creates a
field A in a structure:
The generated code algorithm uses that field in the code that represents the block Gain A.
In this case, the global structure variable ex_extModeExample_P uses the type
P_ex_extModeExample_T_:
When you change the value of A in the base workspace, the simulation downloads the new
value to the field A in the target program.
44-45
44 Host/Target Communication in Simulink Coder
You can change the expressions in the Sine Wave block parameters during simulation
because the generated code creates a field in the global structure
ex_extModeExample_P to represent each parameter in the block. When you change an
expression in the block dialog box, the simulation first evaluates the new expression. The
simulation then downloads the resulting numeric value to the corresponding structure
field in the target program.
See “Create Tunable Calibration Parameter in the Generated Code” on page 22-121.
To determine how much memory to allocate, enable verbose mode on the target (by
including OPTS="-DVERBOSE" on the make command line). As it executes, external mode
displays the amount of memory it tries to allocate and the amount of memory available to
it each time it attempts an allocation. If an allocation fails, you can use this console log to
adjust the size in the Static memory buffer size field.
If you intend to generate pure integer code with External mode selected, note these
requirements:
• Trigger signals must be of data type int32. Use a Data Type Conversion block if
needed.
44-46
External Mode Simulation with TCP/IP or Serial Communication
• When pure integer code is generated, the simulation stop time specified in the Solver
options is ignored. To specify a stop time, run your target program from the MATLAB
command line and use the -tf option. See “Run the External Program” (Simulink
Coder). If you do not specify this option, the program executes indefinitely (as if the
stop time were inf).
When executing pure integer target programs, the stop time specified by the -tf
command line option is interpreted as the number of base rate ticks to execute, rather
than as an elapsed time in seconds. The number of ticks is computed as
44-47
44 Host/Target Communication in Simulink Coder
To open the External Mode Control Panel dialog box, in the model window, select Code >
External Mode Control Panel.
44-48
External Mode Simulation with TCP/IP or Serial Communication
The External Mode Control Panel performs the same connect/disconnect and start/stop
functions found in the Simulation menu and the Simulink toolbar (see “Control External
Mode Simulation Through Editor Toolbar” on page 44-47).
Clicking the Connect button connects your model to a waiting or running target
program. While you are connected, the button changes to a Disconnect button.
Disconnect disconnects your model from the target environment, but does not halt real-
time code running in the target environment.
Clicking the Start Real-Time Code button commands the target to start running real-
time code. While real-time code is running in the target environment, the button changes
44-49
44 Host/Target Communication in Simulink Coder
to a Stop Real-Time Code button. Stop Real-Time Code stops target program
execution and disconnects your model from the target environment.
The External Mode Control Panel allows you to trigger and cancel data uploads to the
host. The destination for the uploaded data can be a scope block, Display block, To
Workspace block, or another block or subsystem listed in “Blocks and Subsystems
Compatible with External Mode” on page 44-63.
The Arm Trigger and Cancel Trigger buttons provide manual control of data uploading
to compatible blocks or subsystems, except floating scopes. (For floating scopes, use the
Floating scope section of the External Mode Control Panel.)
• To trigger data uploading to compatible blocks or subsystems, click the Arm Trigger
button. The button changes to Cancel Trigger.
• To cancel data uploading, click the Cancel Trigger button. The button reverts to Arm
Trigger.
You can trigger data uploads manually or automatically. To configure signals and triggers
for data uploads, see “Configure Host Monitoring of Target Program Signal Data” on page
44-52.
A subset of external mode compatible blocks, including Scope, Time Scope, and To
Workspace, allow you to log uploaded data to disk. To configure data archiving, see
“Configure Host Archiving of Target Program Signal Data” on page 44-60.
The Floating scope section of the External Mode Control Panel controls when and for
how long data is uploaded to Floating Scope blocks. When used in external mode, floating
scopes:
• Enable data uploading option, which functions as an Arm Trigger button for
floating scopes. When the target is disconnected, the option controls whether to arm
the trigger when connecting the floating scopes. When the target is connected, the
option acts as a toggle button to arm or cancel the trigger.
44-50
External Mode Simulation with TCP/IP or Serial Communication
The Batch download option on the External Mode Control Panel enables or disables
batch parameter changes.
By default, batch download is disabled. If batch download is disabled, when you click OK
or Apply, changes made directly to block parameters by editing block parameter dialog
boxes are sent to the target. When you perform an Update Diagram, changes to
MATLAB workspace variables are sent.
If you select Batch download, the Download button is enabled. Until you click
Download, changes made to block parameters are stored locally. When you click
Download, the changes are sent in a single transmission.
When parameter changes are awaiting batch download, the External Mode Control Panel
displays the message Parameter changes pending... to the right of the Download
button. This message remains visible until the Simulink engine receives notification that
the new parameters have been installed in the parameter vector of the target system.
The next figure shows the External Mode Control Panel with the Batch download option
activated and parameter changes pending.
44-51
44 Host/Target Communication in Simulink Coder
44-52
External Mode Simulation with TCP/IP or Serial Communication
In external mode, uploading target program signal data to the host depends on a trigger.
The trigger is a set of conditions that must be met for data uploading to begin. The
trigger can be armed or not armed.
• When the trigger is armed, the software checks for the trigger conditions that allow
data uploading to begin.
• If the trigger is not armed, the software does not check for the trigger conditions and
data uploading cannot begin.
• The trigger can be armed automatically, when the host connects to the target, or
manually, by clicking the Arm Trigger button on the External Mode Control Panel.
When the trigger is armed and the trigger conditions are met, the trigger fires and data
uploading begins.
When data has been collected for a defined duration, the trigger event completes and
data uploading stops. The trigger can then rearm, or remain unarmed until you click the
Arm Trigger button.
To select the target program signals to upload and configure how uploads are triggered,
see “Configure Signal Data Uploading” on page 44-53.
Clicking the Signal & Triggering button of the External Mode Control Panel opens the
External Signal & Triggering dialog box.
44-53
44 Host/Target Communication in Simulink Coder
The External Signal & Triggering dialog box displays a list of blocks and subsystems in
your model that support external mode signal uploading. For information on which types
of blocks are external mode compatible, see “Blocks and Subsystems Compatible with
External Mode” on page 44-63.
In the External Signal & Triggering dialog box, you can select the signals that are
collected from the target system and viewed in external mode. You can also select a
trigger signal, which triggers uploading of data based on meeting certain signal
conditions, and define the triggering conditions.
The preceding figure shows the default settings of the External Signal & Triggering
dialog box. The default operation of the External Signal & Triggering dialog box simplifies
44-54
External Mode Simulation with TCP/IP or Serial Communication
monitoring the target program. If you use the default settings, you do not need to
preconfigure signals and triggers. You start the target program and connect the Simulink
engine to it. External mode compatible blocks are selected and the trigger is armed.
Signal uploading begins immediately upon connection to the target program.
• Select all: on
• Source: manual
• Mode: normal
• Duration: 1000
• Delay: 0
• Arm when connecting to target: on
External mode compatible blocks in your model appear in the Signal selection list of the
External Signal & Triggering dialog box. You use this list to select signals that you want
to view. In the Selected column, an X appears for each selected block.
The Select all check box selects all signals. By default, Select all is selected.
If Select all is cleared, you can select or clear individual signals using the on and off
options. To select a signal, click its list entry and select the on option. To clear a signal,
click its list entry and select the off option.
As described in “Role of Trigger in Signal Data Uploading” on page 44-53, signal data
uploading depends on a trigger. The trigger defines conditions that must be met for
uploading to begin. Also, the trigger must be armed for data uploading to begin. When
the trigger is armed and trigger conditions are met, the trigger fires and uploading
begins. When data has been collected for a defined duration, the trigger event completes
and data uploading stops.
To control when and how signal data is collected (uploaded) from the target system,
configure the following Trigger options in the External Signal & Triggering dialog box.
44-55
44 Host/Target Communication in Simulink Coder
Selecting manual directs external mode to use the Arm Trigger button on the
External Mode Control Panel as the trigger to start uploading data. When you click
Arm Trigger, data uploading begins.
Selecting signal directs external mode to use a trigger signal as the trigger to start
uploading data. When the trigger signal satisfies trigger conditions (that is, the signal
crosses the trigger level in the specified direction), a trigger event occurs. (Specify
trigger conditions in the Trigger signal section.) If the trigger is armed, external
mode monitors for the occurrence of a trigger event. When a trigger event occurs,
data uploading begins.
• Mode: normal or one-shot. Controls whether the trigger rearms after a trigger
event completes.
In normal mode, external mode automatically rearms the trigger after each trigger
event. The next data upload begins when the trigger fires.
In one-shot mode, external mode collects only one buffer of data each time you arm
the trigger.
For more information on the Mode setting, see “Configure Host Archiving of Target
Program Signal Data” on page 44-60.
• Duration: Specifies the number of base rate steps for which external mode uploads
data after a trigger event (default is 1000). For example, if Duration is set to 1000,
and the base (fastest) rate of the model is one second:
• For a signal sampled at the base rate, one second (1.0 Hz), external mode collects
1000 contiguous samples during a trigger event.
• For a signal sampled at two seconds (0.5 Hz), external mode collects 500 samples
during a trigger event.
• Delay: Specifies a delay to be applied to data collection. The delay represents the
amount of time that elapses between a trigger event and the start of data collection.
The delay is expressed in base rate steps. It can be positive or negative (default is 0).
A negative delay corresponds to pretriggering. When the delay is negative, data from
the time preceding the trigger event is collected and uploaded.
• Arm when connecting to target: Selected or cleared. Whether a button or a signal
triggers data uploading (as defined by Source), the trigger must be armed to allow
data uploading to begin.
44-56
External Mode Simulation with TCP/IP or Serial Communication
If you select this option, connecting to the target arms the trigger.
If you clear Arm when connecting to target, manually arm the trigger by clicking
the Arm Trigger button on the External Mode Control Panel.
When simulating in external mode, each rate in the model creates a buffer on the target.
Each entry in the buffer is big enough to hold all of the data required of every signal in
that rate for one time step (time plus data plus external mode indices identifying the
signal). The number of entries in the circular buffer is determined by the external mode
trigger Duration parameter (ExtModeTrigDuration). The memory allocated on the
target for buffering signals is proportional to the Duration and the number of signals
uploading. The Duration also provides an indication of the number of base rate steps
with log data after a trigger event in external mode.
The Duration value specifies the number of contiguous points of data to be collected in
each buffer of data. You should enter a Duration value equal to the number of continuous
sample points that you need to collect rather than relying on a series of buffers to be
continuous. If you enter a value less than the total number of sample points, you may lose
sample points during the time spent transferring values from the data buffer to the
MATLAB workspace. The Simulink software maintains point continuity only within one
buffer. Between buffers, because of transfer time, some samples may be omitted.
The Duration value can affect the Limit data points to last value of Scope and To
Workspace blocks. The number of sample points that the blocks save to the MATLAB
workspace is the smaller of the two values. To set the number of sample points that the
blocks save, clear Limit data points to last. Then, use Duration to specify the number
of sample points saved.
You can designate one signal as a trigger signal. To select a trigger signal, from the
Source menu in the Trigger options section, select signal. This action enables the
parameters in the Trigger signal section. Then, select a signal in the Signal selection
list, and click the Trigger Signal button.
44-57
44 Host/Target Communication in Simulink Coder
When you select a signal to be a trigger, a T appears in the Trigger column of the Signal
selection list. In the next figure, the Scope A signal is the trigger. Scope B is also
selected for viewing, as indicated by the X in the Selected column.
After selecting the trigger signal, you can use the Trigger signal section to define the
trigger conditions and set the trigger signal Port and Element parameters.
Use the Trigger signal section of the External Signal & Triggering dialog box to set
trigger conditions and attributes. Trigger signal parameters are enabled only when the
trigger parameter Source is set to signal in the Trigger options section.
By default, any element of the first input port of a specified trigger block can cause the
trigger to fire (that is, Port 1, any element). You can modify this behavior by adjusting the
44-58
External Mode Simulation with TCP/IP or Serial Communication
Port and Element values in the Trigger signal section. The Port field accepts a number
or the keyword last. The Element field accepts a number or the keywords any or last.
In the Trigger signal section, you also define the conditions under which a trigger event
occurs.
• Direction: rising, falling, or either. The direction in which the signal must be
traveling when it crosses the threshold value. The default is rising.
• Level: A value indicating the threshold the signal must cross in a designated direction
to fire the trigger. By default, the level is 0.
• Hold-off: Applies only to normal mode. Expressed in base rate steps, Hold-off is the
time between the termination of one trigger event and the rearming of the trigger.
After you configure signal data uploading, and connect Simulink to a running target
executable, you can modify signal and triggering options without disconnecting from the
target.
If the trigger is armed (for example, if the trigger option Arm when connecting to the
target is selected, which is the default), the External Signal & Triggering dialog box
cannot be modified. To modify signal and triggering options:
44-59
44 Host/Target Communication in Simulink Coder
To understand how the archiving features work, consider the handling of data when
archiving is not enabled. There are two cases, one-shot mode and normal mode.
• In one-shot mode, after a trigger event occurs, each selected block writes its data to
the workspace, as it would at the end of a simulation. If another one-shot is triggered,
the existing workspace data is overwritten.
• In normal mode, external mode automatically rearms the trigger after each trigger
event. Consequently, you can think of normal mode as a series of one-shots. Each one-
shot in this series, except for the last, is referred to as an intermediate result. Because
the trigger can fire at any time, writing intermediate results to the workspace can
44-60
External Mode Simulation with TCP/IP or Serial Communication
result in unpredictable overwriting of the workspace variables. For this reason, the
default behavior is to write only the results from the final one-shot to the workspace.
The intermediate results are discarded. If you know that enough time exists between
triggers for inspection of the intermediate results, you can override the default
behavior by selecting the Write intermediate results to workspace option. This
option does not protect the workspace data from being overwritten by subsequent
triggers.
If you use a Simulink Scope block to archive data to disk, open the Scope parameters
dialog box and select the option Log data to workspace. The option is required for these
reasons:
• The data is first transferred from the scope data buffer to the MATLAB workspace,
before being written to a MAT-file.
• The Variable name entered in the Scope parameters dialog box is the same as the
one in the MATLAB workspace and the MAT-file. Enabling the data to be saved enables
a variable named with the Variable name parameter to be saved to a MAT-file.
Note If you do not select the Scope block option Log data to workspace, the MAT-files
for data logging are created, but they are empty.
• Folder notes
• File notes
• Automated data archiving
On the External Mode Control Panel, click the Data Archiving button to open the Enable
Data Archiving dialog box. If your model is connected to the target environment,
disconnect it while you configure data archiving. To enable the other controls in the
dialog box, select Enable archiving.
44-61
44 Host/Target Communication in Simulink Coder
These operations are supported by the Enable Data Archiving dialog box.
Folder Notes
To add annotations for a collection of related data files in a folder, in the Enable Data
Archiving dialog box, click Edit Directory Note. The MATLAB editor opens. Place
comments that you want saved to a file in the specified folder in this window. By default,
the comments are saved to the folder last written to by data archiving.
File Notes
To add annotations for an individual data file, in the Enable Data Archiving dialog box,
click Edit File Note. A file finder window opens, which by default is set to the last file to
which you have written. Selecting a MAT-file opens an edit window. In this window, add or
edit comments that you want saved with your individual MAT-file.
44-62
External Mode Simulation with TCP/IP or Serial Communication
• Directory: Specifies the folder in which data is saved. If you select Increment
directory when trigger armed, external mode appends a suffix.
• File: Specifies the name of the file in which data is saved. If you select Increment file
after one-shot, external mode appends a suffix.
• Increment directory when trigger armed: Each time that you click the Arm
Trigger button, external mode uses a different folder for writing log files. The folders
are named incrementally, for example, dirname1, dirname2, and so on.
• Increment file after one-shot: New data buffers are saved in incremental files:
filename1, filename2, and so on. File incrementing happens automatically in
normal mode.
• Append file suffix to variable names: Whenever external mode increments file
names, each file contains variables with identical names. Selecting Append file suffix
to variable name results in each file containing unique variable names. For example,
external mode saves a variable named xdata in incremental files (file_1, file_2,
and so on) as xdata_1, xdata_2, and so on. This approach supports loading the MAT-
files into the workspace and comparing variables at the MATLAB command prompt.
Without the unique names, each instance of xdata would overwrite the previous one
in the MATLAB workspace.
• Write intermediate results to workspace: If you want the Simulink Coder software
to write intermediate results to the workspace, select this option.
Compatible Blocks
In external mode, you can use the following types of blocks to receive and view signals
uploaded from the target program:
44-63
44 Host/Target Communication in Simulink Coder
An external mode method is built into the S-function API. This method allows user-
written blocks to support external mode. See matlabroot/simulink/include/
simstruc.h.
• XY Graph blocks
You can designate certain subsystems as Signal Viewing Subsystems and use them to
receive and view signals uploaded from the target program. See “Signal Viewing
Subsystems” on page 44-64 for more information.
You select external mode compatible blocks and subsystems, and arm the trigger, by
using the External Signal & Triggering dialog box. By default, such blocks in a model are
selected, and a manual trigger is set to be armed when connected to the target program.
Note Signal Viewing Subsystems are inactive if placed inside a SIL or PIL component,
such as a top model in SIL or PIL mode, a Model block in SIL or PIL mode, or a SIL or PIL
block. However, a SIL or PIL component can feed a Signal Viewing Subsystem running in
a supported mode.
Signal Viewing Subsystems are useful in situations where you want to process or
condition signals before viewing or logging them, but you do not want to perform these
tasks on the target system. By using a Signal Viewing Subsystem, you can generate
smaller and more efficient code on the target system.
Like other external mode compatible blocks, Signal Viewing Subsystems are displayed in
the External Signal & Triggering dialog box.
44-64
External Mode Simulation with TCP/IP or Serial Communication
1 In the Block Parameters dialog box, select the Treat as atomic unit option.
set_param('blockname', 'SimViewingDevice','on')
• It must be a pure Sink block. That is, it must not contain Outport blocks or Data
Store blocks. It can contain Goto blocks only if the corresponding From blocks are
contained within the subsystem boundaries.
• It must not have continuous states.
The subsystem theSink applies a gain and an offset to its input signal and displays it on
a Scope block.
44-65
44 Host/Target Communication in Simulink Coder
External Signal & Triggering dialog box, the target program uploads the sine wave signal
to theSink during simulation. You can then modify the parameters of the blocks within
theSink and observe the uploaded signal.
If theSink were not declared as a Signal Viewing Subsystem, its Gain, Constant, and
Sum blocks would run as subsystem code on the target system. The Sine Wave signal
would be uploaded to the Simulink engine after being processed by these blocks, and
viewed on sink_examp/theSink/Scope2. Processing demands on the target system
would be increased by the additional signal processing, and by the downloading of
changes in block parameters from the host.
In external mode, you can use the following types of blocks to archive data to disk:
• Scope blocks
• To Workspace blocks
You configure data archiving by using the Enable Data Archiving dialog box, as described
in “Configure Host Archiving of Target Program Signal Data” on page 44-60.
Depending on the setting of the Default parameter behavior option when the target
program is generated, there are differences in the way parameter updates are handled.
“Download Mechanism” on page 44-66 describes the operation of external mode
communication with Default parameter behavior set to Tunable. “Inlined and Tunable
Parameters” on page 44-68 describes the operation of external mode with Default
parameter behavior set to Inlined.
Download Mechanism
In external mode, the Simulink engine does not simulate the system represented by the
block diagram. By default, when external mode is enabled, the Simulink engine
downloads parameters to the target system. After the initial download, the engine
remains in a waiting mode until you change parameters in the block diagram or until the
engine receives data from the target.
44-66
External Mode Simulation with TCP/IP or Serial Communication
When you change a parameter in the block diagram, the Simulink engine calls the
external interface MEX-file, passing new parameter values (along with other information)
as arguments. The external interface MEX-file contains code that implements one side of
the interprocess communication (IPC) channel. This channel connects the Simulink
process (where the MEX-file executes) to the process that is executing the external
program. The MEX-file transfers the new parameter values by using this channel to the
external program.
The other side of the communication channel is implemented within the external
program. This side writes the new parameter values into the target's parameter structure
(model_P).
The Simulink side initiates the parameter download operation by sending a message
containing parameter information to the external program. In the terminology of client/
server computing, the Simulink side is the client and the external program is the server.
The two processes can be remote, or they can be local. Where the client and server are
remote, a protocol such as TCP/IP is used to transfer data. Where the client and server
are local, a serial connection or shared memory can be used to transfer data.
The next figure shows this relationship. The Simulink engine calls the external interface
MEX-file whenever you change parameters in the block diagram. The MEX-file then
downloads the parameters to the external program by using the communication channel.
44-67
44 Host/Target Communication in Simulink Coder
Simulink Process
External Program
Client Server
IPC Code IPC Code
External Interface
ext_svr.
MEX-file (e.g., ext_comm)
By default, parameters (except those listed in “TCP/IP and Serial External Mode
Limitations” on page 44-85) in an external mode program are tunable; that is, you can
change them by using the download mechanism described in this section.
If you set Default parameter behavior to Inlined (on the Optimization pane of the
Configuration Parameters dialog box), the Simulink Coder code generator embeds the
numerical values of model parameters (constants), instead of symbolic parameter names,
44-68
External Mode Simulation with TCP/IP or Serial Communication
in the generated code. Inlining parameters generates smaller and more efficient code.
However, inlined parameters, because they effectively become constants, are not tunable.
The Simulink Coder software lets you improve overall efficiency by inlining most
parameters, while at the same time retaining the flexibility of run-time tuning for selected
parameters that are important to your application. When you inline parameters, you can
use Simulink.Parameter objects to remove individual parameters from inlining and
declare them to be tunable. In addition, you can use these objects to control how
parameters are represented in the generated code.
For more information on tunable parameters, see “Create Tunable Calibration Parameter
in the Generated Code” on page 22-121.
Each time the Simulink engine connects to a target program that was generated with
Default parameter behavior set to Inlined, the target program uploads the current
value of its tunable parameters to the host. These values are assigned to the
corresponding MATLAB workspace variables. This procedure synchronizes the host and
target with respect to parameter values.
Workspace variables required by the model must be initialized at the time of host/target
connection. Otherwise the uploading cannot proceed and an error results. Once the
connection is made, these variables are updated to reflect the current parameter values
on the target system.
Automatic parameter uploading takes place only if the target program was generated
with Default parameter behavior set to Inlined. “Download Mechanism” on page 44-
66 describes the operation of external mode communication with Default parameter
behavior set to Tunable.
44-69
44 Host/Target Communication in Simulink Coder
Introduction
The Simulink Coder product provides code to implement both the client and server side of
external mode communication using either TCP/IP or serial protocols. You can use the
socket-based external mode implementation provided by the Simulink Coder product with
the generated code, provided that your target system supports TCP/IP. If not, use or
customize the serial transport layer option provided.
A low-level transport layer handles physical transmission of messages. Both the Simulink
engine and the model code are independent of this layer. Both the transport layer and
code directly interfacing to the transport layer are isolated in separate modules that
format, transmit, and receive messages and data packets.
You can use TCP/IP-based client/server implementation of external mode with real-time
programs on The Open Group UNIX or PC systems. For help in customizing external mode
transport layers, see “Create a Transport Layer for TCP/IP or Serial External Mode
Communication” (Simulink Coder).
• Make sure that the external interface MEX-file for your target's TCP/IP transport is
specified.
Targets provided by MathWorks specify the name of the external interface MEX-file in
matlabroot/toolbox/simulink/simulink/extmode_transports.m. The name
of the interface appears as uneditable text in the External mode configuration
section of the Interface pane of the Configuration Parameters dialog box. The TCP/IP
default is ext_comm.
To specify a TCP/IP transport for a custom target, you must add an entry of the
following form to an sl_customization.m file on the MATLAB path:
function sl_customization(cm)
cm.ExtModeTransports.add('stf.tlc', 'transport', 'mexfile', 'Level1');
%end function
• stf.tlc is the name of the system target file for which you are registering the
transport (for example, 'mytarget.tlc')
• transport is the transport name to display in the Transport layer menu on the
Interface pane of the Configuration Parameters dialog box (for example, 'tcpip')
44-70
External Mode Simulation with TCP/IP or Serial Communication
• mexfile is the name of the transport's associated external interface MEX-file (for
example, 'ext_comm')
• Be sure that the template makefile is configured to link the source files for the TCP/IP
server code and that it defines the compiler flags when building the generated code.
• Build the external program.
• Run the external program.
• Set the Simulink model to external mode and connect to the target.
44-71
44 Host/Target Communication in Simulink Coder
Process block
parameter changes
ext_svr.c
Update block parameters
ext_comm
TCP/IP on Ethernet
In the External Target Interface dialog box, you can specify optional arguments that are
passed to the external mode interface MEX-file for communicating with executing targets.
• Target network name: the network name of the computer running the external
program. By default, this is the computer on which the Simulink product is running,
for example, 'myComputer'. You can also use the IP address, for example,
'148.27.151.12'.
• Verbosity level: controls the level of detail of the information displayed during the data
transfer. The value is either 0 or 1 and has the following meaning:
44-72
External Mode Simulation with TCP/IP or Serial Communication
0 — No information
1 — Detailed information
• TCP/IP server port number: The default value is 17725. You can change the port
number to a value between 256 and 65535 to avoid a port conflict.
The arguments are positional and must be specified in the following order:
For example, if you want to specify the verbosity level (the second argument), then you
must also specify the target network name (the first argument). Arguments can be
delimited by white space or commas. For example:
'148.27.151.12' 1 30000
You can specify command-line options to the external program when you launch it. See
“Run the External Program” on page 44-75.
• Make sure that the external interface MEX-file for your target's serial transport is
specified.
Targets provided by MathWorks specify the name of the external interface MEX-file in
matlabroot/toolbox/simulink/simulink/extmode_transports.m. The name
of the interface appears as uneditable text in the External mode configuration
section of the Interface pane of the Configuration Parameters dialog box. The serial
default is serial.
To specify a serial transport for a custom target, you must add an entry of the
following form to an sl_customization.m file on the MATLAB path:
function sl_customization(cm)
cm.ExtModeTransports.add('stf.tlc', 'transport', 'mexfile', 'Level1');
%end function
• stf.tlc is the name of the system target file for which you are registering the
transport (for example, 'mytarget.tlc')
44-73
44 Host/Target Communication in Simulink Coder
• transport is the transport name to display in the Transport layer menu on the
Interface pane of the Configuration Parameters dialog box (for example,
'serial')
• mexfile is the name of the transport's associated external interface MEX-file (for
example, 'ext_serial_win32_comm')
• Be sure that the template makefile is configured to link the source files for the serial
server code and that it defines the compiler flags when building the generated code.
• Build the external program.
• Run the external program.
• Set the Simulink model to external mode and connect to the target.
MEX-File Optional Arguments for Serial Transport
In the MEX-file arguments field of the Interface pane of the Configuration Parameters
dialog box, you can specify arguments that are passed to the external mode interface
MEX-file for communicating with the executing targets. For serial transport, the optional
arguments to ext_serial_win32_comm are as follows:
• Verbosity level: This argument controls the level of detail of the information displayed
during data transfer. The value of this argument is:
• 0 (no information), or
• 1 (detailed information)
• Serial port ID: The port ID of the host, specified as an integer or character vector. For
example, specify the port ID of a USB to serial converter as'/dev/
ttyusb0'.Simulink Coder prefixes integer port IDs with \\.\COM on Windows and
by /dev/ttyS on Unix.
When you start the target program using a serial connection, you must specify the
port ID to use to connect it to the host. Do this by including the -port command-line
option. For example:
mytarget.exe -port 2 -w
44-74
External Mode Simulation with TCP/IP or Serial Communication
The MEX-file options arguments are positional and must be specified in the following
order:
<VerbosityLevel> <SerialPortID> <BaudRate>
For example, if you want to specify the serial port ID (the second argument), then you
must also specify the verbosity level (the first argument). Arguments can be delimited by
white space or commas. For example:
1 '/dev/ttyusb0' 57600
When you launch the external program, you can specify command-line options.
Before you can use the Simulink product in external mode, the external program must be
running.
If the target program is executing on the same machine as the host and communication is
through a loopback serial cable, the target's port ID must differ from that of the host (as
specified in the MEX-file arguments edit field).
model is the name of the external program and -opt1 ... -optN are options. (See
“Command-Line Options for the External Program” on page 44-76.) In the examples in
this section, the name of the external program is ext_example.
Running the External Program in the Windows Environment
In the Windows environment, you can run the external programs in either of the following
ways:
• Open a Command Prompt window. At the command prompt, type the name of the
target executable, followed by possible options, such as:
ext_example -tf inf -w
• Alternatively, you can launch the target executable from the MATLAB Command
Window. The command must be preceded by an exclamation point (!) and followed by
an ampersand (&), as in the following example:
44-75
44 Host/Target Communication in Simulink Coder
The ampersand (&) causes the operating system to spawn another process to run the
target executable. If you do not include the ampersand, the program still runs, but you
cannot enter commands at the MATLAB command prompt or manually terminate the
executable.
In the UNIX environment, you can run the external programs in either of the following
ways:
• Open an Xterm window. At the command prompt, type the name of the target
executable, followed by possible options, such as:
The ampersand (&) causes the operating system to spawn another process to run the
target executable.
External mode target executables generated by the Simulink Coder code generator
support the following command-line options:
• -tf n
The -tf option overrides the stop time set in the Simulink model. The argument n
specifies the number of seconds the program will run. The value inf directs the model
to run indefinitely. In this case, the model code runs until the target program receives
a stop message from the Simulink engine.
ext_example -tf 10
44-76
External Mode Simulation with TCP/IP or Serial Communication
When integer-only ERT targets are built and executed in external mode, the stop time
parameter (-tf) is interpreted by the target as the number of base rate ticks rather than
the number of seconds to execute.
• -w
Instructs the target program to enter a wait state until it receives a message from the
host. At this point, the target is running, but not executing the model code. The start
message is sent when you select Start Real-Time Code from the Simulation menu or
click the Start Real-Time Code button in the External Mode Control Panel.
Use the -w option if you want to view data from time step 0 of the target program
execution, or if you want to modify parameters before the target program begins
execution of model code.
• -port n
Specifies the TCP/IP port number or the serial port ID, n, for the target program. The
port number of the target program must match that of the host for TCP/IP transport.
The port number depends on the type of transport.
• For TCP/IP transport: Port number is an integer between 256 and 65535, with the
default value being 17725.
• For serial transport: Port ID is an integer or a character vector. For example,
specify the port ID of a USB to serial converter as '/dev/ttyusb0'
• -baud r
If you want to implement your own transport layer for external mode communication, you
must modify certain code modules provided by the Simulink Coder product and create a
new external interface MEX-file. See “Create a Transport Layer for TCP/IP or Serial
External Mode Communication” (Simulink Coder).
44-77
44 Host/Target Communication in Simulink Coder
The following model simulation commands assume that a Simulink model is open and that
you have loaded a target program to which the model will connect using external mode.
set_param(gcs,'SimulationMode','external')
2 Connect the open model to the loaded target program:
set_param(gcs,'SimulationCommand','connect')
3 Start running the target program:
set_param(gcs,'SimulationCommand','start')
4 Stop running the target program:
set_param(gcs,'SimulationCommand','stop')
5 Disconnect the target program from the model:
set_param(gcs,'SimulationCommand','disconnect')
To tune a workspace parameter, change its value at the command prompt. If the
workspace parameter is a Simulink.Parameter object, assign the new value to the
Value property.
myVariable = 5.23;
myParamObj.Value = 5.23;
To download the workspace parameter in external mode, you update the model diagram.
The following model simulation command initiates a model update:
set_param(gcs,'SimulationCommand','update')
set_param(gcs,'ExtModeCommand','armWired')
set_param(gcs,'ExtModeCommand','cancelWired')
The next table lists external mode command-line parameters that you can use in
get_param and set_param commands. The table provides brief descriptions, valid
44-78
External Mode Simulation with TCP/IP or Serial Communication
values (bold type highlights defaults), and a mapping to External Mode dialog box
equivalents. For external mode parameters that are equivalent to Interface pane options
in the Configuration Parameters dialog box, see “Model Configuration Parameters: Code
Generation Interface” (Simulink Coder).
44-79
44 Host/Target Communication in Simulink Coder
44-80
External Mode Simulation with TCP/IP or Serial Communication
44-81
44 Host/Target Communication in Simulink Coder
44-82
External Mode Simulation with TCP/IP or Serial Communication
44-83
44 Host/Target Communication in Simulink Coder
In: Select:
Signal selection Chart you want to animate
pane
Trigger pane Arm when connecting to target check box
Trigger pane normal from drop-down menu in Mode field
8 Build the model to generate an executable file.
9 Start the target in the background. At the MATLAB prompt, type:
!model_name.exe -w &
For example, if the name of your model is my_control_sys, enter this command:
!my_control_sys.exe -w &
-w allows the target code to wait for the Simulink model connection.
10 In the Model Editor, select Simulation > Mode > External, and then select
Simulation > Connect to Target.
44-84
External Mode Simulation with TCP/IP or Serial Communication
When you simulate a chart in external mode, you can designate chart data of local scope
to be test points and view the test point data in floating scopes and signal viewers.
1 Open the Model Explorer and for each data you want to view, follow these steps:
a In the middle Contents pane, select the state or local data of interest.
b In the right Dialog pane, select the Logging tab and select Test point check
box.
2 From a floating scope or signal viewer, click the signal selection button:
The scope or viewer displays the values of the test point signals as the simulation
runs.
For more information, see “Behavior of Scopes and Viewers with Rapid Accelerator
Mode” (Simulink).
44-85
44 Host/Target Communication in Simulink Coder
Changing Parameters
In general, you cannot change a parameter if doing so results in a change in the structure
of the model. For example, you cannot change
If you make these changes to the block diagram, then you must rebuild the program with
newly generated code.
You can change parameters in transfer function and state space representation blocks in
specific ways:
• The parameters (numerator and denominator polynomials) for the Transfer Fcn
(continuous and discrete) and Discrete Filter blocks can be changed (as long as the
number of states does not change).
• Zero entries in the State-Space and Zero Pole (both continuous and discrete) blocks in
the user-specified or computed parameters (that is, the A, B, C, and D matrices
obtained by a zero-pole to state-space transformation) cannot be changed once
external simulation is started.
• In the State-Space block, if you specify the matrices in the controllable canonical
realization, then all changes to the A, B, C, D matrices that preserve this realization
and the dimensions of the matrices are allowed.
44-86
External Mode Simulation with TCP/IP or Serial Communication
If the Simulink block diagram does not match the external program, Simulink produces
an error stating that the checksums do not match. The checksums take into account the
top models, but not referenced models. Use the updated block diagram to rebuild the
target program.
When you use external mode, the machine running the Simulink product and the machine
running the target executable must have matching bit architectures, either 32-bit or 64-
bit. The Simulink Coder software varies a model's checksum based on whether it is
configured for a 32-bit or 64-bit platform.
If you attempt to connect from a 32-bit machine to a 64-bit machine or vice versa, the
external mode connection fails.
Uploading Data
External mode does not support uploading data values for fixed-point or enumerated
types into workspace parameters.
External mode does not support uploading variable-size signals for the following targets:
• Simulink Real-Time
• Texas Instruments™ C2000™
External mode does not support graphical display of signal values in models (described in
“Displaying Signal Values in Model Diagrams” (Simulink)). For example, you cannot use
the Data Display in Simulation menu selections Show Value Labels When Hovering,
Toggle Value Labels When Clicked, and Show Value Label of Selected Port.
External mode does not support uploading or downloading tunable structure parameters.
Archiving Data
External mode supports the Scope and To Workspace blocks for archiving data to disk.
However, external mode does not support scopes other than the Scope block for archiving
44-87
44 Host/Target Communication in Simulink Coder
data. For example, you cannot use Floating Scope blocks or Signal and Scope Manager
viewer objects to archive data in external mode.
In a model hierarchy, if the top model simulates in external mode and a referenced model
simulates in normal or accelerator mode, scopes in the referenced model are not
displayed.
However, if the top model is changed to simulate in normal mode, the behavior of scopes
in the referenced models differs between normal and accelerator mode. Scopes in a
referenced model simulating in normal mode are displayed, while scopes in a referenced
model simulating in accelerator mode are not displayed.
External mode does not support nonzero simulation start times. In the Configuration
Parameters dialog box, Solver pane, leave Start time set to the default value of 0.0.
File-Scoped Data
External mode does not support file-scoped data, for example, data items to which you
apply the built-in custom storage class FileScope. File-scoped data are not externally
accessible.
External mode simulations support the use of printf calls to display error and
information messages from the target program. For some target hardware, the use of
printf statements can increase the external mode binary file size. To disable printf
calls, specify the preprocessor macro definition EXTMODE_DISABLEPRINTF for your
target program compiler.
Command-Line Arguments
External mode simulations support the use of command-line arguments for running target
programs. These limitations apply:
44-88
See Also
External mode simulations do not support code generated with the row-major format.
See Also
More About
• “External Mode Simulation with XCP Communication” on page 44-8
• “Create a Transport Layer for TCP/IP or Serial External Mode Communication” on
page 44-90
44-89
44 Host/Target Communication in Simulink Coder
In this section...
“Design of External Mode” on page 44-90
“External Mode Communications Overview” on page 44-93
“External Mode Source Files” on page 44-94
“Implement a Custom Transport Layer” on page 44-98
This section helps you to connect your custom target by using external mode using your
own low-level communications layer. The topics include:
This section assumes that you are familiar with the execution of Simulink Coder
programs, and with the basic operation of external mode.
A low-level transport layer handles physical transmission of messages. Both the Simulink
engine and the model code are independent of this layer. Both the transport layer and
code directly interfacing to the transport layer are isolated in separate modules that
format, transmit, and receive messages and data packets.
This design makes it possible for different targets to use different transport layers. The
GRT, ERT, and RSim targets support host/target communication by using TCP/IP and
RS-232 (serial) communication. The Simulink Desktop Real-Time target supports shared
memory communication. The Wind River Systems Tornado® target supports TCP/IP only.
44-90
Create a Transport Layer for TCP/IP or Serial External Mode Communication
The Simulink Coder product provides full source code for both the client and server-side
external mode modules, as used by the GRT, ERT, Rapid Simulation, and Tornado targets,
and the Simulink Desktop Real-Time and Simulink Real-Time products. The main client-
side module is ext_comm.c. The main server-side module is ext_svr.c.
These two modules call the specified transport layer through the following source files.
44-91
44 Host/Target Communication in Simulink Coder
Note Do not modify working source files. Use the templates provided in the /custom
or /rtiostream folder as starting points, guided by the comments within them.
You need only provide code that implements low-level communications. You need not be
concerned with issues such as data conversions between host and target, or with the
formatting of messages. The Simulink Coder software handles these functions.
On the client (Simulink engine) side, communications are handled by ext_comm (for
TCP/IP) and ext_serial_win32_comm (for serial) MEX-files.
On the server (target) side, external mode modules are linked into the target executable.
This takes place automatically if the External mode code generation option is selected at
code generation time, based on the External mode transport option selected in the
target code generation options dialog box. These modules, called from the main program
and the model execution engine, are independent of the generated model code.
The general procedure for implementing your own client-side low-level transport protocol
is as follows:
1 Edit the template rtiostream_tcpip.c to replace low-level communication calls
with your own communication calls.
2 Generate a MEX-file executable for your custom transport.
3 Register your new transport layer with the Simulink software, so that the transport
can be selected for a model using the Interface pane of the Configuration
Parameters dialog box.
44-92
Create a Transport Layer for TCP/IP or Serial External Mode Communication
For more details, see “Create a Custom Client (Host) Transport Protocol” on page 44-99.
The general procedure for implementing your own server-side low-level transport
protocol is as follows:
1 Edit the template rtiostream_tcpip.c to replace low-level communication calls
with your own communication calls. Typically this involves writing or integrating
device drivers for your target hardware.
2 Modify template makefiles to support the new transport.
For more details, see “Create a Custom Server (Target) Transport Protocol” on page 44-
102.
For communication to take place, both the server (target) program and the Simulink
software must be executing. This does not mean that the model code in the server system
must be executing. The server can be waiting for the Simulink engine to issue a command
to start model execution.
The client and server communicate by using bidirectional sockets carrying packets.
Packets consist either of messages (commands, parameter downloads, and responses) or
data (signal uploads).
If the target program was invoked with the -w command-line option, the program enters a
wait state until it receives a message from the host. Otherwise, the program begins
execution of the model. While the target program is in a wait state, the Simulink engine
can download parameters to the target and configure data uploading.
When the user chooses the Connect to Target option from the Simulation menu, the
host initiates a handshake by sending an EXT_CONNECT message. The server responds
with information about itself. This information includes
• Checksums. The host uses model checksums to determine that the target code is an
exact representation of the current Simulink model.
• Data format information. The host uses this information when formatting data to be
downloaded, or interpreting data that has been uploaded.
44-93
44 Host/Target Communication in Simulink Coder
At this point, host and server are connected. The server is either executing the model or
in the wait state. (In the latter case, the user can begin model execution by selecting
Start Real-Time Code from the Simulation menu.)
During model execution, the message server runs as a background task. This task
receives and processes messages such as parameter downloads.
Data uploading comprises both foreground execution and background servicing of the
signal packets. As the target computes model outputs, it also copies signal values into
data upload buffers. This occurs as part of the task associated with each task identifier
(tid). Therefore, data collection occurs in the foreground. Transmission of the collected
data, however, occurs as a background task. The background task sends the data in the
collection buffers to the Simulink engine by using data packets.
The host initiates most exchanges as messages. The target usually sends a response
confirming that it has received and processed the message. Examples of messages and
commands are:
Model execution terminates when the model reaches its final time, when the host sends a
terminate command, or when a Stop Simulation block terminates execution. On
termination, the server informs the host that model execution has stopped, and shuts
down its socket. The host also shuts down its socket, and exits external mode.
The source files for the MEX-file interface component are located in the folder
matlabroot/toolbox/coder/simulinkcoder_core/ext_mode/host (open), except
as noted:
44-94
Create a Transport Layer for TCP/IP or Serial External Mode Communication
• common/ext_comm.c
This file is the core of external mode communication. It acts as a relay station between
the target and the Simulink engine. ext_comm.c communicates to the Simulink
engine by using a shared data structure, ExternalSim. It communicates to the target
by using calls to the transport layer.
This file is an interface between the external mode protocol and an rtiostream
communications channel. For more details on implementing an rtiostream
communications channel, see “Communications rtiostream API” on page 67-48.
Implement your rtiostream communications channel using the documented
interface to avoid having to change the file rtiostream_interface.c or other
external mode related files.
• matlabroot/rtw/c/src/rtiostream/rtiostreamtcpip/rtiostream_tcpip.c
This file implements required TCP/IP transport layer functions. The version of
rtiostream_tcpip.c shipped with the Simulink Coder software uses TCP/IP
functions including recv(), send(), and socket().
• matlabroot/rtw/c/src/rtiostream/rtiostreamserial/
rtiostream_serial.c
This file implements required serial transport layer functions. The version of
rtiostream_serial.c shipped with the Simulink Coder software uses serial
functions including ReadFile(), WriteFile(), and CreateFile().
• serial/ext_serial_transport.c
This file is a MEX-file wrapper for external mode. ext_main.c interfaces to the
Simulink engine by using the standard mexFunction call. (See the mexFunction
reference page and “MATLAB API for Other Languages” (MATLAB) for more
44-95
44 Host/Target Communication in Simulink Coder
This file contains functions used for converting data from host to target formats (and
vice versa). Functions include byte-swapping (big to little- endian), conversion from
non-IEEE floats to IEEE doubles, and other conversions. These functions are called
both by ext_comm.c and directly by the Simulink engine (by using function pointers).
This file defines the ExternalSim data structure and access macros. This structure is
used for communication between the Simulink engine and ext_comm.c.
• common/extutil.h
This file contains only conditionals for compilation of the assert macro.
• common/ext_transport.h
This file defines functions that must be implemented by the transport layer.
These files are linked into the model.exe executable. They are located within
matlabroot/rtw/c/src/ext_mode (open) except as noted.
• common/ext_svr.c
44-96
Create a Transport Layer for TCP/IP or Serial External Mode Communication
This file is an interface between the external mode protocol and an rtiostream
communications channel. For more details on implementing an rtiostream
communications channel, see “Communications rtiostream API” on page 67-48.
Implement your rtiostream communications channel by using the documented
interface to avoid having to change the file rtiostream_interface.c or other
external mode related files.
• matlabroot/rtw/c/src/rtiostream/rtiostreamtcpip/rtiostream_tcpip.c
This file implements required TCP/IP transport layer functions. The version of
rtiostream_tcpip.c shipped with the Simulink Coder software uses TCP/IP
functions including recv(), send(), and socket().
• matlabroot/rtw/c/src/rtiostream/rtiostreamserial/
rtiostream_serial.c
This file implements required serial transport layer functions. The version of
rtiostream_serial.c shipped with the software uses serial functions including
ReadFile(), WriteFile(), and CreateFile().
• matlabroot/rtw/c/src/rtiostream.h
updown.c handles the details of interacting with the target model. During parameter
downloads, updown.c does the work of installing the new parameters into the model's
parameter vector. For data uploading, updown.c contains the functions that extract
data from the model's blockio vector and write the data to the upload buffers.
updown.c provides services both to ext_svr.c and to the model code (for example,
grt_main.c). It contains code that is called by using the background tasks of
ext_svr.c as well as code that is called as part of the higher priority model
execution.
• matlabroot/rtw/c/src/dt_info.h (included by generated model build file
model.h)
44-97
44 Host/Target Communication in Simulink Coder
These files contain data type transition information that allows access to multi-data
type structures across different computer architectures. This information is used in
data conversions between host and target formats.
• common/updown_util.h
This file contains only conditionals for compilation of the assert macro.
• common/ext_svr_transport.h
This file defines the Ext* functions that must be implemented by the server (target)
transport layer.
• common/ext_share.h
Contains message code definitions and other definitions required by both the host and
target modules.
• serial/ext_serial_utils.c
Contains functions and data structures for communication, MEX link, and generated
code required by both the host and target modules of the transport layer for serial
protocols.
• The serial transport implementation includes the additional files
44-98
Create a Transport Layer for TCP/IP or Serial External Mode Communication
a Copy and rename the file to rtiostream_name.c (replacing name with a name
meaningful to you).
b Replace the functions rtIOStreamOpen, rtIOStreamClose,
rtIOStreamSend, and rtIOStreamRecv with functions (of the same name)
that call your low-level communication primitives. These functions are called
from other external mode modules via rtiostream_interface.c. For more
information, see “Communications rtiostream API” on page 67-48.
c Build your rtiostream implementation into a shared library that exports the
rtIOStreamOpen, rtIOStreamClose, rtIOStreamRecv and
rtIOStreamSend functions.
2 Build the customized MEX-file executable using the MATLAB mex function. See
“MATLAB Commands to Rebuild ext_comm and ext_serial_win32 MEX-Files” on page
44-100 for examples of mex invocations.
Do not replace the existing ext_comm MEX-file if you want to preserve its existing
function. Instead, use the -output option to name the resulting executable (for
example, mex -output ext_myrtiostream_comm ... builds
ext_myrtiostream_comm.mexext, on Windows platforms).
3 Register your new client transport layer with the Simulink software, so that the
transport can be selected for a model using the Interface pane of the Configuration
Parameters dialog box. For details, see “Register a Custom Client (Host) Transport
Protocol” on page 44-101.
44-99
44 Host/Target Communication in Simulink Coder
Sample commands for rebuilding external mode MEX-files are listed in “MATLAB
Commands to Rebuild ext_comm and ext_serial_win32 MEX-Files” on page 44-100.
The following table lists the commands for building the standard ext_comm and
ext_serial_win32 modules on PC and UNIX platforms.
Platform Commands
Windows, TCP/IP >> cd (matlabroot)
>> mex toolbox\coder\simulinkcoder_core\ext_mode\host\common\ext_comm.c ...
toolbox\coder\simulinkcoder_core\ext_mode\host\common\ext_convert.c ...
toolbox\coder\simulinkcoder_core\ext_mode\host\common\rtiostream_interface.c ...
toolbox\coder\simulinkcoder_core\ext_mode\host\common\ext_util.c ...
-Irtw\c\src -Irtw\c\src\rtiostream\utils ...
-Irtw\c\src\ext_mode\common ...
-Itoolbox\coder\simulinkcoder_core\ext_mode\host\common ...
-Itoolbox\coder\simulinkcoder_core\ext_mode\host\common\include ...
-lmwrtiostreamutils -lsl_services ...
-DEXTMODE_TCPIP_TRANSPORT ...
-DSL_EXT_DLL -output toolbox\coder\simulinkcoder_core\ext_comm
44-100
Create a Transport Layer for TCP/IP or Serial External Mode Communication
Platform Commands
Windows, serial >> cd (matlabroot)
>> mex toolbox\coder\simulinkcoder_core\ext_mode\host\common\ext_comm.c ...
toolbox\coder\simulinkcoder_core\ext_mode\host\common\ext_convert.c ...
toolbox\coder\simulinkcoder_core\ext_mode\host\serial\ext_serial_transport.c ...
toolbox\coder\simulinkcoder_core\ext_mode\host\serial\ext_serial_pkt.c ...
toolbox\coder\simulinkcoder_core\ext_mode\host\serial\rtiostream_serial_interface.c ...
toolbox\coder\simulinkcoder_core\ext_mode\host\common\ext_util.c ...
-Irtw\c\src -Irtw\c\src\rtiostream\utils ...
-Irtw\c\src\ext_mode\common ...
-Irtw\c\src\ext_mode\serial ...
-Itoolbox\coder\simulinkcoder_core\ext_mode\host\common ...
-Itoolbox\coder\simulinkcoder_core\ext_mode\host\common\include ...
-lmwrtiostreamutils -lsl_services ...
-DEXTMODE_SERIAL_TRANSPORT -DSL_EXT_DLL ...
-output toolbox\coder\simulinkcoder_core\ext_serial_win32_comm
Note mex requires a compiler supported by the MATLAB API. See the mex reference
page and “MATLAB API for Other Languages” (MATLAB) for more information about the
mex function.
To register a custom client transport protocol with the Simulink software, you must add
an entry of the following form to an sl_customization.m file on the MATLAB path:
44-101
44 Host/Target Communication in Simulink Coder
function sl_customization(cm)
cm.ExtModeTransports.add('stf.tlc', 'transport', 'mexfile', 'Level1');
% -- end of sl_customization
where
• stf.tlc is the name of the system target file for which the transport will be
registered (for example, 'grt.tlc')
• transport is the transport name to display in the Transport layer menu on the
Interface pane of the Configuration Parameters dialog box (for example, 'mytcpip')
• mexfile is the name of the transport's associated external interface MEX-file (for
example, 'ext_mytcpip_comm')
44-102
Create a Transport Layer for TCP/IP or Serial External Mode Communication
To implement the server (target) side of your low-level TCP/IP or serial transport protocol:
a Copy and rename the file to rtiostream_name.c (replacing name with a name
meaningful to you).
b Replace the functions rtIOStreamOpen, rtIOStreamClose,
rtIOStreamSend, and rtIOStreamRecv with functions (of the same name)
that call your low-level communication drivers.
For example:
44-103
44 Host/Target Communication in Simulink Coder
• Add the file created in the previous step to the build information:
path/rtiostream_name.c
Note For external mode, check that rtIOStreamRecv is not a blocking implementation.
Otherwise, it might cause the external mode server to block until the host sends data
through the comm layer.
For serial communication, if the serial receive buffer of your target is smaller than 64
bytes:
1 Update the following macro with the actual target buffer size:
#define TARGET_SERIAL_RECEIVE_BUFFER_SIZE 64
See Also
Related Examples
• “How Generated Code Exchanges Data with an Environment” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
• “External Mode Simulation with TCP/IP or Serial Communication” on page 44-36
44-104
See Also
44-105
45
Note Data logging is available only for system target files that have access to a file
system. In addition, only the RSim target executables are capable of accessing MATLAB
workspace data.
For MAT-file logging limitations, see the configuration parameter “MAT-file logging”
(Simulink Coder).
In this section...
“Log Data for Analysis” on page 45-2
“Configure State, Time, and Output Logging” on page 45-9
“Log Data with Scope and To Workspace Blocks” on page 45-11
“Log Data with To File Blocks” on page 45-11
“Data Logging Differences Between Single- and Multitasking” on page 45-12
This example shows how data generated by a copy of the model slexAircraftExample
is logged to the file myAircraftExample.mat. Refer to “Build Process Workflow for
Real-Time Systems” on page 43-32 for instructions on setting up a copy of
slexAircraftExample asmyAircraftExample in a working folder if you have not
done so already.
45-2
Log Program Execution Results
Note When you configure the code generator to produce code that includes support for
data logging during execution, the code generator can include text for block names in the
block paths included in the log file. If the text includes characters that are unrepresented
in the character set encoding for the model, the code generator replaces the characters
with XML escape sequences. For example, the code generator replaces the Japanese full-
width Katakana letter ア with the escape sequence ア. For more information, see
“Internationalization and Code Generation” (Simulink Coder).
To configure data logging, open the Configuration Parameters dialog box and select the
Data Import/Export pane. The process is the same as configuring a Simulink model to
save output to the MATLAB workspace. For each workspace return variable you define
and enable, the Simulink Coder software defines a parallel MAT-file variable. For example,
if you save simulation time to the variable tout, your generated program logs the same
data to a variable named rt_tout. You can change the prefix rt_ to a suffix (_rt), or
eliminate it entirely. You do this by setting Configuration Parameters > Code
Generation > Interface > Advanced parameters > MAT-file variable name
modifier.
Simulink lets you log signal data from anywhere in a model. In the Simulink Editor, select
the signals that you want to log and then in the Simulation Data Inspector button drop-
down, select Log Selected Signals. However, the Simulink Coder software does not use
this method of signal logging in generated code. To log signals in generated code, you
must either use the Data Import/Export options described below or include To File or To
Workspace blocks in your model.
Note If you enable MAT-file and signal logging (through the Data Import/Export pane)
and select signals for logging (through the Simulink Editor), you see the following
warning when you build the model:
Warning: MAT-file logging does not support signal logging.
When your model code executes, the signal logging variable 'rt_logsout' will
not be saved to the MAT-file.
To avoid this warning, clear the Data Import/Export > Signal logging check box.
In this example, you modify the myAircraftExample model so that the generated
program saves the simulation time and system outputs to the file
myAircraftExample.mat. Then you load the data into the base workspace and plot
simulation time against one of the outputs. The myAircraftExample model should be
45-3
45 Logging in Simulink Coder
configured as described in “Build Process Workflow for Real-Time Systems” on page 43-
32.
45-4
Log Program Execution Results
8 Click Apply and OK to register your changes and close the dialog box.
9 Save the model.
10 In the model window, double-click the scope symbol next to the Aircraft Dynamics
Model block, then run the model by choosing Simulation > Run in the model
window. The resulting scope display is shown below.
45-5
45 Logging in Simulink Coder
11 Verify that the simulation time and outputs have been saved to the base workspace in
MAT-files. At the MATLAB prompt, type:
whos yout
Simulink displays:
Name Size Bytes Class Attributes
12 Verify that alpha, rad was logged by plotting simulation time versus that variable.
In the Command Window, type:
plot(yout.time,yout.signals.values)
45-6
Log Program Execution Results
In the second part of this example, you build and run a Simulink Coder executable of the
myAircraftExample model that outputs a MAT-file containing the simulation time and
output you previously examined. Even though you have already generated code for the
myAircraftExample model, you must now regenerate that code because you have
changed the model by enabling data logging. The steps below explain this procedure.
To avoid overwriting workspace data with data from simulation runs, the code generator
modifies identifiers for variables logged by Simulink. You can control these modifications.
1 Set Configuration Parameters > Code Generation > Interface > Advanced
parameters > MAT-file variable name modifier to _rt. This adds the suffix _rt to
each variable that you selected to be logged in the first part of this example.
2 Click Apply and OK to register your changes and close the dialog box.
3 Save the model.
4 Build an executable.
5 When the build concludes, run the executable with the command:
!myAircraftExample
6 The program now produces two message lines, indicating that the MAT-file has been
written.
45-7
45 Logging in Simulink Coder
load myAircraftExample.mat
whos yout*
Simulink displays:
Note the size and bytes of the structures resulting from the simulation run and
generated code are the same.
8 Plot the generated code output by entering the following command in the Command
Window:
plot(yout_rt.time,yout_rt.signals.values)
The plot should be identical to the plot that you produced in the previous part of this
example.
45-8
Log Program Execution Results
Tip For UNIX platforms, run the executable in the Command Window with the syntax !./
executable_name. If preferred, run the executable from an OS shell with the syntax ./
executable_name. For more information, see “Run External Commands, Scripts, and
Programs” (MATLAB).
Before using this data logging feature, you should learn how to configure a Simulink
model to return output to the MATLAB workspace. This is discussed in “Export Simulation
Data” (Simulink).
For each workspace return variable that you define and enable, the code generator
defines a MAT-file variable. For example, if your model saves simulation time to the
workspace variable tout, your generated program logs the same data to a variable
named (by default) rt_tout.
The code generated by the code generator logs the following data:
The sort order of the rt_yout array is based on the port number of the Outport block,
starting with 1.
• Continuous and discrete states in the model
By default, the code generation software prefixes the text rt_ to the variable names for
system outputs, states, and simulation time to form MAT-file variable names. To change
45-9
45 Logging in Simulink Coder
this prefix for a model, select a prefix (rt_), a suffix (_rt), or no modifier (none) for
Configuration Parameters > Code Generation > Interface > Advanced parameters
> MAT-file variable name modifier. Other system target files might not support this
parameter.
You can specify compiler options to override the following MAT-file attributes in generated
code:
Note Valid option syntax can vary among compilers. For example, Microsoft Visual C++
compilers typically accept /DSAVEFILE=filename as well as -DSAVEFILE=filename.
For a template makefile (TMF) based target, append the compiler option to the Make
command field on the Code Generation pane of the Configuration Parameters dialog
box. For example:
For a toolchain-based target such as GRT or ERT, add the compiler option to the Build
configuration settings on the Code Generation pane of the Configuration Parameters
dialog box. Set Build configuration to Specify, and add the compiler option to the C
Compiler row of the Tool/Options table. For example:
To add the compiler option to a custom toolchain, you can modify and reregister the
custom toolchain using the procedures shown in the example “Adding a Custom
Toolchain” (MATLAB Coder). For example, to add the compiler option to the MATLAB
source file for the custom toolchain, you could define myCompilerOpts as follows:
optimsOffOpts = {'/c /Od'};
optimsOnOpts = {'/c /O2'};
45-10
Log Program Execution Results
Then you can add myCompilerOpts to the flags for each configuration and compiler to
which it applies, for example:
cfg = tc.getBuildConfiguration('Faster Builds');
cfg.setOption('C Compiler', horzcat(cCompilerOpts, myCompilerOpts, optimsOffOpts));
As shown in “Adding a Custom Toolchain” (MATLAB Coder), after modifying the custom
toolchain, you save the configuration to a MAT-file and refresh the target registry.
• Scope blocks that have the Log data to workspace parameter enabled
You must specify the variable name and data format in each Scope block's dialog box.
• To Workspace blocks in the model
You must specify the variable name and data format in each To Workspace block's
dialog box.
The variables are written to model.mat, along with variables logged from the
Workspace I/O pane.
Note Models referenced by Model blocks do not perform data logging in that context
except for states, which you can include in the state logged for top models. Code
generated by the Simulink Coder software for referenced models does not perform data
logging to MAT-files.
45-11
45 Logging in Simulink Coder
In multitasking mode, the logging of states and outputs is done after the first task
execution (and not at the end of the first time step). In single-tasking mode, the code
generated by the build procedure logs states and outputs after the first time step.
See Data Logging in Single-Tasking and Multitasking Model Execution (Simulink Coder)
for more details on the differences between single-tasking and multitasking data logging.
Note The rapid simulation target (RSim) provides enhanced logging options. See
“Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim
System Target File” (Simulink Coder) for more information.
See Also
Related Examples
• “How Generated Code Exchanges Data with an Environment” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
45-12
46
• “Exchange Data Between Generated and External Code Using C API” on page 46-2
• “Use C API to Access Model Signals and States” on page 46-24
• “Use C API to Access Model Parameters” on page 46-30
46 Data Interchange Using the C API in Simulink Coder
The C API minimizes its memory footprint by sharing information common to signals,
states, root-level inputs/outputs, and parameters in smaller structures. Signal, state, root-
level input/output, and parameter structures include an index into the structure map,
allowing multiple signals, states, root-level inputs/outputs, or parameters to share data.
To get started with an example, see “Use C API to Access Model Signals and States” on
page 46-24 or “Use C API to Access Model Parameters” on page 46-30.
In this section...
“Generated C API Files” on page 46-2
“Generate C API Files” on page 46-3
“Description of C API Files” on page 46-5
“Generate C API Data Definition File for Exchanging Data with a Target System” on page
46-20
“C API Limitations” on page 46-22
46-2
Exchange Data Between Generated and External Code Using C API
model.c model.h
model.mdl
Generate code
model_capi.c model_capi.h
Note When you configure the code generator to produce code that includes support for
the C API interface and data logging, the code generator can include text for block names
in the block paths logged to C API files model_capi.c (or .cpp) and model_capi.h. If
the text includes characters that are unrepresented in the character set encoding for the
model, the code generator replaces the characters with XML escape sequences. For
example, the code generator replaces the Japanese full-width Katakana letter ア with the
escape sequence ア. For more information, see “Internationalization and Code
Generation” (Simulink Coder).
1 Select the C API interface for your model. There are two ways to select the C API
interface for your model, as described in the following sections.
After generating code, you can examine the files model_capi.c (or .cpp) and
model_capi.h in the model build folder.
46-3
46 Data Interchange Using the C API in Simulink Coder
• If you want to generate C API code for global block output signals, select
Generate C API for: signals.
• If you want to generate C API code for global block parameters, select Generate
C API for: parameters.
• If you want to generate C API code for discrete and continuous states, select
Generate C API for: states.
• If you want to generate C API code for root-level inputs and outputs, select
Generate C API for: root-level I/O.
From the MATLAB command line, you can use the set_param function to select or clear
the C API check boxes on the Interface pane of the Configuration Parameters dialog box.
At the MATLAB command line, enter one or more of the following commands, where
modelname is the name of your model.
46-4
Exchange Data Between Generated and External Code Using C API
set_param('modelname','RTWCAPIStates','off')
set_param('modelname','RTWCAPIRootIO','on')
set_param('modelname','RTWCAPIRootIO','off')
The model_capi.c (or .cpp) file provides external applications with a consistent
interface to model data. Depending on your configuration settings, the data could be a
signal, state, root-level input or output, or parameter. In this document, the term data
item refers to either a signal, a state, a root-level input or output, or a parameter. The C
API uses structures that provide an interface to the data item properties. The interface
packages the properties of each data item in a data structure. If the model contains
multiple data items, the interface generates an array of data structures. The members of
a data structure map to data properties.
To interface with data items, an application requires the following properties for each
data item:
• Name
• Block path
46-5
46 Data Interchange Using the C API in Simulink Coder
As illustrated in the next figure, the properties of data item A, for example, are located in
data structure DS_A. The properties of data item B are located in data structure DS_B.
DS_A DS_B
Property 1 Unique value located here Property 1 Unique value located here
Property 2 Shared value located in DS_C Property 2 Shared value located in DS_C
Pointer Pointer value located here Pointer Pointer value located here
Property 3 Unique value located here Property 3 Unique value located here
... ...
DS_C
Shared value of Property 2
Shared values of other properties ...
Some property values can be unique to each data item, and there are some property
values that several data items can share in common. Name, for example, has a unique
value for each data item. The interface places the unique property values directly in the
structure for the data item. The name value of data item A is in DS_A, and the name value
of data item B is in DS_B.
But data type could be a property whose value several data items have in common. The
ability of some data items to share a property allows the C API to have a reuse feature. In
this case, the interface places only an index value in DS_A and an index value in DS_B.
These indices point to a different data structure, DS_C, that contains the actual data type
value. The next figure shows this scheme with more detail.
46-6
Exchange Data Between Generated and External Code Using C API
The figure shows three signals. signal1 and signal2 share the same data type,
double. Instead of specifying this data type value in each signal data structure, the
interface provides only an index value, 0, in the structure. "double" is described by
entry 0 in the rtDataTypeMap array, which is referenced by both signals. Additionally,
property values can be shared between signals, states, root-level inputs/outputs, and
46-7
46 Data Interchange Using the C API in Simulink Coder
parameters, so states, root-level inputs/outputs, and parameters also might reference the
double entry in the rtDataTypeMap array. This reuse of information reduces the
memory size of the generated interface.
As with data type, the interface maps other common properties (such as address,
dimension, fixed-point scaling, and sample time) into separate structures and provides an
index in the structure for the data item. For a complete list of structure definitions, refer
to the file matlabroot/rtw/c/src/rtw_capi.h. This file also describes each member
in a structure. The structure arrays generated in the model_capi.c (or .cpp) file are of
structure types defined in the rtw_capi.h file. Here is a brief description of the
structure arrays generated in model_capi.c (or .cpp):
46-8
Exchange Data Between Generated and External Code Using C API
Subtopics “C API Signals” on page 46-11, “C API States” on page 46-14, “C API Root-
Level Inputs and Outputs” on page 46-15, and “C API Parameters” on page 46-16
discuss generated C API structures using the example model rtwdemo_capi. To generate
code from the example model, do the following:
46-9
46 Data Interchange Using the C API in Simulink Coder
Note The setting of Generate C API for: root-level I/O must match between the
top model and the referenced model. If you modify the option, save the top model and
the referenced model to the same writable work folder.
3 Generate code for the model by double-clicking Generate Code Using Simulink
Coder.
Note The C API code examples in the next subtopics are generated with C as the target
language.
This model has three global block output signals that will appear in C API generated code:
• top_sig1, which is a test point at the output of the Gain1 block in the top model
• sig2_eg, which appears in the top model and is defined in the base workspace as a
Simulink.Signal object having storage class ExportedGlobal
• bot_sig1, which appears in the referenced model rtwdemo_capi_bot and is
defined as a Simulink.Signal object having storage class Model default
The model also has two discrete states that will appear in the C API generated code:
• top_state, which is defined for the Delay1 block in the top model
• bot_state, which is defined for the Discrete Filter block in the referenced model
The model has root-level inputs/outputs that will appear in the C API generated code if
you select the option Generate C API for: root-level I/O:
Additionally, the model has five global block parameters that will appear in C API
generated code:
46-10
Exchange Data Between Generated and External Code Using C API
• Kp (top model Gain1 block and referenced model Gain2 block share)
• Ki (referenced model Gain3 block)
• p1 (lookup table lu1d)
• p2 (lookup table lu2d)
• p3 (lookup table lu3d)
C API Signals
The rtwCAPI_Signals structure captures signal information including the signal name,
address, block path, output port number, data type information, dimensions information,
fixed-point information, and sample-time information.
{ 1, 0, "rtwdemo_capi/lu2d",
"sig2_eg", 0, 0, 1, 0, 0 },
{
0, 0, (NULL), (NULL), 0, 0, 0, 0, 0
}
};
Note To better understand the code, read the comments in the file. For example, notice
the comment that begins on the third line in the preceding code. This comment lists the
members of the rtwCAPI_Signals structure, in order. This tells you the order in which
the assigned values for each member appear for a signal. In this example, the comment
tells you that signalName is the fourth member of the structure. The following lines
describe the first signal:
{ 0, 0, "rtwdemo_capi/Gain1",
"top_sig1", 0, 0, 0, 0, 0 },
From these lines you infer that the name of the first signal is top_sig1.
46-11
46 Data Interchange Using the C API in Simulink Coder
Each array element, except the last, describes one output port for a block signal. The final
array element is a sentinel, with all elements set to null values. For example, examine the
second signal, described by the following code:
{ 1, 0, "rtwdemo_capi/lu2d",
"sig2_eg", 0, 0, 1, 0, 0 },
This signal, named sig2_eg, is the output signal of the first port of the block
rtwdemo_capi/lu2d. (This port is the first port because the zero-based index for
portNumber displayed on the second line is assigned the value 0.)
The address of this signal is given by addrMapIndex, which, in this example, is displayed
on the first line as 1. This provides an index into the rtDataAddrMap array, found later in
rtwdemo_capi_capi.c:
/* Declare Data Addresses statically */
static void* rtDataAddrMap[] = {
&rtwdemo_capi_B.top_sig1, /* 0: Signal */
&sig2_eg[0], /* 1: Signal */
&rtwdemo_capi_DWork.top_state, /* 2: Discrete State */
&rtP_Ki, /* 3: Model Parameter */
&rtP_Kp, /* 4: Model Parameter */
&rtP_p1[0], /* 5: Model Parameter */
&rtP_p2[0], /* 6: Model Parameter */
&rtP_p3[0], /* 7: Model Parameter */
};
The index of 1 points to the second element in the rtDataAddrMap array. From the
rtDataAddrMap array, you can infer that the address of this signal is &sig2_eg[0].
This level of indirection supports multiple code instances of the same model. For multiple
instances, the signal information remains constant, except for the address. In this case,
the model is a single instance. Therefore, the rtDataAddrMap is declared statically. If
you choose to generate reusable code, an initialize function is generated that initializes
the addresses dynamically per instance. For details on generating reusable code, see
“Configure Code Generation for Model Entry-Point Functions” (Simulink Coder) and see
“Configure Code Reuse Support” on page 33-15.
The dataTypeIndex provides an index into the rtDataTypeMap array, found later in
rtwdemo_capi_capi.c, indicating the data type of the signal:
/* Data Type Map - use dataTypeMapIndex to access this structure */
static const rtwCAPI_DataTypeMap rtDataTypeMap[] = {
/* cName, mwName, numElements, elemMapIndex, dataSize, slDataId, *
* isComplex, isPointer */
{ "double", "real_T", 0, 0, sizeof(real_T), SS_DOUBLE, 0, 0 }
};
46-12
Exchange Data Between Generated and External Code Using C API
Because the index is 0 for sig2_eg, the index points to the first structure element in the
array. You can infer that the data type of the signal is double. The value of isComplex is
0, indicating that the signal is not complex. Rather than providing the data type
information directly in the rtwCAPI_Signals structure, a level of indirection is
introduced. The indirection allows multiple signals that share the same data type to point
to one map structure, saving memory for each signal.
The dimIndex (dimensions index) provides an index into the rtDimensionMap array,
found later in rtwdemo_capi_capi.c, indicating the dimensions of the signal. Because
this index is 1 for sig2_eg, the index points to the second element in the
rtDimensionMap array:
/* Dimension Map - use dimensionMapIndex to access elements of ths structure*/
static const rtwCAPI_DimensionMap rtDimensionMap[] = {
/* dataOrientation, dimArrayIndex, numDims, vardimsIndex */
{ rtwCAPI_SCALAR, 0, 2, 0 },
{ rtwCAPI_VECTOR, 2, 2, 0 },
...
};
From this structure, you can infer that this is a nonscalar signal having a dimension of 2.
The dimArrayIndex value, 2, provides an index into rtDimensionArray, found later in
rtwdemo_capi_capi.c:
/* Dimension Array- use dimArrayIndex to access elements of this array */
static const uint_T rtDimensionArray[] = {
1, /* 0 */
1, /* 1 */
2, /* 2 */
...
};
The fxpIndex (fixed-point index) provides an index into the rtFixPtMap array, found
later in rtwdemo_capi_capi.c, indicating fixed-point information about the signal. Your
code can use the scaling information to compute the real-world value of the signal, using
the equation V=SQ+B, where V is “real-world” (that is, base-10) value, S is user-specified
slope, Q is “quantized fixed-point value” or “stored integer,” and B is user-specified bias.
For details, see “Scaling” (Fixed-Point Designer).
Because this index is 0 for sig2_eg, the signal does not have fixed-point information. A
fixed-point map index of zero means that the signal does not have fixed-point information.
The sTimeIndex (sample-time index) provides the index to the rtSampleTimeMap array,
found later in rtwdemo_capi_capi.c, indicating task information about the signal. If
you log multirate signals or conditionally executed signals, the sampling information can
be useful.
46-13
46 Data Interchange Using the C API in Simulink Coder
Note model_capi.c (or .cpp) includes rtw_capi.h. A source file that references the
rtBlockSignals array also must include rtw_capi.h.
C API States
The rtwCAPI_States structure captures state information including the state name,
address, block path, type (continuous or discrete), data type information, dimensions
information, fixed-point information, and sample-time information.
{
0, -1, (NULL), (NULL), (NULL), 0, 0, 0, 0, 0, 0
}
};
Each array element, except the last, describes a state in the model. The final array
element is a sentinel, with all elements set to null values. In this example, the C API code
for the top model displays one state:
{ 2, -1, "rtwdemo_capi/Delay1",
"top_state", "", 0, 0, 0, 0, 0, 0 },
This state, named top_state, is defined for the block rtwdemo_capi/Delay1. The
value of isContinuous is zero, indicating that the state is discrete rather than
continuous. The other fields correspond to the like-named signal equivalents described in
“C API Signals” on page 46-11, as follows:
• The address of the signal is given by addrMapIndex, which, in this example, is 2. This
is an index into the rtDataAddrMap array, found later in rtwdemo_capi_capi.c.
Because the index is zero based, 2 corresponds to the third element in
rtDataAddrMap, which is &rtwdemo_capi_DWork.top_state.
• The dataTypeIndex provides an index into the rtDataTypeMap array, found later in
rtwdemo_capi_capi.c, indicating the data type of the parameter. The value 0
corresponds to a double, noncomplex parameter.
46-14
Exchange Data Between Generated and External Code Using C API
• The dimIndex (dimensions index) provides an index into the rtDimensionMap array,
found later in rtwdemo_capi_capi.c. The value 0 corresponds to the first entry,
which is { rtwCAPI_SCALAR, 0, 2, 0 }.
• The fixPtIndex (fixed-point index) provides an index into the rtFixPtMap array,
found later in rtwdemo_capi_capi.c, indicating fixed-point information about the
parameter. As with the corresponding signal attribute, a fixed-point map index of zero
means that the parameter does not have fixed-point information.
{ 4, 0, "rtwdemo_capi/In2",
"", 2, 0, 0, 0, 0 },
{ 5, 0, "rtwdemo_capi/In3",
"", 3, 0, 0, 0, 0 },
{ 6, 0, "rtwdemo_capi/In4",
"", 4, 0, 0, 0, 0 },
{
0, 0, (NULL), (NULL), 0, 0, 0, 0, 0
}
};
46-15
46 Data Interchange Using the C API in Simulink Coder
{ 8, 0, "rtwdemo_capi/Out2",
"", 2, 0, 0, 0, 0 },
{ 9, 0, "rtwdemo_capi/Out3",
"", 3, 0, 0, 0, 0 },
{ 10, 0, "rtwdemo_capi/Out4",
"", 4, 0, 0, 0, 0 },
{ 11, 0, "rtwdemo_capi/Out5",
"sig2_eg", 5, 0, 1, 0, 0 },
{ 12, 0, "rtwdemo_capi/Out6",
"", 6, 0, 1, 0, 0 },
{
0, 0, (NULL), (NULL), 0, 0, 0, 0, 0
}
};
For information about interpreting the values in the rtwCAPI_Signals structure, see
the previous section “C API Signals” on page 46-11.
C API Parameters
The rtModelParameters array contains entries for workspace variables that are
referenced as tunable Simulink block parameters or Stateflow data of machine scope. For
example, tunable parameters include Simulink.Parameter objects that use a storage
class other than Auto. The Simulink Coder software assigns its elements only NULL or
zero values in the absence of such data.
The setting that you select for the model configuration parameter Default parameter
behavior determines how information is generated into the rtBlockParameters array
in model_capi.c (or .cpp).
46-16
Exchange Data Between Generated and External Code Using C API
The last member of each array is a sentinel, with all elements set to null values.
In this example, only the final, sentinel array element is generated, with all members of
the structure rtwCAPI_BlockParameters set to NULL and zero values. This is because
Default parameter behavior is set to Inlined by default for the rtwdemo_capi
example model. If you set Default parameter behavior to Tunable, the block
parameters are generated in the rtwCAPI_BlockParameters structure. However,
MATLAB variables and tunable parameters appear in the rtwCAPI_ModelParameters
structure.
{ 3, TARGET_STRING("Kp"), 0, 0, 0 },
{ 4, TARGET_STRING("p1"), 0, 2, 0 },
{ 5, TARGET_STRING("p2"), 0, 3, 0 },
{ 6, TARGET_STRING("p3"), 0, 4, 0 },
{ 0, (NULL), 0, 0, 0 }
};
In this example, the rtModelParameters array contains entries for each variable that is
referenced as a tunable Simulink block parameter.
46-17
46 Data Interchange Using the C API in Simulink Coder
For example, the varName (variable name) of the fourth parameter is p2. The other fields
correspond to the like-named signal equivalents described in “C API Signals” on page 46-
11, as follows:
For more information about tunable parameter storage in the generated code, see “How
Generated Code Stores Internal Signal, State, and Parameter Data” on page 22-50.
The real-time model data structure encapsulates model data and associated information
that describes the model fully. When you select the C API feature and generate code, the
Simulink Coder code generator adds another member to the real-time model data
structure generated in model.h:
/*
* DataMapInfo:
* The following substructure contains information regarding
* structures generated in the model's C API.
*/
struct {
rtwCAPI_ModelMappingInfo mmi;
} DataMapInfo;
This member defines mmi (for model mapping information) of type struct
rtwCAPI_ModelMappingInfo. The structure is located in matlabroot/rtw/c/src/
rtw_modelmap.h. The mmi substructure defines the interface between the model and the
46-18
Exchange Data Between Generated and External Code Using C API
C API files. More specifically, members of mmi map the real-time model data structure to
the structures in model_capi.c (or .cpp).
Initializing values of mmi members to the arrays accomplishes the mapping, as shown in
“Map Model to C API Arrays of Structures” on page 46-20. Each member points to one
of the arrays of structures in the generated C API file. For example, the address of the
rtBlockSignals array of structures is allocated to the first member of the mmi
substructure in model.c (or .cpp), using the following code in the rtw_modelmap.h
file:
/* signals */
struct {
rtwCAPI_Signals const *signals; /* Signals Array */
uint_T numSignals; /* Num Signals */
rtwCAPI_Signals const *rootInputs; /* Root Inputs array */
uint_T numRootInputs; /* Num Root Inputs */
rtwCAPI_Signals const *rootOutputs; /* Root Outputs array */
uint_T numRootOutputs;/* Num Root Outputs */
} Signals;
The model initialize function in model.c (or .cpp) performs the initializing by calling the
C API initialize function. For example, the following code is generated in the model
initialize function for example model rtwdemo_capi:
/* Initialize DataMapInfo substructure containing ModelMap for C API */
rtwdemo_capi_InitializeDataMapInfo(rtwdemo_capi_M);
46-19
46 Data Interchange Using the C API in Simulink Coder
matlabroot/rtw/c/src/rtw_modelmap.h model_capi.c
Note This figure lists the arrays in the order that their structures appear in
rtw_modelmap.h, which differs slightly from their generated order in model_capi.c.
46-20
Exchange Data Between Generated and External Code Using C API
open_system('rtwdemo_capi');
The C API is useful for real-time interaction with application data, without having to stop
execution or recompile the generated code. Typically, a client/server protocol is set up
from a host to a target using serial, TCP/IP, or dual-port memory connection. The purpose
46-21
46 Data Interchange Using the C API in Simulink Coder
of this example is not the client/server protocol. Rather, this model shows the necessary
data interface required by the C client/server programs.
You enable the C API by selecting one or more C API options on the Code Generation >
Interface pane of the Configuration Parameters dialog box. Any signal or parameter or
state with an addressable storage class is placed in the C API data structure in
model_capi.c. Note that signals, states, and parameters in the referenced model can be
accessed using C API. So make sure that C API is enabled for the referenced model.
C API Limitations
The C API feature has the following limitations.
• The C API does not support the following values for the CodeFormat TLC variable:
• S-Function
• Accelerator_S-Function (for accelerated simulation)
• For ERT-based targets, the C API requires that support for floating-point code be
enabled.
• Local block output signals are not supported.
• Local Stateflow parameters are not supported.
• The following custom storage class objects are not supported:
Note Custom Storage Class objects work in code generation, only if you use the ERT
system target file and clear the model configuration parameter Ignore custom storage
classes.
46-22
See Also
See Also
Related Examples
• “Access Signal, State, and Parameter Data During Execution” (Simulink Coder)
• “How Generated Code Exchanges Data with an Environment” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
46-23
46 Data Interchange Using the C API in Simulink Coder
The C API provides you with the flexibility of writing your own application code to interact
with model signals, states, root-level inputs/outputs, and parameters. Your target-based
application code is compiled with the Simulink Coder generated code into an executable.
The target-based application code accesses the C API structure arrays in model_capi.c
(or .cpp). You might have host-based code that interacts with your target-based
application code. Or, you might have other target-based code that interacts with your
target-based application code. The files rtw_modelmap.h and rtw_capi.h, located in
matlabroot/rtw/c/src (open), provide macros for accessing the structures in these
arrays and their members.
Here is an example application that logs global signals and states in a model to a text file.
This code is intended as a starting point for accessing signal and state addresses. You can
extend the code to perform signal logging and monitoring, state logging and monitoring,
or both.
• rtmGetDataMapInfo macro
Accesses the model mapping information (MMI) substructure of the real-time model
structure. In the following macro call, rtM is the pointer to the real-time model
structure in model.c (or .cpp):
rtwCAPI_ModelMappingInfo* mmi = &(rtmGetDataMapInfo(rtM).mmi);
• rtmGetTPtr macro
Accesses the absolute time information for the base rate from the timing substructure
of the real-time model structure. In the following macro call, rtM is the pointer to the
real-time model structure in model.c (or .cpp):
rtmGetTPtr(rtM)
46-24
Use C API to Access Model Signals and States
You can integrate these custom functions into generated model code using one or
more of the following methods:
• Code Generation > Custom Code pane of the Configuration Parameters dialog
box
• Custom Code library blocks
• TLC custom code functions
This tutorial uses the Code Generation > Custom Code pane and the System
Outputs block from the Custom Code library to insert calls to the custom functions
into model.c (or .cpp), as follows:
The following excerpts of generated code from model.c (rearranged to reflect their order
of execution) show how the function interfaces are used.
void rtwdemo_capi_initialize(void)
{
...
/* user code (Initialize function Body) */
/* C API Custom Logging Function: Start Signal and State logging via C API.
* capi_StartLogging: Function prototype in rtwdemo_capi_datalog.h
*/
{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_capi_M).mmi);
printf("** Started state/signal logging via C API **\n");
capi_StartLogging(MMI, MAX_DATA_POINTS);
}
...
}
...
/* Model step function */
void rtwdemo_capi_step(void)
{
...
/* user code (Output function Trailer) */
/* System '<Root>' */
46-25
46 Data Interchange Using the C API in Simulink Coder
/* C API Custom Logging Function: Update Signal and State logging buffers.
* capi_UpdateLogging: Function prototype in rtwdemo_capi_datalog.h
*/
{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_capi_M).mmi);
capi_UpdateLogging(MMI, rtmGetTPtr(rtwdemo_capi_M));
}
...
}
...
/* Model terminate function */
void rtwdemo_capi_terminate(void)
{
/* user code (Terminate function Body) */
/* C API Custom Logging Function: Dump Signal and State buffers into a text file.
* capi_TerminateLogging: Function prototype in rtwdemo_capi_datalog.h
*/
{
capi_TerminateLogging("rtwdemo_capi_ModelLog.txt");
printf("** Finished state/signal logging. Created rtwdemo_capi_ModelLog.txt **\n");
}
}
The following procedure illustrates how you can use the C API macro and function
interfaces to log global signals and states in a model to a text file.
1 At the MATLAB command line, enter rtwdemo_capi to open the example model.
2 Save the top model rtwdemo_capi and the referenced model rtwdemo_capi_bot
to the same writable work folder.
3 Open the Configuration Parameters dialog box.
4 If you are licensed for Embedded Coder software and you want to use the ert.tlc
system target file instead of the default grt.tlc, go to the Code Generation pane
and use the System target file parameter to select an ert.tlc system target tile.
Make sure that you also select ert.tlc for the referenced model
rtwdemo_capi_bot.
5 In the top model, go to the Code Generation > Interface pane. Confirm these
model configuration parameter settings:
a Select Generate C API for signals, Generate C API for states, and Generate
C API for parameters.
b If you are using the ert.tlc system target file, select Support complex
numbers
c Select MAT-file logging.
d Click Apply.
e Update configuration parameter settings in the referenced model,
rtwdemo_capi_bot, to match changes you made in the top model.
46-26
Use C API to Access Model Signals and States
6 Use the Custom Code pane to embed your custom application code in the generated
code. Select the Custom Code pane, and then click Include directories. The
Include directories input field is displayed.
7 In the Include directories field, type matlabroot/toolbox/rtw/rtwdemos,
where matlabroot represents the root of your MATLAB installation folder. (If you
are specifying a Windows path that contains a space, place the text inside double
quotes.)
8 In the Additional Build Information subpane, click Source files, and type
rtwdemo_capi_datalog.c.
9 In the Include custom C code in generated subpane, click Source file, and type
or copy and paste the following include statement:
#include "rtwdemo_capi_datalog.h"
10 In the Initialize function field, type or copy and paste the following application
code:
/* C API Custom Logging Function: Start Signal and State logging via C API.
* capi_StartLogging: Function prototype in rtwdemo_capi_datalog.h
*/
{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_capi_M).mmi);
printf("** Started state/signal logging via C API **\n");
capi_StartLogging(MMI, MAX_DATA_POINTS);
}
Note If you renamed the top model rtwdemo_capi, update the name
rtwdemo_capi_M in the application code to reflect the new model name.
11 In the Terminate function field, type or copy and paste the following application
code:
/* C API Custom Logging Function: Dump Signal and State buffers into a text file.
* capi_TerminateLogging: Function prototype in rtwdemo_capi_datalog.h
*/
{
46-27
46 Data Interchange Using the C API in Simulink Coder
capi_TerminateLogging("rtwdemo_capi_ModelLog.txt");
printf("** Finished state/signal logging. Created rtwdemo_capi_ModelLog.txt **\n");
}
Click Apply.
12 In the MATLAB Command Window, enter custcode to open the Simulink Coder
Custom Code library. At the top level of the rtwdemo_capi model, add a System
Outputs block.
13 Double-click the System Outputs block to open the System Outputs Function Custom
Code dialog box. In the System Outputs Function Exit Code field, type or copy and
paste the following application code:
/* C API Custom Logging Function: Update Signal and State logging buffers.
* capi_UpdateLogging: Function prototype in rtwdemo_capi_datalog.h
*/
{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_capi_M).mmi);
capi_UpdateLogging(MMI, rtmGetTPtr(rtwdemo_capi_M));
}
Note If you renamed the top model rtwdemo_capi, update two instances of the
name rtwdemo_capi_M in the application code to reflect the new model name.
Click OK.
14 On the Code Generation pane, verify that the Generate code only check box is
cleared.
Build the model and generate an executable program. For example, on a Windows
system, the build generates the executable file rtwdemo_capi.exe in your current
working folder.
15 In the MATLAB Command Window, enter the command !rtwdemo_capi to run the
executable file. During execution, signals and states are logged using the C API and
then written to the text file rtwdemo_capi_ModelLog.txt in your current working
folder.
>> !rtwdemo_capi
16 Examine the text file in the MATLAB editor or other text editor. Here is an excerpt of
the signal and state logging output.
46-28
See Also
See Also
Related Examples
• “How Generated Code Exchanges Data with an Environment” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
46-29
46 Data Interchange Using the C API in Simulink Coder
The C API provides you with the flexibility of writing your own application code to interact
with model signals, states, root-level inputs/outputs, and parameters. Your target-based
application code is compiled with generated code into an executable program. The target-
based application code accesses the C API structure arrays in model_capi.c (or .cpp).
You might have host-based code that interacts with your target-based application code.
Or, you might have other target-based code that interacts with your target-based
application code. The files rtw_modelmap.h and rtw_capi.h, located in
matlabroot/rtw/c/src (open), provide macros for accessing the structures in these
arrays and their members.
Here is an example application that prints the parameter values of tunable parameters in
a model to the standard output. This code is intended as a starting point for accessing
parameter addresses. You can extend the code to perform parameter tuning. The
application:
• Uses the rtmGetDataMapInfo macro to access the mapping information in the mmi
substructure of the real-time model structure
where rtM is the pointer to the real-time model structure in model.c (or .cpp).
• Uses rtwCAPI_GetNumModelParameters to get the number of model parameters in
mapped C API:
46-30
Use C API to Access Model Parameters
{
/* Get CAPI Mapping structure from Real-Time Model structure */
rtwCAPI_ModelMappingInfo* capiMap = \
&(rtmGetDataMapInfo(rtwdemo_capi_M).mmi);
To become familiar with the example code, try building a model that displays the tunable
block parameters and MATLAB variables. You can use rtwdemo_capi, the C API example
model. The following steps apply to both grt.tlc and ert.tlc system target files,
unless otherwise indicated.
1 At the MATLAB command line, enter rtwdemo_capi to open the example model.
2 Save the top model rtwdemo_capi and the referenced model rtwdemo_capi_bot
to the same writable work folder.
3 If you are licensed for Embedded Coder software and you want to use the ert.tlc
system target tile instead of the default grt.tlc, go to the Code Generation pane
of the Configuration Parameters dialog box and use the System target file
parameter to select an ert.tlc system target file. Make sure that you also select
ert.tlc for the referenced model rtwdemo_capi_bot.
4 Confirm these model configuration parameter settings:
46-31
46 Data Interchange Using the C API in Simulink Coder
Note If you renamed the top model rtwdemo_capi, update the name
rtwdemo_capi_M in the application code to reflect the new model name.
7 Click Include directories, and type matlabroot/rtw/c/src, where matlabroot
represents the root of your MATLAB installation folder. (If you are specifying a
Windows path that contains a space, place the text inside double quotes.)
8 In the Additional Build Information subpane, click Source files, and type
rtw_capi_examples.c.
46-32
Use C API to Access Model Parameters
Click Apply.
9 On the Code Generation pane, verify that the Generate code only check box is
cleared.
Build the model and generate an executable program. For example, on a Windows
system, the build generates the executable file rtwdemo_capi.exe in your current
working folder.
10 In the MATLAB Command Window, enter !rtwdemo_capi to run the executable file.
Running the program displays parameter information in the Command Window.
>> !rtwdemo_capi
46-33
46 Data Interchange Using the C API in Simulink Coder
ans(:,:,2) =
0.64 0.54 0.74 0.68
0.45 0.29 0.18 0.18
See Also
Related Examples
• “How Generated Code Exchanges Data with an Environment” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
46-34
47
The code generator lets you export an ASAP2 file containing information about your
model during the code generation process.
You can run an interactive example of ASAP2 file generation. To open the example at the
MATLAB command prompt, enter the following command:
rtwdemo_asap2
Note Simulink Coder support for ASAP2 file generation is version-neutral. By default, the
software generates ASAP2 version 1.31 format, but the generated model information is
generally compatible with all ASAP2 versions. ASAP2 file generation also is neutral with
respect to the specific needs of ASAP2 measurement and calibration tools. The software
provides customization APIs that you can use to customize ASAP2 file generation to
generate any ASAP2 version and to meet the specific needs of your ASAP2 tools.
In this section...
“What You Should Know” on page 47-3
“Targets Supporting ASAP2” on page 47-3
“Define ASAP2 Information” on page 47-3
“Generate an ASAP2 File” on page 47-9
“Structure of the ASAP2 File” on page 47-12
“Create a Host-Based ASAM-ASAP2 Data Definition File for Data Measurement and
Calibration” on page 47-13
47-2
Export ASAP2 File for Data Measurement and Calibration
• ASAM and the ASAP2 standard and terminology. See the ASAM Web site at http://
www.asam.net.
• Simulink data objects. Data objects are used to supply information not contained in the
model. For an overview, see “Data Objects” (Simulink).
• Storage and representation of signals and parameters in generated code. See “Data
Access for Prototyping and Debugging” (Simulink Coder).
• If you are licensed for Embedded Coder, see also the Embedded Coder topic “Data
Representation and Access”.
• Generic Real-Time Target (grt.tlc) lets you generate an ASAP2 file as part of
the code generation and build process.
• Embedded Coder (ert.tlc) system target file selections also let you generate an
ASAP2 file as part of the code generation and build process.
• ASAM-ASAP2 Data Definition Target (asap2.tlc) lets you generate only an
ASAP2 file, without building an executable program.
Procedures for generating ASAP2 files by using these target configurations are given in
“Generate an ASAP2 File” on page 47-9.
47-3
47 ASAP2 Data Measurement and Calibration in Simulink Coder
The ASAP2 file generation process requires information about parameters and signals in
your model. Some of this information is contained in the model itself. You must supply the
rest by using Simulink data objects in a workspace or data dictionary. In some cases, the
use of workspace objects is optional.
You can use the Model Data Editor and built-in Simulink data objects to provide the
information. For example, you can use Simulink.Signal objects to provide
MEASUREMENT information and Simulink.Parameter objects to provide
CHARACTERISTIC information. Also, you can use data objects from data classes that are
derived from Simulink.Signal and Simulink.Parameter to provide the information.
For information about data objects, see “Data Objects” (Simulink). For information about
the Model Data Editor, see “Configure Data Properties by Using the Model Data Editor”
(Simulink).
The following table contains the minimum set of data attributes required for ASAP2 file
generation. Some data attributes are defined in the model; others are supplied in the
properties of objects. For attributes that are defined in Simulink.Signal or
Simulink.Parameter objects, the table gives the associated property name.
47-4
Export ASAP2 File for Data Measurement and Calibration
If the memory address attribute is unknown before code generation, the code generator
inserts ECU Address placeholder text in the generated ASAP2 file. You can substitute an
actual address for the placeholder by postprocessing the generated file. See the file
matlabroot/toolbox/rtw/targets/asap2/asap2/asap2post.m for an example.
asap2post.m parses through the linker map file that you provide and replaces the ECU
Address placeholders in the ASAP2 file with the actual memory addresses. Since linker
map files vary from compiler to compiler, you might need to modify the regular expression
code in asap2post.m to match the format of the linker map you use.
Note If Embedded Coder is licensed and installed on your system, and if you are
generating ELF (Executable and Linkable Format) files for your embedded target, you can
use the rtw.asap2SetAddress function to automate ECU address replacement. For
more information, see “Automatic ECU Address Replacement for ASAP2 Files (Embedded
Coder)” on page 47-6.
If the memory address attribute is known before code generation, it can be defined in the
data item or data object. By default, the MemoryAddress_ASAP2 property does not exist
in the Simulink.Signal or Simulink.Parameter data object classes. If you want to
add the attribute, add a property called MemoryAddress_ASAP2 to a custom class that is
a subclass of the Simulink or ASAP2 class. For information on subclassing Simulink data
classes, see “Define Data Classes” (Simulink).
Note In previous releases, for ASAP2 file generation, you had to define objects explicitly
as ASAP2.Signal and ASAP2.Parameter. This is no longer a limitation. As explained
above, you can use built-in Simulink objects for generating an ASAP2 file. If you have
been using an earlier release, you can continue to use the ASAP2 objects. If one of these
ASAP2 objects was created in the previous release, and you use it in this release, the
MATLAB Command Window displays a warning the first time the objects are loaded.
The following table indicates the Simulink object properties that have replaced the ASAP2
object properties of the previous release:
47-5
47 ASAP2 Data Measurement and Calibration in Simulink Coder
If Embedded Coder is licensed and installed on your system, and if you are generating
ELF (Executable and Linkable Format) files for your embedded target, you can use the
rtw.asap2SetAddress function to automate the replacement of ECU Address
placeholder memory address values with actual addresses in the generated ASAP2 file.
If the memory address attribute is unknown before code generation, the code generator
inserts ECU Address placeholder text in the generated ASAP2 file, as shown in the
example below.
/begin CHARACTERISTIC
/* Name */ Ki
/* Long Identifier */ ""
/* Type */ VALUE
/* ECU Address */ 0x0
/*ECU_Address@Ki@ */
To substitute actual addresses for the ECU Address placeholders, process the generated
ASAP2 file using the rtw.asap2SetAddress function. The general syntax is as follows:
rtw.asap2SetAddress(ASAP2File, InfoFile)
where the arguments are character vectors specifying the name of the generated ASAP2
file and the name of the generated executable ELF file or DWARF debug information file
for the model. When called, rtw.asap2SetAddress extracts the actual ECU address
from the specified ELF or DWARF file and replaces the placeholder in the ASAP2 file with
the actual address, for example:
/begin CHARACTERISTIC
/* Name */ Ki
/* Long Identifier */ ""
47-6
Export ASAP2 File for Data Measurement and Calibration
/* Type */ VALUE
/* ECU Address */ 0x40009E60
Simulink Coder software generates ASAP2 descriptions for lookup table data and its
breakpoints. The software represents 1-D table data as CURVE information, 2-D table data
as MAP information, and breakpoints as AXIS_DESCR and AXIS_PTS information. You can
model lookup tables using one of the following Simulink Lookup Table blocks:
The software supports the following types of lookup table breakpoints (axis points):
• For table data, use a Simulink.Parameter data object with a non-Auto storage
class.
47-7
47 ASAP2 Data Measurement and Calibration in Simulink Coder
• For tunable breakpoint data that is shared among multiple table axes (COM_AXIS), use
a Simulink.Parameter data object with a non-Auto storage class.
• For fixed, nontunable breakpoint data (FIX_AXIS), use workspace variables or arrays
specified in the block parameters dialog box. The breakpoints should be stored as
integers in the code, so the data type should be a built-in integer type (int8, int16,
int32, uint8, uint16, or uint32), a fixed-point data type, or an equivalent alias
type.
• For tunable breakpoint data that is not shared among multiple tables (STD_AXIS):
1 Create a Simulink.Bus object to define the struct packaging (names and order
of the fields). The fields of the parameter structure must correspond to the lookup
table data and each axis of the lookup table block. For example, in an n-D Lookup
Table block with 2 dimensions, the structure must contain only three fields. This
bus object describes the record layout for the lookup characteristic.
2 Create a Simulink.Parameter object to represent a tunable parameter.
3 Create table and axis values.
4 Optionally, specify the Units, Minimum, and Maximum properties for the
parameter object. The properties will be applied to table data only.
Here is an example of an n-D Lookup Table record generated into an ASAP2 file in
Standard Axis format:
/begin CHARACTERISTIC
/* Name */ STDAxisParam
...
/* Record Layout */ Lookup1D_X_WORD_Y_FLOAT32_IEEE
...
begin AXIS_DESCR
/* Description of X-Axis Points */
/* Axis Type */ STD_AXIS
...
/end AXIS_DESCR
/end CHARACTERISTIC
47-8
Export ASAP2 File for Data Measurement and Calibration
Note The example model rtwdemo_asap2 illustrates ASAP2 file generation for Lookup
Table blocks, including both tunable (COM_AXIS) and fixed (FIX_AXIS) lookup table
breakpoints.
You can generate an ASAP2 file from your model in one of the following ways:
• Use the Generic Real-Time Target or a Embedded Coder target to generate an ASAP2
file as part of the code generation and build process.
• Use the ASAM-ASAP2 Data Definition Target to generate only an ASAP2 file, without
building an executable.
This section discusses how to generate an ASAP2 file by using the targets that have built-
in ASAP2 support. For an example, see the ASAP2 example model rtwdemo_asap2.
The procedure for generating the ASAP2 data definition for a model using the Generic
Real-Time Target or Embedded Coder system target file is as follows:
1 Use the Model Data Editor (View > Model Data Editor) to apply storage classes to
signals, block states, and block parameters as described in “Apply Storage Classes to
Individual Signal, State, and Parameter Data Elements” on page 22-81. Use signal
and state names to refer to corresponding MEASUREMENT records and parameter
object names to refer to CHARACTERISTIC records.
Use any storage class or custom storage class other than Auto, FileScope, or, if you
set the default storage class of the corresponding data category to Default in the
Code Mapping Editor (the default setting), Model default. For example, using
ExportedGlobal configures the data item as an unstructured global variable in the
generated code.
47-9
47 ASAP2 Data Measurement and Calibration in Simulink Coder
Note The data item is not represented in the ASAP2 file if any of the following
conditions exist:
• You apply one of the storage classes Auto, FileScope, or Default (through
Model default).
• You apply a custom storage class that causes the code generator to generate a
macro or non-addressable variable.
2 Use the Model Data Editor to configure the remaining properties as desired for each
data item.
3 On the Code Generation pane, click Browse to open the System Target File
Browser. In the browser, select grt.tlc or an ERT based target file and click OK.
4 On the Code Generation > Interface pane, in the Data exchange interface
subgroup, select ASAP2 interface.
5 Select the Generate code only check box on the Code Generation pane.
6 Click Apply.
7 Build the model.
The code generator writes the ASAP2 file to the build folder. By default, the file is
named model.a2l, where model is the name of the model. The ASAP2 setup file
controls the ASAP2 file name. For details, see “Customize Generated ASAP2 File” on
page 72-2.
The procedure for generating the ASAP2 data definition for a model using the ASAM-
ASAP2 Data Definition Target is as follows:
1 Use the Model Data Editor (View > Model Data Editor) to apply storage classes to
signals, block states, and block parameters as described in “Apply Storage Classes to
Individual Signal, State, and Parameter Data Elements” on page 22-81. Use signal
and state names to refer to corresponding MEASUREMENT records and parameter
object names to refer to CHARACTERISTIC records.
Use any storage class or custom storage class other than Auto, FileScope, or, if you
set the default storage class of the corresponding data category to Default in the
Code Mapping Editor (the default setting), Model default. For example, using
ExportedGlobal configures the data item as an unstructured global variable in the
generated code.
47-10
Export ASAP2 File for Data Measurement and Calibration
Note The data item is not represented in the ASAP2 file if any of the following
conditions exist:
• You apply one of the storage classes Auto, FileScope, or Default (through
Model default).
• You apply a custom storage class that causes the code generator to generate a
macro or non-addressable variable.
2 Use the Model Data Editor to configure the remaining properties as desired for each
data item.
3 On the Code Generation pane, click Browse to open the System Target File
Browser. In the browser, select asap2.tlc and click OK.
4 Select the Generate code only check box on the Code Generation pane.
5 Click Apply.
6 Build the model.
The Simulink Coder code generator writes the ASAP2 file to the build folder. By
default, the file is named model.a2l, where model is the name of the model. The
ASAP2 setup file controls the ASAP2 file name. For details, see “Customize Generated
ASAP2 File” on page 72-2.
The build process can generate an ASAP2 file for each referenced model in a model
reference hierarchy. In the generated ASAP2 file, MEASUREMENT records represent
signals and states inside the referenced model.
To generate ASAP2 files for referenced models, select ASAP2 file generation for the top
model and for each referenced model in the reference hierarchy. For example, if you are
using the Generic Real-Time Target or an Embedded Coder target, follow the procedure
described in “Use GRT or ERT System Target File” on page 47-9 for the top model and
each referenced model.
Use function rtw.asap2MergeMdlRefs to merge the ASAP2 files generated for top and
referenced models. The function has the following syntax:
[status,info]=rtw.asap2MergeMdlRefs(topModelName,asap2FileName)
47-11
47 ASAP2 Data Measurement and Calibration in Simulink Coder
• topModelName is the name of the model containing one or more referenced models.
• asap2FileName is the name you specify for the merged ASAP2 file.
• Optional:: status returns false (logical 0) if the merge completes and true (logical 1)
otherwise.
• Optional:: info returns additional information about merge failure if status is true.
Otherwise, it returns an empty character vector.
[status,info]=rtw.asap2MergeMdlRefs('myTopMdl','merged.a2l')
This command merges the ASAP2 files generated for the top model myTopMdl and its
referenced models in the file merged.a2l.
47-12
Export ASAP2 File for Data Measurement and Calibration
open_system('rtwdemo_asap2');
47-13
47 ASAP2 Data Measurement and Calibration in Simulink Coder
ASAP2 data definition is achieved with Simulink® data objects and test point signals.
Using the Target Language Compiler (TLC), you can create highly customized solutions
for your application. See the Simulink Coder® documentation for details on ASAP2 file
generation.
47-14
See Also
You can configure ASAP2 file generation by selecting ASAP2 interface on the Code
Generation > Interface pane of the Configuration Parameters dialog box.
See Also
Related Examples
• “Create Tunable Calibration Parameter in the Generated Code” on page 22-121
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
47-15
48
Use of the global data map requires knowledge of the Target Language Compiler and of
the structure of the model.rtw file. See “Target Language Compiler Overview” (Simulink
Coder) for information on these topics.
The TLC functions that are required to generate and access the global data map record
are contained in matlabroot/rtw/c/tlc/mw/globalmaplib.tlc. The comments in
the source code fully document the global data map structures and the library functions.
The global data map structures and functions might be modified or enhanced in future
releases.
See Also
Related Examples
• “How Generated Code Exchanges Data with an Environment” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” (Simulink
Coder)
48-2
49
• “Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using
RSim System Target File” on page 49-2
• “Run Rapid Simulations Over Range of Parameter Values” on page 49-35
• “Run Batch Simulations Without Recompiling Generated Code” on page 49-43
• “Use MAT-Files to Feed Data to Inport Blocks for Rapid Simulations” on page 49-51
• “Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-
Function Target” on page 49-59
49 Desktops in Simulink Coder
• Define parameter values and input signals in one or more MAT-files that you can load
and reload at the start of simulations without rebuilding your model.
• Redirect logging data to one or more MAT-files that you can then analyze and
compare.
• Control simulation time.
• Specify external mode options.
Note To run an RSim executable, configure your computer to run MATLAB and have the
MATLAB and Simulink installation folders accessible. To deploy a standalone host
executable ( i.e., without MATLAB and Simulink installed), consider using the Host-Based
Shared Library target (ert_shrlib)."
49-2
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
speed difference for your model, time your standard Simulink simulation and compare the
results with a rapid simulation. In addition, test the model simulation in Rapid
Accelerator simulation mode.
49-3
49 Desktops in Simulink Coder
No
Configure and
build model
Batch
or Monte Carlo Yes
Program script
simulations?
No
Run simulation
Analyze simulation
results
49-4
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
49-5
49 Desktops in Simulink Coder
If you do not have control over the model content, you might need to modify the data in
the MAT-file to conform to what the model expects for input. Input data characteristics
and specifications of the Inport block that receives the data must match.
For details on adjusting these parameters and on creating a MAT-file for use with an
Inport block, see “Create a MAT-File for an Inport Block” on page 49-14. For
descriptions of the preceding block parameters, see the block description of Inport.
49-6
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
On the Code Generation pane, the code generator populates the Make command
and “Template makefile” (Simulink Coder) fields with default settings and adds the
RSim Target pane under Code Generation.
5 Click RSim Target to view the RSim Target pane.
6 Set the RSim target configuration parameters to your rapid simulation requirements.
49-7
49 Desktops in Simulink Coder
For more information on compilers that are compatible with the Simulink Coder
product, see “Select and Configure C or C++ Compiler or IDE” on page 43-3 and
“Template Makefiles and Make Options” on page 43-26 .
The format and setup of input data for a rapid simulation depends on your requirements.
49-8
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
The RSim target requires that MAT-files used as input for From File and Inport blocks
contain data. The grt target inserts MAT-file data directly into the generated code, which
is then compiled and linked as an executable. In contrast, RSim allows you to replace data
sets for each successive simulation. A MAT-file containing From File or Inport block data
must be present if a From File block or Inport block exists in your model.
If you want to run simulations over varying data sets, consider converting the parameter
structure to a cell array and saving the parameter variations to a single MAT-file.
Get the Parameter Structure for a Model
Get the global parameter structure (model_P) for a model by calling the function
rsimgetrtp.
param_struct = rsimgetrtp('model')
Argument Description
model The model for which you are running the rapid simulations.
The rsimgetrtp function forces an update diagram action for the specified model and
returns a structure that contains the following fields.
49-9
49 Desktops in Simulink Coder
Field Description
modelChecksum A four-element vector that encodes the structure of the model. The
code generator uses the checksum to check whether the structure
of the model has changed since the RSim executable was
generated. If you delete or add a block, and then generate a new
model_P vector, the new checksum does not match the original
checksum anymore. The RSim executable detects this
incompatibility in parameter vectors and exits to avoid returning
incorrect simulation results. If the model structure changes, you
must regenerate the code for the model.
parameters A structure that contains the model's global parameters.
Field Description
dataTypeName The name of the parameter data type, for example, double
dataTypeID Internal data type identifier used by the code generator
complex The value 0 if real; 1 if complex
dtTransIdx Internal data index used by the code generator
values A vector of the parameter values associated with this structure
map This field contains the mapping information that correlates the
'values' to the tunable parameters of the model. This mapping
information, in conjunction with rsimsetrtpparam, is useful for
creating subsequent rtP structures without compiling the block
diagram.
The code generator reports a tunable fixed-point parameter according to its stored value.
For example, an sfix(16) parameter value of 1.4 with a scaling of 2^-8 has a value of
358 as an int16.
In the following example, rsimgetrtp returns the parameter structure for the example
model rtwdemo_rsimtf to param_struct.
param_struct = rsimgetrtp('rtwdemo_rsimtf')
param_struct =
49-10
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
After you issue a call to rsimgetrtp, save the return value of the function call to a MAT-
file. Using a command-line option, you can then specify that MAT-file as input for rapid
simulations.
The following example saves the parameter structure returned for rtwdemo_rsimtf to
the MAT-file myrsimdemo.mat.
For information on using command-line options to specify required files, see “Run Rapid
Simulations” on page 49-19.
Convert the Parameter Structure for Running Simulations on Varying Data Sets
To use rapid simulations to test changes to specific parameters, you can convert the
model parameter structure to a cell array. You can then access a specific parameter set by
using the @ operator to specify the index for a specific parameter set in the file.
param_struct = rsimgetrtp('rtwdemo_rsimtf');
param_struct = rsimsetrtpparam(param_struct,3);
The function converts the parameters field to a cell array with three elements. Each
element contains information for a single parameter set. By default, the function
creates the second and third elements of the cell array by copying the first element.
Therefore, all of the parameter sets use the same parameter values.
3 Specify new values for the parameters in the second and third parameter sets.
49-11
49 Desktops in Simulink Coder
Alternatively, you can modify the block parameters in the model, and use rsimgetrtp to
create multiple parameter sets:
param_struct = rsimsetrtpparam(param_struct,3);
The function converts the parameters field to a cell array with three elements. Each
element contains information for a single parameter set. By default, the function
creates the second and third elements of the cell array by copying the first element.
Therefore, all of the parameter sets use the same parameter values.
3 Change the values of block parameters or workspace variables. For example, change
the value of the variable w from 70 to 72.
w = 72;
4 Use rimsgetrtp to get another structure containing parameter information. Store
the structure in a temporary variable rtp_temp.
rtp_temp = rsimgetrtp('rtwdemo_rsimtf');
5 Assign the value of the parameters field of rtp_temp to the structure
param_struct as a second parameter set.
param_struct.parameters{2} = rtp_temp.parameters;
6 Change the value of the variable w from 72 to 75.
w = 75;
7 Use rimsgetrtp to get another structure containing parameter information. Then,
assign the value of the parameters field to param_struct as a third parameter set.
49-12
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
rtp_temp = rsimgetrtp('rtwdemo_rsimtf');
param_struct.parameters{3} = rtp_temp.parameters;
8 Save the structure containing the parameter set information to a MAT-file.
save rtwdemo_rsimtf.mat param_struct;
For more information on how to specify each parameter set when you run the simulations,
see “Change Block Parameters for an RSim Simulation” on page 49-28.
You can use a MAT-file as the input data source for a From File block. The format of the
data in the MAT-file must match the data format expected by that block. For example, if
you are using a matrix as an input for the MAT file, this cannot be different from the
matrix size for the executable.
1 For array format data, in the workspace create a matrix that consists of two or more
rows. The first row must contain monotonically increasing time points. Other rows
contain data points that correspond to the time point in that column. The time and
data points must be data of type double.
For example:
t=[0:0.1:2*pi]';
Ina1=[2*sin(t) 2*cos(t)];
Ina2=sin(2*t);
Ina3=[0.5*sin(3*t) 0.5*cos(3*t)];
var_matrix=[t Ina1 Ina2 Ina3]';
For other supported data types, such as int16 or fixed-point, the time data points
must be of type double, just as for array format data. However, the sample data can
be of any dimension.
For more information on setting up the input data, see the block description of From
File.
2 Save the matrix to a MAT-file.
49-13
49 Desktops in Simulink Coder
Using a command-line option, you can then specify that MAT-file as input for rapid
simulations.
You can use a MAT-file as the input data source for an Inport block.
The format of the data in the MAT-file must adhere to one of the three column-based
formats listed in the following table. The table lists the formats in order from least flexible
to most flexible.
Format Description
Single time/data • Least flexible.
matrix • One variable.
• Two or more columns. Number of columns must equal the sum of the
dimensions of all root Inport blocks plus 1. First column must contain
monotonically increasing time points. Other columns contain data points
that correspond to the time point in a given row.
• Data of type double.
49-14
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
Format Description
Signal-and-time • More flexible than the single time/data matrix format.
structure • One variable.
• Must contain two top-level fields: time and signals. The time field
contains a column vector of the simulation times. The signals field
contains an array of substructures, each of which corresponds to an
Inport block. The substructure index corresponds to the Inport block
number. Each signals substructure must contain a field named
values. The values field must contain an array of inputs for the
corresponding Inport block, where each input corresponds to a time
point specified by the time field.
• If the time field is set to an empty value, clear the check box for the
Inport block Interpolate data parameter.
• Data type must match Inport block settings.
49-15
49 Desktops in Simulink Coder
Format Description
Per-port structure • Most flexible
• Multiple variables. Number of variables must equal the number of Inport
blocks.
• Consists of a separate structure-with-time or structure-without-time for
each Inport block. Each Inport block data structure has only one
signals field. To use this format, in the Input text field, enter the
names of the structures as a comma-separated list, in1, in2,..., inN,
where in1 is the data for your model's first port, in2 for the second
port, and so on.
• Each variable can have a different time vector.
• If the time field is set to an empty value, clear the check box for the
Inport block Interpolate data parameter.
• Data type must match Inport block settings.
• To save multiple variables to the same data file, you must save them in
the order expected by the model, using the -append option.
The supported formats and the following procedure are illustrated in rtwdemo_rsim_i.
By default, the Inport block inherits parameter settings from downstream blocks. To
import data from an external MAT-file, explicitly set the following parameters to
match the source data in the MAT-file.
49-16
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
If you choose to use a structure format for workspace variables and the time field is
empty, you must clear Interpolate data or modify the field so that it is set to a
nonempty value. Interpolation requires time data.
For descriptions of the preceding block parameters, see the block description of
Inport.
3 Build an RSim executable program for the model. The build process creates and
calculates a structural checksum for the model and embeds it in the generated
executable. The RSim target uses the checksum to verify that data being passed into
the model is consistent with what the model executable expects.
4 Create the MAT-file that provides the source data for the rapid simulations. You can
create the MAT-file from a workspace variable. Using the specifications in the
preceding format comparison table, create the workspace variables for your
simulations.
t=[0:0.1:2*pi]';
Ina1=[2*sin(t) 2*cos(t)];
Ina2=sin(2*t);
Ina3=[0.5*sin(3*t) 0.5*cos(3*t)];
var_matrix=[t Ina1 Ina2 Ina3];
Signal-and-time structure
t=[0:0.1:2*pi]';
var_single_struct.time=t;
var_single_struct.signals(1).values(:,1)=2*sin(t);
var_single_struct.signals(1).values(:,2)=2*cos(t);
var_single_struct.signals(2).values=sin(2*t);
var_single_struct.signals(3).values(:,1)=0.5*sin(3*t);
var_single_struct.signals(3).values(:,2)=0.5*cos(3*t);
v=[var_single_struct.signals(1).values...
var_single_struct.signals(2).values...
var_single_struct.signals(3).values];
Per-port structure
t=[0:0.1:2*pi]';
Inb1.time=t;
Inb1.signals.values(:,1)=2*sin(t);
49-17
49 Desktops in Simulink Coder
Inb1.signals.values(:,2)=2*cos(t);
t=[0:0.2:2*pi]';
Inb2.time=t;
Inb2.signals.values(:,1)=sin(2*t);
t=[0:0.1:2*pi]';
Inb3.time=t;
Inb3.signals.values(:,1)=0.5*sin(3*t);
Inb3.signals.values(:,2)=0.5*cos(3*t);
5 Save the workspace variables to a MAT-file.
The following example saves the workspace variable var_matrix to the MAT-file
rsim_i_matrix.mat.
save rsim_i_matrix.mat var_matrix;
Signal-and-time structure
Per-port structure
To order data when saving per-port structure variables to a single MAT-file, use the
save command's -append option. Be sure to append the data in the order that the
model expects it.
The following example saves the workspace variables Inb1, Inb2, and Inb3 to MAT-
file rsim_i_multi_struct.mat.
save rsim_i_multi_struct.mat Inb1;
save rsim_i_multi_struct.mat Inb2 -append;
save rsim_i_multi_struct.mat Inb3 -append;
The save command does not preserve the order in which you specify your workspace
variables in the command line when saving data to a MAT-file. For example, if you
specify the variables v1, v2, and v3, in that order, the order of the variables in the
MAT-file could be v2 v1 v3.
Using a command-line option, you can then specify the MAT-files as input for rapid
simulations.
49-18
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
Create a file for the Windows platform with a text editor and execute it by typing the file
name, for example, mybatch, where the name of the text file is mybatch.bat.
rtwdemo_rsimtf -f rtwdemo_rsimtf.mat=run1.mat -o results1.mat -tf 10.0
rtwdemo_rsimtf -f rtwdemo_rsimtf.mat=run2.mat -o results2.mat -tf 10.0
rtwdemo_rsimtf -f rtwdemo_rsimtf.mat=run3.mat -o results3.mat -tf 10.0
rtwdemo_rsimtf -f rtwdemo_rsimtf.mat=run4.mat -o results4.mat -tf 10.0
In this case, batch simulations run using four sets of input data in files run1.mat,
run2.mat, and so on. The RSim executable saves the data to the files specified with the -
o option.
The variable names containing simulation results in each of the files are identical.
Therefore, loading consecutive sets of data without renaming the data once it is in the
MATLAB workspace results in overwriting the prior workspace variable with new data. To
avoid overwriting, you can copy the result to a new MATLAB variable before loading the
next set of data.
You can also write MATLAB scripts to create new signals and new parameter structures,
as well as to save data and perform batch runs using the bang command (!).
For details on running simulations and available command-line options, see “Run Rapid
Simulations” on page 49-19. For an example of a rapid simulation batch script, see the
example “Run Batch Simulations Without Recompiling Generated Code” (Simulink
Coder).
49-19
49 Desktops in Simulink Coder
• “Specify New Signal Data File for a From File Block” on page 49-23
• “Specify Signal Data File for an Inport Block” on page 49-26
• “Change Block Parameters for an RSim Simulation” on page 49-28
• “Specify a New Output File Name for a Simulation” on page 49-29
• “Specify New Output File Names for To File Blocks” on page 49-30
Rapid Simulations
Using the RSim target, you can build a model once and run multiple simulations to study
effects of varying parameter settings and input signals. You can run a simulation directly
from your operating system command line, redirect the command from the MATLAB
command line by using the bang (!) character, or execute commands from a script.
rtwdemo_rsimtf
!rtwdemo_rsimtf
The following table lists ways you can use RSim target command-line options to control a
simulation.
To... Use...
Read input data for a From File block from a model -f
MAT-file other than the MAT-file used for the oldfilename.mat=newfilename.mat
previous simulation
Print a summary of the options for RSim executable filename -h
executable targets
Read input data for an Inport block from a MAT- model -i filename.mat
file
Time out after n clock time seconds, where n is a model -L n
positive integer value
Write MAT-file logging data to file model -o filename.mat
filename.mat
Read a parameter vector from file model -p filename.mat
filename.mat
49-20
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
To... Use...
Override the default TCP port (17725) for model -port TCPport
external mode
Write MAT-file logging data to a MAT-file other model -t
than the MAT-file used for the previous oldfilename.mat=newfilename.mat
simulation
Run the simulation until the time value model -tf stoptime
stoptime is reached
Run in verbose mode model -v
Wait for the Simulink engine to start the model model -w
in external mode
The following sections use the rtwdemo_rsimtf example model in examples to illustrate
some of these command-line options. In each case, the example assumes you have already
done the following:
copyfile(fullfile(matlabroot,'toolbox','rtw','rtwdemos',...
'rsimdemos','rsim_tfdata.mat'),pwd);
The following requirements apply to both fixed and variable step executables.
• You must run the RSim executable on a computer configured to run MATLAB. Also, the
RSim.exe file must be able to access the MATLAB and Simulink installation folders on
this machine. To obtain that access, your PATH environment variable must include /bin
and /bin/($ARCH), where ($ARCH) represents your operating system architecture. For
example, for a personal computer running on a Windows platform, ($ARCH) is
“win64”, whereas for a Linux machine, ($ARCH) is “glnxa64”.
• On GNU Linux platforms, to run an RSim executable, define the LD_LIBRARY_PATH
environment variable to provide the path to the MATLAB installation folder, as follows:
% setenv LD_LIBRARY_PATH /matlab/sys/os/glnx64:$LD_LIBRARY_PATH
49-21
49 Desktops in Simulink Coder
• On the Apple Macintosh OS X platform, to run RSim target executables, you must
define the environment variable DYLD_LIBRARY_PATH to include the folders bin/mac
and sys/os/mac under the MATLAB installation folder. For example, if your MATLAB
installation is under /MATLAB, add /MATLAB/bin/mac and /MATLAB/sys/os/mac to
the definition for DYLD_LIBRARY_PATH.
If a model experiences frequent zero crossings and the model's minor step size is small,
consider setting a time limit for a rapid simulation. To set a time limit, specify the -L
option with a positive integer value. The simulation aborts after running for the specified
amount of clock time (not simulation time). For example,
!rtwdemo_rsimtf -L 20
Based on your clock, after the executable runs for 20 seconds, the program terminates.
You see a message similar to one of the following:
You do not need to do anything to your model or to its configuration to use this option.
By default, a rapid simulation runs until the simulation time reaches the time specified
the Configuration Parameters dialog box, on the Solver pane. You can override the model
simulation stop time by using the -tf option. For example, the following simulation runs
until the time reaches 6.0 seconds.
The RSim target stops and logs output data using MAT-file data logging rules.
If the model includes a From File block, the end of the simulation is regulated by the stop
time setting specified in the Configuration Parameters dialog box, on the Solver pane, or
with the RSim target option -tf. The values in the block's time vector are ignored.
49-22
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
However, if the simulation time exceeds the endpoints of the time and signal matrix (if the
final time is greater than the final time value of the data matrix), the signal data is
extrapolated to the final time value.
To read the model parameter vector into a rapid simulation, you must first create a MAT-
file that includes the parameter structure as described in “Create a MAT-File That
Includes a Model Parameter Structure” on page 49-9. You can then specify the MAT-file in
the command line with the -p option.
For example:
param_struct = rsimgetrtp('rtwdemo_rsimtf');
save myrsimdata.mat param_struct
3 Run the executable with the new parameter set.
!rtwdemo_rsimtf -p myrsimdata.mat
load myrsimdata.mat
plot(rt_yout)
If your model's input data source is a From File block, you can feed the block with input
data during simulation from a single MAT-file or you can change the MAT-file from one
simulation to the next. Each MAT-file must adhere to the format described in “Create a
MAT-File for a From File Block” on page 49-13.
To change the MAT-file after an initial simulation, you specify the executable with the -f
option and an oldfile.mat=newfile.mat parameter, as shown in the following
example.
49-23
49 Desktops in Simulink Coder
w = 100;
theta = 0.5;
2 Build an RSim executable for the example model rtwdemo_rsimtf.
3 Run the executable.
!rtwdemo_rsimtf
The RSim executable runs a set of simulations and creates output MAT-files
containing the specific simulation result.
4 Load the workspace variables and plot the simulation results by entering the
following commands:
load rtwdemo_rsimtf.mat
plot(rt_yout)
The resulting plot shows simulation results based on default input data.
5 Create a new data file, newfrom.mat, that includes the following data:
t=[0:.001:1];
u=sin(100*t.*t);
49-24
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
tu=[t;u];
save newfrom.mat tu;
6 Run a rapid simulation with the new data by using the -f option to replace the
original file, rsim_tfdata.mat, with newfrom.mat.
!rtwdemo_rsimtf -f rsim_tfdata.mat=newfrom.mat
7 Load the data and plot the new results by entering the following commands:
load rtwdemo_rsimtf.mat
plot(rt_yout)
From File blocks require input data of type double. If you need to import signal data of a
data type other than double, use an Inport block (see “Create a MAT-File for an Inport
Block” on page 49-14) or a From Workspace block with the data specified as a structure.
variable.time
variable.signals.values
49-25
49 Desktops in Simulink Coder
If you have more than one signal, use the following format:
variable.time
variable.signals(1).values
variable.signals(2).values
If your model's input data source is an Inport block, you can feed the block with input
data during simulation from a single MAT-file or you can change the MAT-file from one
simulation to the next. Each MAT-file must adhere to one of the three formats described in
“Create a MAT-File for an Inport Block” on page 49-14.
To specify the MAT-file after a simulation, you specify the executable with the -i option
and the name of the MAT-file that contains the input data. For example:
t=[0:0.01:2*pi]';
s1=[2*sin(t) 2*cos(t)];
s2=sin(2*t);
s3=[0.5*sin(3*t) 0.5*cos(3*t)];
plot(t, [s1 s2 s3])
49-26
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
5 Prepare the MAT-file by using one of the three available file formats described in
“Create a MAT-File for an Inport Block” on page 49-14. The following example defines
a signal-and-time structure in the workspace and names it var_single_struct.
t=[0:0.1:2*pi]';
var_single_struct.time=t;
var_single_struct.signals(1).values(:,1)=2*sin(t);
var_single_struct.signals(1).values(:,2)=2*cos(t);
var_single_struct.signals(2).values=sin(2*t);
var_single_struct.signals(3).values(:,1)=0.5*sin(3*t);
var_single_struct.signals(3).values(:,2)=0.5*cos(3*t);
v=[var_single_struct.signals(1).values...
var_single_struct.signals(2).values...
var_single_struct.signals(3).values];
6 Save the workspace variable var_single_struct to MAT-file
rsim_i_single_struct.
save rsim_i_single_struct.mat var_single_struct;
7 Run a rapid simulation with the input data by using the -i option. Load and plot the
results.
!rtwdemo_rsim_i -i rsim_i_single_struct.mat
49-27
49 Desktops in Simulink Coder
RSim can read the MAT-file and replace the entire model_P structure whenever you
change one or more parameters, without recompiling the entire model.
49-28
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
For example, assume that you changed one or more parameters in your model, generated
the new model_P vector, and saved model_P to a new MAT-file called mymatfile.mat.
To run the same rtwdemo_rsimtf model and use these new parameter values, use the -
p option, as shown in the following example:
!rtwdemo_rsimtf -p mymatfile.mat
load rtwdemo_rsimtf
plot(rt_yout)
If you have converted the parameter structure to a cell array for running simulations on
varying data sets, as described in “Convert the Parameter Structure for Running
Simulations on Varying Data Sets” on page 49-11, you must add an @n suffix to the MAT-
file specification. n is the element of the cell array that contains the specific input that
you want to use for the simulation.
ans =
dataTypeName: 'double'
dataTypeId: 0
complex: 0
dtTransIdx: 0
values: [-140 -4900 0 4900]
map: []
structParamInfo: []
If you have specified one or more of the Save to Workspace options — Time, States,
Outputs, or Final States — in the Configuration Parameters dialog box, on the Data
Import/Export pane, the default is to save simulation logging results to the file
model.mat. For example, the example model rtwdemo_rsimtf normally saves data to
rtwdemo_rsimtf.mat, as follows:
49-29
49 Desktops in Simulink Coder
!rtwdemo_rsimtf
created rtwdemo_rsimtf.mat
You can specify a new output file name for data logging by using the -o option when you
run an executable.
!rtwdemo_rsimtf -o rsim1.mat
In this case, the set of parameters provided at the time of code generation, including
From File block data parameters, is run.
In much the same way as you can specify a new system output file name, you can also
provide new output file names for data saved from one or more To File blocks. To do this,
specify the original file name at the time of code generation with a new name, as shown in
the following example:
!rtwdemo_rsimtf -t rtwdemo_rsimtf_data.mat=mynewrsimdata.mat
In this case, assume that the original model wrote data to the output file
rtwdemo_rsimtf_data.mat. Specifying a new file name forces RSim to write to the file
mynewrsimdata.mat. With this technique, you can avoid overwriting an existing
simulation run.
For this example, Default parameter behavior is set to Inlined. The model declares
workspace variables as tunable parameters. To use RSim with Default parameter
behavior set to Tunable, and without explicitly declaring tunable parameters, see “Run
Batch Simulations Without Recompiling Generated Code” (Simulink Coder).
49-30
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File
open_system('rtwdemo_rsim_param_tuning');
49-31
49 Desktops in Simulink Coder
49-32
See Also
This model uses the RSim target and the rsimgetrtp function to allow a non real time
executable to be passed new data without the need to recompile the Simulink model. This
feature allows you to get a map of the tunable parameters declared in a model and save it
in a MAT-file. You can then create your own MATLAB GUI or a standalone GUI
(independent of MATLAB) to read and write the MAT-file and rerun the executable to
produce new output files.
Double-click the buttons at the upper right sequentially to run the example.
To review the code used to create both the MATLAB GUI and standalone GUI, double-
click the View MATLAB programs button.
For more information, you can also refer to the "Rapid Simulation Target" section in the
Simulink Coder documentation.
See Also
More About
• “Acceleration” (Simulink)
49-33
49 Desktops in Simulink Coder
49-34
Run Rapid Simulations Over Range of Parameter Values
It is very easy to customize this example for your own application by modifying the
MATLAB® script used to build this example. Click the link in the top left corner of this
page to edit the MATLAB® script. Click the link in the top right corner to run this
example from MATLAB®. When running this example, make sure you are in a writable
directory. The example creates files that you may want to investigate later.
For this example, Default parameter behavior is set to Inlined. In the example, you
create Simulink.Parameter objects as tunable parameters. To use RSim with Default
parameter behavior set to Tunable, and without explicitly declaring tunable
parameters, see “Run Batch Simulations Without Recompiling Generated Code” (Simulink
Coder).
To quickly run multiple simulations in the Simulink environment, consider using rapid
accelerator instead of RSim. For information about rapid accelerator, see “What Is
Acceleration?” (Simulink). To sweep parameter values, see “Optimize, Estimate, and
Sweep Block Parameter Values” (Simulink).
Step 1. Preparation
Make sure the current directory is writable because this example will be creating files.
Open the model and configure it to use the RSim target. For more information on doing
this graphically and setting up other RSim target related options, look here.
mdlName = 'rtwdemo_rsim_vdp';
open_system(mdlName);
cs = getActiveConfigSet(mdlName);
cs.switchTarget('rsim.tlc',[]);
49-35
49 Desktops in Simulink Coder
Specify as Tunable the variables INIT_X1 (the initial condition for state x1), INIT_X2 (the
initial condition for state x2), and MU (the gain value). To create tunable parameters,
convert the variables to Simulink.Parameter objects, and use a storage class other
than Auto for each object. In this example we will be investigating how the state
trajectories evolve from different initial values for the states x1 and x2 in the model.
INIT_X1 = Simulink.Parameter(INIT_X1);
INIT_X1.StorageClass = 'Model default';
INIT_X2 = Simulink.Parameter(INIT_X2);
INIT_X2.StorageClass = 'Model default';
MU = Simulink.Parameter(MU);
MU.StorageClass = 'Model default';
Define the names of files that will be created during this example.
49-36
Run Rapid Simulations Over Range of Parameter Values
Build the RSim executable for the model. During the build process, a structural checksum
is calculated for the model and embedded into the generated executable. This checksum
is used to check that a parameter set passed to the executable is compatible with it.
rtwbuild(mdlName);
Get the default rtP structure (parameter set) for the model. The modelChecksum field in
the rtP structure is the structural checksum of the model. This must match the checksum
embedded in the RSim executable (generated in step 2 above). If the two checksums do
not match, the executable will generate an error. rsimgetrtp generates an rtP structure
with entries for the named tunable variables INIT_X1, INIT_X2 and MU in the model.
rtp = rsimgetrtp(mdlName)
rtp =
Using the rtp structure from step 4, we build a structure array with different values for
the tunable variables in the model. As mentioned earlier, in this example we want to see
how the state trajectories evolve for different initial values for the states x1 and x2 in the
model. Hence we generate different parameter sets with different values for INIT_X1 and
INIT_X2 and leave the tunable variable MU at the default value.
INIT_X1_vals = -5:1:5;
INIT_X2_vals = -5:1:5;
49-37
49 Desktops in Simulink Coder
MU_vals = 1;
nPrmSets = length(INIT_X1_vals)*length(INIT_X2_vals)*length(MU_vals)
nPrmSets =
121
Note that in this example we have nPrmSets parameter sets, i.e., we need to run that
many simulations. Initialize aggData, which is a structure array used to hold the
parameter set and the corresponding results.
aggData = struct('tout', [], 'yout', [], ...
'prms', struct('INIT_X1',[],'INIT_X2',[], 'MU', []))
aggData = repmat(aggData, nPrmSets, 1);
aggData =
tout: []
yout: []
prms: [1x1 struct]
The utility function rsimsetrtpparam is a convenient way to build the rtP structure by
adding parameter sets one at a time with different parameters values.
idx = 1;
for iX1 = INIT_X1_vals
for iX2 = INIT_X2_vals
for iMU = MU_vals
rtp = rsimsetrtpparam(rtp,idx,'INIT_X1',iX1,'INIT_X2',iX2,'MU',iMU);
aggData(idx).prms.INIT_X1 = iX1;
aggData(idx).prms.INIT_X2 = iX2;
aggData(idx).prms.MU = iMU;
idx = idx + 1;
end
end
end
Save the rtP structure array with the parameter sets to a MAT-file.
save(prmFileName,'rtp');
49-38
Run Rapid Simulations Over Range of Parameter Values
We create a batch/script file to run the RSim executable over the parameter sets. Each
run reads the specified parameter set from the parameter MAT-file and writes the results
to the specified output MAT-file. Note that we use the time out option so that if a
particular run were to hang (because the model may have a singularity for that particular
parameter set), we abort the run after the specified time limit is exceeded and proceed to
the next run.
specifies using the third parameter set from the rtP structure in prm.mat, writing the
results to run3.mat, and aborting execution if a run takes longer than 3600 seconds of
CPU time. In addition, messages from model.exe while it is running are piped to run.log.
In case of problems, we can look at run.log to help debug.
fid = fopen(batFileName, 'w');
idx = 1;
for iX1 = INIT_X1_vals
for iX2 = INIT_X2_vals
for iMU = MU_vals
outMatFile = [mdlName, '_run',num2str(idx),'.mat'];
cmd = [exeFileName, ...
' -p ', prmFileName, '@', int2str(idx), ...
' -o ', outMatFile, ...
' -L 3600'];
if ispc
cmd = [cmd, ' 2>&1>> ', logFileName];
else % (unix)
cmd = ['.' filesep cmd, ' 1> ', logFileName, ' 2>&1'];
end
fprintf(fid, ['echo "', cmd, '"\n']);
fprintf(fid, [cmd, '\n']);
idx = idx + 1;
end
end
end
if isunix,
system(['touch ', logFileName]);
system(['chmod +x ', batFileName]);
end
fclose(fid);
49-39
49 Desktops in Simulink Coder
Creating a batch file to run the simulations enables us to call the system command once
to run the simulations (or even run the batch script outside MATLAB®) instead of calling
the system command in a loop for each simulation. This results in a performance
improvement because the system command has significant overhead.
Run the batch/script file, which runs the RSim executable once for each parameter set
and saves the results to a different MAT-file each time. Note that this batch file can be run
from outside MATLAB®.
[stat, res] = system(['.' filesep batFileName]);
if stat ~= 0
error(['Error running batch file ''', batFileName, ''' :', res]);
end
In this example we put the simulation runs into one batch file, ran the batch file to
sequentially run 'n' simulations over 'n' parameter sets. For your application this script
can be modified to generate multiple batch files, and these batch files are run in parallel
by distributing them across multiple computers. Also the batch files can be run without
launching MATLAB®.
Here we collect the simulation results from the output MAT-files into the aggData
structure. If the output MAT-file corresponding to a particular run is not found, we set the
results corresponding to that run to be NaN (not a number). This situation can occur if a
simulation run with a particular set of parameters encounters singularities in the model.
idx = 1;
for iX1 = INIT_X1_vals
for iX2 = INIT_X2_vals
for iMU = MU_vals
outMatFile = [mdlName, '_run',num2str(idx),'.mat'];
if exist(outMatFile,'file')
load(outMatFile);
aggData(idx).tout = rt_tout;
aggData(idx).yout = rt_yout;
else
aggData(idx).tout = nan;
aggData(idx).yout = nan;
end
idx = idx + 1;
end
49-40
Run Rapid Simulations Over Range of Parameter Values
end
end
Save the aggData structure to the results MAT-file. At this point, you can delete the other
MAT-files, as the aggData data structure contains the aggregation of input (parameters
sets) and output data (simulation results).
save(aggDataFile,'aggData');
disp(['Took ', num2str(cputime-startTime), ...
' seconds to generate results from ', ...
num2str(nPrmSets), ' simulation runs (Steps 2 to 7).']);
Took 11.875 seconds to generate results from 121 simulation runs (Steps 2 to 7).
We now have data to plot the phase diagram (X2 versus X1) with different initial values
for x1 and x2. The diagram shows that, irrespective of the initial condition, the Van der
Pol oscillator converges to its natural oscillator mode.
49-41
49 Desktops in Simulink Coder
49-42
Run Batch Simulations Without Recompiling Generated Code
To quickly run multiple simulations in the Simulink environment, consider using rapid
accelerator instead of RSim. See “What Is Acceleration?” (Simulink).
Step 1. Preparation
Make sure the current directory is writable because this example will be creating files.
Open the model and configure it to use the RSim target. For more information on doing
this graphically and setting up other RSim target related options, look here.
mdlName = 'rtwdemo_rsimtf';
open_system(mdlName);
cs = getActiveConfigSet(mdlName);
cs.switchTarget('rsim.tlc',[]);
49-43
49 Desktops in Simulink Coder
if ~isempty(dir('rsim_tfdata.mat')),
delete('rsim_tfdata.mat');
end
str1 = fullfile(matlabroot,'toolbox','rtw','rtwdemos','rsimdemos','rsim_tfdata.mat');
str2 = ['copyfile(''', str1, ''',''rsim_tfdata.mat'',''writable'')'];
eval(str2);
Build the RSim executable for the model. During the build process, a structural checksum
is calculated for the model and embedded into the generated executable. This checksum
is used to check that a parameter set passed to the executable is compatible with it.
evalin('base','w = 70;')
evalin('base','theta = 1.0;')
disp('Building compiled RSim simulation.')
rtwbuild(mdlName);
Step 3. Get the Default Parameter Set and Create 10 Parameters Sets
49-44
Run Batch Simulations Without Recompiling Generated Code
eval(savestr);
evalin('base','theta = theta - .1;');
end
disp('Finished creating parameter data files.')
Step 4. Run 10 RSim Simulations Using New Parameter Sets and Plot the Results
figure
for i=1:10
% Bang out and run a simulation using new parameter data
runstr = ['.', filesep, 'rtwdemo_rsimtf -p params',num2str(i),'.mat', ' -v'];
[status, result] = system(runstr);
if status ~= 0, error(result); end
% Load simulation data into MATLAB for plotting.
load rtwdemo_rsimtf.mat;
axis([0 1 0 2]);
plot(rt_tout, rt_yout)
hold on
end
49-45
49 Desktops in Simulink Coder
The time vector has 4096 points in the event we want to do windowing and spectral
analysis on simulation results.
dt = .001;
nn = [0:1:4095];
t = dt*nn; [m,n] = size(t);
wlo = 1; whi = 4;
omega = [wlo:((whi-wlo)/n):whi - (whi-wlo)/n];
49-46
Run Batch Simulations Without Recompiling Generated Code
49-47
49 Desktops in Simulink Coder
Step 7. Run the RSim Compiled Simulation Using New Signal Data
Replace the original signal data (rsim_tfdata.mat) with the files sweep1.mat, sweep2.mat,
and so on.
49-48
Run Batch Simulations Without Recompiling Generated Code
plotstr = strcat('subplot(5,1,',num2str(i),');');
eval(plotstr);
plot(rt_tout, rt_yout); axis([0 4.1 -3 3]);
end
zoom on
% cleanup
evalin('base','clear w theta')
disp('This part of the example illustrates a sequence of 5 plots. Each plot')
disp('shows the simulation results for the next frequency range. Using the')
disp('mouse, zoom in on each signal to observe signal amplitudes.')
close_system(mdlName, 0);
49-49
49 Desktops in Simulink Coder
49-50
Use MAT-Files to Feed Data to Inport Blocks for Rapid Simulations
This flexibility lends itself well to applications for which you must run simulations over a
range of input data stored in different data files. This example explains how to use this
feature.
To quickly run multiple simulations in the Simulink environment, consider using rapid
accelerator instead of RSim. See “What Is Acceleration?” (Simulink).
Step 1. Preparation
Open the model and configure it to use the Simulink® Coder™ RSim target. For more
information on doing this graphically and setting up other RSim target related options,
look here.
mdlName = 'rtwdemo_rsim_i';
open_system(mdlName);
cs = getActiveConfigSet(mdlName);
cs.switchTarget('rsim.tlc',[]);
49-51
49 Desktops in Simulink Coder
To use the RSim -i option, you must configure each Inport block properly. You can double-
click an Inport block to view its properties. By default, Inport blocks inherit their
properties from downstream blocks. Before you can import data from external MAT-files,
you must set the parameters of each Inport block to match the data in the MAT file. In
most cases, the following parameters of an Inport block must be set: Interpolate Data,
Port Dimensions, Data Type, and Signal Type. For more information on these parameters,
click the Help button. In this example model, three Inport blocks exist. We want Inport 1
and Inport 2 to interpolate between data, and Inport 3 to not interpolate. The dimension
of the Inport blocks are 2, 1, and 2, respectively. Signals are real. The settings are as
follows:
for i =1:3
portName =['/In', num2str(i)];
Interp = get_param(strcat(mdlName,portName),'Interpolate');
PortDimension = get_param(strcat(mdlName,portName),'PortDimensions');
DataType = get_param(strcat(mdlName,portName),'OutDataTypeStr');
49-52
Use MAT-Files to Feed Data to Inport Blocks for Rapid Simulations
SignalType = get_param(strcat(mdlName,portName),'SignalType');
s1= sprintf('For inport %s ', portName(2:4));
disp('-----------------------------');
disp(s1);
s2= sprintf('The interpolation flag is %s', Interp);
disp(s2);
s3 = sprintf(' The port dimension is %s', PortDimension);
disp(s3);
s4 = sprintf(' The data type is %s', DataType);
disp(s4);
s5 = sprintf(' The signal type is %s\n', SignalType);
disp(s5);
end
-----------------------------
For inport In1
The interpolation flag is on
The port dimension is 2
The data type is double
The signal type is real
-----------------------------
For inport In2
The interpolation flag is on
The port dimension is 1
The data type is double
The signal type is real
-----------------------------
For inport In3
The interpolation flag is off
The port dimension is 2
The data type is double
The signal type is real
Build the RSim executable for the model. During the build process, a structural checksum
is calculated for the model and embedded into the generated executable. This checksum
is used to check that a parameter set passed to the executable is compatible with it.
evalc('rtwbuild(mdlName)');
49-53
49 Desktops in Simulink Coder
Once the Inport block is configured, the data file should be prepared based on the Inport
blocks. The following figure shows the input signals to be used.
t=[0:0.01:2*pi]';
s1 = [2*sin(t) 2*cos(t)];
s2 = sin(2*t);
s3 = [0.5*sin(3*t) 0.5*cos(3*t)];
figure;
plot(t, [s1 s2 s3]);
disp('The following figure displays the input signals.');
49-54
Use MAT-Files to Feed Data to Inport Blocks for Rapid Simulations
Generally, the MAT-file can be created from a workspace variable. The RSim -i option
supports three data file formats:
1) The MAT-file contains one variable in TU matrix format of doubles. For this format, the
first column is the time vector and the remaining columns are input vectors. The number
of columns in the TU matrix equals the sum of the dimensions of the root Inport blocks
plus 1. The following MATLAB® code generates a MAT-file containing one variable
var_matrix in TU matrix format. Note that you can use this format only if the input ports
in your model have the same data type.
t=[0:0.1:2*pi]';
Ina1 = [2*sin(t) 2*cos(t)];
Ina2 = sin(2*t);
Ina3 = [0.5*sin(3*t) 0.5*cos(3*t)];
var_matrix = [ t Ina1 Ina2 Ina3];
save rsim_i_matrix.mat var_matrix;
disp('rsim_i_matrix.mat contains one variable var_matrix in TU matrix format.');
2) The MAT-file contains one variable in structure format. For this format, the variable
must contain two fields called time and signals. If one of the Inport block sets Interpolate
Data to On, then the time field of the variable must not be an empty vector. Also, the
width of the signals must equal the total width of the Inport blocks. The following code
generates a MAT-file that contains one variable var_matrix in signal variable structure
format. This format is more flexible than the TU matrix format because it can support
input ports with different data types.
t= [0:0.1:2*pi]';
var_single_struct.time = t;
var_single_struct.signals(1).values(:,1) = 2*sin(t);
var_single_struct.signals(1).values(:,2) = 2*cos(t);
var_single_struct.signals(2).values = sin(2*t);
var_single_struct.signals(3).values(:,1) = 0.5*sin(3*t) ;
var_single_struct.signals(3).values(:,2) = 0.5*cos(3*t) ;
v=[var_single_struct.signals(1).values var_single_struct.signals(2).values ...
var_single_struct.signals(3).values ];
save rsim_i_single_struct.mat var_single_struct;
disp('rsim_i_single_struct.mat contains one variable var_single_struct in')
disp('struct format.');
49-55
49 Desktops in Simulink Coder
3) The MAT-file contains multiple variables in structure format. For this format, the
number of variables equals the number of Inport blocks. Different variables can have
different time vectors. The following code generates a MAT-file that contains multiple
variables, each in structure format. This is the most flexible format because it allows each
Inport block to have its own time vector.
t= [0:0.1:2*pi]';
Inb1.time = t;
Inb1.signals.values(:,1) = 2*sin(t);
Inb1.signals.values(:,2) = 2*cos(t);
t= [0:0.2:2*pi]';
Inb2.time = t;
Inb2.signals.values(:,1) = sin(2*t);
t= [0:0.1:2*pi]';
Inb3.time = t;
Inb3.signals.values(:,1) = 0.5*sin(3*t);
Inb3.signals.values(:,2) = 0.5*cos(3*t);
save rsim_i_multi_struct.mat Inb1;
save rsim_i_multi_struct.mat Inb2 -append;
save rsim_i_multi_struct.mat Inb3 -append;
disp('rsim_i_multi_struct.mat contains three variables Inb1\Inb2\Inb3');
disp('in struct format. Note that command save -append option must be');
disp('used to generate the MAT-file to preserve the order of the');
disp('variables in the MAT-file generated. The command:')
disp('save rsim_i_multi_struct.mat Inb1 Inb2 Inb3 might not preserve');
disp('the order of the variables in the MAT-file and you should not use it');
disp('to generate the MAT-file.');
Step 6. Run 3 RSim Simulations Using Different Files and Plot the Results
RSim -i options can also be used for batch mode simulation. Prepare different MAT-files
and run the RSim target with them.
49-56
Use MAT-Files to Feed Data to Inport Blocks for Rapid Simulations
figure
fileName = ({'rsim_i_matrix', 'rsim_i_single_struct', 'rsim_i_multi_struct'});
for i=1:3
% bang out and run a simulation using new parameter data
name = fileName(i);
runstr = ['.', filesep, 'rtwdemo_rsim_i -i ',char(name),'.mat', ' -v'];
evalc('system(runstr)');
pause(0.5);
% load simulation data into MATLAB(R) for plotting.
load rtwdemo_rsim_i.mat;
subplot(3,1,i);
axis([0,6, -5, 5]);
plot(rt_tout, rt_yout);
hold on
end
49-57
49 Desktops in Simulink Coder
49-58
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target
The following sections describe the properties of S-function targets and illustrate how to
generate them. For more details on the structure of S-functions, see “S-Functions”
(Simulink).
In this section...
“About the S-Function Target” on page 49-59
“Create S-Function Blocks from a Subsystem” on page 49-63
“Tunable Parameters in Generated S-Functions” on page 49-67
“System Target File” on page 49-68
“Checksums and the S-Function Target” on page 49-68
“Generated S-Function Compatibility” on page 49-69
“S-Function Target Limitations” on page 49-70
The 'S-Function' value for CodeFormat TLC variable used by the S-function target
generates code that conforms to the Simulink C MEX S-function application programming
interface (API). Applications of this format include
49-59
49 Desktops in Simulink Coder
You can place a generated S-function block into another model from which you can
generate another S-function. This approach allows any level of nested S-functions. For
limitations related to nesting, see “Limitations on Nesting S-Functions” on page 49-74.
Note While the S-function target provides a means to deploy an application component
for reuse while shielding its internal logic from inspection and modification, the preferred
solutions for protecting intellectual property in distributed components are:
• The protected model, a referenced model that hides all block and line information. For
more information, see “Simulate Protected Models from Third Parties” (Simulink).
• The shared library system target file, used to generate a shared library for a model or
subsystem for use in a system simulation external to Simulink. For more information,
see “Package Generated Code as Shared Libraries” on page 50-2.
There are different files required to deploy a generated S-Function block for simulation
versus code generation.
To deploy your generated S-Function block for inclusion in other models for simulation,
you need only provide the binary MEX-file object that was generated in the current
working folder when the S-Function block was created. The required file is:
• subsys_sf.mexext
49-60
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target
To deploy your generated S-Function block for inclusion in other models for code
generation, you must provide all of the files that were generated in the current working
folder when the S-Function block was created. The required files are:
Note The generated S-function code uses Configuration Parameters > Hardware
Implementation parameter values that match the host system on which the function was
built. When you use the S-function in a model for code generation, make sure that these
parameter values for the model match the parameter values of the S-function.
A generated S-Function block can inherit its sample time from the model in which it is
placed if certain criteria are met. Conditions that govern sample time propagation for
both Model blocks and generated S-Function blocks are described in “Inherit Sample
Times for Model Referencing” (Simulink) and “Inherited Sample Time for Referenced
Models” on page 4-25.
To generate an S-Function block that meets the criteria for inheriting sample time, you
must constrain the solver for the model from which the S-Function block is generated. On
the Solver configuration parameters dialog box pane, set Type to Fixed-step and
Periodic sample time constraint to Ensure sample time independent. If the
model is unable to inherit sample times, this setting causes the Simulink software to
display an error message when building the model. For more information about this
option, see “Periodic sample time constraint” (Simulink).
The table shows the possible combinations of top-level model solver types as these types
relate to subsystem build types and solver types for generated S-functions.
49-61
49 Desktops in Simulink Coder
Note S-functions generated from a subsystem have parameters that are hard coded into
the block. Simulink calculates parameters such as sample time when it generates the
block, not during simulation run time. Hence, it is important to verify whether the
generated S-Function block works as expected in the destination model.
There are instances when the subsystem build type selection produces an override of the
subsystem solver type. The table summarizes the relationships between subsystem build
types and the applied subsystem solver types.
Top-level Model Solver Type Overrides of Subsystem Solver Types by Build Type
49-62
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target
The next figure shows SourceModel, a simple model that inputs signals to a subsystem.
The subsequent figure shows the subsystem, SourceSubsys. The signals, which have
different widths and sample times, are:
SourceModel
49-63
49 Desktops in Simulink Coder
SourceSubsys
The objective is to extract SourceSubsys from the model and build an S-Function block
from it, using the S-function target. The S-Function block must perform identically to the
subsystem from which it was generated.
In this model, SourceSubsys inherits sample times and signal widths from its input
signals. However, S-Function blocks created from a model using the S-function target has
all signal attributes (such as signal widths or sample times) hard-wired. (The sole
exception to this rule concerns sample times, as described in “Sample Time Propagation
in Generated S-Functions” on page 49-61.)
In this example, you want the S-Function block to retain the properties of SourceSubsys
as it exists in SourceModel. Therefore, before you build the subsystem as a separate S-
function component, you must set the inport sample times and widths explicitly. In
addition, the solver parameters of the S-function component must be the same as those
parameters of the original model. The generated S-function component operates
identically to the original subsystem (see “Choose a Solver Type” on page 49-61 for more
information).
1 Create a new model and copy/paste the SourceSubsys block into the empty window.
2 Set the signal widths and sample times of inports inside SourceSubsys such that
they match those of the signals in the original model. Inport 1, Filter, has a width
of 1 and a sample time of 1. Inport 2, Xferfcn, has a width of 1 and a sample time of
0.5. Inport 3, offsets, has a width of 2 and a sample time of 0.5.
49-64
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target
3 The generated S-Function block should have three inports and one outport. Connect
inports and an outport to SourceSubsys, as shown in the next figure.
The signal widths and sample times are propagated to these ports.
4 Set the solver type, mode, and other solver parameters such that they are identical to
those of the source model. This is easiest to do if you use Model Explorer.
5 In the Configuration Parameters dialog box, go to the Code Generation pane.
6 Click Browse to open the System Target File Browser.
7 In the System Target File Browser, select the S-function target, rtwsfcn.tlc, and
click OK.
8 Select the S-Function Target pane. Make sure that Create new model is selected,
as shown in the next figure:
When this option is selected, the build process creates a new model after it builds the
S-function component. The new model contains an S-Function block, linked to the S-
function component.
Click Apply.
9 Save the new model containing your subsystem, for example as SourceSubsys.
10 Build the model.
49-65
49 Desktops in Simulink Coder
11 The build process produces the S-function component in the working folder. After the
build, a new model window is displayed.
Note For a list of files required to deploy your S-Function block for simulation or
code generation, see “Required Files for S-Function Deployment” on page 49-60.
The next figure shows the S-Function block plugged into the original model. Given
identical input signals, the S-Function block performs identically to the original
subsystem.
The speed at which the S-Function block executes is typically faster than the original
model. This difference in speed is more pronounced for larger and more complicated
models. By using generated S-functions, you can increase the efficiency of your modeling
process.
49-66
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target
• Use the Generate S-function feature (see “Generate S-Function from Subsystem” on
page 11-62).
or
• Use the Model Parameter Configuration dialog box (see “Declare Workspace Variables
as Tunable Parameters Using the Model Parameter Configuration Dialog Box”
(Simulink Coder)) to declare desired block parameters tunable.
Block parameters that are declared tunable with the auto storage class in the source
model become tunable parameters of the generated S-function. These parameters do not
become part of a generated model_P (formerly rtP) parameter data structure, as they
would in code generated from other targets. Instead, the generated code accesses these
parameters by using MEX API calls such as mxGetPr or mxGetData. Your code should
access these parameters in the same way.
For more information on MEX API calls, see “About C S-Functions” (Simulink) and
“MATLAB API for Other Languages” (MATLAB).
S-Function blocks created by using the S-function target are automatically masked. The
mask displays each tunable parameter in an edit field. By default, the edit field displays
the parameter by variable name, as in the following example.
49-67
49 Desktops in Simulink Coder
You can choose to display the value of the parameter rather than its variable name by
selecting Use value for tunable parameters on the Code Generation > S-Function
Target pane of the Configuration Parameters dialog box.
When this option is chosen, the value of the variable (at code generation time) is
displayed in the edit field, as in the following example.
49-68
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target
An S-function can add additional information, not captured during the block property
analysis, to a checksum by calling the function ssSetChecksumVal. For the S-Function
target, the value that gets added to the checksum is the checksum of the model or
subsystem from which the S-function is generated.
The code generator applies the subsystem and model checksums as follows:
• Code reuse — If two subsystems in a model have the same checksum, the code
generator produces code for one function only.
• Model reference — If the current model checksum matches the checksum when the
model was built, the build process does not rebuild referenced models.
• External mode — If the current model checksum does not match the checksum of the
code that is running on the target hardware, the build process generates an error.
• S-function target generated code from previous MATLAB release software is not
compatible with newer releases. Do not recompile the generated code from a previous
release with newer MATLAB release software. Use the same MATLAB release software
to generate code for the S-function target and compile the code into a MEX file.
• You can use binary S-function MEX files generated from previous MATLAB release
software with the same or newer releases with the same compatibility considerations
as handwritten S-functions. For more information, see “S-Function Compatibility”
(Simulink).
• The code generator can generate code and build an executable from a model that
contains generated S-functions. This support requires that the S-functions are built
with the same MATLAB release software that builds the model. It is not possible to
incorporate a generated S-function MEX file from previous MATLAB release software
into a model and build the model with newer releases.
49-69
49 Desktops in Simulink Coder
Certain limitations apply to the use of tunable variables in expressions. When the code
generator encounters an unsupported expression while producing code, a warning
appears and the equivalent numeric value is generated in the code. For a list of the
limitations, see “Tunable Expression Limitations” on page 22-135.
Parameter Tuning
The S-Function block does not support tuning of tunable parameters with:
• Complex values.
• Values or data types that are transformed to a constant (by setting the model
configuration parameter Optimization > Default parameter behavior to Inlined).
• Data types that are not built-in.
49-70
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target
If you select these tunable parameters (through the Generate S-Function for Subsystem
dialog box):
If you set the S-function upgrades needed option on the Diagnostics > Compatibility
pane of the Configuration Parameters dialog box to warning or error, the code
generator instructs you to upgrade S-functions that you create with the Generate S-
function feature. This is because the S-function system target file does not register run-
time parameters. Run-time parameters are only supported for inlined S-Functions and the
generated S-Function supports features that prevent it from being inlined (for example, it
can call or contain other noninlined S-functions).
You can work around this limitation by setting the S-function upgrades needed option
to none.
When using the S-function system target file, the code generator restricts I/O to
correspond to the root model Inport and Outport blocks (or the Inport and Outport blocks
of the Subsystem block from which the S-function target was generated). No code is
generated for Goto or From blocks.
To work around this restriction, create your model and subsystem with the required
Inport and Outport blocks, instead of using Goto and From blocks to pass data between
the root model and subsystem. In the model that incorporates the generated S-function,
you would then add Goto and From blocks.
49-71
49 Desktops in Simulink Coder
• Subsystem1 with a Goto block, which has global visibility and passes its input to the
From block in the root model
An Outport block replaces the GoTo block in Subsystem1. When you plug the generated
S-function into the root model, its output connects directly to the To Workspace block.
The following limitations apply to building and updating S-functions using the S-function
system target file:
49-72
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target
• You cannot build models that contain Model blocks using the S-function system target
file. This also means that you cannot build a subsystem module by right-clicking (or by
using Code > C/C++ Code > Build Selected Subsystem) if the subsystem contains
Model blocks. This restriction applies only to S-functions generated using the S-
function target, not to ERT S-functions.
• If you modify the model that generated an S-Function block, the build process does
not automatically rebuild models containing the generated S-Function block. This is in
contrast to the practice of automatically rebuilding models referenced by Model blocks
when they are modified (depending on the Model Reference Rebuild configuration
setting).
• Handwritten S-functions without corresponding TLC files must contain exception-free
code. For more information on exception-free code, see “Exception Free Code”
(Simulink).
Unsupported Blocks
The S-function format does not support the following built-in blocks:
• MATLAB language S-functions (unless you supply a TLC file for C code generation)
• Fortran S-functions (unless you supply a TLC file for C code generation)
• C/C++ MEX S-functions that call into the MATLAB environment
• Scope block
• To Workspace block
The S-function format does not support blocks from the embeddedtargetslib block
library.
You can use SimState within C-MEX and Level-2 MATLAB language S-functions to save
and restore the simulation state. See “S-Function Compliance with the SimState”
(Simulink). However, SimState is not supported for code generation, including with the
S-function system target file.
49-73
49 Desktops in Simulink Coder
Profiling the performance of generated code using the Target Language Compiler (TLC)
hook function interface described in “Profile Code Performance” (Simulink Coder) is not
supported for the S-function target.
Note If you have an Embedded Coder license, see “Code Execution Profiling” for an
alternative and simpler approach based on software-in-the-loop (SIL) or processor-in-the-
loop (PIL) simulations.
• The software does not support nonvirtual bus input and output signals for a nested S-
function.
• You should avoid nesting an S-function in a model or subsystem having the same name
as the S-function (possibly several levels apart). In such situations, the S-function can
be called recursively. The software currently does not detect such loops in S-function
dependency, which can result in aborting or hanging your MATLAB session. To prevent
this from happening, be sure to name the subsystem or model to be generated as an S-
function target uniquely, to avoid duplicating existing MEX filenames on the MATLAB
path.
The S-function system target file does not support the HeaderFile property that can be
specified on user-defined data types, including those based on Simulink.AliasType,
Simulink.Bus, and Simulink.NumericType objects. If a user-defined data type in
your model uses the HeaderFile property to specify an associated header file, code
generation with the S-function system target file disregards the value and does not
generate a corresponding include statement.
49-74
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target
block inside the Function-Call Subsystem block is set to inherit. You must set the States
when enabling parameter to reset or held, otherwise Simulink reports an error.
If an S-function generated using the S-function target has bus input or output signals, the
generated bus data structures might include padding to align fields of the bus elements
with the Simulink representation used during simulation. However, if you insert the S-
function in a model and generate code using a model target such as grt.tlc, the bus
structure alignment generated for the model build might be incompatible with the
padding generated for the S-function and might affect the numerical results of code
execution. To make the structure alignment consistent between model simulation and
execution of the model code, for each Simulink.Bus object, you can modify the
HeaderFile property to remove the unpadded bus structure header file. This will cause
the bus typedefs generated for the S-function to be reused in the model code.
The S-function target does not support creating an S-Function block from a subsystem
that has a function-call trigger input or a function-call output.
When an S-Function in your model accesses a data store during simulation, Simulink
disables data store diagnostics.
• If you created the S-Function from a model, the diagnostic is disabled for global data
stores as well.
• If you created the S-Function from a subsystem, the diagnostic is disabled for the
following data stores:
You cannot specify any Inport or Outport block parameters through subsystem mask
variables if you want to generate an S-Function block from the subsystem. The software
produces an error when you try to run a simulation that uses the S-Function block, for
example:
49-75
49 Desktops in Simulink Coder
See Also
More About
• “Acceleration” (Simulink)
• “Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using
RSim System Target File” (Simulink Coder)
49-76
50
1 Open your model and configure it to use the ert_shrlib.tlc system target file.
50-2
Package Generated Code as Shared Libraries
Selecting the ert_shrlib.tlc system target file causes the build process to
generate a shared library version of your model code into your current working
folder. The selection does not change the code that the code generator produces for
your model.
2 Build the model.
3 After the build completes, examine the generated code in the model subfolder and
examine the .dll, .so, or .dylib file in your current folder.
In the model, click the blue button to run a script. The script:
1 Builds a shared library file from the model (for example,
rtwdemo_shrlib_win64.dll on 64-bit Windows).
2 Compiles and links an example application, rtwdemo_shrlib_app, that loads and
uses the shared library file.
3 Executes the example application.
Tip Explicit linking is preferred for portability. But, on Windows systems, the
ert_shrlib system target file generates and retains the .lib file to support implicit
linking.
50-3
50 Desktops in Embedded Coder
To use implicit linking, the generated model.h file needs a small modification for you to
use it with t with the generated ert_main.c. For example, if you are using Visual C++,
declare __declspec(dllimport) in front of data to be imported implicitly from the
shared library file.
The model uses the following example application files, which are located in the folder
matlabroot/toolbox/rtw/rtwdemos/shrlib_demo (open).
File Description
rtwdemo_shrlib_app.h Example application header file
rtwdemo_shrlib_app.c Example application that loads and uses the
shared library file generated for the model
run_rtwdemo_shrlib_app.m Script to compile, link, and execute the example
application
You can view each of these files by clicking white buttons in the model window.
Additionally, running the script places the relevant source and generated code files in
your current folder. The files can be used as templates for writing application code for
your own ERT shared library files.
The following sections present key excerpts of the example application files.
typedef struct {
int32_T Input;
} ExternalInputs_rtwdemo_shrlib;
typedef struct {
int32_T Output;
} ExternalOutputs_rtwdemo_shrlib;
#endif /*_APP_MAIN_HEADER_*/
50-4
Package Generated Code as Shared Libraries
#else /* UNIX */
#include <dlfcn.h>
#define GETSYMBOLADDR dlsym
#define LOADLIB dlopen
#define CLOSELIB dlclose
#endif
int main()
{
void* handleLib;
...
#if defined(_WIN64)
handleLib = LOADLIB("./rtwdemo_shrlib_win64.dll");
#else
#if defined(_WIN32)
handleLib = LOADLIB("./rtwdemo_shrlib_win32.dll");
#else /* UNIX */
handleLib = LOADLIB("./rtwdemo_shrlib.so", RTLD_LAZY);
#endif
#endif
...
return(CLOSELIB(handleLib));
}
The following code excerpt shows how the C application accesses the model's exported
data and functions. Notice the hooks for adding user-defined initialization, step, and
termination code.
int32_T i;
...
void (*mdl_initialize)(boolean_T);
void (*mdl_step)(void);
void (*mdl_terminate)(void);
ExternalInputs_rtwdemo_shrlib (*mdl_Uptr);
ExternalOutputs_rtwdemo_shrlib (*mdl_Yptr);
uint8_T (*sum_outptr);
...
#if (defined(LCCDLL)||defined(BORLANDCDLL))
50-5
50 Desktops in Embedded Coder
if ((mdl_initialize && mdl_step && mdl_terminate && mdl_Uptr && mdl_Yptr &&
sum_outptr)) {
/* === user application initialization function === */
mdl_initialize(1);
/* insert other user defined application initialization code here */
50-6
Package Generated Code as Shared Libraries
The application script run_rtwdemo_shrlib_app loads and rebuilds the model, and
then compiles, links, and executes the model's shared library target file. You can view the
script source file by opening rtwdemo_shrlib and clicking a white button to view source
code. The script constructs platform-dependent command character vectors for
compilation, linking, and execution that may apply to your development environment. To
run the script, click the blue button.
addpath(fullfile(matlabroot,'toolbox','rtw','rtwdemos','shrlib_demo'))
• Code generation for the ert_shrlib.tlc system target file exports the following as
data:
50-7
50 Desktops in Embedded Coder
See Also
More About
• “Design Models for Generated Embedded Code Deployment” on page 1-2
• “Configure a System Target File” on page 33-2
• “Model Protection”
50-8
51
The following figure shows a typical approach for real-time rapid prototyping.
System model
Host
generation
Tuning and
Code
logging
Real-time Harness
simulator
51-2
Deploy Algorithm Model for Real-Time Rapid Prototyping
products you intend to use (for example, for example, the Simulink Real-Time or Simulink
Desktop Real-Time product), you can use real-time prototyping to:
1 Create or acquire a real-time system that runs in real time on rapid prototyping
hardware. The Simulink Real-Time product facilitates real-time rapid prototyping.
This product provides a real-time operating system that makes PCs run in real time.
It also provides device driver blocks for numerous hardware I/O cards. You can then
create a rapid prototyping system using inexpensive commercial-off-the-shelf (COTS)
hardware. In addition, third-party vendors offer products based on the Simulink Real-
Time product or other code generation technology that you can integrate into a
development environment.
2 Use provided system target files to generate code that you can deploy onto a real-
time simulator. See the following information.
“Event-Based Scheduling”
(Simulink Coder)
Embedded Coder
51-3
51 Real-Time Systems in Simulink Coder
See Also
More About
• “Access Signal, State, and Parameter Data During Execution” on page 22-7
• “Basic Process Steps” (Simulink Real-Time)
51-4
Deploy Environment Model for Real-Time Hardware-In-the-Loop (HIL) Simulation
During HIL simulation, you gradually replace parts of a system environment with
hardware components as you refine and fabricate the components. HIL simulation offers
an efficient design process that eliminates costly iterations of part fabrication.
The code that you build for the system simulator provides real-time system capabilities.
For example, the code can include VxWorks from Wind River or another real-time
operating system (RTOS).
Simulink
generation
Code
Code
Embedded Real-time
Harness
system simulator
51-5
51 Real-Time Systems in Simulink Coder
The HIL platform available from MathWorks is the Simulink Real-Time product. Several
third-party products are also available for use as HIL platforms. The Simulink Real-Time
product offers hard real-time performance for PCs with Intel or AMD® 32-bit processors
functioning as your real-time target. The Simulink Real-Time product enables you to add
I/O interface blocks to your models and automatically generate code with code generation
technology. The Simulink Real-Time product can download the code to a second PC
running the Simulink Real-Time real-time kernel. System integrator solutions that are
based on Simulink Real-Time are also available.
For more information, see “Compare System Target File Support” (Simulink Coder).
2 Generate an executable for the environment model.
3 Download the executable for the environment model to the HIL simulation platform.
4 Replace software representing a system component with corresponding hardware.
5 Test the hardware in the context of the HIL system.
6 Repeat steps 4 and 5 until you can simulate the system after including components
that require testing.
See Also
More About
• “Access Signal, State, and Parameter Data During Execution” on page 22-7
• “Real-Time Simulation and Testing” (Simulink Real-Time)
51-6
52
In this section...
“Generate a Standalone Program” on page 52-2
“Standalone Program Components” on page 52-3
“Main Program” on page 52-3
“rt_OneStep and Scheduling Considerations” on page 52-4
“Static Main Program Module” on page 52-11
“Rate Grouping Compliance and Compatibility Issues” on page 52-17
“Generate Code That Dereferences Data from a Literal Memory Address” on page 52-
21
1 In the Custom templates section of the Code Generation > Templates pane of the
Configuration Parameters dialog box, select the Generate an example main
program option (which is on by default). This enables the Target operating system
menu.
2 From the Target operating system menu, select BareBoardExample (the default
selection).
3 Generate the code.
Different code is generated for multirate models depending on the following factors:
52-2
Deploy Generated Standalone Executable Programs To Target Hardware
These factors affect the scheduling algorithms used in generated code, and in some cases
affect the API for the model entry point functions. The following sections discuss these
variants.
The main loop is periodically interrupted by a timer. The function rt_OneStep is either
installed as a timer interrupt service routine (ISR), or called from a timer ISR at each
clock step.
The execution driver, rt_OneStep, sequences calls to the model_step functions. The
operation of rt_OneStep differs depending on whether the generating model is single-
rate or multirate. In a single-rate model, rt_OneStep simply calls the model_step
function. In a multirate model, rt_OneStep prioritizes and schedules execution of blocks
according to the rates at which they run.
Main Program
• “Overview of Operation” on page 52-3
• “Guidelines for Modifying the Main Program” on page 52-4
Overview of Operation
main()
{
Initialization (including installation of rt_OneStep as an
interrupt service routine for a real-time clock)
Initialize and start timer hardware
Enable interrupts
While(not Error) and (time < final time)
Background task
EndWhile
Disable interrupts (Disable rt_OneStep from executing)
Complete any background tasks
Shutdown
}
52-3
52 Real-Time and Embedded Systems in Embedded Coder
The pseudocode is a design for a harness program to drive your model. The main program
only partially implements this design. You must modify it according to your specifications.
This section describes the minimal modifications you should make in your production
version of the main program module to implement your harness program.
1 Call model_initialize.
2 Initialize target-specific data structures and hardware, such as ADCs or DACs.
3 Install rt_OneStep as a timer ISR.
4 Initialize timer hardware.
5 Enable timer interrupts and start the timer.
Note rtModel is not in a valid state until model_initialize has been called.
Servicing of timer interrupts should not begin until model_initialize has been
called.
6 Optionally, insert background task calls in the main loop.
7 On termination of the main loop (if applicable):
52-4
Deploy Generated Standalone Executable Programs To Target Hardware
Overview of Operation
Permitted Solver Modes for Embedded Real-Time System Target Files summarizes the
permitted solver modes for single-rate and multirate models. Note that for a single-rate
model, only SingleTasking solver mode is allowed.
The generated code for rt_OneStep (and associated timing data structures and support
functions) is tailored to the number of rates in the model and to the solver mode. The
following sections discuss each possible case.
The only valid solver mode for a single-rate model is SingleTasking. Such models run
in “single-rate” operation.
rt_OneStep()
{
Check for interrupt overflow or other error
Enable "rt_OneStep" (timer) interrupt
Model_Step() -- Time step combines output,logging,update
}
52-5
52 Real-Time and Embedded Systems in Embedded Coder
void model_step(void)
The overrun flag is cleared only upon successful return from model_step. Therefore, if
rt_OneStep is reinterrupted before completing model_step, the reinterruption is
detected through the overrun flag.
Note that the design of rt_OneStep assumes that interrupts are disabled before
rt_OneStep is called. rt_OneStep should be noninterruptible until the interrupt
overflow flag has been checked.
rt_OneStep()
{
Check for base-rate interrupt overrun
Enable "rt_OneStep" interrupt
Determine which rates need to run this time step
52-6
Deploy Generated Standalone Executable Programs To Target Hardware
EndFor
}
Task Identifiers
The execution of blocks having different sample rates is broken into tasks. Each block
that executes at a given sample rate is assigned a task identifier (tid), which associates it
with a task that executes at that rate. Where there are NumTasks tasks in the system, the
range of task identifiers is 0..NumTasks-1.
Prioritization of Base-Rate and Subrate Tasks
Tasks are prioritized, in descending order, by rate. The base-rate task is the task that runs
at the fastest rate in the system (the hardware clock rate). The base-rate task has highest
priority (tid 0). The next fastest task (tid 1) has the next highest priority, and so on
down to the slowest, lowest priority task (tid NumTasks-1).
The slower tasks, running at multiples of the base rate, are called subrate tasks.
Rate Grouping and Rate-Specific model_step Functions
In a single-rate model, the block output computations are performed within a single
function, model_step. For multirate, multitasking models, the code generator tries to
use a different strategy. This strategy is called rate grouping. Rate grouping generates
separate model_step functions for the base rate task and each subrate task in the
model. The function naming convention for these functions is
model_stepN
where N is a task identifier. For example, for a model named my_model that has three
rates, the following functions are generated:
void my_model_step0 (void);
void my_model_step1 (void);
void my_model_step2 (void);
Each model_stepN function executes the blocks sharing tid N; in other words, the
block code that executes within task N is grouped into the associated model_stepN
function.
Scheduling model_stepN Execution
On each clock tick, rt_OneStep maintains scheduling counters and event flags for each
subrate task. The counters are implemented as taskCounter arrays indexed on tid. The
event flags are implemented as arrays indexed on tid.
52-7
52 Real-Time and Embedded Systems in Embedded Coder
The scheduling counters and task flags for sub-rates are maintained by rt_OneStep. The
scheduling counters are basically clock rate dividers that count up the sample period
associated with each sub-rate task. A pair of tasks that exchanges data maintains an
interaction flag at the faster rate. Task interaction flags indicate that both fast and slow
tasks are scheduled to run.
The event flags indicate whether or not a given task is scheduled for execution.
rt_OneStep maintains the event flags based on a task counter that is maintained by code
in the main program module for the model. When a counter indicates that a task's sample
period has elapsed, the main code sets the event flag for that task.
On each invocation, rt_OneStep updates its scheduling data structures and steps the
base-rate task (rt_OneStep calls model_step0 because the base-rate task must execute
on every clock step). Then, rt_OneStep iterates over the scheduling flags in tid order,
unconditionally calling model_stepN for any task whose flag is set. The tasks are
executed in order of priority.
Preemption
Note that the design of rt_OneStep assumes that interrupts are disabled before
rt_OneStep is called. rt_OneStep should be noninterruptible until the base-rate
interrupt overflow flag has been checked (see pseudocode above).
The event flag array and loop variables used by rt_OneStep are stored as local (stack)
variables. Therefore, rt_OneStep is reentrant. If rt_OneStep is reinterrupted, higher
priority tasks preempt lower priority tasks. Upon return from interrupt, lower priority
tasks resume in the previously scheduled order.
Overrun Detection
Note If you have developed multirate S-functions, or if you use a customized static main
program module, see “Rate Grouping Compliance and Compatibility Issues” on page 52-
17 for information about how to adapt your code for rate grouping compatibility. This
adaptation lets your multirate, multitasking models generate more efficient code.
52-8
Deploy Generated Standalone Executable Programs To Target Hardware
In a multirate single-tasking program, blocks execute at different rates, but under the
same task identifier. The operation of rt_OneStep, in this case, is a simplified version of
multirate multitasking operation. Rate grouping is not used. The only task is the base-rate
task. Therefore, only one model_step function is generated:
void model_step(void)
On each clock tick, rt_OneStep checks the overrun flag and calls model_step. The
scheduling function for a multirate single-tasking program is rate_scheduler (rather
than rate_monotonic_scheduler). The scheduler maintains scheduling counters on
each clock tick. There is one counter for each sample rate in the model. The counters are
implemented in an array (indexed on tid) within the Timing structure within rtModel.
The counters are clock rate dividers that count up the sample period associated with each
subrate task. When a counter indicates that a sample period for a given rate has elapsed,
rate_scheduler clears the counter. This condition indicates that blocks running at that
rate should execute on the next call to model_step, which is responsible for checking
the counters.
rt_OneStep does not require extensive modification. The only required modification is to
reenable interrupts after the overrun flags and error conditions have been checked. If
applicable, you should also
• Save and restore your FPU context on entry and exit to rt_OneStep.
• Set model inputs associated with the base rate before calling model_step0.
• Get model outputs associated with the base rate after calling model_step0.
Note If you modify rt_OneStep to read a value from a continuous output port after
each base-rate model step, see the relevant cautionary guideline below.
• In a multirate, multitasking model, set model inputs associated with subrates before
calling model_stepN in the subrate loop.
• In a multirate, multitasking model, get model outputs associated with subrates after
calling model_stepN in the subrate loop.
52-9
52 Real-Time and Embedded Systems in Embedded Coder
In multirate rt_OneStep, you can improve performance by unrolling for and while
loops.
In addition, you may choose to modify the overrun behavior to continue execution after
error recovery is complete.
• You should not modify the way in which the counters, event flags, or other timing data
structures are set in rt_OneStep, or in functions called from rt_OneStep. The
rt_OneStep timing data structures (including rtModel) and logic are critical to the
operation of the generated program.
• If you have customized the main program module to read model outputs after each
base-rate model step, be aware that selecting model options Support: continuous
time and Single output/update function together may cause output values read
from main for a continuous output port to differ slightly from the corresponding
output values in the model's logged data. This is because, while logged data is a
snapshot of output at major time steps, output read from main after the base-rate
model step potentially reflects intervening minor time steps. To eliminate the
discrepancy, either separate the generated output and update functions (clear the
Single output/update function option) or place a Zero-Order Hold block before the
continuous output port.
• It is possible to observe a mismatch between results from simulation and logged MAT
file results from generated code if you do not set model inputs before each time you
call the model step function. In the generated example main program, the following
comments show the locations for setting the inputs and stepping the model with your
code:
If your model applies signal reuse and you are using MatFileLogging for comparing
results from simulation against generated code, modify rt_OneStep to write model
inputs in every time step as directed by these comments. Alternatively, you could
“Choose a SIL or PIL Approach” on page 67-12 for verification.
52-10
Deploy Generated Standalone Executable Programs To Target Hardware
Overview
In most cases, the easiest strategy for deploying generated code is to use the Generate
an example main program option to generate the ert_main.c or .cpp module (see
“Generate a Standalone Program” on page 52-2).
However, if you turn the Generate an example main program option off, you can use a
static main module as an example or template for developing your embedded
applications. Static main modules provided by MathWorks include:
The static main module is not part of the generated code; it is provided as a basis for your
custom modifications, and for use in simulation. If your existing applications depend upon
a static ert_main.c (developed in releases before R2012b), rt_main.c,
rt_malloc_main.c, or rt_cppclass_main.cpp, you may need to continue using a
static main program module.
When developing applications using a static main module, you should copy the module to
your working folder and rename it before making modifications. For example, you could
rename rt_main.c to model_rt_main.c. Also, you must modify the template makefile
or toolchain settings such that the build process creates a corresponding object file, such
as model_rt_main.obj (on UNIX, model_rt_main.o), in the build folder.
52-11
52 Real-Time and Embedded Systems in Embedded Coder
For single-rate models, the operation of rt_OneStep and the main function are
essentially the same in the static main module as they are in the automatically generated
version described in “Deploy Generated Standalone Executable Programs To Target
Hardware” on page 52-2. For multirate, multitasking models, however, the static and
generated code are slightly different. The next section describes this case.
Targets based on the ERT target sometimes use a static main module and disallow use of
the Generate an example main program option. This is done because target-specific
modifications have been added to the static main module, and these modifications would
not be preserved if the main program were regenerated.
Your static main module may or may not use rate grouping compatible model_stepN
functions. If your main module is based on the static rt_main.c, rt_malloc_main.c,
or rt_cppclass_main.cpp module, it does not use rate-specific model_stepN function
calls. It uses the old-style model_step function, passing in a task identifier:
By default, when the Generate an example main program option is off, the ERT target
generates a model_step “wrapper” for multirate, multitasking models. The purpose of
the wrapper is to interface the rate-specific model_stepN functions to the old-style call.
The wrapper code dispatches to the model_stepN call with a switch statement, as in
the following example:
switch(tid) {
case 0 :
mymodel_step0();
break;
case 1 :
mymodel_step1();
break;
case 2 :
52-12
Deploy Generated Standalone Executable Programs To Target Hardware
mymodel_step2();
break;
default :
break;
}
}
The following pseudocode shows how rt_OneStep calls model_step from the static
main program in a multirate, multitasking model.
rt_OneStep()
{
Check for base-rate interrupt overflow
Enable "rt_OneStep" interrupt
Determine which rates need to run this time step
You can use the TLC variable RateBasedStepFcn to specify that only the rate-based step
functions are generated, without the wrapper function. If your target calls the rate
grouping compatible model_stepN function directly, set RateBasedStepFcn to 1. In
this case, the wrapper function is not generated.
As with the generated ert_main.c or .cpp, you should make a few modifications to the
main loop and rt_OneStep. See “Guidelines for Modifying the Main Program” on page
52-4 and “Guidelines for Modifying rt_OneStep” on page 52-9.
Also, you should replace the rt_OneStep call in the main loop with a background task
call or null statement.
52-13
52 Real-Time and Embedded Systems in Embedded Coder
• If applicable, follow comments in the code regarding where to add code for reading/
writing model I/O and saving/restoring FPU context.
If you are using a static main program module, and your model is configured for
Reusable function code interface packaging, but the model option Use dynamic
52-14
Deploy Generated Standalone Executable Programs To Target Hardware
memory allocation for model initialization is not selected, model instance data must
be allocated either statically or dynamically by the calling main code. Pointers to the
individual model data structures (such as Block IO, DWork, and Parameters) must be set
up in the top-level real-time model data structure.
To support main modifications, the build process generates a subset of the following real-
time model (RTM) macros, based on the data requirements of your model, into model.h.
Use these macros in your static main program to access individual model data structures
within the RTM data structure. For example, suppose that the example model
rtwdemo_reusable is configured with Reusable function code interface packaging,
52-15
52 Real-Time and Embedded Systems in Embedded Coder
Use dynamic memory allocation for model initialization cleared, Pass root-level
I/O as set to Individual arguments, and Optimization pane option Remove root
level I/O zero initialization cleared. Building the model generates the following model
data structures and model entry-points into rtwdemo_reusable.h:
/* Block states (auto storage) for system '<Root>' */
typedef struct {
real_T Delay_DSTATE; /* '<Root>/Delay' */
} D_Work;
Additionally, if Generate an example main program is not selected for the model,
rtwdemo_reusable.h contains definitions for the RTM macros rtmGetDefaultParam,
rtmsetDefaultParam, rtmGetRootDWork, and rtmSetRootDWork.
Also, for reference, the generated rtmodel.h file contains an example parameter
definition with initial values (non-executing code):
#if 0
#endif
In the definitions section of your static main file, you could use the following code to
statically allocate the real-time model data structures and arguments for the
rtwdemo_reusable model:
static RT_MODEL rtM_;
static RT_MODEL *const rtM = &rtM_; /* Real-time model */
static Parameters rtP = {
2.0 /* Variable: k1
* Referenced by: '<Root>/Gain'
*/
52-16
Deploy Generated Standalone Executable Programs To Target Hardware
}; /* Modifiable parameters */
/* '<Root>/In1' */
static real_T rtU_In1;
/* '<Root>/In2' */
static real_T rtU_In2;
/* '<Root>/Out1' */
static real_T rtY_Out1;
In the body of your main function, you could use the following RTM macro calls to set up
the model parameters and DWork data in the real-time model data structure:
int_T main(int_T argc, const char *argv[])
{
...
/* Pack model data into RTM */
rtmSetDefaultParam(rtM, &rtP);
rtmSetRootDWork(rtM, &rtDWork);
/* Initialize model */
rtwdemo_reusable_initialize(rtM, &rtU_In1, &rtU_In2, &rtY_Out1);
...
}
Follow a similar approach to set up multiple instances of model data, where the real-time
model data structure for each instance has its own data. In particular, the parameter
structure (rtP) should be initialized, for each instance, to the desired values, either
statically as part of the rtP data definition or at run time.
When the Generate an example main program option is off, code generation produces
slightly different rate grouping code, for compatibility with the older static ert_main.c
module. See “Rate Grouping and the Static Main Program” on page 52-12 for details.
Built-in Simulink blocks, as well as DSP System Toolbox blocks, are compliant with the
requirements for generating rate grouping code. However, user-written multirate inlined
52-17
52 Real-Time and Embedded Systems in Embedded Coder
S-functions may not be rate grouping compliant. Noncompliant blocks generate less
efficient code, but are otherwise compatible with rate grouping. To take full advantage of
the efficiency of rate grouping, your multirate inlined S-functions must be upgraded to be
fully rate grouping compliant. You should upgrade your TLC S-function implementations,
as described in this section.
To make your S-functions rate grouping compliant, you can use the following TLC
functions to generate ModelOutputs and ModelUpdate code, respectively:
The code listings below illustrate generation of output computations without rate
grouping (Listing 1) and with rate grouping (Listing 2). Note the following:
if (%<LibIsSFcnSampleHit(portName)>)
as in Listing 2.
52-18
Deploy Generated Standalone Executable Programs To Target Hardware
if (*enabled) {
%assign signal = LibBlockInputSignal(1, "", "", 0)
if (%<LibIsSFcnSampleHit("OutputPortIdx0")>) {
%assign y = LibBlockOutputSignal(0, "", "", 0)
%<y> = %<signal>;
}
if (%<LibIsSFcnSampleHit("OutputPortIdx1")>) {
%assign y = LibBlockOutputSignal(1, "", "", 0)
%<y> = %<signal>;
}
}
}
%endfunction
%% [EOF] sfun_multirate.tlc
52-19
52 Real-Time and Embedded Systems in Embedded Coder
%endfunction
%switch(tid)
%case LibGetGlobalTIDFromLocalSFcnTID("InputPortIdx0")
%if LibGetSFcnTIDType("InputPortIdx0") == "continuous"
%% Only check the enable signal on a major time step.
if (%<LibIsMajorTimeStep()>) {
%<enabled> = (%<enable> > 0.0);
}
%else
%<enabled> = (%<enable> > 0.0);
%endif
%break
%case LibGetGlobalTIDFromLocalSFcnTID("OutputPortIdx0")
if (%<enabled>) {
%assign y = LibBlockOutputSignal(0, "", "", 0)
%<y> = %<signal>;
}
%break
%case LibGetGlobalTIDFromLocalSFcnTID("OutputPortIdx1")
if (%<enabled>) {
52-20
Deploy Generated Standalone Executable Programs To Target Hardware
%endfunction
%% [EOF] sfun_multirate.tlc
In this example, you generate an algorithm that acquires input data from a 16-bit block of
memory at address 0x8675309. Assume that a hardware device asynchronously
populates only the lower 10 bits of the address. The algorithm must treat the address as
read-only (const), volatile (volatile) data, and ignore the upper 6 bits of the address.
The generated code can access the data by defining a macro that dereferences
0x8675309 and masks the unnecessary bits:
To configure a model to generate code that defines and uses this macro, you must create
an advanced custom storage class and write Target Language Compiler (TLC) code. For
an example that shows how to use the Custom Storage Class Designer without writing
TLC code, see “Create and Apply a Custom Storage Class” on page 26-26.
As an alternative to writing TLC code, you can use memory sections to generate code that
includes pragmas. Depending on your build toolchain, you can use pragmas to specify a
literal memory address for storing a global variable. For more information about memory
sections, see “Control Data and Function Placement in Memory by Inserting Pragmas” on
page 30-2.
52-21
52 Real-Time and Embedded Systems in Embedded Coder
In this example, you configure the generated code to define and use the dereferencing
macro. To determine the correct syntax for the macro, start by recording the target
address.
0x8675309
Cast the address as a pointer to a 16-bit integer. Use the Simulink Coder data type name
uint16_T.
(uint16_T *)0x8675309
Add the storage type qualifier const because the generated code must not write to the
address. Add volatile because the hardware can populate the address at an arbitrary
time.
After the dereference operation, apply a mask to retain only the 10 bits that the hardware
populates. Use explicit parentheses to control the order of operations.
As a safe coding practice, wrap the entire construct in another layer of parentheses.
For the Inport block, set the output data type to uint16. Name the signal as A2D_INPUT.
The Inport block and the signal line represent the data that the hardware populates.
52-22
Deploy Generated Standalone Executable Programs To Target Hardware
For the Gain block, set the output data type to double.
Create Package to Contain Definitions of Data Class and Custom Storage Class
In your current folder, create a folder named +MemoryMap. The folder defines a package
named MemoryMap.
To make the package available for use outside of your current folder, you can add the
folder containing the +MemoryMap folder to the MATLAB path.
To generate code that defines and reads A2D_INPUT as a macro, you must create a
custom storage class that you can apply to the signal line in the model. Later, you write
TLC code that complements the custom storage class.
Open the Custom Storage Class designer in advanced mode. To design a custom storage
class that operates through custom TLC code, you must use the advanced mode.
cscdesigner('MemoryMap','-advanced');
In the Custom Storage Class Designer, click New. A new custom storage class,
NewCSC_1, appears in the list of custom storage class definitions.
• Type to Other. The custom storage class can operate through custom TLC code that
you write later.
• Data scope to Exported. For data items that use this custom storage class, Simulink
Coder generates the definition (for example, the #define statement that defines a
macro).
• Data initialization to None. Simulink Coder does not generate code that initializes
the data item. Use this setting because this custom storage class represents read-only
data. You do not select Macro because the Custom Storage Class Designer does not
allow you to use Macro for signal data.
• Definition file to Specify (leave the text box empty). For data items that consume
memory in the generated code, Definition file specifies the .c source file that
allocates the memory. However, this custom storage class yields a macro, which does
not require memory. Typically, header files (.h), not .c files, define macros. Setting
52-23
52 Real-Time and Embedded Systems in Embedded Coder
After you finish selecting the settings, click Apply and Save.
Now, when you apply the custom storage class to a data item, such as the A2D_INPUT
signal line, you can specify a header file to contain the generated macro definition.
However, you cannot yet specify a memory address for the data item. To enable
specification of a memory address, create a custom attributes class that you can associate
with the MemoryMappedAddress custom storage class.
Define a MATLAB class to store additional information for data items that use the custom
storage class. In this case, the additional information is the memory address.
Later, you associate this MATLAB class with the MemoryMappedAddress custom storage
class. Then, when you apply the custom storage class to a data item, you can specify a
memory address.
52-24
Deploy Generated Standalone Executable Programs To Target Hardware
Write TLC code that uses the attributes of the custom storage class, such as HeaderFile
and MemoryAddress, to generate correct C code for each data item.
edit(fullfile(matlabroot,...
'toolbox','rtw','targets','ecoder','csc_templates','TEMPLATE_v1.tlc'))
In memory_map_csc.tlc, find the portion that controls the generation of C-code data
declarations.
%case "declare"
%% ==========================================================================
The declare case (%case) constructs a return value (%return), which the code
generator emits into the header file that you specify for each data item. To control the C
code that declares each data item, adjust the return value in the declare case.
Replace the existing %case content with this new code, which specifies a different return
value:
%case "declare"
52-25
52 Real-Time and Embedded Systems in Embedded Coder
%assign dt = LibGetRecordCompositeDataTypeName(record)
%% This TLC code constructs the full macro, with correct C syntax,
%% based on the values of TLC variables such as 'address' and 'dt'.
%% This TLC code also asserts that the data item must be a scalar.
%if width == 1
%assign macro = ...
"#define %<id> ((*(volatile const %<dt>*)%<address>) & 0x03FF)"
%else
%error( "Non scalars are not supported yet." )
%endif
%return "%<macro>"
%%break
%% ==========================================================================
The new TLC code uses built-in, documented TLC functions, such as
LibGetRecordIdentifier, and other TLC commands and operations to access
information about the data item. Temporary variables such as dt and address store that
52-26
Deploy Generated Standalone Executable Programs To Target Hardware
information. The TLC code constructs the full macro, with the correct C syntax, by
expanding the variables, and stores the macro in the variable macro.
In the same file, find the portion that controls the generation of data definitions.
%case "define"
%% ==========================================================================
The define case derives a return value that the code generator emits into a .c file,
which defines data items that consume memory.
%case "define"
%return ""
%%break
%% ==========================================================================
MemoryMappedAddress yields a macro in the generated code, so you use the declare
case instead of the define case to construct and emit the macro. To prevent the define
case from emitting a duplicate macro definition, the new TLC code returns an empty
string.
Find the portion that controls the generation of code that initializes data.
%case "initialize"
%% ==========================================================================
52-27
52 Real-Time and Embedded Systems in Embedded Coder
The initialize case generates code that initializes data items (for example, in the
model_initialize function).
%case "initialize"
%return ""
%%break
%% ==========================================================================
Your new MATLAB class, MemoryMapAttribs, can enable users of your new custom
storage class, MemoryMappedAddress, to specify a memory address for each data item.
To allow this specification, associate MemoryMapAttribs with MemoryMappedAddress.
To generate correct C code based on the information that you specify for each data item,
associate the customized TLC file, memory_map_csc.tlc, with MemoryMappedAddress.
To apply the custom storage class to a signal in a model, in the MemoryMap package, you
must create a MATLAB class that derives from Simulink.Signal. When you configure
the signal in the model, you select this new data class instead of the default class,
Simulink.Signal.
52-28
Deploy Generated Standalone Executable Programs To Target Hardware
The file defines a class named MemoryMap.Signal. The class definition overrides the
setupCoderInfo method, which the Simulink.Signal class already implements. The
new implementation specifies that objects of the MemoryMap.Signal class use custom
storage classes from the MemoryMap package (instead of custom storage classes from the
Simulink package). When you configure a signal in a model by selecting the
MemoryMap.Signal class, you can select the new custom storage class,
MemoryMappedAddress.
Navigate to the folder that contains the example model and open the model.
In the Property Inspector, under Code Generation, set Signal object class to
MemoryMap.Signal. If you do not see MemoryMap.Signal, select Customize class
lists and use the dialog box to enable the selection of MemoryMap.Signal.
52-29
52 Real-Time and Embedded Systems in Embedded Coder
Inspect the generated header file memory_mapped_addresses.h. The file defines the
macro A2D_INPUT, which corresponds to the signal line in the model.
See Also
More About
• “Design Models for Generated Embedded Code Deployment” on page 1-2
• “How Generated Code Exchanges Data with an Environment” on page 22-33
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
52-30
Deploy Generated Component Software to Application Target Platforms
The operating system integration techniques that are demonstrated in this example use
one or more blocks the blocks in the vxlib1 library. These blocks provide starting point
examples to help you develop custom blocks for your target environment.
Example Model
model = 'rtwdemo_vxworks';
open_system(model);
%
52-31
52 Real-Time and Embedded Systems in Embedded Coder
Model Description
The example model contains two asynchronously executed subsystems, Count and
Algorithm. Count executes at interrupt level. Algorithm executes in an asynchronous
task. The generated code for these blocks is tailored for the VxWorks® operating system.
However, you can modify the Async Interrupt and Task Sync blocks to generate
code for your run-time environment whether you are using an operating system or not.
52-32
Deploy Generated Component Software to Application Target Platforms
Related Information
• Async Interrupt
• Task Sync
• “Generate Interrupt Service Routines” (Simulink Coder)
• “Timers in Asynchronous Tasks” (Simulink Coder)
• “Create a Customized Asynchronous Library” (Simulink Coder)
• “Import Asynchronous Event Data for Simulation” (Simulink Coder)
• “Load Data to Root-Level Input Ports” (Simulink)
• “Asynchronous Events” (Simulink Coder)
• “Rate Transitions and Asynchronous Blocks” (Simulink Coder)
• “Asynchronous Support Limitations” (Simulink Coder)
The model is configured to display sample-time colors upon diagram update. Red
represents the fastest discrete sample time in the model, green represents the second
fastest, and yellow represents mixed sample times. Click the Display Sample Time
Colors button to update the diagram and show sample-time colors.
Example Model
model = 'rtwdemo_mrmtos';
open_system(model);
52-33
52 Real-Time and Embedded Systems in Embedded Coder
52-34
See Also
53
(For more detailed information about the default calling interface for the model_step
function, see the model_step reference page.)
The Configure Model Functions button on the Interface pane provides you flexible
control over the model function interfaces that are generated for your model. Clicking
Configure Model Functions launches a dialog box that you can use to customize and
preview the function interfaces. Once you validate and apply your changes, you can
generate code based on your modifications.
For more information about using the Configure Model Functions button and the Model
Interface dialog box, see “Customize Generated C Function Interfaces” on page 29-2 and
the example model rtwdemo_fcnprotoctrl, which is preconfigured to demonstrate
function interface control.
Alternatively, you can use a programming interface to control model function interfaces.
For more information, see “Configure C Initialize and Step Function Interfaces
Programmatically” on page 29-19.
You can also control model function interfaces for nonvirtual subsystems, if you generate
subsystem code using right-click build. To launch the Model Interface for subsystem
dialog box, use the RTW.configSubsystemBuild function.
Right-click building the subsystem generates the step and initialization functions
according to the customizations you make. For more information, see “Customize
Function Interfaces for Nonvirtual Subsystems” on page 29-32.
53-2
See Also
For limitations that apply, see “Function Interface Customization Limitations for Rate-
Based Models” on page 29-3.
See Also
More About
• “Design Models for Generated Embedded Code Deployment” on page 1-2
• “Configure Code Generation for Model Entry-Point Functions” on page 28-2
• “Generate Component Source Code for Export to External Code Base” on page 42-52
• “Export-Function Models” (Simulink)
• “How Generated Code Exchanges Data with an Environment” on page 22-33
53-3
53 Export Code Generated from Model to External Application in Embedded Coder
C++ class encapsulation also works for right-click builds of nonvirtual subsystems. (For
information on requirements that apply, see “Configure C++ Class Interfaces for
Nonvirtual Subsystems” on page 29-55.)
The general procedure for generating C++ class interfaces to model code is as follows:
1 Configure your model to use an ert.tlc system target file provided by MathWorks.
2 Select the C++ language for your model.
3 Select C++ class code interface packaging for your model.
4 Optionally, configure related C++ class interface settings for your model code, using
either a graphical user interface (GUI) or application programming interface (API).
5 Generate model code and examine the results.
To get started with an example, see “Simple Use of C++ Class Control” on page 29-37.
For more details about configuring C++ class interfaces for your model code, see
“Customize C++ Class Interfaces Using Graphical Interfaces” on page 29-44 and
“Customize C++ Class Interfaces Programmatically” on page 29-55. For limitations that
apply, see “C++ Class Interface Control Limitations” on page 29-62.
Note For an example of C++ class code generation, see the example model
rtwdemo_cppclass.
53-4
See Also
See Also
More About
• “Design Models for Generated Embedded Code Deployment” on page 1-2
• “Configure Code Generation for Model Entry-Point Functions” on page 28-2
• “Generate Component Source Code for Export to External Code Base” on page 42-52
• “Export-Function Models” (Simulink)
53-5
54
54-2
What Is Code Replacement Customization?
1 Creates and partially populates a code replacement entry object with the function or
operator name or key and conceptual arguments.
2 Uses the entry object to query the configured code replacement library for a
conceptual representation match. The code generator searches the tables in a code
replacement library for a match in the order that the tables appear in the library.
When searching for a match, the code generator takes into account:
54-3
54 Code Replacement Customization for Simulink Models in Embedded Coder
4 Uses the C or C++ replacement function prototype in the code replacement object to
generate code.
• Arguments associated with a built-in custom storage class with DataScope set
to Exported or the imported built-in custom storage class GetSet
• Software-in-the-loop (SIL)
• Processor-in-the-loop (PIL)
• Model reference parameters
• Exported functions in Stateflow charts
• Replaced functions that are generated with C function prototype control or C++
class I/O arguments step method and that use root-level I/O variables
• Replaced functions that are generated with the AUTOSAR system target file and
that use root-level I/O or AUTOSAR inter-runnable access functions
• If the following conditions exist, the code generator includes data alignment
directives for root-level I/O variables in the ert_main.c or ert_main.cpp file it
produces:
54-4
What Is Code Replacement Customization?
If you discard the generated example main program, align used root-level I/O
variables correctly.
If you choose not to generate an example main program in this case, the code
generator does not replace the function.
• If a replacement imposes alignment requirements on the shared utility interface
arguments, the code generator does not honor data alignment. Under these
conditions, replacement does not occur. Replacement is allowed if the registered
data alignment type specification supports alignment of local variables, and the
replacement involves only local variables.
• For Simulink.Bus:
54-5
54 Code Replacement Customization for Simulink Models in Embedded Coder
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Develop a Code Replacement Library” on page 54-27
• “Quick Start Code Replacement Library Development - Simulink®” on page 54-28
• “What Is Code Replacement?” on page 40-2
54-6
Code You Can Replace From Simulink Models
For information on how to explore functions and operators that a code replacement
library supports, see “Choose a Code Replacement Library” on page 41-8 license and
want to develop a custom code replacement library, see Code Replacement
Customization.
In this section...
“Math Functions – Simulink Support” on page 54-7
“Math Functions – Stateflow Support” on page 54-14
“Memory Functions” on page 54-19
“Nonfinite Functions” on page 54-20
“Mutex and Semaphore Functions” on page 54-20
“Operators” on page 54-21
54-7
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-8
Code You Can Replace From Simulink Models
54-9
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-10
Code You Can Replace From Simulink Models
54-11
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-12
Code You Can Replace From Simulink Models
54-13
54 Code Replacement Customization for Simulink Models in Embedded Coder
Function Data Type Support Scalar, Vector, Matrix Real, Complex Support
Support
abs1 Integer Scalar Real
Floating point
acos2 Floating point Scalar Real
Vector Complex
Matrix Complex input/complex
output
Real input/complex
output
acosd3 Floating point Scalar Real
Vector Complex
Matrix
acot3 Floating point Scalar Real
Vector Complex
Matrix
acotd3 Floating point Scalar Real
Vector Complex
Matrix
acoth3,5 Floating point Scalar Real
Vector Complex
Matrix
acsc3 Floating point Scalar Real
Vector Complex
Matrix
acscd3 Floating point Scalar Real
Vector Complex
Matrix
54-14
Code You Can Replace From Simulink Models
Function Data Type Support Scalar, Vector, Matrix Real, Complex Support
Support
acsch3 Floating point Scalar Real
Vector Complex
Matrix
asec3 Floating point Scalar Real
Vector Complex
Matrix
asecd3 Floating point Scalar Real
Vector Complex
Matrix
asech3 Floating point Scalar Real
Vector Complex
Matrix
asin2 Floating point Scalar Real
Vector Complex
Matrix Complex input/complex
output
Real input/complex
output
asind3 Floating point Scalar Real
Vector Complex
Matrix
atan2 Floating point Scalar Real
Vector Complex
Matrix Complex input/complex
output
Real input/complex
output
atan22 Floating point Scalar Real
Vector
Matrix
atan2d3 Floating point Scalar Real
Vector
Matrix
54-15
54 Code Replacement Customization for Simulink Models in Embedded Coder
Function Data Type Support Scalar, Vector, Matrix Real, Complex Support
Support
atand3 Floating point Scalar Real
Vector Complex
Matrix
ceil • Floating-point • Floating-point • Floating-point
• Scalar • Scalar • Scalar
3
cos Floating point Scalar Real
Vector Complex
Matrix Complex input/complex
output
Real input/complex
output
cosd3 Floating point Scalar Real
Vector Complex
Matrix
cosh2 Floating point Scalar Real
Vector Complex
Matrix Complex input/complex
output
Real input/complex
output
cot3 Floating point Scalar Real
Vector Complex
Matrix
cotd3 Floating point Scalar Real
Vector Complex
Matrix
coth3 Floating point Scalar Real
Vector Complex
Matrix
csc3 Floating point Scalar Real
Vector Complex
Matrix
54-16
Code You Can Replace From Simulink Models
Function Data Type Support Scalar, Vector, Matrix Real, Complex Support
Support
cscd3 Floating point Scalar Real
Vector Complex
Matrix
csch3 Floating point Scalar Real
Vector Complex
Matrix
exp Floating point Scalar Real
floor • Floating-point • Floating-point • Floating-point
• Scalar • Scalar • Scalar
fmod Floating point Scalar Real
hypot3 Floating point Scalar Real
Vector
Matrix
ldexp Floating point Scalar Real
log2 Floating point Scalar Real
Vector Complex
Matrix
log102 Floating point Scalar Real
Vector Complex
Matrix
log23 Floating point Scalar Real
Vector Complex
Matrix
max Integer Scalar Real
Floating point
min Integer Scalar Real
Floating point
pow Floating point Scalar Real
sec3 Floating point Scalar Real
Vector Complex
Matrix
54-17
54 Code Replacement Customization for Simulink Models in Embedded Coder
Function Data Type Support Scalar, Vector, Matrix Real, Complex Support
Support
secd3 Floating point Scalar Real
Vector Complex
Matrix
sech3 Floating point Scalar Real
Vector Complex
Matrix
sin2 Floating point Scalar Real
Vector Complex
Matrix Complex input/complex
output
Real input/complex
output
sind3 Floating point Scalar Real
Vector Complex
Matrix
sinh2 Floating point Scalar Real
Vector Complex
Matrix Complex input/complex
output
Real input/complex
output
sqrt Floating point Scalar Real
tan2 Floating point Scalar Real
Vector Complex
Matrix Complex input/complex
output
Real input/complex
output
tand3 Floating point Scalar Real
Vector Complex
Matrix
54-18
Code You Can Replace From Simulink Models
Function Data Type Support Scalar, Vector, Matrix Real, Complex Support
Support
tanh2 Floating point Scalar Real
Vector Complex
Matrix Complex input/complex
output
Real input/complex
output
1
Wrap on integer overflow only.
2
For models involving vectors or matrices, the code generator replaces only functions coded in the
MATLAB action language.
3
The code generator replaces only functions coded in the MATLAB action language.
Memory Functions
Depending on code replacement libraries available in your development environment, you
can configure the code generator to replace instances of the following memory functions
with application-specific implementations.
54-19
54 Code Replacement Customization for Simulink Models in Embedded Coder
Some target processors provide optimized functions to set memory to zero. Use the code
replacement library programming interface to replace the memset2zero function with
more efficient target-specific functions.
Nonfinite Functions
Depending on code replacement libraries available in your development environment, you
can configure the code generator to replace instances of the following nonfinite functions
with application-specific implementations.
• Before code for a data transfer between tasks enters the critical section, mutex
lock or semaphore wait function calls to reserve a critical section of code.
• After code for a data transfer between tasks finishes executing the critical section,
mutex unlock or semaphore post function calls to release the critical section of
code.
54-20
Code You Can Replace From Simulink Models
• In model termination code, an optional destroy function call to explicitly delete the
mutex or semaphore.
Function Key
Mutex Destroy RTW_MUTEX_DESTROY
Mutex Init RTW_MUTEX_INIT
Mutex Lock RTW_MUTEX_LOCK
Mutex Unlock RTW_MUTEX_UNLOCK
Semaphore Destroy RTW_SEM_DESTROY
Semaphore Init RTW_SEM_INIT
Semaphore Post RTW_SEM_POST
Semaphore Wait RTW_SEM_WAIT
Operators
When generating C/C++ code from a Simulink model, depending on code replacement
libraries available in your development environment, you can configure the code
generator to replace instances of the following operators with application-specific
implementations.
Mixed data type support indicates that you can specify different data types for different
inputs.
54-21
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-22
Code You Can Replace From Simulink Models
54-23
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-24
See Also
See Also
More About
• “Lookup Table Function Code Replacement” on page 54-115
54-25
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-26
Develop a Code Replacement Library
To experiment with the process and tools, see “Quick Start Code Replacement Library
Development - Simulink®” on page 54-28.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Identify Code Replacement Requirements” on page 54-39
• “Quick Start Code Replacement Library Development - Simulink®” on page 54-28
• “What Is Code Replacement Customization?” on page 54-3
54-27
54 Code Replacement Customization for Simulink Models in Embedded Coder
Prerequisites
• MATLAB®
• MATLAB Coder™
• Simulink®
• Simulink Coder™
• Embedded Coder®
• Compiler
3. At the command prompt, enter the crtool command. The Code Replacement Tool
window opens.
1. In the Code Replacement Tool window, select File > New table
2. In the right pane, name the table crl_table_sinfcn and click Apply. When you save
the table, the tool saves it with the file name crl_table_sinfcn.m.
54-28
Quick Start Code Replacement Library Development - Simulink®
Create a table entry that maps a sin function with double input and double output to a
custom implementation function.
1. In the left pane, select table crl_table_sinfcn. Then, select File > New entry >
Function. The entry appears in the middle pane, initially without a name.
3. In the right pane, on the Mapping Information tab, from the Function menu, select
sin.
6. Leave the remaining parameters in the Replacement function group set to default
values.
54-29
54 Code Replacement Customization for Simulink Models in Embedded Coder
7. Click Apply. The tool updates the Function signature preview to reflect the specified
replacement function name.
8. Scroll to the bottom of the Mapping Information tab and click Validate entry. The
tool validates your entry.
54-30
Quick Start Code Replacement Library Development - Simulink®
54-31
54 Code Replacement Customization for Simulink Models in Embedded Coder
1. On the Build Information tab, for the Implementation header file parameter, enter
sin_dbl.h.
3. Click Apply.
4. Optionally, you can revalidate the entry. Return to the Mapping Information tab and
click Validate entry.
Create an entry that maps a sin function with single input and double output to a
custom implementation function named sin_sgl. Create the entry by copying and
pasting the sin_dbl entry.
4. On the Mapping Information tab, in the Conceptual function section, set the data
type of input argument u1 to single.
5. In the Replacement function section, name the function sin_sgl. Set the data type
of input argument u1 to single.
6. Click Apply. Note the changes that appear for the Function signature preview.
54-32
Quick Start Code Replacement Library Development - Simulink®
7. On the Build Information tab, for the Implementation header file parameter, enter
sin_sgl.h. Leave the remaining parameters set to default values and click Apply.
2. If the tool reports errors, fix them, and rerun the validation. Repeat fixing and
validating errors until the tool does not report errors. The following figure shows a
validation report.
Save the code replacement table to a MATLAB file in your working folder. Select File >
Save table. By default, the tool uses the table name to name the file. For this example,
the tool saves the table in the file crl_table_sinfcn.m.
Consider reviewing the MATLAB code for your code replacement table definition. After
using the tool to create an initial version of a table definition file, you can update,
enhance, or copy the file in a text editor.
To review it, in MATLAB or another text editor, open the file crl_table_sinfcn.m.
Before you can use your code replacement table, you must register it as part of a code
replacement library. Use the Code Replacement Tool to generate a registration file.
1. In the Code Replacement Tool, select File > Generate registration file.
2. In the Generate registration file dialog box, edit the dialog box fields to match the
following figure, and click OK.
54-33
54 Code Replacement Customization for Simulink Models in Embedded Coder
3. In the Select location to save the registration file dialog box, specify a location for
the registration file. The location must be on the MATLAB path or in the current working
folder. Save the file. The tool saves the file as rtwTargetInfo.m.
RTW.TargetRegistry.getInstance('reset');
Apply your code replacement library. Verify that the code generator makes code
replacements that you expect.
1. Check for errors. At the command line, invoke the table definition file. For example:
|tbl = crl_table_sinfcn
tbl =
Version: '1.0'
ReservedSymbols: []
54-34
Quick Start Code Replacement Library Development - Simulink®
StringResolutionMap: []
AllEntries: [2x1 RTW.TflCFunctionEntry]
EnableTrace: 1|
If an error exists in the definition file, the invocation triggers a message. Fix the error and
try again.
2. Use the Code Replacement Viewer to check your code replacement entries. For
example:
In the viewer, select entries in your table and verify that the content is what you expect.
The viewer can help you detect issues such as:
3. Identify existing model or create a model that includes a Trigonometric block that is set
to the sin function. For example:
4. Open the model and configure it for code generation with an Embedded Coder (ERT-
based) target.
5. See whether your library is listed as an available option for the Code Generation >
Interface > Code replacement library model configuration parameter. If it is, select it.
If it is not listed, open the registration file, rtwTargetInfo.m. See whether you entered
the correct code replacement table name when you created the file. If you hover the
54-35
54 Code Replacement Customization for Simulink Models in Embedded Coder
cursor over the selected library, a tool tip appears. This tip contains information derived
from your code replacement library registration file, such as the library description and
the list of tables it contains.
6. To find parameters quickly, in the Configuration Parameters dialog box Search field,
type the parameter name. Configure the code generation report for code replacement
analysis by selecting the following parameters:
7. Configure the model to generate code only. Before you build an executable program,
confirm that the code generator is replacing code as expected.
9. Review code replacement results in the Code Replacement Report section of the code
generation report.
54-36
Quick Start Code Replacement Library Development - Simulink®
The report indicates that the code generator found a match and applied the replacement
code for the function sin_dbl.
10. Review the code replacements. In the model window, right-click the Trigonometric
Function block. Select C/C++ Code > Navigate to C/C++ Code. The code generation
report opens and highlights the code replacement in my_sin_func.c. In this case, the
code generator replaced sin with sin_dbl.
54-37
54 Code Replacement Customization for Simulink Models in Embedded Coder
More About
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Develop a Code Replacement Library” on page 54-27
• “What Is Code Replacement Customization?” on page 54-3
54-38
Identify Code Replacement Requirements
• Math operation
• Function
• BLAS operation
• CBLAS operation
• Net slope fixed-point operation
• Semaphore or mutex functions
• Do you want to change the inline or nonfinite behavior for functions?
• What specific functions and operations do you want to replace?
• What input and output arguments does the function or operator that you are replacing
take? For each argument, what is the data type, complexity, and dimensionality?
• What does the prototype for your replacement code look like?
54-39
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-40
See Also
• Do you need to specify data alignment for the library? What data alignments are
required? For each specification, what type of alignment is required and for what
programming language?
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Develop a Code Replacement Library” on page 54-27
• “Prepare for Code Replacement Library Development” on page 54-42
• “What Is Code Replacement Customization?” on page 54-3
54-41
54 Code Replacement Customization for Simulink Models in Embedded Coder
• Common entries
• Entries for TI devices
• Entries for TI C6xx devices
• Entries specific to the TI C67x device
• If support files, such as header files, additional source files, and dynamically linked
libraries are not in your current working folder, note their location. You need to specify
the paths for such files.
Next, based on your requirements and preparation, define code replacement mappings.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Identify Code Replacement Requirements” on page 54-39
• “Define Code Replacement Mappings” on page 54-43
• “Develop a Code Replacement Library” on page 54-27
• “What Is Code Replacement Customization?” on page 54-3
54-42
Define Code Replacement Mappings
Situation Approach
Defining mappings for the first Code Replacement Tool.
time.
Rapid prototyping mappings. Code Replacement Tool to quickly generate, register,
and test mappings.
Developing a mapping as a Code Replacement Tool to generate definition code
template or starting point for that you can copy and modify.
defining similar mappings.
Modifying a registration file, MATLAB Editor to update the programming interface
including copying and pasting directly.
content.
Defining mappings that specify Programming interface.
attributes not available from the
Code Replacement Tool (for
example, sets of algorithm
parameters).
Reusing existing code for new Programming interface.
mappings by copying, pasting,
and editing existing mappings.
54-43
54 Code Replacement Customization for Simulink Models in Embedded Coder
An Embedded Coder license is not required to create a custom code replacement library.
However, you must have an Embedded Coder license to use a such a library.
By default, the tool displays, left to right, a root pane, a list pane, and a dialog pane. You
can manipulate the display:
• Drag boundaries to widen, narrow, shorten, or lengthen panes, and to resize table
columns.
• Select View > Show dialog pane to hide or display the right-most pane.
• Click a table column heading to sort the table based on contents of the selected
column.
• Right-click a table column heading and select Hide to remove the column from the
display. (You cannot hide the Name column.)
1 In the Code Replacement Tool window, select File > New table.
2 In the right pane, name the table and click Apply. Later, when you save the table, the
tool uses the table name that you specify to name the file. For example, if you enter
the name my_sinfcn, the tool names the file my_sinfcn.m.
54-44
Define Code Replacement Mappings
Create one or more table entries. Each entry maps the conceptual representation of a
function or operator to your implementation representation. The information that you
enter depends on the type of entry you create. Enter the following information:
1 In the left pane, select the table to which you want to add the entry.
2 Select File > New entry > entry-type, where entry-type is one of:
• Math Operation
• Function
• BLAS Operation
• CBLAS Operation
• Net Slope Fixed-Point Operation
• Semaphore entry
• Customization entry
The new entry appears in the middle pane, initially without a name.
3 In the middle pane, select the new entry.
4 In the right pane, on the Mapping Information tab, from the Function or
Operation menu, select the function or operation that you want the code generator
to replace. Regardless of the entry type, make a selection from this menu. Your
selection determines what other information you specify.
Except for customization entries, you also specify information for your replacement
function prototype. You can also specify implementation attributes, such as the
rounding modes to apply.
5 If prompted, specify additional entry information that you want the code generator to
use when searching for a match. For example, when you select an addition or
subtraction operation, the tool prompts you to specify an algorithm (Cast before
operation or Cast after operation).
6 Review the conceptual argument information that the tool populates for the function
or operation. Conceptual input and output arguments represent arguments for the
function or operator being replaced. Conceptual arguments observe naming
conventions ('y1', 'u1', 'u2', ...) and data types familiar to the code generator.
54-45
54 Code Replacement Customization for Simulink Models in Embedded Coder
When validating the entry, the code generator validates that each conceptual
argument has an I/O type that is compatible with the argument name. For example,
an input must have IOType of RTW_IO_INPUT.
If you do not want the data types for your implementation to be the same as the
conceptual argument types, clear the Make the conceptual and implementation
argument types the same check box. For example, most ANSI-C functions operate
on and return double data. Clear the check box if want to map a conceptual
representation of the function to an implementation representation that specifies an
argument and return value. For example, clear the check box to map the conceptual
representation of the function sin to an implementation representation that specifies
an argument and return value of type single (single sin(single)), of type
double (double sin(double). In this case, the code generator produces the
following code:
y = (single) sin(u1);
If you select Custom for a function entry, specify only conceptual argument
information.
7 Specify the name and argument information for your replacement function. As you
enter the information and click Apply, the tool updates the Function signature
preview.
When validating the entry, the code generator validates that each implementation
argument has an I/O type that is compatible with the conceptual argument to which it
is mapped. For example, an conceptual argument of type RTW_IO_OUTPUT requires a
compatible implementation argument of type RTW_IO_OUTPUT or
RTW_IO_INPUT_OUTPUT. The default I/O type is RTW_IO_INPUT.
8 Specify additional implementation attributes that apply. For example, depending on
the type and name of the entry that you specify, the tool prompts you to specify:
The Code Replacement Tool provides a way to validate the syntax of code replacement
tables and table entries as you define them. If the tool finds validation errors, you can
54-46
Define Code Replacement Mappings
address them and retry the validation. Repeat the process until the tool does not report
errors.
To Do
Validate table entries Select an entry, scroll to the bottom of the Mapping
Information tab, and click Validate entry.
Alternatively, select one or more entries, right-click, and
select Validate entries.
Validate a table Select the table. Then, select Actions > Validate table.
Save a Table
If you open multiple tables, you can manage the tables together. For example, use the tool
to:
54-47
54 Code Replacement Customization for Simulink Models in Embedded Coder
• Modifying tables that you create with the Code Replacement Tool.
• Defining mappings for specialized entries that you cannot create with the Code
Replacement Tool.
• Replicating and modifying similar entries and tables.
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_sinfcn()
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
For each function or operator that you want the code generator to replace, map a
conceptual representation of the function or operator to an implementation
representation as a table entry.
1 Within the body of a table definition file, create a code replacement entry object. Call
one of the following functions.
54-48
Define Code Replacement Mappings
For example:
hEnt = RTW.TflCFunctionEntry;
You can combine steps of creating the entry, setting entry parameters, creating
conceptual and implementation arguments, and adding the entry to a table with a single
function call to registerCFunctionEntry, registerCPPFunctionEntry, or
registerCPromotableMacroEntry if you are creating an entry for a function and the
function implementation meets the following criteria:
• Implementation argument names and order match the names and order of
corresponding conceptual arguments.
• Input arguments are of the same type.
• The return and input argument names follow the code generator’s default naming
conventions:
For example:
54-49
54 Code Replacement Customization for Simulink Models in Embedded Coder
As another alternative, you can significantly reduce the amount of code that you write by
combining the steps of creating the entry and conceptual and implementation arguments
with a call to the createCRLEntry function. In this case, specify the conceptual and
implementation information as character vector specifications.
For example:
• C++ implementations
• Data alignment
• Operator replacement with net slope arguments
• Entry parameter specifications (for example, priority, algorithm, building information)
• Semaphore and mutex function replacements
Set entry parameters, such as the priority, algorithm information, and implementation
(replacement) function name. Call the function listed in the following table for the entry
type that you created.
54-50
Define Code Replacement Mappings
To see a list of the parameters that you can set, at the command line, create a new entry
and omit the semicolon at the end of the command. For example:
hEnt = RTW.TflCFunctionEntry
hEnt =
54-51
54 Code Replacement Customization for Simulink Models in Embedded Coder
GenCallback: ''
GenFileName: ''
SaturationMode: 'RTW_SATURATE_UNSPECIFIED'
RoundingModes: {'RTW_ROUND_UNSPECIFIED'}
TypeConversionMode: 'RTW_EXPLICIT_CONVERSION'
AcceptExprInput: 1
SideEffects: 0
UsageCount: 0
RecordedUsageCount: 0
Description: ''
StoreFcnReturnInLocalVar: 0
TraceManager: [1x1 RTW.TflTraceManager]
ans =
HeaderFile: ''
SourceFile: ''
HeaderPath: ''
SourcePath: ''
Return: []
StructFieldMap: []
Name: ''
Arguments: [0x1 RTW.Argument]
ArgumentDescriptor: []
For example, to set entry parameters for the sin function and name your replacement
function sin_dbl, use the following function call:
setTflCFunctionEntryParameters(hEnt, ...
'Key', 'sin', ...
'ImplementationName', 'sin_dbl');
Create conceptual arguments and add them to the entry’s array of conceptual arguments.
54-52
Define Code Replacement Mappings
1 Identify whether the argument is for input or output, the name, and data type. If you
do not know what arguments to specify for a supported function or operation, use the
Code Replacement Tool to find them. For example, to find the conceptual arguments
for the sin function, open the tool, create a table, create a function entry, and in the
Function menu select sin.
When validating the entry, the code generator validates that each conceptual
argument has an I/O type that is compatible with the argument name. For example,
an input must have IOType of RTW_IO_INPUT.
2 Create and add the conceptual argument to an entry. You can choose a method from
the methods listed in this table.
If Then
You want simpler code Call the function createAndAddConceptualArg.
or want to explicitly For example:
specify whether the
argument is scalar or createAndAddConceptualArg(hEnt, ...
'RTW.TflArgNumeric', ...
nonscalar (vector or
'Name', 'y1',...
matrix). 'IOType', 'RTW_IO_OUTPUT',...
'DataTypeMode', 'double');
54-53
54 Code Replacement Customization for Simulink Models in Embedded Coder
If Then
You want to create an Call getTflArgFromString to create the argument.
argument based on a Then, call addConceptualArg to add the argument
built-in argument to the entry.
definition (for example,
scalar or nonscalar). arg = getTflArgFromString(hEnt, 'y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(hEnt, arg);
You need to define Call createCRLEntry to create the entry and specify
several similar conceptual and implementation arguments in a single
mappings, you want to function call.
minimize the code to
write, and the entries do hEnt = createCRLEntry(hTable, ...
'double y1 = sin(double u1)', ...
not require data
'mySin');
alignment, use net slope
arguments, or involve
semaphore or mutex
replacements.
The following code shows the second approach listed in the table for specifying the
conceptual output and input argument definitions for the sin function.
% Conceptual Args
Create implementation arguments for the C or C++ replacement function and add them
to the entry.
• When replacing code, the code generator uses the argument names to determine how
it passes data to the implementation function.
• For function replacements, the order of implementation argument names must match
the order of the conceptual argument names.
54-54
Define Code Replacement Mappings
• For operator replacements, the order of implementation argument names do not have
to match the order of the conceptual argument names. For example, for an operator
replacement for addition, y1=u1+u2, the conceptual arguments are y1, u1, and u2, in
that order. If the signature of your implementation function is t myAdd(t u2, t
u1), where t is a valid C type, based on the argument name matches, the code
generator passes the value of the first conceptual argument, u1, to the second
implementation argument of myAdd. The code generator passes the value of the
second conceptual argument, u2, to the first implementation argument of myAdd.
• For operator replacements, you can remap operator output arguments to
implementation function input arguments.
1 Identify whether the argument is for input or output, the name, and the data type.
When validating the entry, the code generator validates that each implementation
argument has an I/O type that is compatible with the conceptual argument to which it
is mapped. For example, an conceptual argument of type RTW_IO_OUTPUT requires a
compatible implementation argument of type RTW_IO_OUTPUT or
RTW_IO_INPUT_OUTPUT. The default I/O type is RTW_IO_INPUT.
2 Create and add the implementation argument to an entry. You can choose a method
from the methods listed in this table.
If Then
You want to populate Call the function
implementation copyConceptualArgsToImplementation. For
arguments as copies of example:
previously created
matching conceptual copyConceptualArgsToImplementation(hEnt);
arguments
54-55
54 Code Replacement Customization for Simulink Models in Embedded Coder
If Then
You want to create and Call functions
add implementation createAndSetCImplementationReturn
arguments individually, andcreateAndAddImplementationArg . For
or vary argument example:
attributes, while
maintaining conceptual createAndSetCImplementationReturn(hEnt,
'RTW.TflArgNumeric', ...
argument order
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', true, ...
'WordLength', 32, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry,
'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT',...
'IsSigned', true,...
'WordLength', 32, ...
'FractionLength', 0 );
54-56
Define Code Replacement Mappings
If Then
You want to minimize Create the argument with a call to the function
the amount of code, or getTflArgFromString. Then, use the convenience
specify constant method setReturn or addArgument to specify
arguments to pass to whether an argument is a return value or argument
the implementation and to add the argument to the entry’s array of
function implementation arguments. For example:
arg = getTflArgFromString(hEnt,...
'y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);
arg = getTflArgFromString(hEnt,...
'u1','double');
hEnt.Implementation.addArgument(arg);
arg = getTflArgFromString(hEnt,...
'u2', 'int16', 0)
hEnt.Implementation.addArgument(arg);
arg = getTflDWorkFromString(...
'd1', 'void*')
hEnt.addDWorkArg(arg);
arg = hEnt.getTflArgFromString(...
'y1', 'void');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setRetrurn(arg);
arg = hEnt.getTflArgFromString(...
'u1', 'integer');
hEnt.Implementation.addArgument(arg);
54-57
54 Code Replacement Customization for Simulink Models in Embedded Coder
If Then
arg = hEnt.getTflArgFromString(...
'd1', 'void**');
hEnt.Implementation.addArgument(arg);
You need to define Call createCRLEntry to create the entry and specify
several similar conceptual and implementation arguments in a single
mappings, you want to function call.
minimize the code to
write, and the entries hEnt = createCRLEntry(hTable, ...
'double y1 = sin(double u1)', ...
do not require data
'mySin');
alignment, use net
slope arguments, or
involve semaphore or
mutex replacements.
The following code shows the third approach listed in the table for specifying the
implementation output and input argument definitions for the sin function:
% Implementation Args
arg = hEnt.getTflArgFromString('y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);
arg = hEnt.getTflArgFromString('u1','double');
hEnt.Implementation.addArgument(arg);
Validate Entry
After you create or modify a code replacement table entry, validate it by invoking it at the
MATLAB command line. For example:
hTbl = crl_table_sinfcn
hTbl =
54-58
See Also
RTW.TflTable
Version: '1.0'
AllEntries: [2x1 RTW.TflCFunctionEntry]
ReservedSymbols: []
StringResolutionMap: []
If the table includes errors, MATLAB reports them. The following examples shows how
MATLAB reports a typo in a data type name:
hTbl = crl_table_sinfcn
Save Table
Save the table definition file. Use the name of the table definition function to name the
file, for example, crl_table_sinfcn.m.
Next, from your requirements, determine whether you need to specify build information
for your replacement code.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Math Function Code Replacement” on page 54-97
• “Memory Function Code Replacement” on page 54-99
• “Nonfinite Function Code Replacement” on page 54-102
• “Semaphore and Mutex Function Replacement” on page 54-105
• “Algorithm-Based Code Replacement” on page 54-112
• “Lookup Table Function Code Replacement” on page 54-115
• “Data Alignment for Code Replacement” on page 54-136
• “Replace MATLAB Functions with Custom Code Using coder.replace” on page 54-
146
• “Replace MATLAB Functions Specified in MATLAB Function Blocks” on page 54-153
54-59
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-60
Specify Build Information for Replacement Code
• Interactively, by using the Build Information tab in the Code Replacement Tool.
• Programmatically, by using a MATLAB programming interface.
Build Information
The build information can include:
Situation Approach
Creating code replacement Code Replacement Tool.
entries for the first time.
You used the Code Replacement Code Replacement Tool to specify the build
Tool to create the entries for information quickly .
which the build information
applies.
54-61
54 Code Replacement Customization for Simulink Models in Embedded Coder
Situation Approach
Rapid prototyping entries. Code Replacement Tool to generate, register, and test
entries quickly.
Developing an entry to use as a Code Replacement Tool to generate entry code that
template or starting point for you can copy and modify.
defining similar entries.
Modifying existing mappings. MATLAB Editor to update the programming interface
directly.
• If an entry uses header, source, or object files, consider whether to make the files
accessible to the code generator. You can copy files to the build folder or you can
specify individual file names and paths explicitly.
• If you specify additional header files/include paths or source files/paths and you copy
files, the compiler and utilities such as packNGo might find duplicate instances of files
(an instance in the build folder and an instance in the original folder).
• If you choose to copy files to the build folder and you are using the packNGo function
to relocate static and generated code files to another development environment:
54-62
Specify Build Information for Replacement Code
Parameter Specify
Implementation header file File name and extension for the header file
the code generator needs to generate the
replacement code. For example, sin_dbl.h.
Implementation source file File name and extension for the C or C++
source file the code generator needs to
generate the replacement code. For example,
sin_dbl.c.
Additional header files/ Paths and file names for additional header
include paths files the code generator needs to generate the
replacement code. For example, C:\libs
\headerFiles and C:\libs\headerFiles
\common.h. This parameter adds -I to the
compile line in the generated makefile.
Additional source files/ paths Paths and file names for additional source
files the code generator needs to generate the
replacement code. For example, C:\libs
\srcFiles and C:\libs\srcFiles
\common.c. This parameter adds -I to the
compile line in the generated makefile.
Additional object files/ paths Paths and file names for additional object files
the linker needs to build the replacement
code. For example, C:\libs\objFiles and
C:\libs\objFiles\common.obj.
Additional link flags Flags the linker needs to generate an
executable file for the replacement code.
Additional compile flags Flags the compiler needs to generate object
code for the replacement code.
54-63
54 Code Replacement Customization for Simulink Models in Embedded Coder
Parameter Specify
Copy files to build directory Whether to copy header, source, or object
files, which are required to generate
replacement code, to the build folder before
code generation. If you specify files with
Additional header files/include paths or
Additional source files/ paths and you copy
files, the compiler and utilities such as
packNGo might find duplicate instances of
files.
6 Click Apply.
7 Select the Mapping Information tab. Scroll to the bottom of that table and click
Validate entry. The tool validates the changes that you made to the entry.
8 Save the table that includes the entry that you just modified.
1 Identify or create the code replacement entry that you want to specify the build
information.
2 Determine what information to specify.
3 Specify your build information.
54-64
Specify Build Information for Replacement Code
Specify Action
Implementation Use one of the following:
header file
• Set properties ImplementationHeaderFile and
ImplementationHeaderPath in a call to
setTflCFunctionEntryParameters,
setTflCOperationEntryParameters, or
setTflCSemaphoreEntryParameters. For example:
setTflCFunctionEntryParameters(hEnt, ...
'ImplementationHeaderFile', 'sin_dbl.h', ...
'ImplementationHeaderPath', 'D:/lib/headerFiles'
'Key', 'sin', ...
'ImplementationName', 'sin_dbl');
• Set argument headerFile in a call to registerCFunctionEntry,
registerCPPFunctionEntry, or
registerCPromotableMacroEntry
Implementation Set properties ImplementationSourceFile and
source file ImplementationSourcePath in a call to
setTflCFunctionEntryParameters,
setTflCOperationEntryParameters, or
setTflCSemaphoreEntryParameters. For example:
setTflCFunctionEntryParameters(hEnt, ...
'ImplementationHeaderFile', 'sin_dbl.c', ...
'ImplementationHeaderPath', 'D:/lib/sourceFiles'
'Key', 'sin', ...
'ImplementationName', 'sin_dbl');
Additional header For each file, specify the file name and path in calls to the functions
files/include paths addAdditionalHeaderFile and addAdditionalIncludePath. For
example:
hEnt = RTW.TflCFunctionEntry;
addAdditionalHeaderFile(hEnt, 'common.h');
addAdditionalIncludePath(hEnt, fullfile(libdir, 'include'));
54-65
54 Code Replacement Customization for Simulink Models in Embedded Coder
Specify Action
Additional source For each file, specify the file name and path in calls to the functions
files/paths addAdditionalSourceFile and addAdditionalSourcePath. For
example:
hEnt = RTW.TflCFunctionEntry;
addAdditionalSourceFile(hEnt, 'common.c');
addAdditionalSourcePath(hEnt, fullfile(libdir, 'src'));
hEnt = RTW.TflCFunctionEntry;
addAdditionalLinkObj(hEnt, 'sin.o');
addAdditionalLinkObjPath(hEnt, fullfile(libdir, 'bin'));
Compile flags Set the entry property AdditionalCompileFlags to a cell array of
character vectors representing the required compile flags. For example:
hEnt = RTW.TflCFunctionEntry;
hEnt = RTW.TflCFunctionEntry;
54-66
Specify Build Information for Replacement Code
Specify Action
Whether to copy Use one of the following:
header, source, or
object files, which are • Set property GenCallback to 'RTW.copyFileToBuildDir' in a
required to generate call to setTflCFunctionEntryParameters,
replacement code, to setTflCOperationEntryParameters, or
the build folder setTflCSemaphoreEntryParameters. For example:
before code
setTflCFunctionEntryParameters(hEnt, ...
generation 'ImplementationHeaderFile', 'sin_dbl.h', ...
'ImplementationHeaderPath', 'D:/lib/headerFiles'
'Key', 'sin', ...
'ImplementationName', 'sin_dbl'
'GenCallback', 'RTW.copyFileToBuildDir');
• Set argument genCallback in a call to registerCFunctionEntry,
registerCPPFunctionEntry, or
registerCPromotableMacroEntry to
'RTW.copyFileToBuildDir'.
The following example defines a table entry for an optimized multiplication function that
takes signed 32-bit integers and returns a signed 32-bit integer, taking saturation into
account. Multiplications in the generated code are replaced with calls to the optimized
function. The optimized function does not reside in the build folder. For the code
generator to access the files, copy them into the build folder to be compiled and linked
into the application.
The table entry specifies the source and header file names and paths. To request the copy
operation, the table entry sets the genCallback property to
'RTW.copyFileToBuildDir' in the call to the setTflCOperationEntryParameters
function. In this example, the header file s32_mul.h contains an inlined function that
invokes assembly functions contained in s32_mul.s. If a match occurs for the table entry,
54-67
54 Code Replacement Customization for Simulink Models in Embedded Coder
the function RTW.copyFileToBuildDir copies the specified source and header files to
the build folder for use during the remainder of the build process.
function hTable = make_my_crl_table
hTable = RTW.TflTable;
op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 100, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'}, ...
'ImplementationName', 's32_mul_s32_s32_sat', ...
'ImplementationHeaderFile', 's32_mul.h', ...
'ImplementationSourceFile', 's32_mul.s', ...
'ImplementationHeaderPath', {fullfile('$(MATLAB_ROOT)','crl')}, ...
'ImplementationSourcePath', {fullfile('$(MATLAB_ROOT)','crl')}, ...
'GenCallback', 'RTW.copyFileToBuildDir');
.
.
.
addEntry(hTable, op_entry);
op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 90, ...
'SaturationMode', 'RTW_SATURATE_UNSPECIFIED', ...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'}, ...
'ImplementationName', 's32_add_s32_s32', ...
'ImplementationHeaderFile', 's32_add_s32_s32.h', ...
'ImplementationSourceFile', 's32_add_s32_s32.c'...
'GenCallback', 'RTW.copyFileToBuildDir');
addAdditionalHeaderFile(op_entry, 'all_additions.h');
addAdditionalIncludePath(op_entry, fullfile(libdir, 'include'));
addAdditionalSourceFile(op_entry, 'all_additions.c');
addAdditionalSourcePath(op_entry, fullfile(libdir, 'src'));
addAdditionalLinkObj(op_entry, 'addition.o');
addAdditionalLinkObjPath(op_entry, fullfile(libdir, 'bin'));
.
54-68
See Also
.
.
addEntry(hTable, op_entry);
Next, include your code replacement table in a code replacement library and register the
library with the code generator.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Register Code Replacement Mappings” on page 54-70
• “Develop a Code Replacement Library” on page 54-27
• “What Is Code Replacement Customization?” on page 54-3
54-69
54 Code Replacement Customization for Simulink Models in Embedded Coder
If... Then...
Registering a code replacement Use the Code Replacement Tool.
table for the first time
You used the Code Replacement Use the Code Replacement Tool to quickly register the
Tool to create the table table.
Rapid prototyping code Use the Code Replacement Tool to quickly generate,
replacement register, and test entries.
Creating registration file to use Use the Code Replacement Tool to generate code that
as a template or starting point for you can copy and modify.
defining similar registration files
Modifying existing registration Use the MATLAB Editor to update the registration file.
files
Defining multiple code Use the MATLAB Editor to create a new or extend an
replacement libraries in one existing registration file.
registration file
Defining code replacement library Use the MATLAB Editor to create a new or extend an
hierarchy in a registration file existing registration file.
54-70
Register Code Replacement Mappings
1 After you validate and save a code replacement table, select File > Generate
registration file to open the Generate registration file dialog box.
For... Specify...
Registry name Text naming the code replacement library. For example,
Sin Function Example.
54-71
54 Code Replacement Customization for Simulink Models in Embedded Coder
For... Specify...
Table list Text naming one or more code replacement tables to
include in the library. Specify each table as one of the
following:
crl_table_sinfcn, c:/work_crl/
crl_table_muldiv
For... Specify...
Description Text that describes the purpose and content of the library.
Target HW device Text naming one or more hardware devices the code
replacement library supports. Separate names with a
comma. To support all device types, enter an asterisk (*).
For example, TI C28x, TI C62x.
Base CRL Text naming a code replacement library that you want to
serve as a base library for the library you are registering.
Use this field to specify library hierarchies. For example,
you can specify a general TI device library as the
base library for a more specific TI C28x device library.
Generate data Flag that enables data alignment specification.
alignment
specification
54-72
Register Code Replacement Mappings
The basic workflow for creating a registration file programmatically consists of the
following steps:
function rtwTargetInfo(cm)
cm.registerTargetInfo(@loc_register_crl);
this(1) = RTW.TflRegistry;
this(1).Name = 'crl-name';
this(1).TableList = {'table',...};
For... Replace...
this(1).Name = 'crl- crl-name with text naming the code
name'; replacement library. For example, Sin
Function Example.
54-73
54 Code Replacement Customization for Simulink Models in Embedded Coder
For... Replace...
this(1).TableList = table with text that identifies the code
{'table',...}; replacement table that contains your code
replacement entries. Specify a table as one
of the following:
For... Replace...
this(1).Description = text with text that describes the purpose
'text' and content of the library.
this(1).TargetHWDeviceTyp device-type with text that names a
e = {'device-type',...} hardware device the code replacement
library supports. You can specify multiple
device types. Separate device types with a
comma. For example, TI C28x, TI C62x.
To support all device types, enter an asterisk
(*).
54-74
Register Code Replacement Mappings
For... Replace...
this(1).BaseTfl = 'base- base-lib with text that names a code
lib' replacement library that you want to serve as
a base library for the library you are
registering. Use this field to specify library
hierarchies. For example, you can specify a
general TI device library as the base
library for a TI C28x device library.
For example:
function rtwTargetInfo(cm)
cm.registerTargetInfo(@loc_register_crl);
this(1) = RTW.TflRegistry;
this(1).Name = 'Sin Function Example';
this(1).TableList = {'crl_table_sinfcn'};
this(1).TargetHWDeviceType = {'*'};
this(1).Description = 'Example - sin function replacement';
2 Save the file with the name rtwTargetInfo.m.
3 Place the file on the MATLAB path. When the file is on the MATLAB path, the code
generator reads the file after starting and applies the customizations during the
current MATLAB session.
sl_refresh_customizations
54-75
54 Code Replacement Customization for Simulink Models in Embedded Coder
cm.registerTargetInfo(@locCrlRegFcn);
54-76
See Also
cm.registerTargetInfo(@locCrlRegFcn);
After registering your code replacement mappings, verify that code replacements occur.
See Also
More About
• “Troubleshoot Code Replacement Library Registration” on page 54-78
• “Specify Build Information for Replacement Code” on page 54-61
• “Verify Code Replacements” on page 54-79
• “Develop a Code Replacement Library” on page 54-27
• “What Is Code Replacement Customization?” on page 54-3
54-77
54 Code Replacement Customization for Simulink Models in Embedded Coder
• Refresh the library registration information within the current MATLAB session
(RTW.TargetRegistry.getInstance('reset'); or for the Simulink
environment,sl_refresh_customizations).
• See whether the registration file, rtwTargetInfo.m, contains an error.
See Also
More About
• “Register Code Replacement Mappings” on page 54-70
54-78
Verify Code Replacements
The code generator overwrites the hit and miss cache data each time it produces code.
The cache data reflects hits and misses for only the last application component (MATLAB
code or Simulink model) for which you generate code.
You can use the Code Replacement Viewer to review trace information based on logged
hit and miss trace data. The hit cache provides trace information that helps to verify code
replacements.
The miss cache and related miss data collected and stored in code replacement tables
provide trace information for misses. Use this information for misses to troubleshoot
expected code replacements that do not occur. Trace information for a miss:
54-79
54 Code Replacement Customization for Simulink Models in Embedded Coder
ans =
MATLAB displays errors that occur. In the following example, MATLAB detects a typo in a
data type name.
isvalid(crl_table_sinfcn)
1 Open the viewer to display the contents of your library. At the command prompt,
enter the following command:
crviewer('library')
For example:
crviewer('Addition & Subtraction Examples')
54-80
Verify Code Replacements
2 Review the list of tables in the left pane. Are tables missing? Are the tables listed in
the correct relative order? By default, the viewer displays tables in search order.
3 In the left pane, click each table and review the list of entries in the center pane. Are
entries missing? Does the list include extraneous or unexpected entries?
54-81
54 Code Replacement Customization for Simulink Models in Embedded Coder
1 Open the viewer to display the contents of your table. At the command prompt, enter
the following command. table is a MATLAB file that defines code replacement
tables. The file must be in the current folder or on the MATLAB path.
crviewer(table)
For example:
crviewer(crl_table_addsub)
54-82
Verify Code Replacements
2 Review the list of entries in the center pane. Are entries missing? Does the list
include extraneous or unexpected entries? By default, the viewer displays entries in
search order.
3 In the center pane, click each entry and verify the entry information in the right
pane.
54-83
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-84
Verify Code Replacements
The Code Replacements Report details the code replacement library functions that the
code generator uses for code replacements. The report provides a mapping between each
replacement instance and the model element that triggered the replacement.
• Check the Code Replacements Report section of the code generation report for
expected replacements.
• Trace code replacements.
For models that consist of model hierarchies, repeat the following procedure for each
model in the hierarchy. Generate code for and review the trace information of each
referenced model separately. Logged cache hit and miss information captured in the Code
Replacement Viewer is valid for the last model for which code was generated. As you
generate code for each model in the hierarchy, the code generator overwrites logged
information.
1 Open the model where you anticipate that a function or operator replacement occurs.
This example uses the model rtwdemo_crladdsub.
2 Configure the code generator to use your code replacement library. For this example,
set the library to Addition & Subtraction Examples.
3 Configure the code generation report to include the Code Replacements Report. On
the Code Generation > Report pane, select Create code generation report and
Open report automatically. In the Advanced parameters section, select Model-
to-code and Summarize which blocks triggered code replacements.
54-85
54 Code Replacement Customization for Simulink Models in Embedded Coder
4 Configure comments for the generated code. On the Code Generation > Comments
pane, select:
• Include comments
• Either or both of Simulink block comments and Simulink block descriptions
The report lists the replacement functions that the code generator used. It provides a
mapping between each replacement instance and the Simulink block that triggered
the replacement.
54-86
Verify Code Replacements
Inspect the generated code to see if the function or operator replacement occurred as
you expected.
If a function or operator is not replaced as expected, the code generator used a higher-
priority (lower-priority value) match or did not find a match.
54-87
54 Code Replacement Customization for Simulink Models in Embedded Coder
To analyze and troubleshoot code replacement misses, use the trace information that the
Code Replacement Viewer provides. See “Troubleshoot Code Replacement Misses” on
page 54-89.
See Also
More About
• “Troubleshoot Code Replacement Misses” on page 54-89
• “Register Code Replacement Mappings” on page 54-70
• “Deploy Code Replacement Library” on page 54-96
• “What Is Code Replacement Customization?” on page 54-3
54-88
Troubleshoot Code Replacement Misses
For example:
1. Mismatched data types (argument name, CSO value, table entry value)
The parenthetical information represents placeholders for actual values that appear in
the report details.
In the Miss Source Locations table that lists the miss details, the Reason column
includes:
The following Reason details indicate a data type mismatch because the call site object
specifies data type int8 for arguments y1, u1, and u2, while the code replacement table
entry specifies uint32.
Depending on your situation and the reported miss reason, troubleshoot reported misses
by looking for instances of the following:
• A typo in the code replacement table entry definition or a source parameter setting.
54-89
54 Code Replacement Customization for Simulink Models in Embedded Coder
• Information missing from the code replacement table entry or a source parameter
setting.
• Invalid or incorrect information in the code replacement table entry definition or a
source parameter setting.
• Arguments incorrectly ordered in the code replacement table entry definition or the
source being replaced with replacement code.
• Failed algorithm classification for an addition or subtraction operation due to:
• An ideal accumulator not being calculated because the type of an input argument is
not fixed-point or the slope adjustment factors of the input arguments are not
equal.
• Input or output casts with a floating-point cast type.
• Input or output casts with cast types that have different slope adjustment factors or
biases.
• Output casts not being convertible to a single output cast.
• Input casts resulting in loss of bits.
1 Review the code generated for a model element, looking for expected code
replacements. For this example, examine the code generated for block Sub32 in
model rtwdemo_crladdsub. Right-click the block and select C/C++ Code >
Navigate to C/C++ Code.
The Code Generation Report opens to the location of the generated code for that
block.
The code generator replaced code, but the replacement was for the signed version of
the 32-bit subtraction operation. You expected an unsigned operation.
54-90
Troubleshoot Code Replacement Misses
2 Regenerate or reopen the Code Replacements Report for your model. If you already
generated the code generation report that includes the Code Replacements Report
for model rtwdemo_crladdsub, open the file rtwdemo_crladdsub_ert_rtw/
html/rtwdemo_crladdsub_codegen_rpt.html. For information on how to
regenerate the report, see “Review Code Replacements” on page 54-85.
3 Click the link to open the Code Replacement Viewer.
4 In the viewer left pane, select your code replacement table. The following display
shows entries for code replacement table crl_table_addsub.
5 In the middle pane, select table entry RTW_OP_MINUS with implementation function
u32_sub_u32_u32.
6 In the right pane, select the Trace Information tab.
54-91
54 Code Replacement Customization for Simulink Models in Embedded Coder
The Trace Information is a table that lists the following information for each miss:
• Call site object preview. The call site object is the conceptual representation of a
subtraction operator. The code generator uses this object to query the code
replacement library for a match.
54-92
Troubleshoot Code Replacement Misses
• A link to the source location in the model for which the code generator considered
replacing code.
• The reasons that the miss occurred. For the list of reasons that misses occur, see
“Miss Reason Messages” on page 54-89.
For this example, the report shows misses for two blocks: Sub32 and Sub8.
7 Find that source in the trace information. Depending on your situation and the
reported miss reason, consider looking for a condition such as a typo in the code
replacement table entry definition or in a source parameter setting. “Miss Reason
Messages” on page 54-89 lists conditions to consider.
For this example, determine why code for the Sub32 block was not replaced with
code for an unsigned 32-bit subtraction operation. The miss reason for the Sub32
block indicates a data type mismatch. The data type in the call site object for the
three arguments is a signed 32-bit integer. The code replacement entry specifies an
unsigned 32-bit integer.
8 Correct the model or code replacement table entry. If the issue is in the model, use
the source location link in the trace information to find the model element to correct.
For this example, you expected an unsigned subtraction operation for the Sub32
block. Click the link in the trace report for the Sub32 block.
54-93
54 Code Replacement Customization for Simulink Models in Embedded Coder
Change the data type setting for the two input signals and the output signal for the
Sub32 block to uint32.
9 Regenerate code. Use the Code Replacement Viewer trace information to verify that
your model or code replacement table entry corrects the code replacement issue. In
the following display, the trace information shows a hit for block Sub32.
54-94
See Also
See Also
More About
• “Verify Code Replacements” on page 54-79
54-95
54 Code Replacement Customization for Simulink Models in Embedded Coder
1 Move your code replacement table files to an area that is on the MATLAB search path
and that is accessible to and shared by other users.
2 Move the rtwTargetInfo.m registration file, to an area that is on the MATLAB
search path and that is accessible to and shared by other users. If you are deploying
a library to a folder in a development environment that already contains a
rtwTargetInfo.m file, copy the registration code from your code replacement
library version of rtwTargetInfo.m and paste it into the shared version of that file.
3 Register the library customizations or restart MATLAB.
4 Verify that the libraries are available for configuring the code generator and that
code replacements occur as expected.
5 Inform users that the libraries are available and provide direction on when and how
to apply them.
See Also
More About
• “Verify Code Replacements” on page 54-79
• “Relocate Code to Another Development Environment” (Simulink Coder)
• “Develop a Code Replacement Library” on page 54-27
• “What Is Code Replacement Customization?” on page 54-3
54-96
Math Function Code Replacement
54-97
54 Code Replacement Customization for Simulink Models in Embedded Coder
copyConceptualArgsToImplementation(fcn_entry);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, fcn_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Algorithm-Based Code Replacement” on page 54-112
• “Data Alignment for Code Replacement” on page 54-136
• “Reserved Identifiers and Code Replacement” on page 54-157
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-98
Memory Function Code Replacement
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create an entry for the function mapping with a call to the
RTW.TflCFunctionEntry function.
54-99
54 Code Replacement Customization for Simulink Models in Embedded Coder
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, fcn_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
3 Select the diagram and use Edit > Subsystem to make it a subsystem.
54-100
See Also
5 In the Model Explorer, configure the Signal Attributes for the In1, In2, and In3
source blocks. For each, set Port dimensions to [1,100], and set Data type to
int32. Apply the changes. Save the model.
6 Generate code and a code generation report.
7 Review the code replacements.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Data Alignment for Code Replacement” on page 54-136
• “Reserved Identifiers and Code Replacement” on page 54-157
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-101
54 Code Replacement Customization for Simulink Models in Embedded Coder
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create entries for the function mappings. To minimize the size of this function, the
example uses a local function, locAddFcnEnt, to group lines of code repeated for
each entry. A call to the RTW.TflCFunctionEntry function creates an entry for the
collection of local function entry definitions.
%% Create entries for nonfinite utility functions
% locAddFcnEnt(hTable, key, implName, out, in1, hdr)
%% Local Function
function locAddFcnEnt(hTable, key, implName, out, in1, hdr)
if isempty(hTable)
return;
end
fcn_entry = RTW.TflCFunctionEntry;
5 Create conceptual arguments y1 and u1. There are multiple ways to set up the
conceptual arguments. This example uses calls to the getTflArgFromString and
addConceptualArg functions to create and add the arguments.
arg = getTflArgFromString(hTable, 'y1', out);
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(fcn_entry, arg);
54-102
Nonfinite Function Code Replacement
6 Copy the conceptual arguments to the implementation arguments. There are multiple
ways to set up the implementation arguments. This example uses a call to the
copyConceptualArgsToImplementation function to create and add
implementation arguments to the entry by copying matching conceptual arguments.
copyConceptualArgsToImplementation(fcn_entry);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, fcn_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
54-103
54 Code Replacement Customization for Simulink Models in Embedded Coder
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Data Alignment for Code Replacement” on page 54-136
• “Reserved Identifiers and Code Replacement” on page 54-157
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-104
Semaphore and Mutex Function Replacement
Note A custom target that supports concurrent multitasking must set the target
configuration parameter ConcurrentExecutionCompliant. For more information, see
“Support Concurrent Execution of Multiple Tasks” (Simulink Coder).
If the build process generates semaphore or mutex function calls for data transfer
between tasks during code generation for a multicore target environment, use a custom
library. The library can specify code replacements for custom semaphore or mutex
implementations that are optimal for your target environment. Using the Code
Replacement Tool (crtool) or equivalent code replacement functions, you can:
• Configure code replacement table entries for custom semaphore or mutex functions.
During system startup, execution of the code for data transfer between tasks, and
system shutdown the generated code calls these functions.
• Configure DWork arguments that represent global data, which the semaphore or
mutex functions access. A DWork pointer is passed to the model entry functions.
54-105
54 Code Replacement Customization for Simulink Models in Embedded Coder
This example shows how to create code replacement table entries for a mutex
replacement scenario. You configure a multicore target model for concurrent execution
and for data transfer between tasks of differing rates, which Rate Transition blocks
handle. In the generated code for the model, each Rate Transition block has a separate,
unique mutex. Mutex lock and unlock operations within the Rate Transition block
generated code share access to the same global data. They achieve this by using the
unique mutex created for that Rate Transition block.
a Select File > New entry > Semaphore entry to open a new table entry for
configuring a semaphore or mutex replacement.
b In the Mapping Information tab, use the Function parameter to select Mutex
Init. Initial default values for the table entry appear. In the Conceptual
function section, typically you can leave the argument settings at their defaults.
c In the DWork attributes section, the Allocate DWork option is selected. The
dialog box provides a unique entry tag for the DWork argument d1.
54-106
Semaphore and Mutex Function Replacement
In this example, the DWork argument for the Mutex Init function defines a
unique entry tag, entry_25576. That function also defines DWork arguments for
Mutex Lock, Mutex Unlock, and Mutex Destroy, which reference the entry
tag to share the DWork data.
The only data type supported for the DWork Data type parameter is void*.
d In the Replacement function section, enter a function name in the Name field.
This example uses myMutexCreate. In the list of Function arguments, leave
the DWork argument d1 data type as void**.
54-107
54 Code Replacement Customization for Simulink Models in Embedded Coder
d In the Replacement function section, Name field, enter a function name. This
example uses myMutexLock, myMutexUnlock, and myMutexDelete. In the list
of Function arguments, leave the DWork argument d1 data type as void*.
54-108
Semaphore and Mutex Function Replacement
54-109
54 Code Replacement Customization for Simulink Models in Embedded Coder
7 Save the table to a MATLAB file in your working folder, for example, using File >
Save table. The name of the saved file is the table name, crl_table_rt_mutex,
with an .m extension. Optionally, you can open the saved file and examine the
MATLAB code for the code replacement table definition.
3 Configure the model for a multicore target environment and the following settings:
54-110
See Also
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Data Alignment for Code Replacement” on page 54-136
• “Reserved Identifiers and Code Replacement” on page 54-157
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-111
54 Code Replacement Customization for Simulink Models in Embedded Coder
You can define code replacement entries to replace these functions for one or all of the
available computation methods. For example, you can define an entry to replace only
Newton-Raphson instances of the rSqrt function.
To set the algorithm for a function in an entry definition, use the EntryInfoAlgorithm
property in a call to the function setTflCFunctionEntryParameters. The following
table lists arguments for specifying the computation method to match during code
generation.
Function Argument
rSqrt • 'RTW_DEFAULT' (match the default computation method,
Exact)
• 'RTW_NEWTON_RAPHSON'
• 'RTW_UNSPECIFIED' (match any computation method)
sin • 'RTW_CORDIC'
cos • 'RTW_DEFAULT' (match the default approximation
sincos method, None)
• 'RTW_UNSPECIFIED' (match any approximation method)
For example, to replace only Newton-Raphson instances of the rSqrt function, create
an entry as follows:
1 Create a table definition file that contains a function definition. For example:
54-112
Algorithm-Based Code Replacement
hTable = RTW.TflTable;
3 Create an entry for the function mapping with a call to the
RTW.TflCFunctionEntry function.
% Create entry for rsqrt function replacement
fcn_entry = RTW.TflCFunctionEntry;
4 Set function entry parameters with a call to the
setTflCFunctionEntryParameters function.
setTflCFunctionEntryParameters(fcn_entry, ...
'Key', 'rSqrt', ...
'Priority', 80, ...
'ImplementationName', 'rsqrt_newton', ...
'ImplementationHeaderFile', 'rsqrt.h', ...
'EntryInfoAlgorithm', 'RTW_NEWTON_RAPHSON');
5 Create conceptual arguments y1 and u1. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call.
createAndAddConceptualArg(fcn_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'DataTypeMode', 'double');
The generated code for a Newton-Raphson instance of the rSqrt function looks like the
following code:
/* Model step function */
void mrsqrt_step(void)
{
54-113
54 Code Replacement Customization for Simulink Models in Embedded Coder
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Math Function Code Replacement” on page 54-97
• “Define Code Replacement Mappings” on page 54-43
• “Develop a Code Replacement Library” on page 54-27
54-114
Lookup Table Function Code Replacement
For more information about using lookup table blocks, see “Nonlinearity” (Simulink).
54-115
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-116
Lookup Table Function Code Replacement
54-117
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-118
Lookup Table Function Code Replacement
When defining a table entry programmatically, you might also need to change the values
of required (primary) and optional algorithm parameters.
tableEntry = RTW.TflCFunctionEntry;
54-119
54 Code Replacement Customization for Simulink Models in Embedded Coder
2 Identify the lookup table function in the table entry. Use the Key table entry
parameter in a call to setTflCFunctionEntryParameters. The following example
identifies an entry for the prelookup function.
setTflCFunctionEntryParameters(tableEntry, ...
'Key', 'prelookup', ...
'Priority', 100, ...
'ImplementationName', 'myPrelookup');
3 Get the algorithm parameter set for the entry with a call to
getAlgorithmParameters.
algParams = getAlgorithmParameters(tableEntry);
algParams =
ans =
Name: 'ExtrapMethod'
Options: {'Linear' 'Clip'}
Primary: 1
Value: {'Linear'}
algParams.RndMeth
ans =
Name: 'RndMeth'
Options: {1x7 cell}
Primary: 0
Value: {1x7 cell}
algParams.RndMeth.Value
ans =
Columns 1 through 6
Column 7
'Zero'
algParams.IndexSearchMethod
54-120
Lookup Table Function Code Replacement
ans =
Name: 'IndexSearchMethod'
Options: {'Linear search' 'Binary search' 'Evenly spaced points'}
Primary: 0
Value: {'Binary search' 'Evenly spaced points' 'Linear search'}
algParams.UseLastBreakpoint
ans =
Name: 'UseLastBreakpoint'
Options: {'off' 'on'}
Primary: 0
Value: {'off' 'on'}
algParams.RemoveProtectionInput
ans =
Name: 'RemoveProtectionInput'
Options: {'off' 'on'}
Primary: 0
Value: {'off' 'on'}
Identify or create the C or C++ replacement function for the algorithm that you want to
use in place of a Simulink software algorithm.
This example uses the following C replacement function header and source files, which
are in the folder matlab/toolbox/rtw/rtwdemos/crl_demo:
• myLookup1D.h
• myLookup1D.c
54-121
54 Code Replacement Customization for Simulink Models in Embedded Coder
Open and examine the code in myLookup1D.c. Note the function signature. When you
enter the implementation argument specification in the Code Replacement Tool, specify
argument properties.
#include "myLookup1D.h"
real_T my_Lookup1D_Repl(real_T u0, const real_T *bp0, const real_T *table, uint32_T tdl)
{
real_T y;
uint16_T frac;
uint32_T bpIdx;
uint32_T maxIndex=tdl-1;
while ((bpIdx < maxIndex - 1U) && (u0 >= bp0[bpIdx + 1U])) {
bpIdx++;
}
if (bpIdx == maxIndex) {
y = table[bpIdx];
} else {
y = (table[bpIdx + 1U] - table[bpIdx]) * ((real_T)frac * 3.0517578125E-5) +
table[bpIdx];
}
return y;
}
This example uses the model rtwdemo_crllookup1D to test your code replacement
specification. Place a copy of the model in your working folder and name it
my_lookup1d.slx.
Open and examine the model. Note input and output specifications and block parameter
settings. To achieve a match, you must specify conceptual arguments based on how the 1-
D Lookup Table block is configured in the example model.
54-122
Lookup Table Function Code Replacement
1 At the command prompt, enter crtool to open the Code Replacement Tool.
2 Add a new table, select that table, and add a new function entry.
3 On the Mapping Information tab, select Custom for the Function parameter.
4 Look up the call signature and algorithm parameter information for the lookup table
function that you want to update with an algorithm replacement. See “Lookup Table
Function Signatures” on page 54-115.
For this example, you replace the algorithm for the conceptual function associated
with the 1-D Lookup Table block. The signature for that function is:
Arguments u1, u2, u3, u4 represent input, breakpoint data, table data, and table
dimension length, respectively. The function returns output to y1.
5 To the right of the Function drop-down list, in the function-name text box, enter the
name of the Simulink lookup table function. For this example, type the name
lookup1D. Type the name exactly as it appears in the documented signature,
including character casing. Press Enter.
The tool displays algorithm parameter settings that trigger a match for the 1-D
Lookup Table block in the example model. Required parameters appear with only one
value. For this example, do not change the values. Optional parameters appear with
multiple values. Changes to optional parameters do not affect the match process.
6 Specify the conceptual arguments. Under the Conceptual arguments list box, click
+ to add the arguments that are in the documented function signature. The
lookup1D function takes one output argument and four input arguments. Click +
five times.
54-123
54 Code Replacement Customization for Simulink Models in Embedded Coder
The tool creates an output argument y1 and four input arguments u1, u2, u3, and u4.
By default, the four arguments are scalars of type double.
You can adjust the conceptual argument properties. For this example, you do not
make changes for y1 and u1. However, as the block parameter dialog box for the
example model shows, you must adjust the argument properties for the breakpoint
and table data arguments.
Adjust the conceptual argument properties by using the following table. Click Apply.
54-124
Lookup Table Function Code Replacement
In the Replacement function > Function prototype section, type the function
name my_Lookup1D_Repl in the Name text box.
8 Specify the arguments for the replacement function. Under the Function
arguments list box, click + five times to add five implementation arguments.
You might need to adjust the function argument properties. As the replacement
function signature shows, adjust the argument properties for the breakpoint, table
data, and table dimension length arguments. For u2 (breakpoints) and u3 (table),
select the Const check box. For u4, set Data type to uint32.
On the Build Information tab, specify information relevant to generating C or C++ code
and building an executable from the model. Enter myLookup1D.h for Implementation
Header File and myLookup1D.c for Implementation Source File.
54-125
54 Code Replacement Customization for Simulink Models in Embedded Coder
If you copied the example files to a folder other than the working folder containing the
test model, lookup1d.slx, specify the source and header file paths. Otherwise, leave the
other Build Information parameters set to default values. Click Apply.
Programmatic Specification
This example shows how to specify code replacement table entries for lookup table
functions programmatically.
Identify or create the C or C++ replacement function for the algorithm that you want to
use in place of a Simulink software algorithm.
This example uses the following C replacement function header and source files, which
are in the folder matlab/toolbox/rtw/rtwdemos/crl_demo:
• myLookup1D.h
• myLookup1D.c
54-126
Lookup Table Function Code Replacement
Open and examine the code in myLookup1D.c. Note the function signature. When you
enter the implementation argument specification in the Code Replacement Tool, specify
argument properties.
#include "myLookup1D.h"
real_T my_Lookup1D_Repl(real_T u0, const real_T *bp0, const real_T *table, uint32_T tdl)
{
real_T y;
uint16_T frac;
uint32_T bpIdx;
uint32_T maxIndex=tdl-1;
while ((bpIdx < maxIndex - 1U) && (u0 >= bp0[bpIdx + 1U])) {
bpIdx++;
}
if (bpIdx == maxIndex) {
y = table[bpIdx];
} else {
y = (table[bpIdx + 1U] - table[bpIdx]) * ((real_T)frac * 3.0517578125E-5) +
table[bpIdx];
}
return y;
}
Look up the call signature information for the lookup function that you want to update
with an algorithm replacement. See “Lookup Table Function Signatures” on page 54-115.
Replace the algorithm for the function associated with the 1–D Lookup Table block. The
signature for that function is:
Arguments u1, u2, u3, and u4 represent input, breakpoint data, table data, and table
dimension length, respectively. The function returns output to y1.
54-127
54 Code Replacement Customization for Simulink Models in Embedded Coder
Create a code replacement table file as a MATLAB function, that describes the lookup
table function code replacement table entries. Place a copy of the file matlab/
toolbox/rtw/rtwdemos/crl_demo/crl_table_lookup1D.m in your working folder.
This file defines a code replacement table for the C function my_Lookup1D_Repl.
1 Create a table definition file that contains a function definition. For example:
hLib = RTW.TflTable;
3 Create an entry for the function mapping with a call to the
RTW.TflCFunctionEntry function.
hEnt = RTW.TflCFunctionEntry;
4 Set function entry parameters with a call to the
setTflCFunctionEntryParameters function. The function key, implementation
name, and header and source files in the function call identify the Simulink lookup
table function name, lookup1D, and the following information for replacement
function my_Lookup1D_Repl:
• Function name
• Header file
• Source file
Specify the Simulink lookup table function name exactly as it appears in the
documented signature, including character casing (see “Lookup Table Function
Signatures” on page 54-115). If you copied the example files to a folder other than
the working folder that contains the test model, rtwdemo_crllookup1D, specify the
source and header file paths.
setTflCFunctionEntryParameters(hEnt, ...
'Key', 'lookup1D', ...
'Priority', 100, ...
'ImplementationName', 'my_Lookup1D_Repl', ...
'ImplementationHeaderFile', 'myLookup1D.h', ...
'ImplementationSourceFile', 'myLookup1D.c', ...
'GenCallback', 'RTW.copyFileToBuildDir');
54-128
Lookup Table Function Code Replacement
5 Create conceptual arguments and add them to the entry. This example uses calls to
the getTflArgFromString and addConceptualArg functions to create and add
the arguments.
The example defines five conceptual arguments for the lookup1D function, one
output argument y1 and four input arguments u1, u2, u3, and u4. Arguments y1 and
u1 are defined as scalar double data. Arguments u2 and u3 represent bp1 and
table in the signature and are defined as 1x10 matrices of double data. Argument
u4 represents tdl and is defined as scalar of uint32 data. This definition triggers a
match with the example model.
arg = hEnt.getTflArgFromString('y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(hEnt, arg);
arg = hEnt.getTflArgFromString('u1','double');
addConceptualArg(hEnt, arg);
arg = hEnt.getTflArgFromString('u4','uint32');
addConceptualArg(hEnt, arg);
6 Review the algorithm parameter information for the lookup function that you want to
update with an algorithm replacement. Use the getAlgorithmParameters function
to display the parameter information.
algParams = getAlgorithmParameters(hEnt)
algParams =
Examine the information for each parameter. The Options property lists possible
values. Primary indicates whether a parameter is required (1) or optional (0). The
Value property specifies the current value. For required parameters, initially, Value
is set to the default value for a given lookup table function.
54-129
54 Code Replacement Customization for Simulink Models in Embedded Coder
algParams.InterpMethod
ans =
Name: 'InterpMethod'
Options: {'Linear' 'Flat' 'Nearest'}
Primary: 1
Value: {'Linear'}
algParams.RndMeth
ans =
Name: 'RndMeth'
Options: {1x7 cell}
Primary: 0
Value: {1x7 cell}
algParams.RndMeth.Options
ans =
Columns 1 through 5
Columns 6 through 7
'Simplest' 'Zero'
algParams.RndMeth
7 Set the algorithm properties for the lookup1D table entry. Assign a value to each
parameter. Update the parameter settings for the entry by calling the function
setAlgorithmParameters. The following parameter settings trigger a match with
the example model.
algParams.InterpMethod = 'Linear';
algParams.ExtrapMethod = 'Clip';
algParams.RndMeth = 'Round';
algParams.IndexSearchMethod = 'Linear search';
algParams.UseLastTableValue = 'Evenly spaced point';
54-130
Lookup Table Function Code Replacement
algParams.RemoveProtectionInput = 'off';
algParams.SaturateOnIntegerOverflow = 'off';
algParams.SupportTunableTableSize = 'off';
algParams.BPPower2Spacing = 'off';
setAlgorithmParameters(hEnt, algParams);
ans =
Name: 'RndMeth'
Options: {1x7 cell}
Primary: 0
Value: {1x7 cell}
.
.
.
To verify your changes, call getAlgorithmParameters to get the parameter set for
the table entry. Examine the value of each parameter.
getAlgorithmParameters(hEnt, algParams);
algParams.InterpMethod.Value
ans =
'Linear'
algParams.ExtrapMethod.Value
ans =
'Clip'
algParams.RndMeth.Value
ans =
'Round'
.
.
.
8 Create the implementation arguments and add them to the entry. This example uses
calls to the getTflArgFromString function to create five implementation
arguments that map to arguments in the replacement function prototype: one output
54-131
54 Code Replacement Customization for Simulink Models in Embedded Coder
argument y1 and four input arguments u1, u2, u3, and u4. The convenience methods
setReturn and addArgument specify whether an argument is a return value or
argument. The addArgument function also adds each argument to the entry’s array
of implementation arguments.
arg = hEnt.getTflArgFromString('y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);
arg = hEnt.getTflArgFromString('u1','double');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u2','double*');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u3','double*');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u4','uint32');
hEnt.Implementation.addArgument(arg);
9 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hLib, hEnt);
10 Save the table definition file. Use the name of the table definition function to name
the file.
54-132
Lookup Table Function Code Replacement
• On the Code Generation > Interface pane, select the code replacement library
that contains your lookup table function entry.
hLib = RTW.TflTable;
hEnt = RTW.TflCFunctionEntry;
setTflCFunctionEntryParameters(hEnt, ...
'Key', 'lookup2D', ...
'Priority', 100, ...
% Conceptual Args
arg = hEnt.getTflArgFromString('y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(hEnt, arg);
arg = hEnt.getTflArgFromString('u1','double');
addConceptualArg(hEnt, arg);
arg = hEnt.getTflArgFromString('u2','double');
addConceptualArg(hEnt, arg);
54-133
54 Code Replacement Customization for Simulink Models in Embedded Coder
arg.DimRange = [1 1; 10 1];
addConceptualArg(hEnt, arg);
arg = hEnt.getTflArgFromString('u6','uint32');
addConceptualArg(hEnt, arg);
arg = hEnt.getTflArgFromString('u7','uint32');
addConceptualArg(hEnt, arg);
% Algorithm Parameters
addAlgorithmProperty(hEnt, 'ExtrapMethod','Clip');
addAlgorithmProperty(hEnt, 'IndexSearchMethod','Linear search');
addAlgorithmProperty(hEnt, 'InterpMethod','Linear');
addAlgorithmProperty(hEnt, 'RemoveProtectionInput','off');
addAlgorithmProperty(hEnt, 'UseLastTableValue','on');
% Implementation Args
arg = hEnt.getTflArgFromString('y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);
arg = hEnt.getTflArgFromString('u1','double');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u2','double');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u3','double*');
arg.Type.BaseType.ReadOnly = true;
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u4','double*');
arg.Type.BaseType.ReadOnly = true;
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u5','double*');
arg.Type.BaseType.ReadOnly = true;
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u6','uint32');
hEnt.Implementation.addArgument(arg);
54-134
See Also
arg = hEnt.getTflArgFromString('u7','uint32');
hEnt.Implementation.addArgument(arg);
hLib.addEntry(hEnt);
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Data Alignment for Code Replacement” on page 54-136
• “Reserved Identifiers and Code Replacement” on page 54-157
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-135
54 Code Replacement Customization for Simulink Models in Embedded Coder
For examples, see “Basic Example of Code Replacement Data Alignment” on page 54-143
and the “Data Alignment for Function Implementations” section of the “Optimize
Generated Code By Developing and Using Code Replacement Libraries - Simulink®”
example page.
54-136
Data Alignment for Code Replacement
hLib = RTW.TflTable;
entry = RTW.TflCOperationEntry;
arg = getTflArgFromString(hLib, 'u1','single*');
desc = RTW.ArgumentDescriptor;
desc.AlignmentBoundary = 16;
arg.Descriptor = desc;
entry.Implementation.addArgument(arg);
54-137
54 Code Replacement Customization for Simulink Models in Embedded Coder
The equivalent alignment boundary specification in the Code Replacement Tool dialog box
is in this figure.
54-138
Data Alignment for Code Replacement
Additionally, you can specify the alignment boundary for complex types by using the
addComplexTypeAlignment function.
• If you are generating a customization file function using the Code Replacement Tool,
fill out the following fields for each compiler.
54-139
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-140
Data Alignment for Code Replacement
54-141
54 Code Replacement Customization for Simulink Models in Embedded Coder
as = RTW.AlignmentSpecification;
as.AlignmentType = {'DATA_ALIGNMENT_LOCAL_VAR', ...
'DATA_ALIGNMENT_STRUCT_FIELD', ...
'DATA_ALIGNMENT_GLOBAL_VAR'};
as.AlignmentSyntaxTemplate = '__attribute__((aligned(%n)))';
as.AlignmentPosition = 'DATA_ALIGNMENT_PREDIRECTIVE';
as.SupportedLanguages = {'c', 'c++'};
da.addAlignmentSpecification(as);
tc = RTW.TargetCharacteristics;
tc.DataAlignment = da;
Here is the corresponding specification in the Generate customization dialog box of the
Code Replacement Tool.
54-142
Data Alignment for Code Replacement
1 Create and save the following code replacement table definition file,
crl_table_mmul_4x4_single_align.m. This table defines a replacement entry
for the * (multiplication) operator, the single data type, and input dimensions
[4,4]. The entry also specifies a data alignment boundary of 16 bytes for each
replacement function argument. The entry expresses the requirement that the
starting memory address for the data allocated for the function arguments during
code generation is a multiple of 16.
function hLib = crl_table_mmul_4x4_single_align
%CRL_TABLE_MMUL_4x4_SINGLE_ALIGN - Describe matrix operator entry with data alignment
hLib = RTW.TflTable;
entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 90, ...
'ImplementationName', 'matrix_mul_4x4_s');
% conceptual arguments
createAndAddConceptualArg(entry, 'RTW.TflArgMatrix',...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'single', ...
'DimRange', [4 4]);
54-143
54 Code Replacement Customization for Simulink Models in Embedded Coder
createAndAddConceptualArg(entry, 'RTW.TflArgMatrix',...
'Name', 'u1', ...
'BaseType', 'single', ...
'DimRange', [4 4]);
createAndAddConceptualArg(entry, 'RTW.TflArgMatrix',...
'Name', 'u2', ...
'BaseType', 'single', ...
'DimRange', [4 4]);
% implementation arguments
arg = getTflArgFromString(hLib, 'y2', 'void');
arg.IOType = 'RTW_IO_OUTPUT';
entry.Implementation.setReturn(arg);
hLib.addEntry(entry);
2 Create and save the following registration file, rtwTargetInfo.m. If you want to
compile the code generated in this example, first modify the
AlignmentSyntaxTemplate property for the compiler that you use. For example,
for the MSVC compiler, replace the gcc template character vector
__attribute__((aligned(%n))) with __declspec(align(%n)).
function rtwTargetInfo(cm)
% rtwTargetInfo function to register a code replacement library (CRL)
% for use with code generation
54-144
See Also
as = RTW.AlignmentSpecification;
as.AlignmentType = {'DATA_ALIGNMENT_LOCAL_VAR', ...
'DATA_ALIGNMENT_GLOBAL_VAR', ...
'DATA_ALIGNMENT_STRUCT_FIELD'};
as.AlignmentSyntaxTemplate = '__attribute__((aligned(%n)))';
as.SupportedLanguages={'c', 'c++'};
3 To register your library with code generator without having to restart MATLAB, enter
this command:
RTW.TargetRegistry.getInstance('reset');
4 Configure the code generator to use your code replacement library.
5 Generate code and a code generation report.
6 Review the code replacements. For example, check whether a multiplication
operation is replaced with a matrix_mul_4x4_s function call. In mmalign.h, check
whether the gcc alignment directive __attribute__((aligned(16))) is
generated to align the function variables.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Develop a Code Replacement Library” on page 54-27
54-145
54 Code Replacement Customization for Simulink Models in Embedded Coder
• MATLAB Coder
• MATLAB code in a Simulink MATLAB Function block
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Develop a Code Replacement Library” on page 54-27
54-146
Replace coder.ceval Calls to External Functions
• MATLAB Coder
• MATLAB code in a Simulink MATLAB Function block
Example Files
For the examples in “Interactive External Function Call Replacement Specification with
Code Replacement Tool” on page 55-107 and “Programmatic External Function Call
Replacement Specification” on page 55-109 you must have set up the following:
/* my_add.c */
#include "my_add.h"
/* my_add.h */
y=0.0;
if ~coder.target('Rtw')
54-147
54 Code Replacement Customization for Simulink Models in Embedded Coder
in1=10;
in2=20;
y = call_my_add(in1, in2);
disp('Output')
disp('y =')
disp(y);
• Replacement C function my_add_replacement.c.
/* my_add_replacement.c */
#include "my_add_replacement.h"
/* my_add_replacement.h */
1 Identify or create the C/C++ code and relevant header files, the MATLAB function
that calls coder.ceval, a MATLAB test function, and the source and header files for
54-148
Replace coder.ceval Calls to External Functions
your replacement code. To follow along with this example, set up the files identified
in “Example Files” on page 55-106.
2 In the Code Replacement Tool, add a table, select that table, and add a function entry.
For more information, see “Define Code Replacement Mappings” on page 55-29.
3 On the Mapping Information tab, select Custom for the Function parameter.
4 In the function-name text box, type the custom function name. For this example,
type the name my_add.
5 Under the Conceptual arguments list box, click + to add three arguments. By
default, the tool creates an output argument y1 and input arguments u1 and u2 of
type double.
6 In the Replacement function > Function prototype section, type the name
my_add_replacement in the Name text box.
7 Under the Function arguments list box, click + to add three function
implementation arguments. By default, the tool creates an output argument y1 and
input arguments u1 and u2 of type double. Use the default settings.
8 In the Function signature preview box, if you see the expected function signature,
click Apply. The function signature for this example, appears as:
1 Register the table that contains the entry in a code replacement library.
2 Configure the code generator to use the code replacement library and to include the
Code Replacements Report in the code generation report.
3 Generate code and the report.
4 Review the code replacements.
54-149
54 Code Replacement Customization for Simulink Models in Embedded Coder
1 Identify or create the C/C++ code and relevant header files, the MATLAB function
that calls coder.ceval to invoke the C/C++ function, a MATLAB test function, and
the source and header files for your replacement code. To follow along with this
example, set up the files identified in “Example Files” on page 55-106.
2 Create a table definition file that contains a function definition. For example:
hEnt = RTW.TflCFunctionEntry;
5 Set function entry parameters with a call to the
setTflCFunctionEntryParameters function.
hEnt.setTflCFunctionEntryParameters( ...
'Key', 'my_add', ...
'Priority', 100, ...
'ImplementationName', 'my_add_replacement', ...
'ImplementationHeaderFile', 'my_add_replacement.h', ...
'ImplementationSourceFile', 'my_add_replacement.c');
6 Create conceptual arguments y1, u1, and u1. This example uses calls to the
getTflArgFromString and addConceptualArg functions to create and add the
arguments.
arg = hEnt.getTflArgFromString('y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.addConceptualArg(arg);
arg = hEnt.getTflArgFromString('u1','double');
hEnt.addConceptualArg(arg);
arg = hEnt.getTflArgFromString('u2','double');
hEnt.addConceptualArg(arg);
54-150
See Also
7 Create the implementation arguments and add them to the entry. This example uses
calls to the getTflArgFromString function to create implementation arguments.
These functions map to arguments in the replacement function prototype: output
argument y1 and input arguments u1 and u2. For each argument, the example uses
the convenience method setReturn or addArgument to specify whether an
argument is a return value or argument. For each argument, this example adds the
argument to the entry array of implementation arguments.
arg = hEnt.getTflArgFromString('y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);
arg = hEnt.getTflArgFromString('u1','double');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u2','double');
hEnt.Implementation.addArgument(arg);
8 Add the entry to a code replacement table with a call to the addEntry function.
hLib.addEntry(hEnt);
9 Save the table definition file. Use the name of the table definition function to name
the file.
1 Register the table that contains the entry in a code replacement library.
2 Configure the code generator to use the code replacement library and to include the
Code Replacements Report in the code generation report.
3 Generate code and the report.
4 Review the code replacements.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Integrate MATLAB Algorithm in Model” (Simulink)
• “Define Code Replacement Mappings” on page 54-43
54-151
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-152
Replace MATLAB Functions Specified in MATLAB Function Blocks
addpath(fullfile(docroot,'toolbox','ecoder','examples'))
ex_replace
2 View the MATLAB Function Block code. In the model, double-click the MATLAB
Function block to view the code in the MATLAB editor.
assert(isa(u1,'int32'));
assert(isa(u2,'int32'));
y = power(u1,u2);
hTable = RTW.TflTable;
5 Create an entry for the function mapping with a call to the
RTW.TflCFunctionEntry function.
hEnt = RTW.TflCFunctionEntry;
6 Set function entry parameters with a call to the
setTflCFunctionEntryParameters function.
54-153
54 Code Replacement Customization for Simulink Models in Embedded Coder
setTflCFunctionEntryParameters(hEnt, ...
'Key', 'customFcn', ...
'Priority', 100, ...
'ImplementationName', 'scalarFcnReplacement', ...
'ImplementationHeaderFile', 'MyMath.h', ...
'ImplementationSourceFile', 'MyMath.c')
7 Create conceptual arguments y1, u1, and u2. This example uses calls to the
getTflArgFromString and addConceptualArg functions to create and add the
arguments.
arg = getTflArgFromString(hEnt, 'y1','int32');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(hEnt, arg);
8 Create the implementation arguments and add them to the entry. This example uses
calls to the getTflArgFromString function to create implementation arguments
that map to arguments in the replacement function prototype: output argument
void, input arguments u1 and u2, and output argument y1. The convenience
methods setReturn and addArgument specify whether an argument is a return
value or argument. The addArgument function also adds each argument to the
entry’s array of implementation arguments.
addEntry(hLib, hEnt);
10 Save the table definition file. Use the name of the table definition function to name
the file.
54-154
Replace MATLAB Functions Specified in MATLAB Function Blocks
MyMath.c
#include "MyMath.h"
MyMath.h
#ifndef _ScalarMath_h
#define _ScalarMath_h
#include "rtwtypes.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
3 Open the ex_replace model.
4 Configure the code generator to use the code replacement library and to include the
Code Replacements Report in the code generation report.
5 Generate the replacement code and a code generation report.
6 Review the code replacements. In the code generation report, view the generated
code for ex_replace.c.
void ex_replace_step(void)
{
int32_T y;
54-155
54 Code Replacement Customization for Simulink Models in Embedded Coder
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Develop a Code Replacement Library” on page 54-27
54-156
Reserved Identifiers and Code Replacement
To view a list of reserved identifiers for the code replacement library that you use to
generate code, specify the name of the library in a call to the function
RTW.TargetRegistry.getInstance.getTflReservedIdentifiers. For example:
crl_ids = RTW.TargetRegistry.getInstance.getTflReservedIdentifiers('GNU99 (GNU)')
In a code replacement table, the code generator registers each function implementation
name defined by a table entry as a reserved identifier. You can register additional
reserved identifiers for the table on a per-header-file basis. Providing additional reserved
identifiers can help prevent duplicate symbols and other identifier-related compile and
link issues.
You can register up to four reserved identifier structures in a code replacement table. You
can associate one set of reserved identifiers with a code replacement library, while the
other three (if present) must be associated with ANSI C. The following example shows a
reserved identifier structure that specifies two identifiers and the associated header file.
d{1}.LibraryName = 'ANSI_C';
d{1}.HeaderInfos{1}.HeaderName = 'math.h';
d{1}.HeaderInfos{1}.ReservedIds = {'y0', 'y1'};
The code generator adds the identifiers to the list of reserved identifiers and honors them
during the build procedure.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
54-157
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-158
Customize Match and Replacement Process
• Preset match criteria to identify functions and operators for which application-specific
implementations replace default implementations.
• Preset replacement function signatures.
It is possible that preset match criteria and preset replacement function signatures do not
completely meet your function and operator replacement needs. For example:
To add extra logic into the code replacement match and replacement process, create
custom code replacement table entries. With custom entries, you can specify additional
match criteria and modify the replacement function signature to meet application needs.
• Add match criteria that the base class does not provide. The base class provides a
match based on:
• Argument number
• Argument name
• Signedness
• Word size
• Slope (if not specified with wildcards)
• Bias (if not specified with wildcards)
54-159
54 Code Replacement Customization for Simulink Models in Embedded Coder
During code generation, the code replacement match process tries to match function or
operator call sites with the base class of your derived entry class. If the process finds a
match, the software calls your do_match method to execute your additional match logic
(if any) and your replacement function customizations (if any).
• Modify a sine function replacement only if the integer size on the current target
platform is 32 bits.
• Change the replacement such that the implementation function passes in a degrees-
versus-radians flag as an input argument.
1 To exercise the table entries that you create in this example, create an ERT-based
model with a sine function block. For example:
In the Inport block parameters, set the signal Data type to double. If the value
selected for Configuration Parameters > Hardware Implementation > Device
type supports an integer size other than 32, do one of the following:
54-160
Customize Match and Replacement Process
• ent is the return handle, which is returned either as empty (indicating that the
match failed) or as a TflCFunctionEntry handle.
• hThis is a handle to the class instance.
• hCSO is a handle to an object that the code generator creates for querying the
library for a replacement.
• Remaining arguments are the number of bits for various data types of the current
target.
• Adds required additional match criteria that the base class does not provide.
• Makes required modifications to the implementation signature.
Alternatively, create and add the additional implementation function argument for
passing a units flag in each code replacement table definition file that instantiates
this class. In that case, this class definition code does not create the argument. That
code sets only the argument value. For an example of creating and adding additional
implementation function arguments in a table definition file, see “Customize Code
Match and Replacement for Scalar Operations” on page 54-167.
classdef TflCustomFunctionEntry < RTW.TflCFunctionEntryML
methods
function ent = do_match(hThis, ...
hCSO, ... %#ok
targetBitPerChar, ... %#ok
targetBitPerShort, ... %#ok
targetBitPerInt, ... %#ok
54-161
54 Code Replacement Customization for Simulink Models in Embedded Coder
ent = []; % default the return to empty, indicating the match failed.
Exit the class folder and return to the previous working folder.
3 Create and save the following code replacement table definition file,
crl_table_custom_sinfcn_double.m. This file defines a code replacement table
that contains a function table entry for sine with double input and output. This entry
instantiates the derived class from the previous step, TflCustomFunctionEntry.
function hTable = crl_table_custom_sinfcn_double
hTable = RTW.TflTable;
%% Add TflCustomFunctionEntry
fcn_entry = TflCustomFunctionEntry;
setTflCFunctionEntryParameters(fcn_entry, ...
'Key', 'sin', ...
'Priority', 30, ...
'ImplementationName', 'mySin', ...
'ImplementationHeaderFile', 'mySin.h', ...
'ImplementationSourceFile', 'mySin.c');
54-162
Customize Match and Replacement Process
'DataTypeMode', 'double');
addEntry(hTable, fcn_entry);
tbl = crl_table_custom_sinfcn_double
• In the Code Replacement Viewer, view the table definition file.
crviewer(crl_table_custom_sinfcn_double)
This example restricts the match criteria for an element-wise multiplication replacement
to entries with a specific dimension range. When a match occurs, the custom do_match
method modifies the replacement signature to pass the number of elements into the
function.
Files for developing and testing this code replacement library example are available in
matlab/help/toolbox/ecoder/examples/code_replacement/custom_elemmult:
54-163
54 Code Replacement Customization for Simulink Models in Embedded Coder
To create custom code replacement entries that add logic to the code replacement match
and replacement process:
1 Create a class, for example MyElemMultEntry, which is derived from the base class
RTW.TflCOperationEntryML. The derived class defines a do_match method with
the following signature:
• ent is the return handle, which is returned as empty (indicating that the match
failed) or as a TflCOperationEntry handle.
• hThis is the handle to the derived instance.
• hCSO is a handle to an object that the code generator creates for querying the
library for a replacement.
• Remaining arguments are the number of bits for various data types of the current
target.
• Adds match criteria that the base class does not provide.
• Makes changes to the implementation signature.
The do_match method relies on the base class for checking data types and
dimension ranges. If the code generator finds a match, do_match:
54-164
Customize Match and Replacement Process
• Updates the code replacement entry such that it matches CSOs that have the
same argument dimensions.
classdef MyElemMulyEntry < RTW.TflCOperationEntryML
methods
function obj = MyElemMultEntry(varargin)
mlock;
[email protected](varargin{:});
end
ent = RTW.TflCOperationEntry(hThis);
54-165
54 Code Replacement Customization for Simulink Models in Embedded Coder
libPath = fullfile(fileparts(which(mfilename)),'src');
hLib = RTW.TflTable;
%---------- entry: RTW_OP_ELEM_MUL -----------
hEnt = MyElemMultEntry;
hEnt.setTflCOperationEntryParameters( ...
'Key', 'RTW_OP_ELEM_MUL', ...
'Priority', 100, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW', ...
'ImplementationName', 'myElemMul_s32', ...
'ImplementationSourceFile', 'myMulImplLib.c', ...
'ImplementationSourcePath', libPath, ...
'ImplementationHeaderFile', 'myMulImplLib.h', ...
'ImplementationHeaderPath', libPath, ...
'SideEffects', true, ...
'GenCallback','RTW.copyFileToBuildDir');
% Conceptual Args
% Implementation Args
arg = hEnt.getTflArgFromString('unused','void');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);
54-166
Customize Match and Replacement Process
arg = hEnt.getTflArgFromString('u1','int32*');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u2','int32*');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('y1','int32*');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('numElements','uint32',0);
hEnt.Implementation.addArgument(arg);
hLib.addEntry( hEnt );
3 Check the validity of the code replacement table entry.
tbl = myElemMultCrlTable
• In the Code Replacement Viewer, view the table definition file.
crviewer(myElemMultCrlTable)
For example:
• When fraction lengths are within a specific range, replace an operator with a fixed-
point implementation function.
• When a match occurs, modify the replacement function signature based on compile-
time information, such as passing fraction-length values into the function.
This example modifies a fixed-point addition replacement such that the implementation
function passes in the fraction lengths of the input and output data types as arguments.
54-167
54 Code Replacement Customization for Simulink Models in Embedded Coder
To create custom code replacement entries that add logic to the code replacement match
and replacement process:
1 Create a class, for example TflCustomOperationEntry, that is derived from the
base class RTW.TflCOperationEntryML. The derived class defines a do_match
method with the following signature:
function ent = do_match(hThis, ...
hCSO, ...
targetBitPerChar, ...
targetBitPerShort, ...
targetBitPerInt, ...
targetBitPerLong, ...
targetBitPerLongLong)
• ent is the return handle, which is returned as empty (indicating that the match
failed) or as a TflCOperationEntry handle.
• hThis is the handle to the class instance.
• hCSO is a handle to an object that the code generator creates for querying the
library for a replacement.
• Remaining arguments are the number of bits for various data types of the current
target.
The do_match method adds match criteria that the base class does not provide. The
method makes modifications to the implementation signature. In this case, the
do_match method relies on the base class for checking word size and signedness.
do_match must match only the number of conceptual arguments to the value 3 (two
inputs and one output) and the bias for each argument to value 0. If the code
generator finds a match, do_match:
You can create and add three additional implementation function arguments for
passing fraction lengths in the class definition or in each code replacement entry
definition that instantiates this class. This example creates the arguments, adds them
54-168
Customize Match and Replacement Process
to a code replacement table definition file, and sets them to specific values in the
class definition code.
classdef TflCustomOperationEntry < RTW.TflCOperationEntryML
methods
function ent = do_match(hThis, ...
hCSO, ... %#ok
targetBitPerChar, ... %#ok
targetBitPerShort, ... %#ok
targetBitPerInt, ... %#ok
targetBitPerLong, ... %#ok
targetBitPerLongLong) %#ok
% The base class checks word size and signedness. Slopes and biases
% have been wildcarded, so the only additional checking to do is
% to check that the biases are zero and that there are only three
% conceptual arguments (one output, two inputs)
ent = []; % default the return to empty, indicating the match failed
54-169
54 Code Replacement Customization for Simulink Models in Embedded Coder
-1.0*hCSO.ConceptualArgs(2).Type.FixedExponent;
ent.Implementation.Arguments(4).Value = ...
-1.0*hCSO.ConceptualArgs(3).Type.FixedExponent;
ent.Implementation.Arguments(5).Value = ...
-1.0*hCSO.ConceptualArgs(1).Type.FixedExponent;
end
end
end
end
Exit the class folder and return to the previous working folder.
2 Create and save the following code replacement table definition file,
crl_table_custom_sinfcn_double.m. This file defines a code replacement table
that contains a single operator entry, an entry generator for unsigned 32-bit fixed-
point addition operations, with arbitrary fraction-length values on the inputs and the
output. The table entry:
hTable = RTW.TflTable;
54-170
Customize Match and Replacement Process
%% Add TflCustomOperationEntry
op_entry = TflCustomOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 30, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_FLOOR'}, ...
'ImplementationName', 'myFixptAdd', ...
'ImplementationHeaderFile', 'myFixptAdd.h', ...
'ImplementationSourceFile', 'myFixptAdd.c');
54-171
54 Code Replacement Customization for Simulink Models in Embedded Coder
% Add 3 fraction-length args. Actual values are set during code generation.
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumericConstant', ...
'Name', 'fl_in1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0, ...
'Value', 0);
54-172
See Also
'Value', 0);
addEntry(hTable, op_entry);
3 Check the validity of the operator entry.
tbl = crl_table_custom_sinfcn_double
• In the Code Replacement Viewer, view the table definition file.
crviewer(crl_table_custom_sinfcn_double)
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Develop a Code Replacement Library” on page 54-27
54-173
54 Code Replacement Customization for Simulink Models in Embedded Coder
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create an entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the getTflArgFromString and
addConceptualArg functions to create and add the arguments.
arg = getTflArgFromString(hTable, 'y1', 'uint8');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(op_entry, arg);
6 Copy the conceptual arguments to the implementation arguments. There are multiple
ways to set up the implementation arguments. This example uses a call to the
54-174
See Also
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Data Alignment for Code Replacement” on page 54-136
• “Remap Operator Output to Function Input” on page 54-201
54-175
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-176
Addition and Subtraction Operator Code Replacement
Algorithm Options
When creating a code replacement table entry for an addition or subtraction operator,
first determine the type of algorithm that your library function implements.
• Cast-after-operation (CAO) — The algorithm computes the ideal result of the addition
or subtraction operation of the two inputs. The algorithm then type casts the result to
the output data type. Loss occurs during the type cast. This algorithm behaves
similarly to the C language except when the signedness of the operands does not
match. For example, when you add a signed long operand to an unsigned long
operand, standard C language rules convert the signed long operand to an unsigned
long operand. The result is a value that is not ideal.
54-177
54 Code Replacement Customization for Simulink Models in Embedded Coder
Programmatic Specification
Create a code replacement table file, as a MATLAB function, that describes the addition
or subtraction code replacement table entry. In the call to
setTflCOperationEntryParameters, set at least these parameters:
This example sets parameters for a code replacement operator entry for a cast-after-
operation implementation of a uint8 addition.
op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'EntryInfoAlgorithm', 'RTW_CAST_AFTER_OP', ...
'ImplementationName', 'u8_add_u8_u8');
Algorithm Classification
During code generation, the code generator examines addition and subtraction
operations, including adjacent type cast operations, to determine the type of algorithm to
compute the expression result. Based on the data types in the expression and the type of
the accumulator (type used to hold the result of the addition or subtraction operation),
the code generator uses these rules.
54-178
Addition and Subtraction Operator Code Replacement
Algorith Conditions
m
CBO One of the following is true:
Algorith Conditions
m
CBO At least one of the following is true:
54-179
54 Code Replacement Customization for Simulink Models in Embedded Coder
Algorith Conditions
m
CAO Net bias is zero and the data types in the expression have equal slope
adjustment factors. For more information on net bias, see “Addition” or
“Subtraction” in “Fixed-Point Operator Code Replacement” on page
55-149 (for MATLAB code) or “Fixed-Point Operator Code
Replacement” on page 54-204 (for Simulink models).
In many cases, the numerical result of a CBO operation is equal to that of a CAO
operation. For example, if the input and output types are such that the operation
produces the ideal result, as in the case of int8 + int8 —> int16. To maximize the
probability of code replacement occurring in such cases, set the algorithm to cast-after-
operation.
Limitations
• The code generator does not replace operations with nonzero net bias.
• When classifying an operation as a CAO operation, the code generator includes the
adjacent casts in the expression when the expression involves only fixed-point types.
Otherwise, the code generator classifies and replaces only the immediate addition or
subtraction operation. Casts that the code generator excludes from the classification
appear in the generated code.
• To enable the code generator to include multiple cast operations, which follow an
addition or subtraction of fixed-point data, in the classification of an expression, the
rounding mode must be simplest or floor. Consider the expression y=(cast A)
(cast B)(u1+u2). If the rounding mode of (cast A), (cast B), and the addition
operator (+) are set to simplest or floor, the code generator takes into account
(cast A) and (cast B) when classifying the expression and performing the
replacement only.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
54-180
See Also
54-181
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-182
Small Matrix Operation to Processor Code Replacement
argument is valid. The first table entry specifies [2 2] and the second table entry
specifies [3 3].
% Specify operands and result
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [2 2]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [2 2]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [2 2]);
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the getTflArgFromString
to create the arguments. The convenience methods setReturn and addArgument
specify whether an argument is a return value or argument and adds the argument to
the entry’s array of implementation arguments.
arg = getTflArgFromString(hTable, 'y2', 'void');
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);
addEntry(hTable, op_entry);
8 Create the entry for the second operator mapping.
54-183
54 Code Replacement Customization for Simulink Models in Embedded Coder
addEntry(hTable, op_entry);
9 Save the table definition file. Use the name of the table definition function to name
the file.
54-184
See Also
• On the Solver pane, select a fixed-step, discrete solver with a fixed-step size such
as 0.1.
• On the Code Generation pane, select an ERT-based system target file.
• On the Code Generation > Interface pane, select the code replacement library
that contains your addition operation entry.
4 In the Model Explorer, configure the Signal Attributes for the In1 and In2 source
blocks. For each source block, set Port dimensions to [3,3], and set Data type to
double. Apply the changes. Save the model.
5 Generate code and a code generation report.
6 Review the code replacements. The code generator replaces the + operator with
matrix_sum_3x3_double in the generated code.
7 Reconfigure Port dimensions for In1 and In2 to [2 2], regenerate code. Observe
that code containing the + operator is replaced with matrix_sum_2x2_double.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Matrix Multiplication Operation to MathWorks BLAS Code Replacement” on page
54-186
• “Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement” on page
54-194
• “Data Alignment for Code Replacement” on page 54-136
• “Remap Operator Output to Function Input” on page 54-201
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-185
54 Code Replacement Customization for Simulink Models in Embedded Coder
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Define the path for the BLAS function library. If your replacement functions are on
the MATLAB search path or are in your working folder, you can skip this step.
% Define library path for Windows or UNIX
arch = computer('arch');
if ~ispc
LibPath = fullfile('$(MATLAB_ROOT)', 'bin', arch);
else
% Use Stateflow to get the compiler info
compilerInfo = sf('Private','compilerman','get_compiler_info');
compilerName = compilerInfo.compilerName;
if strcmp(compilerName, 'msvc90') || ...
strcmp(compilerName, 'msvc80') || ...
strcmp(compilerName, 'msvc71') || ...
strcmp(compilerName, 'msvc60'), ...
compilerName = 'microsoft';
end
54-186
Matrix Multiplication Operation to MathWorks BLAS Code Replacement
54-187
54 Code Replacement Customization for Simulink Models in Embedded Coder
arg = RTW.TflArgCharConstant('TRANSA');
% Possible values for PassByType property are
% RTW_PASSBY_AUTO, RTW_PASSBY_POINTER,
% RTW_PASSBY_VOID_POINTER, RTW_PASSBY_BASE_POINTER
arg.PassByType = 'RTW_PASSBY_POINTER';
op_entry.Implementation.addArgument(arg);
arg = RTW.TflArgCharConstant('TRANSB');
arg.PassByType = 'RTW_PASSBY_POINTER';
op_entry.Implementation.addArgument(arg);
54-188
Matrix Multiplication Operation to MathWorks BLAS Code Replacement
op_entry.Implementation.addArgument(arg);
addEntry(hTable, op_entry);
54-189
54 Code Replacement Customization for Simulink Models in Embedded Coder
arg = RTW.TflArgCharConstant('TRANS');
arg.PassByType = 'RTW_PASSBY_POINTER';
54-190
Matrix Multiplication Operation to MathWorks BLAS Code Replacement
op_entry.Implementation.addArgument(arg);
addEntry(hTable, op_entry);
54-191
54 Code Replacement Customization for Simulink Models in Embedded Coder
10 Save the table definition file. Use the name of the table definition function to name
the file.
3 For each Product block, set the block parameter Multiplication to the value
Matrix(*).
4 Configure the model with the following settings:
• On the Solver pane, select a fixed-step, discrete solver with a fixed-step size such
as 0.1.
• On the Code Generation pane, select an ERT-based system target file.
• On the Code Generation > Interface pane, select the code replacement library
that contains your addition operation entry.
5 In the Model Explorer, configure the Signal Attributes for the In1, In2, and In3
source blocks. For In1 and In2, set Port dimensions to [3 3] and set the Data
type to double. For In3, set Port dimensions to [3 1] and set the Data type to
double.
6 Generate code and a code generation report.
7 Review the code replacements.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
54-192
See Also
54-193
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-194
Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement
54-195
54 Code Replacement Customization for Simulink Models in Embedded Coder
%
% Since CRLs do not have the ability to specify enums, you must
% use integer. (This will cause problems with C++ code generation,
% so for C++, use a wrapper function to cast each int to the
% corresponding enumeration type.)
%
% When a match occurs, the code generator computes the
% values for M, N, K, LDA, LDB, and LDC and insert them into the
% generated code.
54-196
Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement
addEntry(hTable, op_entry);
9 Create the entry for the second mapping.
% Create table entry for cblas_dgemv
op_entry = RTW.TflCBlasEntryGenerator;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 100, ...
'ImplementationName', 'cblas_dgemv', ...
'ImplementationHeaderFile', 'cblas.h', ...
'ImplementationHeaderPath', LibPath, ...
'AdditionalIncludePaths', {LibPath}, ...
'GenCallback', 'RTW.copyFileToBuildDir', ...
'SideEffects', true);
54-197
54 Code Replacement Customization for Simulink Models in Embedded Coder
addEntry(hTable, op_entry);
10 Save the table definition file. Use the name of the table definition function to name
the file.
54-198
See Also
• On the Solver pane, select a fixed-step, discrete solver with a fixed-step size such
as 0.1.
• On the Code Generation pane, select an ERT-based system target file.
• On the Code Generation > Interface pane, select the code replacement library
that contains your addition operation entry.
4 For each Product block, set the block parameter Multiplication to the value
Matrix(*).
5 In the Model Explorer, configure the Signal Attributes for the In1, In2, and In3
source blocks. For In1 and In2, set Port dimensions to [3 3]. Set the Data type
to double. For In3, set Port dimensions to [3 1]. Set the Data type to double.
6 Generate code and a code generation report.
7 Review the code replacements.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Small Matrix Operation to Processor Code Replacement” on page 54-182
• “Matrix Multiplication Operation to MathWorks BLAS Code Replacement” on page
54-186
• “Data Alignment for Code Replacement” on page 54-136
54-199
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-200
Remap Operator Output to Function Input
For example, for a sum operation, the code generator produces code similar to:
If you remap the output to the first input, the code generator produces code similar to:
The following table definition file for a sum operation remaps operator output y1 as the
first function input argument.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create an entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
54-201
54 Code Replacement Customization for Simulink Models in Embedded Coder
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the getTflArgFromString and
addConceptualArg functions to create and add the arguments.
arg = getTflArgFromString(hTable, 'y1', 'uint8');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(op_entry, arg);
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the getTflArgFromString
function to create the arguments. When defining the implementation function return
argument, create a new void output argument, for example, y2. When defining the
implementation function argument for the conceptual output argument (y1), set the
operator output argument as an additional input argument. Mark its IOType as
output. Make its type a pointer type. The convenience methods setReturn and
addArgument specify whether an argument is a return value or argument and adds
the argument to the entry’s array of implementation arguments.
% Create new void output y2
arg = getTflArgFromString(hTable, 'y2', 'void');
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);
% Set y1 as first input arg, mark IOType as output, and use pointer type
arg=getTflArgFromString(hTable, 'y1', 'uint8*');
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.addArgument(arg);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
54-202
See Also
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Develop a Code Replacement Library” on page 54-27
54-203
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-204
Fixed-Point Operator Code Replacement
createAndAddConceptualArg
function:
54-205
54 Code Replacement Customization for Simulink Models in Embedded Coder
createAndAddConceptualArg
function:
createAndAddConceptualArg
function:
54-206
Fixed-Point Operator Code Replacement
V = V% = SQ + B
•
V is an arbitrarily precise real-world value.
•
V% is the approximate real-world value that results from fixed-point representation.
•
Q is an integer that encodes V% , referred to as the quantized integer.
•
S is a coefficient of Q , referred to as the slope.
•
B is an additive correction, referred to as the bias.
The general equation for an operation between fixed-point operands is:
Addition
The operation V0 = V1 + V2 implies that
ÊS ˆ ÊS ˆ Ê B + B2 - B0 ˆ
Q0 = Á 1 ˜ Q1 + Á 2 ˜ Q2 + Á 1 ˜
Ë S0 ¯ Ë S0 ¯ Ë S0 ¯
If an addition replacement function is defined such that the scaling on the operands and
sum are equal and the net bias
54-207
54 Code Replacement Customization for Simulink Models in Embedded Coder
Ê B1 + B2 - B0 ˆ
Á ˜
Ë S0 ¯
is zero (for example, a function s8_add_s8_s8 that adds two signed 8-bit values and
produces a signed 8-bit result), then the operator entry must set the operator entry
parameters SlopesMustBeTheSame and MustHaveZeroNetBias to true. To match for
replacement, the slopes must be the same for all addition conceptual arguments. (For
parameter descriptions, see the reference page for the function
setTflCOperationEntryParameters.)
Subtraction
The operation V0 = V1 − V2 implies that
ÊS ˆ ÊS ˆ Ê B1 - B2 - B0 ˆ
Q0 = Á 1 ˜ Q1 - Á 2 ˜ Q2 + Á ˜
Ë S0 ¯ Ë S0 ¯ Ë S0 ¯
If a subtraction replacement function is defined such that the scaling on the operands and
difference are equal and the net bias
Ê B1 - B2 - B0 ˆ
Á ˜
Ë S0 ¯
is zero (for example, a function s8_sub_s8_s8 that subtracts two signed 8-bit values and
produces a signed 8-bit result), then the operator entry must set the operator entry
parameters SlopesMustBeTheSame and MustHaveZeroNetBias to true. To match for
replacement, the slopes must be the same for all subtraction conceptual arguments. (For
parameter descriptions, see the reference page for the function
setTflCOperationEntryParameters.)
Multiplication
There are different ways to specify multiplication replacements. The most direct way is to
specify an exact match of the input and output types. This is feasible if a model contains
only a few (known) slope and bias combinations. Use the TflCOperationEntry class
and specify the exact values of slope and bias on each argument. For scenarios where
54-208
Fixed-Point Operator Code Replacement
there are numerous slope/bias combinations, it is not feasible to specify each value with a
different entry. Use a net slope entry or create a custom entry.
It is common to replace all multiplication operations that have a net slope of 1.0 with a
function that performs C-style multiplication. For example, to replace all signed 8-bit
multiplications that have a net scaling of 1.0 with the s8_mul_s8_u8_ replacement
function, the operator entry must define a net slope factor, F2E. You specify the values for
F and E using operator entry parameters NetSlopeAdjustmentFactor and
NetFixedExponent. For the s8_mul_s8_u8 function, set
NetSlopeAdjustmentFactor to 1 and NetFixedExponent to 0.0. Also, set the
operator entry parameters SlopesMustBeTheSame and MustHaveZeroNetBias to
true. To match for replacement, the biases must be zero for all multiplication conceptual
arguments. (For parameter descriptions, see the reference page for the function
setTflCOperationEntryParameters.)
Division
There are different ways to specify division replacements. The most direct way is to
specify an exact match of the input and output types. This is feasible if a model contains
only a few (known) slope and bias combinations. For this, use the TflCOperationEntry
class and specify the exact values of slope and bias on each argument. For scenarios
where there are numerous slope/bias combinations, it is not feasible to specify each value
with a different entry. For this, use a net slope entry or create a custom entry (see
“Customize Match and Replacement Process” on page 54-159).
54-209
54 Code Replacement Customization for Simulink Models in Embedded Coder
ÊSQ ˆ
S0Q0 = Á 1 1 ˜
Ë S2Q2 ¯
ÊQ ˆ
Q0 = S n Á 1 ˜
Ë Q2 ¯
It is common to replace all division operations that have a net slope of 1.0 with a function
that performs C-style division. For example, to replace all signed 8-bit divisions that have
a net scaling of 1.0 with the s8_mul_s8_u8_ replacement function, the operator entry
must define a net slope factor, F2E. You specify the values for F and E using operator
entry parameters NetSlopeAdjustmentFactor and NetFixedExponent. For the
s16_netslope0p5_div_s16_s16 function, you would set
NetSlopeAdjustmentFactor to 1 and NetFixedExponent to 0.0. Also, set the
operator entry parameters SlopesMustBeTheSame and MustHaveZeroNetBias to
true. To match for replacement, the biases must be zero for all division conceptual
arguments. (For parameter descriptions, see the reference page for the function
setTflCOperationEntryParameters.)
ÊS ˆ
Q0 = Á 1 ˜ Q1
Ë S0 ¯
Q0 = S nQ1
where Sn is the net slope. Set the operator entry parameters SlopesMustBeTheSame and
MustHaveZeroNetBias to true. To match for replacement, the biases must be zero for
54-210
See Also
all cast conceptual arguments. (For parameter descriptions, see the reference page for
the function setTflCOperationEntryParameters.)
Shift
The shift left or shift right operation V0 = (V1 / 2n) implies, for binary-point-only scaling,
that
ÊSQ ˆ
S0Q0 = Á 1 n 1 ˜
Ë 2 ¯
Ê S ˆ ÊQ ˆ
Q0 = Á 1 ˜ + Á n1 ˜
Ë S0 ¯ Ë 2 ¯
ÊQ ˆ
Q0 = S n Á n1 ˜
Ë2 ¯
where Sn is the net slope. Set the operator entry parameters SlopesMustBeTheSame and
MustHaveZeroNetBias to true. To match for replacement, the biases must be zero for
all shift conceptual arguments. (For parameter descriptions, see the reference page for
the function setTflCOperationEntryParameters.)
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Binary-Point-Only Scaling Code Replacement” on page 54-213
• “Slope Bias Scaling Code Replacement” on page 54-217
• “Net Slope Scaling Code Replacement” on page 54-221
• “Equal Slope and Zero Net Bias Code Replacement” on page 54-228
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 54-232
• “Shift Left Operations and Code Replacement” on page 54-236
54-211
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-212
Binary-Point-Only Scaling Code Replacement
This example creates a code replacement entry for multiplication of fixed-point data
types. You specify arguments using binary-point-only scaling. The example defines the
function mapping programmatically. Alternatively, you can use the Code Replacement
Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as multiplication, the saturation mode as saturate on integer overflow,
rounding modes as unspecified, and the name of the replacement function as
s32_mul_s16_s16_binarypoint.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 90, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'}, ...
'ImplementationName', 's32_mul_s16_s16_binarypoint', ...
'ImplementationHeaderFile', 's32_mul_s16_s16_binarypoint.h', ...
'ImplementationSourceFile', 's32_mul_s16_s16_binarypoint.c');
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call. Each argument specifies that the data type is fixed-point, the mode is
binary-point-only scaling, and its derived slope and bias values must exactly match
the call-site slope and bias values. The output argument is 32 bits, signed, with a
54-213
54 Code Replacement Customization for Simulink Models in Embedded Coder
fraction length of 28. The input arguments are 16 bits, signed, with fraction lengths
of 15 and 13.
createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', true, ...
'WordLength', 32, ...
'FractionLength', 28);
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the
createAndSetCImplementationReturn and
createAndAddImplementationArg functions to create and add implementation
arguments to the entry. Implementation arguments must describe fundamental
numeric data types (not fixed-point data types). In this case, the output argument is
32 bits and signed (int32). The input arguments are 16 bits and signed (int16).
createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', true, ...
'WordLength', 32, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
54-214
Binary-Point-Only Scaling Code Replacement
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
54-215
54 Code Replacement Customization for Simulink Models in Embedded Coder
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Fixed-Point Operator Code Replacement” on page 54-204
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 54-232
• “Shift Left Operations and Code Replacement” on page 54-236
• “Data Alignment for Code Replacement” on page 54-136
• “Remap Operator Output to Function Input” on page 54-201
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-216
Slope Bias Scaling Code Replacement
This example creates a code replacement entry for division of fixed-point data types. You
specify arguments using slope bias scaling. The example defines the function mapping
programmatically. Alternatively, you can use the Code Replacement Tool to define the
same mapping.
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_fixed_s16divslopebias
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as division, the saturation mode as saturate on integer overflow, rounding
modes as round to ceiling, and the name of the replacement function as
s16_div_s16_s16_slopebias.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_DIV', ...
'Priority', 90, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_CEILING'}, ...
'ImplementationName', 's16_div_s16_s16_slopebias', ...
'ImplementationHeaderFile', 's16_div_s16_s16_slopebias.h', ...
'ImplementationSourceFile', 's16_div_s16_s16_slopebias.c');
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call. Each argument specifies that the data type is fixed-point, the mode is
slope bias scaling, and its specified slope and bias values must exactly match the call-
site slope and bias values. The output argument and input arguments are 16 bits,
signed, each with specific slope bias specifications.
54-217
54 Code Replacement Customization for Simulink Models in Embedded Coder
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
54-218
Slope Bias Scaling Code Replacement
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
54-219
54 Code Replacement Customization for Simulink Models in Embedded Coder
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Fixed-Point Operator Code Replacement” on page 54-204
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 54-232
• “Shift Left Operations and Code Replacement” on page 54-236
• “Data Alignment for Code Replacement” on page 54-136
• “Remap Operator Output to Function Input” on page 54-201
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-220
Net Slope Scaling Code Replacement
This example creates a code replacement entry for division of fixed-point data types,
using wrap on overflow saturation mode and a net slope. The example defines the
function mapping programmatically. Alternatively, you can use the Code Replacement
Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntryGenerator_Netslope function, which provides access
to the fixed-point parameters NetSlopeAdjustmentFactor and
NetFixedExponent.
wv = [16,32];
for iy = 1:2
for inum = 1:2
for iden = 1:2
hTable = getDivOpEntry(hTable, ...
fixdt(1,wv(iy)),fixdt(1,wv(inum)),fixdt(1,wv(iden)));
end
end
end
%---------------------------------------------------------
function hTable = getDivOpEntry(hTable,dty,dtnum,dtden)
%---------------------------------------------------------
% Create an entry for division of fixed-point data types where
% arguments are specified using Slope and Bias scaling
% Saturation on, Rounding unspecified
funcStr = sprintf('user_div_%s_%s_%s',...
typeStrFunc(dty),...
typeStrFunc(dtnum),...
typeStrFunc(dtden));
54-221
54 Code Replacement Customization for Simulink Models in Embedded Coder
op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as division, the saturation mode as wrap on overflow, rounding modes as
unspecified, and the name of the replacement function as user_div_*.
NetSlopeAdjustmentFactor and NetFixedExponent specify the F and E parts of
the net slope F2E.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_DIV', ...
'Priority', 90, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW',...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'},...
'NetSlopeAdjustmentFactor', 1.0, ...
'NetFixedExponent', 0.0, ...
'ImplementationName', funcStr, ...
'ImplementationHeaderFile', [funcStr,'.h'], ...
'ImplementationSourceFile', [funcStr,'.c']);
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call. Specify each argument as fixed-point and signed. Also, for each
argument, specify that code replacement request processing does not check for an
exact match to the call-site slope and bias values.
createAndAddConceptualArg(op_entry, ...
'RTW.TflArgNumeric', ...
'Name', 'y1',...
'IOType', 'RTW_IO_OUTPUT',...
'CheckSlope', false,...
'CheckBias', false,...
'DataTypeMode', 'Fixed-point: slope and bias scaling',...
'IsSigned', dty.Signed,...
'WordLength', dty.WordLength,...
'Bias', 0);
createAndAddConceptualArg(op_entry, ...
'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT',...
'CheckSlope', false,...
'CheckBias', false,...
'DataTypeMode', 'Fixed-point: slope and bias scaling',...
'IsSigned', dtnum.Signed,...
'WordLength', dtnum.WordLength,...
'Bias', 0);
createAndAddConceptualArg(op_entry, ...
'RTW.TflArgNumeric', ...
'Name', 'u2', ...
54-222
Net Slope Scaling Code Replacement
'IOType', 'RTW_IO_INPUT',...
'CheckSlope', false,...
'CheckBias', false,...
'DataTypeMode', 'Fixed-point: slope and bias scaling',...
'IsSigned', dtden.Signed,...
'WordLength', dtden.WordLength,...
'Bias', 0);
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the getTflArgFromString
function to create the arguments. Implementation arguments must describe
fundamental numeric data types (not fixed-point data types). The convenience
methods setReturn and addArgument specify whether an argument is a return
value or argument. These methods add the argument to the entry array of
implementation arguments.
arg = getTflArgFromString(hTable, 'y1', typeStrBase(dty));
op_entry.Implementation.setReturn(arg);
addEntry(hTable, op_entry);
8 Define functions that determine the data type word length.
%-------------------------------------------------------------
function str = typeStrFunc(dt)
%-------------------------------------------------------------
if dt.Signed
sstr = 's';
else
sstr = 'u';
end
str = sprintf('%s%d',sstr,dt.WordLength);
%-------------------------------------------------------------
function str = typeStrBase(dt)
%-------------------------------------------------------------
if dt.Signed
sstr = ;
else
sstr = 'u';
end
str = sprintf('%sint%d',sstr,dt.WordLength);
54-223
54 Code Replacement Customization for Simulink Models in Embedded Coder
9 Save the table definition file. Use the name of the table definition function to name
the file.
This example creates a code replacement entry for division of fixed-point data types,
using the ceiling rounding mode and a net slope scaling factor. The example defines the
function mapping programmatically. Alternatively, you can use the Code Replacement
Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntryGenerator_Netslope function, which provides access
to the fixed-point parameters NetSlopeAdjustmentFactor and
NetFixedExponent.
op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as division, the saturation mode as saturation off, rounding modes as round
to ceiling, and the name of the replacement function as s16_div_s16_s16.
NetSlopeAdjustmentFactor and NetFixedExponent specify the F and E parts of
the relative scaling factor F2E.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_DIV', ...
'Priority', 90, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_CEILING'}, ...
'NetSlopeAdjustmentFactor', 1.0, ...
'NetFixedExponent', 0.0, ...
54-224
Net Slope Scaling Code Replacement
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call. Specify each argument as fixed-point, 16 bits, and signed. Also, for each
argument, specify that code replacement request processing does not check for an
exact match to the call-site slope and bias values.
createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataType', 'Fixed', ...
'IsSigned', true, ...
'WordLength', 16);
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the
createAndSetCImplementationReturn and
createAndAddImplementationArg functions to create and add implementation
arguments to the entry. Implementation arguments must describe fundamental
numeric data types (not fixed-point data types). In this case, the output and input
arguments are 16 bits and signed (int16).
createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
54-225
54 Code Replacement Customization for Simulink Models in Embedded Coder
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
54-226
See Also
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Fixed-Point Operator Code Replacement” on page 54-204
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 54-232
• “Shift Left Operations and Code Replacement” on page 54-236
• “Data Alignment for Code Replacement” on page 54-136
• “Remap Operator Output to Function Input” on page 54-201
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-227
54 Code Replacement Customization for Simulink Models in Embedded Coder
This example creates a code replacement entry for addition of fixed-point data types.
Slopes must be equal and net bias must be zero across the operator inputs and output.
The example defines the function mapping programmatically. Alternatively, you can use
the Code Replacement Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_fixed_slopeseq_netbiaszero
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntryGenerator function, which provides access to the fixed-
point parameters SlopesMustBeTheSame and MustHaveZeroNetBias.
op_entry = RTW.TflCOperationEntryGenerator;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as addition, the saturation mode as saturation off, rounding modes as
unspecified, and the name of the replacement function as
u16_add_SameSlopeZeroBias. SlopesMustBeTheSame and
MustHaveZeroNetBias are set to true, indicating that slopes must be equal and
net bias must be zero across the addition inputs and output.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 90, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'}, ...
'SlopesMustBeTheSame', true, ...
'MustHaveZeroNetBias', true, ...
'ImplementationName', 'u16_add_SameSlopeZeroBias', ...
'ImplementationHeaderFile', 'u16_add_SameSlopeZeroBias.h', ...
'ImplementationSourceFile', 'u16_add_SameSlopeZeroBias.c');
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
54-228
Equal Slope and Zero Net Bias Code Replacement
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the
createAndSetCImplementationReturn and
createAndAddImplementationArg functions to create and add implementation
arguments to the entry. Implementation arguments must describe fundamental
numeric data types (not fixed-point data types). In this case, the output and input
arguments are 16 bits and unsigned (uint16).
createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', false, ...
'WordLength', 16, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 16, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
54-229
54 Code Replacement Customization for Simulink Models in Embedded Coder
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
• Verify that Output data type is set to its default, Inherit via internal
rule.
• Set Integer rounding mode to Zero.
4 Configure the model with the following settings:
54-230
See Also
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Fixed-Point Operator Code Replacement” on page 54-204
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 54-232
• “Shift Left Operations and Code Replacement” on page 54-236
• “Data Alignment for Code Replacement” on page 54-136
• “Remap Operator Output to Function Input” on page 54-201
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-231
54 Code Replacement Customization for Simulink Models in Embedded Coder
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as cast, the saturation mode as saturate on integer overflow, rounding
modes as toward negative infinity, and the name of the replacement function as
my_sat_cast.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_CAST', ...
'Priority', 50, ...
'ImplementationName', 'my_sat_cast', ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_FLOOR'}, ...
'ImplementationHeaderFile', 'some_hdr.h', ...
'ImplementationSourceFile', 'some_hdr.c');
54-232
Data Type Conversions (Casts) and Operator Code Replacement
This example creates a code replacement entry to replace data type conversions (casts) of
fixed-point data types by using a net slope. The example defines the function mapping
programmatically. Alternatively, you can use the Code Replacement Tool to define the
same mapping.
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_cast_fixpt_net_slope
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntryGenerator_Netslope function, which provides access
to the fixed-point parameters NetSlopeAdjustmentFactor and
NetFixedExponent
op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
54-233
54 Code Replacement Customization for Simulink Models in Embedded Coder
54-234
See Also
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the
createAndSetCImplementationReturn and
createAndAddImplementationArg functions to create and add implementation
arguments to the entry. Implementation arguments must describe fundamental
numeric data types (not fixed-point data types).
createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', OutSgn, ...
'WordLength', OutWL, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', InSgn, ...
'WordLength', InWL, ...
'FractionLength', 0);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Fixed-Point Operator Code Replacement” on page 54-204
• “Shift Left Operations and Code Replacement” on page 54-236
• “Data Alignment for Code Replacement” on page 54-136
• “Remap Operator Output to Function Input” on page 54-201
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-235
54 Code Replacement Customization for Simulink Models in Embedded Coder
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as shift left and the name of the replacement function as my_shift_left.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_SL', ...
'Priority', 50, ...
'ImplementationName', 'my_shift_left', ...
'ImplementationHeaderFile', 'some_hdr.h', ...
'ImplementationSourceFile', 'some_hdr.c');
54-236
Shift Left Operations and Code Replacement
6 Create the int16 argument as conceptual and implementation argument u1. This
example uses calls to the getTflArgFromString and addConceptualArg
functions to create the conceptual argument and add it to the entry. Convenience
method addArgument specifies the argument as an implementation input argument.
arg = getTflArgFromString(hTable, 'u1', 'int16');
addConceptualArg(op_entry, arg);
op_entry.Implementation.addArgument(arg);
7 Create the int8 argument as conceptual and implementation argument u2. This
example uses calls to the getTflArgFromString and addConceptualArg
functions to create the conceptual argument and add it to the entry. This argument
specifies the number of bits to shift the previous input argument. Because the
argument type is not relevant, the example disables type checking by setting the
CheckType property to false. Convenience method addArgument specifies the
argument as implementation input argument.
arg = getTflArgFromString(hTable, 'u2', 'int8');
arg.CheckType = false;
addConceptualArg(op_entry, arg);
op_entry.Implementation.addArgument(arg);
addEntry(hTable, op_entry);
• Save the table definition file. Use the name of the table definition function to name the
file.
This example creates a code replacement entry to replace shift left operations for fixed-
point data using a net slope. The example defines the function mapping programmatically.
Alternatively, you can use the Code Replacement Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
54-237
54 Code Replacement Customization for Simulink Models in Embedded Coder
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntryGenerator_Netslope function. This function provides
access to the fixed-point parameters NetSlopeAdjustmentFactor and
NetFixedExponent.
op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as shift left, the saturation mode as saturate on integer overflow, rounding
modes as toward negative infinity, and the name of the replacement function as
my_fxp_shift_left. NetSlopeAdjustmentFactor and NetFixedExponent
specify the F and E parts of the net slope F2E.
InFL = 2;
InWL = 16;
InSgn = true;
OutFL = 4;
OutWL = 32;
OutSgn = true;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_SL', ...
'Priority', 50, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_FLOOR'}, ...
'NetSlopeAdjustmentFactor', 1.0, ...
'NetFixedExponent', (OutFL - InFL),...
'ImplementationName', 'my_fxp_shift_left', ...
'ImplementationHeaderFile', 'some_hdr.h', ...
'ImplementationSourceFile', 'some_hdr.c');
5 Create conceptual arguments y1 and u1. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call. Each argument is specified as fixed-point and signed. Each argument
specifies that code replacement request processing does not check for an exact
match to the call-site slope and bias values.
createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', OutSgn, ...
'WordLength', OutWL, ...
'FractionLength',OutFL);
54-238
Shift Left Operations and Code Replacement
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the
createAndSetCImplementationReturn and
createAndAddImplementationArg functions to create and add implementation
arguments to the entry. Implementation arguments must describe fundamental
numeric data types (not fixed-point data types).
createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', OutSgn, ...
'WordLength', OutWL, ...
'FractionLength', 0);
7 Create the int8 argument as conceptual and implementation argument u2. This
example uses calls to the getTflArgFromString and addConceptualArg
functions to create the conceptual argument and add it to the entry. This argument
specifies the number of bits to shift the previous input argument. Because the
argument type is not relevant, type checking is disabled by setting the CheckType
property to false. Convenience method addArgument specifies the argument as
implementation input argument.
arg = getTflArgFromString(hTable, 'u2', 'uint8');
arg.CheckType = false;
addConceptualArg(op_entry, arg);
op_entry.Implementation.addArgument(arg);
8 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
9 Save the table definition file. Use the name of the table definition function to name
the file.
54-239
54 Code Replacement Customization for Simulink Models in Embedded Coder
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Fixed-Point Operator Code Replacement” on page 54-204
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 54-232
• “Data Alignment for Code Replacement” on page 54-136
• “Remap Operator Output to Function Input” on page 54-201
• “Customize Match and Replacement Process” on page 54-159
• “Develop a Code Replacement Library” on page 54-27
54-240
55
55-2
What Is Code Replacement Customization?
1 Creates and partially populates a code replacement entry object with the function or
operator name or key and conceptual arguments.
2 Uses the entry object to query the configured code replacement library for a
conceptual representation match. The code generator searches the tables in a code
replacement library for a match in the order that the tables appear in the library.
When searching for a match, the code generator takes into account:
55-3
55 Code Replacement Customization for MATLAB Code
4 Uses the C or C++ replacement function prototype in the code replacement object to
generate code.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Develop a Code Replacement Library” on page 55-15
• “Quick Start Library Development” on page 55-16
• “What Is Code Replacement?” (MATLAB Coder)
55-4
Code You Can Replace from MATLAB Code
In this section...
“Math Functions” on page 55-5
“Memory Functions” on page 55-10
“Operators” on page 55-10
Math Functions
When generating C/C++ code from MATLAB code, depending on code replacement
libraries available in your development environment, you can configure the code
generator to replace instances of the following math functions with application-specific
implementations.
55-5
55 Code Replacement Customization for MATLAB Code
55-6
Code You Can Replace from MATLAB Code
55-7
55 Code Replacement Customization for MATLAB Code
55-8
Code You Can Replace from MATLAB Code
55-9
55 Code Replacement Customization for MATLAB Code
Memory Functions
Depending on code replacement libraries available in your development environment, you
can configure the code generator to replace instances of the following memory functions
with application-specific implementations.
Some target processors provide optimized functions to set memory to zero. Use the code
replacement library programming interface to replace the memset2zero function with
more efficient target-specific functions.
Operators
When generating C/C++ code from MATLAB code, depending on code replacement
libraries available in your development environment, you can configure the code
55-10
Code You Can Replace from MATLAB Code
Mixed data type support indicates you can specify different data types of different inputs.
55-11
55 Code Replacement Customization for MATLAB Code
55-12
Code You Can Replace from MATLAB Code
55-13
55 Code Replacement Customization for MATLAB Code
See Also
More About
• “Develop a Code Replacement Library” on page 55-15
• “Quick Start Library Development” on page 55-16
• “What Is Code Replacement?” (MATLAB Coder)
55-14
Develop a Code Replacement Library
To experiment with the process and tools, see “Quick Start Library Development” on page
55-16.
See Also
More About
• “Identify Code Replacement Requirements” on page 55-25
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Quick Start Library Development” on page 55-16
• “What Is Code Replacement Customization?” on page 55-3
55-15
55 Code Replacement Customization for MATLAB Code
Prerequisites
• MATLAB
• MATLAB Coder
• Embedded Coder
• C compiler
1 In the Code Replacement Tool window, select File > New table.
2 In the right pane, name the table crl_table_sinfcn and click Apply. Later, when
you save the table, the tool saves it with the file name crl_table_sinfcn.m.
55-16
Quick Start Library Development
Create a table entry that maps a sin function with double input and double output to a
custom implementation function.
1 In the left pane, select table crl_table_sinfcn. Then, select File > New entry >
Function. The new entry appears in the middle pane, initially without a name.
2 In the middle pane, select the new entry.
3 In the right pane, on the Mapping Information tab, from the Function menu,
select sin.
4 Leave Algorithm set to Unspecified, and leave parameters in the Conceptual
function group set to default values.
5 In the Replacement function group, name the replacement function sin_dbl.
6 Leave the remaining parameters in the Replacement function group set to default
values.
7 Click Apply. The tool updates the Function signature preview to reflect the
specified replacement function name.
55-17
55 Code Replacement Customization for MATLAB Code
8 Scroll to the bottom of the Mapping Information tab and click Validate entry. The
tool validates your entry.
55-18
Quick Start Library Development
55-19
55 Code Replacement Customization for MATLAB Code
1 On the Build Information tab, for the Implementation header file parameter,
enter sin_dbl.h.
2 Leave the remaining parameters set to default values.
3 Click Apply.
4 Optionally, you can revalidate the entry. Return to the Mapping Information tab
and click Validate entry.
Create an entry that maps a sin function with single input and double output to a
custom implementation function named sin_sgl. Create the entry by copying and
pasting the sin_dbl entry.
55-20
Quick Start Library Development
2 If the tool reports errors, fix them, and rerun the validation. Repeat fixing and
validating errors until the tool does not report errors. The following figure shows a
validation report.
Save the code replacement table to a MATLAB file in your working folder. Select File >
Save table. By default, the tool uses the table name to name the file. For this example,
the tool saves the table in the file crl_table_sinfcn.m.
Consider reviewing the MATLAB code for your code replacement table definition. After
using the tool to create an initial version of a table definition file, you can update,
enhance, or copy the file in a text editor.
To review it, in MATLAB or another text editor, open the file crl_table_sinfcn.m.
Before you can use your code replacement table, you must register it as part of a code
replacement library. Use the Code Replacement Tool to generate a registration file.
1 In the Code Replacement Tool, select File > Generate registration file.
2 In the Generate registration file dialog box, edit the dialog box fields to match the
following figure, and then click OK.
55-21
55 Code Replacement Customization for MATLAB Code
3 In the Select location to save the registration file dialog box, specify a location
for the registration file. The location must be on the MATLAB path or in the current
working folder. Save the file. The tool saves the file as rtwTargetInfo.m.
RTW.TargetRegistry.getInstance('reset');
Apply your code replacement library. Verify that the code generator makes code
replacements that you expect.
1 Check for errors. At the command line, invoke the table definition file . For example:
tbl = crl_table_sinfcn
tbl =
Version: '1.0'
ReservedSymbols: []
StringResolutionMap: []
AllEntries: [2x1 RTW.TflCFunctionEntry]
EnableTrace: 1
If an error exists in the definition file, the invocation triggers a message to appear.
Fix the error and try again.
2 Use the Code Replacement Viewer to check your code replacement entries. For
example:
In the viewer, select entries in your table and verify that the content is what you
expect. The viewer can help you detect issues such as:
55-22
Quick Start Library Development
function y = my_sin_fnc(x)
y = sin(x);
end
4 Open the MATLAB Coder app.
5 Add the function that includes a call to the sin function as an entry-point file. For
example, add my_sin_func.m. The app creates a project named my_sin_func.prj.
6 Click Next to go to the Define Input Type step. Define the types for the entry-point
function inputs.
7 Click Next to go to the Check for Run-Time Issues step. This step is optional.
However, it is a best practice to perform this step. Provide a test file that calls your
entry-point function. The app generates a MEX function from your entry-point
function. Then, the app runs the test file, replacing calls to the MATLAB function with
calls to the generated MEX function.
8 Click Next to go to the Generate Code step. To open the Generate dialog box, click
the Generate arrow .
9 Set Build type to generate a library or executable.
10 Click More Settings.
11 Configure the code generator to use your code replacement library. On the Custom
Code tab, set the Code replacement library parameter to the name of your library.
For example, Sin Function Example.
12 Configure the code generation report. On the Debugg tab, set the Always create a
code generation report, Code replacements, and Automatically launch a
report if one is generated parameters.
13 Configure the code generator to generate code only. For Build type, select Source
code. You want to review your code replacements in the generated code before
building an executable.
14 Click Generate to generate C code and a report.
15 Review code replacement results in the Code Replacements Report section of the
code generation report.
The report indicates that the code generator found a match and applied the
replacement code for the function sin_dbl.
55-23
55 Code Replacement Customization for MATLAB Code
16 Review the code replacements. In the report, click the MATLAB function that
triggered the replacement, my_sin_func.m. The MATLAB Editor opens and
highlights the function call that triggers the code replacement.
See Also
More About
• “Develop a Code Replacement Library” on page 55-15
• “What Is Code Replacement Customization?” on page 55-3
55-24
Identify Code Replacement Requirements
• Math operation
• Function
• BLAS operation
• CBLAS operation
• Net slope fixed-point operation
• Semaphore or mutex functions
• Do you want to change the inline or nonfinite behavior for functions?
• What specific functions and operations do you want to replace?
• What input and output arguments does the function or operator that you are replacing
take? For each argument, what is the data type, complexity, and dimensionality?
• What does the prototype for your replacement code look like?
55-25
55 Code Replacement Customization for MATLAB Code
55-26
See Also
• Do you need to specify data alignment for the library? What data alignments are
required? For each specification, what type of alignment is required and for what
programming language?
See Also
Related Examples
• “Develop a Code Replacement Library” on page 55-15
• “Prepare for Code Replacement Library Development” on page 55-28
• “What Is Code Replacement Customization?” on page 55-3
• “Code You Can Replace from MATLAB Code” on page 55-5
55-27
55 Code Replacement Customization for MATLAB Code
• Common entries
• Entries for TI devices
• Entries for TI C6xx devices
• Entries specific to the TI C67x device
• If support files, such as header files, additional source files, and dynamically linked
libraries are not in your current working folder, note their location. You need to specify
the paths for such files.
Next, based on your requirements and preparation, define code replacement mappings.
See Also
More About
• “Identify Code Replacement Requirements” on page 55-25
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Develop a Code Replacement Library” on page 55-15
• “What Is Code Replacement Customization?” on page 55-3
55-28
Define Code Replacement Mappings
Situation Approach
Defining mappings for the first Code Replacement Tool.
time.
Rapid prototyping mappings. Code Replacement Tool to quickly generate, register,
and test mappings.
Developing a mapping as a Code Replacement Tool to generate definition code
template or starting point for that you can copy and modify.
defining similar mappings.
Modifying a registration file, MATLAB Editor to update the programming interface
including copying and pasting directly.
content.
Defining mappings that specify Programming interface.
attributes not available from the
Code Replacement Tool (for
example, sets of algorithm
parameters).
Reusing existing code for new Programming interface.
mappings by copying, pasting,
and editing existing mappings.
55-29
55 Code Replacement Customization for MATLAB Code
An Embedded Coder license is not required to create a custom code replacement library.
However, you must have an Embedded Coder license to use a such a library.
By default, the tool displays, left to right, a root pane, a list pane, and a dialog pane. You
can manipulate the display:
• Drag boundaries to widen, narrow, shorten, or lengthen panes, and to resize table
columns.
• Select View > Show dialog pane to hide or display the right-most pane.
• Click a table column heading to sort the table based on contents of the selected
column.
• Right-click a table column heading and select Hide to remove the column from the
display. (You cannot hide the Name column.)
1 In the Code Replacement Tool window, select File > New table.
2 In the right pane, name the table and click Apply. Later, when you save the table, the
tool uses the table name that you specify to name the file. For example, if you enter
the name my_sinfcn, the tool names the file my_sinfcn.m.
55-30
Define Code Replacement Mappings
Create one or more table entries. Each entry maps the conceptual representation of a
function or operator to your implementation representation. The information that you
enter depends on the type of entry you create. Enter the following information:
1 In the left pane, select the table to which you want to add the entry.
2 Select File > New entry > entry-type, where entry-type is one of:
• Math Operation
• Function
• BLAS Operation
• CBLAS Operation
• Net Slope Fixed-Point Operation
• Semaphore entry
• Customization entry
The new entry appears in the middle pane, initially without a name.
3 In the middle pane, select the new entry.
4 In the right pane, on the Mapping Information tab, from the Function or
Operation menu, select the function or operation that you want the code generator
to replace. Regardless of the entry type, make a selection from this menu. Your
selection determines what other information you specify.
Except for customization entries, you also specify information for your replacement
function prototype. You can also specify implementation attributes, such as the
rounding modes to apply.
5 If prompted, specify additional entry information that you want the code generator to
use when searching for a match. For example, when you select an addition or
subtraction operation, the tool prompts you to specify an algorithm (Cast before
operation or Cast after operation).
6 Review the conceptual argument information that the tool populates for the function
or operation. Conceptual input and output arguments represent arguments for the
function or operator being replaced. Conceptual arguments observe naming
conventions ('y1', 'u1', 'u2', ...) and data types familiar to the code generator.
55-31
55 Code Replacement Customization for MATLAB Code
When validating the entry, the code generator validates that each conceptual
argument has an I/O type that is compatible with the argument name. For example,
an input must have IOType of RTW_IO_INPUT.
If you do not want the data types for your implementation to be the same as the
conceptual argument types, clear the Make the conceptual and implementation
argument types the same check box. For example, most ANSI-C functions operate
on and return double data. Clear the check box if want to map a conceptual
representation of the function to an implementation representation that specifies an
argument and return value. For example, clear the check box to map the conceptual
representation of the function sin to an implementation representation that specifies
an argument and return value of type single (single sin(single)), of type
double (double sin(double). In this case, the code generator produces the
following code:
y = (single) sin(u1);
If you select Custom for a function entry, specify only conceptual argument
information.
7 Specify the name and argument information for your replacement function. As you
enter the information and click Apply, the tool updates the Function signature
preview.
When validating the entry, the code generator validates that each implementation
argument has an I/O type that is compatible with the conceptual argument to which it
is mapped. For example, an conceptual argument of type RTW_IO_OUTPUT requires a
compatible implementation argument of type RTW_IO_OUTPUT or
RTW_IO_INPUT_OUTPUT. The default I/O type is RTW_IO_INPUT.
8 Specify additional implementation attributes that apply. For example, depending on
the type and name of the entry that you specify, the tool prompts you to specify:
The Code Replacement Tool provides a way to validate the syntax of code replacement
tables and table entries as you define them. If the tool finds validation errors, you can
55-32
Define Code Replacement Mappings
address them and retry the validation. Repeat the process until the tool does not report
errors.
To Do
Validate table entries Select an entry, scroll to the bottom of the Mapping
Information tab, and click Validate entry.
Alternatively, select one or more entries, right-click, and
select Validate entries.
Validate a table Select the table. Then, select Actions > Validate table.
Save a Table
If you open multiple tables, you can manage the tables together. For example, use the tool
to:
55-33
55 Code Replacement Customization for MATLAB Code
• Modifying tables that you create with the Code Replacement Tool.
• Defining mappings for specialized entries that you cannot create with the Code
Replacement Tool.
• Replicating and modifying similar entries and tables.
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_sinfcn()
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
For each function or operator that you want the code generator to replace, map a
conceptual representation of the function or operator to an implementation
representation as a table entry.
1 Within the body of a table definition file, create a code replacement entry object. Call
one of the following functions.
55-34
Define Code Replacement Mappings
For example:
hEnt = RTW.TflCFunctionEntry;
You can combine steps of creating the entry, setting entry parameters, creating
conceptual and implementation arguments, and adding the entry to a table with a single
function call to registerCFunctionEntry, registerCPPFunctionEntry, or
registerCPromotableMacroEntry if you are creating an entry for a function and the
function implementation meets the following criteria:
• Implementation argument names and order match the names and order of
corresponding conceptual arguments.
• Input arguments are of the same type.
• The return and input argument names follow the code generator’s default naming
conventions:
For example:
55-35
55 Code Replacement Customization for MATLAB Code
As another alternative, you can significantly reduce the amount of code that you write by
combining the steps of creating the entry and conceptual and implementation arguments
with a call to the createCRLEntry function. In this case, specify the conceptual and
implementation information as character vector specifications.
For example:
• C++ implementations
• Data alignment
• Operator replacement with net slope arguments
• Entry parameter specifications (for example, priority, algorithm, building information)
• Semaphore and mutex function replacements
Set entry parameters, such as the priority, algorithm information, and implementation
(replacement) function name. Call the function listed in the following table for the entry
type that you created.
55-36
Define Code Replacement Mappings
To see a list of the parameters that you can set, at the command line, create a new entry
and omit the semicolon at the end of the command. For example:
hEnt = RTW.TflCFunctionEntry
hEnt =
55-37
55 Code Replacement Customization for MATLAB Code
GenCallback: ''
GenFileName: ''
SaturationMode: 'RTW_SATURATE_UNSPECIFIED'
RoundingModes: {'RTW_ROUND_UNSPECIFIED'}
TypeConversionMode: 'RTW_EXPLICIT_CONVERSION'
AcceptExprInput: 1
SideEffects: 0
UsageCount: 0
RecordedUsageCount: 0
Description: ''
StoreFcnReturnInLocalVar: 0
TraceManager: [1x1 RTW.TflTraceManager]
ans =
HeaderFile: ''
SourceFile: ''
HeaderPath: ''
SourcePath: ''
Return: []
StructFieldMap: []
Name: ''
Arguments: [0x1 RTW.Argument]
ArgumentDescriptor: []
For example, to set entry parameters for the sin function and name your replacement
function sin_dbl, use the following function call:
setTflCFunctionEntryParameters(hEnt, ...
'Key', 'sin', ...
'ImplementationName', 'sin_dbl');
Create conceptual arguments and add them to the entry’s array of conceptual arguments.
55-38
Define Code Replacement Mappings
1 Identify whether the argument is for input or output, the name, and data type. If you
do not know what arguments to specify for a supported function or operation, use the
Code Replacement Tool to find them. For example, to find the conceptual arguments
for the sin function, open the tool, create a table, create a function entry, and in the
Function menu select sin.
When validating the entry, the code generator validates that each conceptual
argument has an I/O type that is compatible with the argument name. For example,
an input must have IOType of RTW_IO_INPUT.
2 Create and add the conceptual argument to an entry. You can choose a method from
the methods listed in this table.
If Then
You want simpler code Call the function createAndAddConceptualArg.
or want to explicitly For example:
specify whether the
argument is scalar or createAndAddConceptualArg(hEnt, ...
'RTW.TflArgNumeric', ...
nonscalar (vector or
'Name', 'y1',...
matrix). 'IOType', 'RTW_IO_OUTPUT',...
'DataTypeMode', 'double');
55-39
55 Code Replacement Customization for MATLAB Code
If Then
You want to create an Call getTflArgFromString to create the argument.
argument based on a Then, call addConceptualArg to add the argument
built-in argument to the entry.
definition (for example,
scalar or nonscalar). arg = getTflArgFromString(hEnt, 'y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(hEnt, arg);
You need to define Call createCRLEntry to create the entry and specify
several similar conceptual and implementation arguments in a single
mappings, you want to function call.
minimize the code to
write, and the entries do hEnt = createCRLEntry(hTable, ...
'double y1 = sin(double u1)', ...
not require data
'mySin');
alignment, use net slope
arguments, or involve
semaphore or mutex
replacements.
The following code shows the second approach listed in the table for specifying the
conceptual output and input argument definitions for the sin function.
% Conceptual Args
Create implementation arguments for the C or C++ replacement function and add them
to the entry.
• When replacing code, the code generator uses the argument names to determine how
it passes data to the implementation function.
• For function replacements, the order of implementation argument names must match
the order of the conceptual argument names.
55-40
Define Code Replacement Mappings
• For operator replacements, the order of implementation argument names do not have
to match the order of the conceptual argument names. For example, for an operator
replacement for addition, y1=u1+u2, the conceptual arguments are y1, u1, and u2, in
that order. If the signature of your implementation function is t myAdd(t u2, t
u1), where t is a valid C type, based on the argument name matches, the code
generator passes the value of the first conceptual argument, u1, to the second
implementation argument of myAdd. The code generator passes the value of the
second conceptual argument, u2, to the first implementation argument of myAdd.
• For operator replacements, you can remap operator output arguments to
implementation function input arguments.
1 Identify whether the argument is for input or output, the name, and the data type.
When validating the entry, the code generator validates that each implementation
argument has an I/O type that is compatible with the conceptual argument to which it
is mapped. For example, an conceptual argument of type RTW_IO_OUTPUT requires a
compatible implementation argument of type RTW_IO_OUTPUT or
RTW_IO_INPUT_OUTPUT. The default I/O type is RTW_IO_INPUT.
2 Create and add the implementation argument to an entry. You can choose a method
from the methods listed in this table.
If Then
You want to populate Call the function
implementation copyConceptualArgsToImplementation. For
arguments as copies of example:
previously created
matching conceptual copyConceptualArgsToImplementation(hEnt);
arguments
55-41
55 Code Replacement Customization for MATLAB Code
If Then
You want to create and Call functions
add implementation createAndSetCImplementationReturn
arguments individually, andcreateAndAddImplementationArg . For
or vary argument example:
attributes, while
maintaining conceptual createAndSetCImplementationReturn(hEnt,
'RTW.TflArgNumeric', ...
argument order
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', true, ...
'WordLength', 32, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry,
'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT',...
'IsSigned', true,...
'WordLength', 32, ...
'FractionLength', 0 );
55-42
Define Code Replacement Mappings
If Then
You want to minimize Create the argument with a call to the function
the amount of code, or getTflArgFromString. Then, use the convenience
specify constant method setReturn or addArgument to specify
arguments to pass to whether an argument is a return value or argument
the implementation and to add the argument to the entry’s array of
function implementation arguments. For example:
arg = getTflArgFromString(hEnt,...
'y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);
arg = getTflArgFromString(hEnt,...
'u1','double');
hEnt.Implementation.addArgument(arg);
arg = getTflArgFromString(hEnt,...
'u2', 'int16', 0)
hEnt.Implementation.addArgument(arg);
arg = getTflDWorkFromString(...
'd1', 'void*')
hEnt.addDWorkArg(arg);
arg = hEnt.getTflArgFromString(...
'y1', 'void');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setRetrurn(arg);
arg = hEnt.getTflArgFromString(...
'u1', 'integer');
hEnt.Implementation.addArgument(arg);
55-43
55 Code Replacement Customization for MATLAB Code
If Then
arg = hEnt.getTflArgFromString(...
'd1', 'void**');
hEnt.Implementation.addArgument(arg);
You need to define Call createCRLEntry to create the entry and specify
several similar conceptual and implementation arguments in a single
mappings, you want to function call.
minimize the code to
write, and the entries hEnt = createCRLEntry(hTable, ...
'double y1 = sin(double u1)', ...
do not require data
'mySin');
alignment, use net
slope arguments, or
involve semaphore or
mutex replacements.
The following code shows the third approach listed in the table for specifying the
implementation output and input argument definitions for the sin function:
% Implementation Args
arg = hEnt.getTflArgFromString('y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);
arg = hEnt.getTflArgFromString('u1','double');
hEnt.Implementation.addArgument(arg);
Validate Entry
After you create or modify a code replacement table entry, validate it by invoking it at the
MATLAB command line. For example:
hTbl = crl_table_sinfcn
hTbl =
55-44
See Also
RTW.TflTable
Version: '1.0'
AllEntries: [2x1 RTW.TflCFunctionEntry]
ReservedSymbols: []
StringResolutionMap: []
If the table includes errors, MATLAB reports them. The following examples shows how
MATLAB reports a typo in a data type name:
hTbl = crl_table_sinfcn
Save Table
Save the table definition file. Use the name of the table definition function to name the
file, for example, crl_table_sinfcn.m.
Next, from your requirements, determine whether you need to specify build information
for your replacement code.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Math Function Code Replacement” on page 55-79
• “Memory Function Code Replacement” on page 55-81
• “Specify In-Place Code Replacement” on page 55-83
• “Replace MATLAB Functions with Custom Code Using coder.replace” on page 55-
105
• “Reserved Identifiers and Code Replacement” on page 55-111
• “Customize Match and Replacement Process” on page 55-113
• “Scalar Operator Code Replacement” on page 55-121
• “Addition and Subtraction Operator Code Replacement” on page 55-123
• “Small Matrix Operation to Processor Code Replacement” on page 55-128
55-45
55 Code Replacement Customization for MATLAB Code
55-46
Specify Build Information for Replacement Code
• Interactively, by using the Build Information tab in the Code Replacement Tool.
• Programmatically, by using a MATLAB programming interface.
Build Information
The build information can include:
Situation Approach
Creating code replacement Code Replacement Tool.
entries for the first time.
You used the Code Replacement Code Replacement Tool to specify the build
Tool to create the entries for information quickly .
which the build information
applies.
55-47
55 Code Replacement Customization for MATLAB Code
Situation Approach
Rapid prototyping entries. Code Replacement Tool to generate, register, and test
entries quickly.
Developing an entry to use as a Code Replacement Tool to generate entry code that
template or starting point for you can copy and modify.
defining similar entries.
Modifying existing mappings. MATLAB Editor to update the programming interface
directly.
• If an entry uses header, source, or object files, consider whether to make the files
accessible to the code generator. You can copy files to the build folder or you can
specify individual file names and paths explicitly.
• If you specify additional header files/include paths or source files/paths and you copy
files, the compiler and utilities such as packNGo might find duplicate instances of files
(an instance in the build folder and an instance in the original folder).
• If you choose to copy files to the build folder and you are using the packNGo function
to relocate static and generated code files to another development environment:
55-48
Specify Build Information for Replacement Code
Parameter Specify
Implementation header file File name and extension for the header file
the code generator needs to generate the
replacement code. For example, sin_dbl.h.
Implementation source file File name and extension for the C or C++
source file the code generator needs to
generate the replacement code. For example,
sin_dbl.c.
Additional header files/ Paths and file names for additional header
include paths files the code generator needs to generate the
replacement code. For example, C:\libs
\headerFiles and C:\libs\headerFiles
\common.h. This parameter adds -I to the
compile line in the generated makefile.
Additional source files/ paths Paths and file names for additional source
files the code generator needs to generate the
replacement code. For example, C:\libs
\srcFiles and C:\libs\srcFiles
\common.c. This parameter adds -I to the
compile line in the generated makefile.
Additional object files/ paths Paths and file names for additional object files
the linker needs to build the replacement
code. For example, C:\libs\objFiles and
C:\libs\objFiles\common.obj.
Additional link flags Flags the linker needs to generate an
executable file for the replacement code.
Additional compile flags Flags the compiler needs to generate object
code for the replacement code.
55-49
55 Code Replacement Customization for MATLAB Code
Parameter Specify
Copy files to build directory Whether to copy header, source, or object
files, which are required to generate
replacement code, to the build folder before
code generation. If you specify files with
Additional header files/include paths or
Additional source files/ paths and you copy
files, the compiler and utilities such as
packNGo might find duplicate instances of
files.
6 Click Apply.
7 Select the Mapping Information tab. Scroll to the bottom of that table and click
Validate entry. The tool validates the changes that you made to the entry.
8 Save the table that includes the entry that you just modified.
1 Identify or create the code replacement entry that you want to specify the build
information.
2 Determine what information to specify.
3 Specify your build information.
55-50
Specify Build Information for Replacement Code
Specify Action
Implementation Use one of the following:
header file
• Set properties ImplementationHeaderFile and
ImplementationHeaderPath in a call to
setTflCFunctionEntryParameters,
setTflCOperationEntryParameters, or
setTflCSemaphoreEntryParameters. For example:
setTflCFunctionEntryParameters(hEnt, ...
'ImplementationHeaderFile', 'sin_dbl.h', ...
'ImplementationHeaderPath', 'D:/lib/headerFiles'
'Key', 'sin', ...
'ImplementationName', 'sin_dbl');
• Set argument headerFile in a call to registerCFunctionEntry,
registerCPPFunctionEntry, or
registerCPromotableMacroEntry
Implementation Set properties ImplementationSourceFile and
source file ImplementationSourcePath in a call to
setTflCFunctionEntryParameters,
setTflCOperationEntryParameters, or
setTflCSemaphoreEntryParameters. For example:
setTflCFunctionEntryParameters(hEnt, ...
'ImplementationHeaderFile', 'sin_dbl.c', ...
'ImplementationHeaderPath', 'D:/lib/sourceFiles'
'Key', 'sin', ...
'ImplementationName', 'sin_dbl');
Additional header For each file, specify the file name and path in calls to the functions
files/include paths addAdditionalHeaderFile and addAdditionalIncludePath. For
example:
hEnt = RTW.TflCFunctionEntry;
addAdditionalHeaderFile(hEnt, 'common.h');
addAdditionalIncludePath(hEnt, fullfile(libdir, 'include'));
55-51
55 Code Replacement Customization for MATLAB Code
Specify Action
Additional source For each file, specify the file name and path in calls to the functions
files/paths addAdditionalSourceFile and addAdditionalSourcePath. For
example:
hEnt = RTW.TflCFunctionEntry;
addAdditionalSourceFile(hEnt, 'common.c');
addAdditionalSourcePath(hEnt, fullfile(libdir, 'src'));
hEnt = RTW.TflCFunctionEntry;
addAdditionalLinkObj(hEnt, 'sin.o');
addAdditionalLinkObjPath(hEnt, fullfile(libdir, 'bin'));
Compile flags Set the entry property AdditionalCompileFlags to a cell array of
character vectors representing the required compile flags. For example:
hEnt = RTW.TflCFunctionEntry;
hEnt = RTW.TflCFunctionEntry;
55-52
Specify Build Information for Replacement Code
Specify Action
Whether to copy Use one of the following:
header, source, or
object files, which are • Set property GenCallback to 'RTW.copyFileToBuildDir' in a
required to generate call to setTflCFunctionEntryParameters,
replacement code, to setTflCOperationEntryParameters, or
the build folder setTflCSemaphoreEntryParameters. For example:
before code
setTflCFunctionEntryParameters(hEnt, ...
generation 'ImplementationHeaderFile', 'sin_dbl.h', ...
'ImplementationHeaderPath', 'D:/lib/headerFiles'
'Key', 'sin', ...
'ImplementationName', 'sin_dbl'
'GenCallback', 'RTW.copyFileToBuildDir');
• Set argument genCallback in a call to registerCFunctionEntry,
registerCPPFunctionEntry, or
registerCPromotableMacroEntry to
'RTW.copyFileToBuildDir'.
The following example defines a table entry for an optimized multiplication function that
takes signed 32-bit integers and returns a signed 32-bit integer, taking saturation into
account. Multiplications in the generated code are replaced with calls to the optimized
function. The optimized function does not reside in the build folder. For the code
generator to access the files, copy them into the build folder to be compiled and linked
into the application.
The table entry specifies the source and header file names and paths. To request the copy
operation, the table entry sets the genCallback property to
'RTW.copyFileToBuildDir' in the call to the setTflCOperationEntryParameters
function. In this example, the header file s32_mul.h contains an inlined function that
invokes assembly functions contained in s32_mul.s. If a match occurs for the table entry,
55-53
55 Code Replacement Customization for MATLAB Code
the function RTW.copyFileToBuildDir copies the specified source and header files to
the build folder for use during the remainder of the build process.
function hTable = make_my_crl_table
hTable = RTW.TflTable;
op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 100, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'}, ...
'ImplementationName', 's32_mul_s32_s32_sat', ...
'ImplementationHeaderFile', 's32_mul.h', ...
'ImplementationSourceFile', 's32_mul.s', ...
'ImplementationHeaderPath', {fullfile('$(MATLAB_ROOT)','crl')}, ...
'ImplementationSourcePath', {fullfile('$(MATLAB_ROOT)','crl')}, ...
'GenCallback', 'RTW.copyFileToBuildDir');
.
.
.
addEntry(hTable, op_entry);
op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 90, ...
'SaturationMode', 'RTW_SATURATE_UNSPECIFIED', ...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'}, ...
'ImplementationName', 's32_add_s32_s32', ...
'ImplementationHeaderFile', 's32_add_s32_s32.h', ...
'ImplementationSourceFile', 's32_add_s32_s32.c'...
'GenCallback', 'RTW.copyFileToBuildDir');
addAdditionalHeaderFile(op_entry, 'all_additions.h');
addAdditionalIncludePath(op_entry, fullfile(libdir, 'include'));
addAdditionalSourceFile(op_entry, 'all_additions.c');
addAdditionalSourcePath(op_entry, fullfile(libdir, 'src'));
addAdditionalLinkObj(op_entry, 'addition.o');
addAdditionalLinkObjPath(op_entry, fullfile(libdir, 'bin'));
.
55-54
See Also
.
.
addEntry(hTable, op_entry);
Next, include your code replacement table in a code replacement library and register the
library with the code generator.
See Also
More About
• “Define Code Replacement Mappings” on page 55-29
• “Register Code Replacement Mappings” on page 55-56
• “Develop a Code Replacement Library” on page 55-15
• “What Is Code Replacement Customization?” on page 55-3
• “Code You Can Replace from MATLAB Code” on page 55-5
55-55
55 Code Replacement Customization for MATLAB Code
If... Then...
Registering a code replacement Use the Code Replacement Tool.
table for the first time
You used the Code Replacement Use the Code Replacement Tool to quickly register the
Tool to create the table table.
Rapid prototyping code Use the Code Replacement Tool to quickly generate,
replacement register, and test entries.
Creating registration file to use Use the Code Replacement Tool to generate code that
as a template or starting point for you can copy and modify.
defining similar registration files
Modifying existing registration Use the MATLAB Editor to update the registration file.
files
Defining multiple code Use the MATLAB Editor to create a new or extend an
replacement libraries in one existing registration file.
registration file
Defining code replacement library Use the MATLAB Editor to create a new or extend an
hierarchy in a registration file existing registration file.
55-56
Register Code Replacement Mappings
1 After you validate and save a code replacement table, select File > Generate
registration file to open the Generate registration file dialog box.
For... Specify...
Registry name Text naming the code replacement library. For example,
Sin Function Example.
55-57
55 Code Replacement Customization for MATLAB Code
For... Specify...
Table list Text naming one or more code replacement tables to
include in the library. Specify each table as one of the
following:
crl_table_sinfcn, c:/work_crl/
crl_table_muldiv
For... Specify...
Description Text that describes the purpose and content of the library.
Target HW device Text naming one or more hardware devices the code
replacement library supports. Separate names with a
comma. To support all device types, enter an asterisk (*).
For example, TI C28x, TI C62x.
Base CRL Text naming a code replacement library that you want to
serve as a base library for the library you are registering.
Use this field to specify library hierarchies. For example,
you can specify a general TI device library as the
base library for a more specific TI C28x device library.
Generate data Flag that enables data alignment specification.
alignment
specification
55-58
Register Code Replacement Mappings
The basic workflow for creating a registration file programmatically consists of the
following steps:
function rtwTargetInfo(cm)
cm.registerTargetInfo(@loc_register_crl);
this(1) = RTW.TflRegistry;
this(1).Name = 'crl-name';
this(1).TableList = {'table',...};
For... Replace...
this(1).Name = 'crl- crl-name with text naming the code
name'; replacement library. For example, Sin
Function Example.
55-59
55 Code Replacement Customization for MATLAB Code
For... Replace...
this(1).TableList = table with text that identifies the code
{'table',...}; replacement table that contains your code
replacement entries. Specify a table as one
of the following:
For... Replace...
this(1).Description = text with text that describes the purpose
'text' and content of the library.
this(1).TargetHWDeviceTyp device-type with text that names a
e = {'device-type',...} hardware device the code replacement
library supports. You can specify multiple
device types. Separate device types with a
comma. For example, TI C28x, TI C62x.
To support all device types, enter an asterisk
(*).
55-60
Register Code Replacement Mappings
For... Replace...
this(1).BaseTfl = 'base- base-lib with text that names a code
lib' replacement library that you want to serve as
a base library for the library you are
registering. Use this field to specify library
hierarchies. For example, you can specify a
general TI device library as the base
library for a TI C28x device library.
For example:
function rtwTargetInfo(cm)
cm.registerTargetInfo(@loc_register_crl);
this(1) = RTW.TflRegistry;
this(1).Name = 'Sin Function Example';
this(1).TableList = {'crl_table_sinfcn'};
this(1).TargetHWDeviceType = {'*'};
this(1).Description = 'Example - sin function replacement';
2 Save the file with the name rtwTargetInfo.m.
3 Place the file on the MATLAB path. When the file is on the MATLAB path, the code
generator reads the file after starting and applies the customizations during the
current MATLAB session.
RTW.TargetRegistry.getInstance('reset');
55-61
55 Code Replacement Customization for MATLAB Code
cm.registerTargetInfo(@locCrlRegFcn);
55-62
See Also
cm.registerTargetInfo(@locCrlRegFcn);
After registering your code replacement mappings, verify that code replacements occur.
See Also
More About
• “Troubleshoot Code Replacement Library Registration” on page 55-64
• “Specify Build Information for Replacement Code” on page 55-47
• “Verify Code Replacements” on page 55-65
• “Develop a Code Replacement Library” on page 55-15
• “What Is Code Replacement Customization?” on page 55-3
• “Code You Can Replace from MATLAB Code” on page 55-5
55-63
55 Code Replacement Customization for MATLAB Code
• Refresh the library registration information within the current MATLAB session
(RTW.TargetRegistry.getInstance('reset'); or for the Simulink
environment,sl_refresh_customizations).
• See whether the registration file, rtwTargetInfo.m, contains an error.
See Also
More About
• “Register Code Replacement Mappings” on page 55-56
55-64
Verify Code Replacements
The code generator overwrites the hit and miss cache data each time it produces code.
The cache data reflects hits and misses for only the last application component (MATLAB
code or Simulink model) for which you generate code.
You can use the Code Replacement Viewer to review trace information based on logged
hit and miss trace data. The hit cache provides trace information that helps to verify code
replacements.
The miss cache and related miss data collected and stored in code replacement tables
provide trace information for misses. Use this information for misses to troubleshoot
expected code replacements that do not occur. Trace information for a miss:
55-65
55 Code Replacement Customization for MATLAB Code
ans =
MATLAB displays errors that occur. In the following example, MATLAB detects a typo in a
data type name.
isvalid(crl_table_sinfcn)
1 Open the viewer to display the contents of your library. At the command prompt,
enter the following command:
crviewer('library')
For example:
crviewer('Addition & Subtraction Examples')
55-66
Verify Code Replacements
2 Review the list of tables in the left pane. Are tables missing? Are the tables listed in
the correct relative order? By default, the viewer displays tables in search order.
3 In the left pane, click each table and review the list of entries in the center pane. Are
entries missing? Does the list include extraneous or unexpected entries?
55-67
55 Code Replacement Customization for MATLAB Code
1 Open the viewer to display the contents of your table. At the command prompt, enter
the following command. table is a MATLAB file that defines code replacement
tables. The file must be in the current folder or on the MATLAB path.
crviewer(table)
For example:
crviewer(crl_table_addsub)
55-68
Verify Code Replacements
2 Review the list of entries in the center pane. Are entries missing? Does the list
include extraneous or unexpected entries? By default, the viewer displays entries in
search order.
3 In the center pane, click each entry and verify the entry information in the right
pane.
55-69
55 Code Replacement Customization for MATLAB Code
55-70
Verify Code Replacements
The Code Replacements Report details the code replacement library functions that the
code generator uses for code replacements. The report provides a mapping between each
replacement instance and the line of MATLAB code that triggered the replacement. The
Code Replacements report is not available for generated MEX functions.
The following example illustrates two complementary approaches for reviewing code
replacements:
• Check the Code Replacements Report section of the code generation report for
expected replacements.
• Trace code replacements.
1 Identify the MATLAB function where you anticipate that a function or operator
replacement occurs. This example uses the function matlabroot/toolbox/rtw/
rtwdemos/crl_demo/addsub_two_int16.m.
y1 = int16(u1 + u2);
y2 = int16(u1 - u2);
2 Identify or create code or a script to exercise the function. For example, consider test
file addsub_to_int16_test.m, which includes the following code:
disp('Input')
u1 = int16(10)
u2 = int16(10)
55-71
55 Code Replacement Customization for MATLAB Code
disp('Output')
disp('y1 =')
disp(y1);
disp('y2 =')
disp(y2);
3 Open the MATLAB Coder app.
4 On the Select Source Files page, add your function to the project. For this example,
add function addsub_two_int16. Click Next.
5 On the Define Input Types page, use the test file addsub_to_int16_test to
automatically define the input types. Click Next.
6 On the Check for Run-Time Issues page, specify the test file
addsub_to_int16_test. The app runs the test file, replacing calls to
addsub_to_int16_test with calls to a MEX version of addsub_to_int16_test.
Click Next.
7 To open the Generate dialog box, on the Generate Code page, click the Generate
arrow .
8 Set Build type to generate source code. Before you build an executable, you want to
review your code replacements in the generated code.
9 In the Generate dialog box, click More Settings.
10 Configure the code generator to use your code replacement library. On the Custom
Code tab, set the Code replacement library parameter to the name of your library.
For this example, set the library to Addition & Subtraction Examples.
11 Configure the code generation report to include the Code Replacements Report. On
the Debugging tab, select:
That report lists the replacement functions that the code generator used. The report
provides a mapping between each replacement instance and the MATLAB code that
triggered the replacement.
55-72
See Also
If a function or operator is not replaced as expected, the code generator used a higher-
priority (lower-priority value) match or did not find a match.
To analyze and troubleshoot code replacement misses, use the trace information that the
Code Replacement Viewer provides. See “Troubleshoot Code Replacement Misses” on
page 55-74.
See Also
More About
• “Troubleshoot Code Replacement Misses” on page 55-74
• “Register Code Replacement Mappings” on page 55-56
• “Deploy Code Replacement Library” on page 55-78
• “Develop a Code Replacement Library” on page 55-15
• “What Is Code Replacement Customization?” on page 55-3
55-73
55 Code Replacement Customization for MATLAB Code
For example:
1. Mismatched data types (argument name, CSO value, table entry value)
The parenthetical information represents placeholders for actual values that appear in
the report details.
In the Miss Source Locations table that lists the miss details, the Reason column
includes:
The following Reason details indicate a data type mismatch because the call site object
specifies data type int8 for arguments y1, u1, and u2, while the code replacement table
entry specifies uint32.
Depending on your situation and the reported miss reason, troubleshoot reported misses
by looking for instances of the following:
• A typo in the code replacement table entry definition or a source parameter setting.
55-74
Troubleshoot Code Replacement Misses
• Information missing from the code replacement table entry or a source parameter
setting.
• Invalid or incorrect information in the code replacement table entry definition or a
source parameter setting.
• Arguments incorrectly ordered in the code replacement table entry definition or the
source being replaced with replacement code.
• Failed algorithm classification for an addition or subtraction operation due to:
• An ideal accumulator not being calculated because the type of an input argument is
not fixed-point or the slope adjustment factors of the input arguments are not
equal.
• Input or output casts with a floating-point cast type.
• Input or output casts with cast types that have different slope adjustment factors or
biases.
• Output casts not being convertible to a single output cast.
• Input casts resulting in loss of bits.
To examine the code generated for the function, from the code generation report,
open the generated file addsub_two_int16.h.
extern void addsub_two_int16(double u1, double u2, short *b_y1, short *y2);
The code generator replaced code, but the replacement is for the signed version of
the 16-bit addition and subtraction operations. You expected code replacements for
operations on unsigned data.
55-75
55 Code Replacement Customization for MATLAB Code
The Trace Information is a table that lists the following information for each miss:
• Call site object preview. The call site object is the conceptual representation of
addition operator. The code generator uses this object to query the code
replacement library for a match.
• A link to the source location in the MATLAB function where the code generator
considered replacing code.
• The reasons that the miss occurred. See “Miss Reason Messages” on page 55-74.
For this example, the report shows misses for function addsub_two_int16.m.
7 Find the source in the trace information. Depending on your situation and the
reported miss reason, consider looking for a condition such as a typo in the code
replacement table entry definition or a source parameter setting. For a list of
conditions to consider, see“Miss Reason Messages” on page 55-74.
For this example, determine why code for function addsub_two_int16 is not
replaced with code for an unsigned 16-bit addition operation. The miss reasons for
the function indicate data type and algorithm mismatches:
• The data type in the call site object is a signed 16-bit integer. The code
replacement entry specifies an unsigned 16-bit integer.
• The algorithm property in the call site object is RTW_CAST_AFTER_OP while the
code replacement entry specifies RTW_CAST_BEFORE_OP.
8 Fix the specified MATLAB code and relevant specifications or code replacement table
entry. If the issue concerns the MATLAB code, use the source location in the trace
information to find the code to fix. For this example, you expected an unsigned
addition operation to occur for the addsub_two_int16 function.
To fix the mismatches, in the test file addsub_to_int16_test, change the data
types definitions for u1 and u2 as follows:
55-76
See Also
u1 = uint16(10)
u2 = uint16(10)
See Also
More About
• “Verify Code Replacements” on page 55-65
55-77
55 Code Replacement Customization for MATLAB Code
1 Move your code replacement table files to an area that is on the MATLAB search path
and that is accessible to and shared by other users.
2 Move the rtwTargetInfo.m registration file, to an area that is on the MATLAB
search path and that is accessible to and shared by other users. If you are deploying
a library to a folder in a development environment that already contains a
rtwTargetInfo.m file, copy the registration code from your code replacement
library version of rtwTargetInfo.m and paste it into the shared version of that file.
3 Register the library customizations or restart MATLAB.
4 Verify that the libraries are available for configuring the code generator and that
code replacements occur as expected.
5 Inform users that the libraries are available and provide direction on when and how
to apply them.
See Also
More About
• “Verify Code Replacements” on page 55-65
• “Package Code for Other Development Environments” (MATLAB Coder)
• “Develop a Code Replacement Library” on page 55-15
• “What Is Code Replacement Customization?” on page 55-3
55-78
Math Function Code Replacement
55-79
55 Code Replacement Customization for MATLAB Code
copyConceptualArgsToImplementation(fcn_entry);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, fcn_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Define Code Replacement Mappings” on page 55-29
• “Specify In-Place Code Replacement” on page 55-83
• “Reserved Identifiers and Code Replacement” on page 55-111
• “Customize Match and Replacement Process” on page 55-113
• “Develop a Code Replacement Library” on page 55-15
55-80
Memory Function Code Replacement
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create an entry for the function mapping with a call to the
RTW.TflCFunctionEntry function.
55-81
55 Code Replacement Customization for MATLAB Code
addEntry(hTable, fcn_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Specify In-Place Code Replacement” on page 55-83
• “Reserved Identifiers and Code Replacement” on page 55-111
• “Customize Match and Replacement Process” on page 55-113
• “Develop a Code Replacement Library” on page 55-15
55-82
Specify In-Place Code Replacement
When you generate C or C++ code from MATLAB code, the code generator supports in-
place function argument code replacement. When you interactively create a code
replacement table entry with the Code Replacement Tool, you can specify in-place
function argument replacement. You can also specify in-place function argument
replacement programmatically with the Code Replacement Library API.
coder.replace('-errorifnoreplacement');
x = sin(x);
2 In the Code Replacement Tool, add a new table, select that table, and add a new
function entry. For more information, see “Define Code Replacement Mappings” on
page 55-29.
3 On the Mapping Information tab, select Custom for the Function parameter.
4 In the function-name text box, name the custom function. For this example, type the
name customFunction.
55-83
55 Code Replacement Customization for MATLAB Code
5 Under the Conceptual arguments list box, click + to add two arguments. By
default, the tool creates an output argument y1 and an input argument u1, both of
type double.
6 In the Replacement function > Function prototype section, type the name
custom_function_inplace_impl in the Name text box.
7 Under the Function arguments list box, click + to add two function implementation
arguments. By default, the tool creates an output argument y1 and an input
argument u1, both of type double.
8 For each input argument that you want to specify as in-place with a corresponding
output argument, in the Argument properties box, select the Pointer check box.
The Argument properties section of the dialog box expands to include an In-place
argument drop-down list. For this example, in the Function arguments list, select
input argument u1, and then select the Pointer check box.
9 From the In-place argument list, select y1, the output argument for the code
replacement mapping. The Function arguments list box is updated to show possible
in-place argument mappings.
55-84
Specify In-Place Code Replacement
10 Select and delete one of the two possible argument mappings. For this example,
delete the mapping y1<-->u1.
11 In the Function signature preview box, if the function signature appears as
expected, click Apply. Otherwise, make adjustments, and then click Apply. The
function signature for this example, appears as
1 Register the table that contains the entry in a code replacement library.
2 Configure the code generator to use a code replacement library and to include the
Code Replacements Report in the code generation report.
3 Generate the replacement code and a code generation report.
4 Review the code replacements.
55-85
55 Code Replacement Customization for MATLAB Code
• Sets the name of the implementation argument to the same name as the
corresponding conceptual argument.
• Associates the corresponding implementation argument with the argument property
ArgumentForInPlaceUse.
1 Create the following MATLAB function, customFunction.m.
function y = customFunction(x)
% Function that updates the input and returns it as an output
coder.replace('-errorifnoreplacement');
x = sin(x);
2 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_inplace()
3 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
4 Create an entry for the function mapping with a call to the
RTW.TflCFunctionEntry function.
hEnt = RTW.TflCFunctionEntry;
5 Set function entry parameters with a call to the
setTflCFunctionEntryParameters function.
setTflCFunctionEntryParameters(hEnt, ...
'Key', 'customFunction', ...
'Priority', 100, ...
'ImplementationName', 'custom_function_inplace_impl', ...
'SideEffects', true);
6 Create conceptual arguments y1 and u1. This example uses calls to the
getTflArgFromString and addConceptualArg functions to create and add the
arguments.
arg = getTflArgFromString(hEnt, 'y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(hEnt, arg);
55-86
See Also
7 Create the implementation arguments and add them to the entry. This example uses
calls to the getTflArgFromString function to create implementation arguments
that map to arguments in the replacement function prototype: output argument y1
and input argument u1. For each argument, the example uses the convenience
method setReturn or addArgument to specify whether an argument is a return
value or argument. For each argument, this example adds the argument to the entry
array of implementation arguments.
addEntry(hLib, hEnt);
9 Save the table definition file. Use the name of the table definition function to name
the file.
1 Register the table that contains the entry in a code replacement library.
2 Configure the code generator to use a code replacement library and to include the
Code Replacements Report in the code generation report.
3 Generate the replacement code and a code generation report.
4 Review the code replacements.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Develop a Code Replacement Library” on page 55-15
55-87
55 Code Replacement Customization for MATLAB Code
For examples, see “Basic Example of Code Replacement Data Alignment” on page 54-143
and the “Data Alignment for Function Implementations” section of the “Optimize
Generated Code By Developing and Using Code Replacement Libraries - Simulink®”
example page.
Note If replacement that requires alignment uses imported data (for example, I/O of an
entry-point function or exported function), specify the data alignment with
coder.dataAlignment statements in the MATLAB code. Specify alignment separately
for each instance of imported data. See “Specify Data Alignment in MATLAB Code for
Imported Data” on page 55-95.
55-88
Data Alignment for Code Replacement
55-89
55 Code Replacement Customization for MATLAB Code
hLib = RTW.TflTable;
entry = RTW.TflCOperationEntry;
arg = getTflArgFromString(hLib, 'u1','single*');
desc = RTW.ArgumentDescriptor;
desc.AlignmentBoundary = 16;
arg.Descriptor = desc;
entry.Implementation.addArgument(arg);
The equivalent alignment boundary specification in the Code Replacement Tool dialog box
is in this figure.
55-90
Data Alignment for Code Replacement
for a data object involved in a code replacement, this value determines if the memory
satisfies the alignment requirement of the replacement. If not, the code generator
does not use the replacement. The default value for DefaultMallocAlignment is
-1, indicating that the default alignment boundary used for dynamically allocated
memory is unknown. In this case, the code generator uses the natural alignment of the
data type to determine whether to allow a replacement.
Additionally, you can specify the alignment boundary for complex types by using the
addComplexTypeAlignment function.
• If you are generating a customization file function using the Code Replacement Tool,
fill out the following fields for each compiler.
55-91
55 Code Replacement Customization for MATLAB Code
55-92
Data Alignment for Code Replacement
55-93
55 Code Replacement Customization for MATLAB Code
as = RTW.AlignmentSpecification;
as.AlignmentType = {'DATA_ALIGNMENT_LOCAL_VAR', ...
'DATA_ALIGNMENT_STRUCT_FIELD', ...
'DATA_ALIGNMENT_GLOBAL_VAR'};
as.AlignmentSyntaxTemplate = '__attribute__((aligned(%n)))';
as.AlignmentPosition = 'DATA_ALIGNMENT_PREDIRECTIVE';
as.SupportedLanguages = {'c', 'c++'};
da.addAlignmentSpecification(as);
tc = RTW.TargetCharacteristics;
tc.DataAlignment = da;
Here is the corresponding specification in the Generate customization dialog box of the
Code Replacement Tool.
55-94
Data Alignment for Code Replacement
If MATLAB Coder code replacements occur that require data alignment (uses imported
data), such as an entry-point or exported function with I/O, specify code replacement data
alignment with coder.DataAlignment statements in the MATLAB code.
To specify the data alignment requirements for imported data in a MATLAB code:
• For each instance of imported data that requires data alignment, specify the alignment
in the function with a coder.dataAlignment statement of the form:
coder.dataAlignment('varName', align_value)
• The varName is a character array of the variable name that requires alignment
information specification. The align_value is an integer number which should be a
power of 2, from 2 through 128. This number specifies the power-of-2 byte alignment
boundary.
• An example function that specifies data alignment is:
function y = testFunction(x1,x2)
55-95
55 Code Replacement Customization for MATLAB Code
y = x1 + x2;
end
If testFunction is an entry-point or exported function, imported data x1, x2, and y are
not aligned automatically by the code generator. The coder.DataAlignment statements
for these variables are only meant as information for the code generator. The call sites
allocating memory for the data need to ensure that the data is aligned as specified.
You also can specify code replacement data alignment for exported data, such as a
global variable or an ExportedGlobal custom storage class. For more information, see
“Built-In Storage Classes You Can Choose” on page 22-85 and “Choose a Storage Class
for Controlling Data Representation in the Generated Code” on page 22-69.
• Specify the data alignment requirements in a table entry. You can specify alignment
for implementation function arguments individually or collectively.
• Specify the data alignment capabilities and syntax for your compiler. Attach an
AlignmentSpecification object to the TargetCharacteristics object of the registry entry
specified in your rtwTargetInfo.m file.
If externally allocated data (e.g. entry-point function arguments) are used in an operation
that can be replaced with an implementation that requires alignment, use the
coder.dataAlignment directive to specify alignment so that replacement occurs.
This example is configured to use either the GCC, Clang, or MSVC compilewhosrs.
The following code creates a folder in your current working folder (pwd). The new folder
will contain the files that are relevant for this example. If you do not want to affect the
55-96
Data Alignment for Code Replacement
current folder (or if you cannot generate files in this folder), you should change your
working folder.
This example is configured to use either GCC, Clang, or MSVC to compile the generated
code.
cc = rtwprivate('getMexCompilerInfo');
isDaDemoSupported = strcmpi(cc.comp.Manufacturer,'GNU') || ...
strcmpi(cc.comp.Manufacturer,'Apple') || ...
strcmpi(cc.comp.Manufacturer,'Microsoft');
if ~isDaDemoSupported
recMsg = ['Use "mex -setup" to select either GCC, Clang,'...
'or MSVC and restart this example'];
warning(['Example %s is configured to use either GCC, Clang,'
'or MSVC to compile the generated code. %s.'], mfilename,recMsg);
end
Set up the configuration object and define the function input types.
cfg = coder.config('lib','ecoder',true);
cfg.GenerateReport = false;
cfg.LaunchReport = false;
cfg.VerificationMode = 'SIL';
cfg.CodeExecutionProfiling = true;
len = 400000;
args = {coder.typeof(single(0),[len,1]), ...
coder.typeof(single(0))};
global g1;
g1 = single(zeros([len,1]));
55-97
55 Code Replacement Customization for MATLAB Code
RTW.TargetRegistry.getInstance('reset');
mcode_da16 = 'biased_sum_of_square_differences_da16';
cfg.CodeReplacementLibrary = 'SIMD Examples';
codegen('-config',cfg, mcode_da16,'-args',args,'-global',{'g1',g1});
Compare performance of normal ANSI code against the earlier generated code that used
SIMD intrinsics.
% Generate ansi code
mcode_noda = 'biased_sum_of_square_differences';
cfg.CodeReplacementLibrary = 'None';
codegen('-config',cfg, mcode_noda,'-args',args,'-global',{'g1',g1});
55-98
Data Alignment for Code Replacement
percent_perf_gain = ...
100 * (avg_selftime_ansi-avg_selftime_simd)/avg_selftime_ansi;
annotation(figObj, 'textbox',axesObj.Position, ...
'String',sprintf(...
'Execution speed increased by %d%% on average',percent_perf_gain), ...
'FontWeight', 'bold', 'FontSize', 12, 'HorizontalAlignment', 'center', ...
'FitBoxToText','On');
55-99
55 Code Replacement Customization for MATLAB Code
Cleanup
55-100
See Also
RTW.TargetRegistry.getInstance('reset');
cleanup
See Also
More About
• “Code You Can Replace From Simulink Models” on page 54-7
• “Define Code Replacement Mappings” on page 54-43
• “Develop a Code Replacement Library” on page 54-27
55-101
55 Code Replacement Customization for MATLAB Code
The following table definition file for a sum operation uses the row-major array layout.
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_rowmajor_matrix
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create an entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
% Create operation entry
hent = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. In the function call, set the
parameter ArrayLayout to ROW_MAJOR
setTflCOperationEntryParameters(hEnt, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 100, ...
'ArrayLayout', 'ROW_MAJOR'
'ImplementationName' 'MyMul_ROW', ...
'ImplementationHeaderFile', 'MyMul_ROW.h', ...
'ImplementationSourceFile', 'MyMul_ROW.c');
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the RTW.TflArgMatrix and
addConceptualArg functions to create and add the arguments.
arg = RTW.TflArgMatrix('y1', 'RTW_IO_OUTPUT', 'double');
arg.DimRange = [2 2; 50 50];
hEnt.addConceptualArg(arg);
55-102
Array Layout and Code Replacement
hEnt.addConceptualArg(arg);
% Implementation Args
arg = hEnt.getTflArgFromString('unused','void');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);
arg = hEnt.getTflArgFromString('u1','double*');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u2','double*');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('y1','double*');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u3','uint32',2);
arg.Type.ReadOnly = true;
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u4','uint32',3);
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u5','uint32',3);
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u6','uint32',4);
hEnt.Implementation.addArgument(arg);
7 Add the entry to a code replacement table with a call to the addEntry function.
55-103
55 Code Replacement Customization for MATLAB Code
addEntry(hTable, hEnt);
8 Save the table definition file. To name the file, use the name of the table definition
function . Then, generate code and a code generation report and review the code
replacements.
See Also
coder.replace | setTflCFunctionEntryParameters |
setTflCOperationEntryParameters
More About
• “Row-Major and Column-Major Array Layouts” (MATLAB Coder)
• “Define Code Replacement Mappings” on page 54-43
55-104
Replace MATLAB Functions with Custom Code Using coder.replace
• MATLAB Coder
• MATLAB code in a Simulink MATLAB Function block
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Develop a Code Replacement Library” on page 55-15
55-105
55 Code Replacement Customization for MATLAB Code
• MATLAB Coder
• MATLAB code in a Simulink MATLAB Function block
Example Files
For the examples in “Interactive External Function Call Replacement Specification with
Code Replacement Tool” on page 55-107 and “Programmatic External Function Call
Replacement Specification” on page 55-109 you must have set up the following:
/* my_add.c */
#include "my_add.h"
/* my_add.h */
y=0.0;
if ~coder.target('Rtw')
55-106
Replace coder.ceval Calls to External Functions
in1=10;
in2=20;
y = call_my_add(in1, in2);
disp('Output')
disp('y =')
disp(y);
• Replacement C function my_add_replacement.c.
/* my_add_replacement.c */
#include "my_add_replacement.h"
/* my_add_replacement.h */
1 Identify or create the C/C++ code and relevant header files, the MATLAB function
that calls coder.ceval, a MATLAB test function, and the source and header files for
55-107
55 Code Replacement Customization for MATLAB Code
your replacement code. To follow along with this example, set up the files identified
in “Example Files” on page 55-106.
2 In the Code Replacement Tool, add a table, select that table, and add a function entry.
For more information, see “Define Code Replacement Mappings” on page 55-29.
3 On the Mapping Information tab, select Custom for the Function parameter.
4 In the function-name text box, type the custom function name. For this example,
type the name my_add.
5 Under the Conceptual arguments list box, click + to add three arguments. By
default, the tool creates an output argument y1 and input arguments u1 and u2 of
type double.
6 In the Replacement function > Function prototype section, type the name
my_add_replacement in the Name text box.
7 Under the Function arguments list box, click + to add three function
implementation arguments. By default, the tool creates an output argument y1 and
input arguments u1 and u2 of type double. Use the default settings.
8 In the Function signature preview box, if you see the expected function signature,
click Apply. The function signature for this example, appears as:
1 Register the table that contains the entry in a code replacement library.
2 Configure the code generator to use the code replacement library and to include the
Code Replacements Report in the code generation report.
3 Generate code and the report.
4 Review the code replacements.
55-108
Replace coder.ceval Calls to External Functions
1 Identify or create the C/C++ code and relevant header files, the MATLAB function
that calls coder.ceval to invoke the C/C++ function, a MATLAB test function, and
the source and header files for your replacement code. To follow along with this
example, set up the files identified in “Example Files” on page 55-106.
2 Create a table definition file that contains a function definition. For example:
hEnt = RTW.TflCFunctionEntry;
5 Set function entry parameters with a call to the
setTflCFunctionEntryParameters function.
hEnt.setTflCFunctionEntryParameters( ...
'Key', 'my_add', ...
'Priority', 100, ...
'ImplementationName', 'my_add_replacement', ...
'ImplementationHeaderFile', 'my_add_replacement.h', ...
'ImplementationSourceFile', 'my_add_replacement.c');
6 Create conceptual arguments y1, u1, and u1. This example uses calls to the
getTflArgFromString and addConceptualArg functions to create and add the
arguments.
arg = hEnt.getTflArgFromString('y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.addConceptualArg(arg);
arg = hEnt.getTflArgFromString('u1','double');
hEnt.addConceptualArg(arg);
arg = hEnt.getTflArgFromString('u2','double');
hEnt.addConceptualArg(arg);
55-109
55 Code Replacement Customization for MATLAB Code
7 Create the implementation arguments and add them to the entry. This example uses
calls to the getTflArgFromString function to create implementation arguments.
These functions map to arguments in the replacement function prototype: output
argument y1 and input arguments u1 and u2. For each argument, the example uses
the convenience method setReturn or addArgument to specify whether an
argument is a return value or argument. For each argument, this example adds the
argument to the entry array of implementation arguments.
arg = hEnt.getTflArgFromString('y1','double');
arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);
arg = hEnt.getTflArgFromString('u1','double');
hEnt.Implementation.addArgument(arg);
arg = hEnt.getTflArgFromString('u2','double');
hEnt.Implementation.addArgument(arg);
8 Add the entry to a code replacement table with a call to the addEntry function.
hLib.addEntry(hEnt);
9 Save the table definition file. Use the name of the table definition function to name
the file.
1 Register the table that contains the entry in a code replacement library.
2 Configure the code generator to use the code replacement library and to include the
Code Replacements Report in the code generation report.
3 Generate code and the report.
4 Review the code replacements.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Develop a Code Replacement Library” on page 55-15
55-110
Reserved Identifiers and Code Replacement
To view a list of reserved identifiers for the code replacement library that you use to
generate code, specify the name of the library in a call to the function
RTW.TargetRegistry.getInstance.getTflReservedIdentifiers. For example:
crl_ids = RTW.TargetRegistry.getInstance.getTflReservedIdentifiers('GNU99 (GNU)')
In a code replacement table, the code generator registers each function implementation
name defined by a table entry as a reserved identifier. You can register additional
reserved identifiers for the table on a per-header-file basis. Providing additional reserved
identifiers can help prevent duplicate symbols and other identifier-related compile and
link issues.
You can register up to four reserved identifier structures in a code replacement table. You
can associate one set of reserved identifiers with a code replacement library, while the
other three (if present) must be associated with ANSI C. The following example shows a
reserved identifier structure that specifies two identifiers and the associated header file.
d{1}.LibraryName = 'ANSI_C';
d{1}.HeaderInfos{1}.HeaderName = 'math.h';
d{1}.HeaderInfos{1}.ReservedIds = {'y0', 'y1'};
The code generator adds the identifiers to the list of reserved identifiers and honors them
during the build procedure.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
55-111
55 Code Replacement Customization for MATLAB Code
55-112
Customize Match and Replacement Process
• Preset match criteria to identify functions and operators for which application-specific
implementations replace default implementations.
• Preset replacement function signatures.
It is possible that preset match criteria and preset replacement function signatures do not
completely meet your function and operator replacement needs. For example:
To add extra logic into the code replacement match and replacement process, create
custom code replacement table entries. With custom entries, you can specify additional
match criteria and modify the replacement function signature to meet application needs.
• Add match criteria that the base class does not provide. The base class provides a
match based on:
• Argument number
• Argument name
• Signedness
• Word size
• Slope (if not specified with wildcards)
• Bias (if not specified with wildcards)
55-113
55 Code Replacement Customization for MATLAB Code
During code generation, the code replacement match process tries to match function or
operator call sites with the base class of your derived entry class. If the process finds a
match, the software calls your do_match method to execute your additional match logic
(if any) and your replacement function customizations (if any).
For example:
• When fraction lengths are within a specific range, replace an operator with a fixed-
point implementation function.
• When a match occurs, modify the replacement function signature based on compile-
time information, such as passing fraction-length values into the function.
This example modifies a fixed-point addition replacement such that the implementation
function passes in the fraction lengths of the input and output data types as arguments.
To create custom code replacement entries that add logic to the code replacement match
and replacement process:
55-114
Customize Match and Replacement Process
targetBitPerShort, ...
targetBitPerInt, ...
targetBitPerLong, ...
targetBitPerLongLong)
• ent is the return handle, which is returned as empty (indicating that the match
failed) or as a TflCOperationEntry handle.
• hThis is the handle to the class instance.
• hCSO is a handle to an object that the code generator creates for querying the
library for a replacement.
• Remaining arguments are the number of bits for various data types of the current
target.
The do_match method adds match criteria that the base class does not provide. The
method makes modifications to the implementation signature. In this case, the
do_match method relies on the base class for checking word size and signedness.
do_match must match only the number of conceptual arguments to the value 3 (two
inputs and one output) and the bias for each argument to value 0. If the code
generator finds a match, do_match:
You can create and add three additional implementation function arguments for
passing fraction lengths in the class definition or in each code replacement entry
definition that instantiates this class. This example creates the arguments, adds them
to a code replacement table definition file, and sets them to specific values in the
class definition code.
classdef TflCustomOperationEntry < RTW.TflCOperationEntryML
methods
function ent = do_match(hThis, ...
hCSO, ... %#ok
targetBitPerChar, ... %#ok
targetBitPerShort, ... %#ok
targetBitPerInt, ... %#ok
targetBitPerLong, ... %#ok
targetBitPerLongLong) %#ok
55-115
55 Code Replacement Customization for MATLAB Code
% The base class checks word size and signedness. Slopes and biases
% have been wildcarded, so the only additional checking to do is
% to check that the biases are zero and that there are only three
% conceptual arguments (one output, two inputs)
ent = []; % default the return to empty, indicating the match failed
Exit the class folder and return to the previous working folder.
55-116
Customize Match and Replacement Process
2 Create and save the following code replacement table definition file,
crl_table_custom_sinfcn_double.m. This file defines a code replacement table
that contains a single operator entry, an entry generator for unsigned 32-bit fixed-
point addition operations, with arbitrary fraction-length values on the inputs and the
output. The table entry:
hTable = RTW.TflTable;
%% Add TflCustomOperationEntry
op_entry = TflCustomOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 30, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_FLOOR'}, ...
'ImplementationName', 'myFixptAdd', ...
55-117
55 Code Replacement Customization for MATLAB Code
55-118
Customize Match and Replacement Process
% Add 3 fraction-length args. Actual values are set during code generation.
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumericConstant', ...
'Name', 'fl_in1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0, ...
'Value', 0);
addEntry(hTable, op_entry);
3 Check the validity of the operator entry.
tbl = crl_table_custom_sinfcn_double
• In the Code Replacement Viewer, view the table definition file.
55-119
55 Code Replacement Customization for MATLAB Code
crviewer(crl_table_custom_sinfcn_double)
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Develop a Code Replacement Library” on page 55-15
55-120
Scalar Operator Code Replacement
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create an entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the getTflArgFromString and
addConceptualArg functions to create and add the arguments.
arg = getTflArgFromString(hTable, 'y1', 'uint8');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(op_entry, arg);
6 Copy the conceptual arguments to the implementation arguments. There are multiple
ways to set up the implementation arguments. This example uses a call to the
55-121
55 Code Replacement Customization for MATLAB Code
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Remap Operator Output to Function Input” on page 55-146
• “Customize Match and Replacement Process” on page 55-113
• “Develop a Code Replacement Library” on page 55-15
• “What Is Code Replacement Customization?” on page 55-3
55-122
Addition and Subtraction Operator Code Replacement
Algorithm Options
When creating a code replacement table entry for an addition or subtraction operator,
first determine the type of algorithm that your library function implements.
• Cast-after-operation (CAO) — The algorithm computes the ideal result of the addition
or subtraction operation of the two inputs. The algorithm then type casts the result to
the output data type. Loss occurs during the type cast. This algorithm behaves
similarly to the C language except when the signedness of the operands does not
match. For example, when you add a signed long operand to an unsigned long
operand, standard C language rules convert the signed long operand to an unsigned
long operand. The result is a value that is not ideal.
55-123
55 Code Replacement Customization for MATLAB Code
Programmatic Specification
Create a code replacement table file, as a MATLAB function, that describes the addition
or subtraction code replacement table entry. In the call to
setTflCOperationEntryParameters, set at least these parameters:
This example sets parameters for a code replacement operator entry for a cast-after-
operation implementation of a uint8 addition.
op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'EntryInfoAlgorithm', 'RTW_CAST_AFTER_OP', ...
'ImplementationName', 'u8_add_u8_u8');
Algorithm Classification
During code generation, the code generator examines addition and subtraction
operations, including adjacent type cast operations, to determine the type of algorithm to
compute the expression result. Based on the data types in the expression and the type of
the accumulator (type used to hold the result of the addition or subtraction operation),
the code generator uses these rules.
55-124
Addition and Subtraction Operator Code Replacement
Algorith Conditions
m
CBO One of the following is true:
Algorith Conditions
m
CBO At least one of the following is true:
55-125
55 Code Replacement Customization for MATLAB Code
Algorith Conditions
m
CAO Net bias is zero and the data types in the expression have equal slope
adjustment factors. For more information on net bias, see “Addition” or
“Subtraction” in “Fixed-Point Operator Code Replacement” on page
55-149 (for MATLAB code) or “Fixed-Point Operator Code
Replacement” on page 54-204 (for Simulink models).
In many cases, the numerical result of a CBO operation is equal to that of a CAO
operation. For example, if the input and output types are such that the operation
produces the ideal result, as in the case of int8 + int8 —> int16. To maximize the
probability of code replacement occurring in such cases, set the algorithm to cast-after-
operation.
Limitations
• The code generator does not replace operations with nonzero net bias.
• When classifying an operation as a CAO operation, the code generator includes the
adjacent casts in the expression when the expression involves only fixed-point types.
Otherwise, the code generator classifies and replaces only the immediate addition or
subtraction operation. Casts that the code generator excludes from the classification
appear in the generated code.
• To enable the code generator to include multiple cast operations, which follow an
addition or subtraction of fixed-point data, in the classification of an expression, the
rounding mode must be simplest or floor. Consider the expression y=(cast A)
(cast B)(u1+u2). If the rounding mode of (cast A), (cast B), and the addition
operator (+) are set to simplest or floor, the code generator takes into account
(cast A) and (cast B) when classifying the expression and performing the
replacement only.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
55-126
See Also
55-127
55 Code Replacement Customization for MATLAB Code
55-128
Small Matrix Operation to Processor Code Replacement
argument is valid. The first table entry specifies [2 2] and the second table entry
specifies [3 3].
% Specify operands and result
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [2 2]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [2 2]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [2 2]);
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the getTflArgFromString
to create the arguments. The convenience methods setReturn and addArgument
specify whether an argument is a return value or argument and adds the argument to
the entry’s array of implementation arguments.
arg = getTflArgFromString(hTable, 'y2', 'void');
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);
addEntry(hTable, op_entry);
8 Create the entry for the second operator mapping.
55-129
55 Code Replacement Customization for MATLAB Code
addEntry(hTable, op_entry);
9 Save the table definition file. Use the name of the table definition function to name
the file.
55-130
See Also
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Matrix Multiplication Operation to MathWorks BLAS Code Replacement” on page
55-132
• “Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement” on page
55-139
• “Remap Operator Output to Function Input” on page 55-146
• “Customize Match and Replacement Process” on page 55-113
• “Develop a Code Replacement Library” on page 55-15
55-131
55 Code Replacement Customization for MATLAB Code
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Define the path for the BLAS function library. If your replacement functions are on
the MATLAB search path or are in your working folder, you can skip this step.
% Define library path for Windows or UNIX
arch = computer('arch');
if ~ispc
LibPath = fullfile('$(MATLAB_ROOT)', 'bin', arch);
else
% Use Stateflow to get the compiler info
compilerInfo = sf('Private','compilerman','get_compiler_info');
compilerName = compilerInfo.compilerName;
if strcmp(compilerName, 'msvc90') || ...
strcmp(compilerName, 'msvc80') || ...
strcmp(compilerName, 'msvc71') || ...
strcmp(compilerName, 'msvc60'), ...
compilerName = 'microsoft';
end
55-132
Matrix Multiplication Operation to MathWorks BLAS Code Replacement
55-133
55 Code Replacement Customization for MATLAB Code
arg = RTW.TflArgCharConstant('TRANSA');
% Possible values for PassByType property are
% RTW_PASSBY_AUTO, RTW_PASSBY_POINTER,
% RTW_PASSBY_VOID_POINTER, RTW_PASSBY_BASE_POINTER
arg.PassByType = 'RTW_PASSBY_POINTER';
op_entry.Implementation.addArgument(arg);
arg = RTW.TflArgCharConstant('TRANSB');
arg.PassByType = 'RTW_PASSBY_POINTER';
op_entry.Implementation.addArgument(arg);
55-134
Matrix Multiplication Operation to MathWorks BLAS Code Replacement
op_entry.Implementation.addArgument(arg);
addEntry(hTable, op_entry);
55-135
55 Code Replacement Customization for MATLAB Code
arg = RTW.TflArgCharConstant('TRANS');
arg.PassByType = 'RTW_PASSBY_POINTER';
55-136
Matrix Multiplication Operation to MathWorks BLAS Code Replacement
op_entry.Implementation.addArgument(arg);
addEntry(hTable, op_entry);
55-137
55 Code Replacement Customization for MATLAB Code
10 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Small Matrix Operation to Processor Code Replacement” on page 55-128
• “Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement” on page
55-139
• “Remap Operator Output to Function Input” on page 55-146
• “Customize Match and Replacement Process” on page 55-113
• “Develop a Code Replacement Library” on page 55-15
55-138
Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement
55-139
55 Code Replacement Customization for MATLAB Code
55-140
Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement
%
% Since CRLs do not have the ability to specify enums, you must
% use integer. (This will cause problems with C++ code generation,
% so for C++, use a wrapper function to cast each int to the
% corresponding enumeration type.)
%
% When a match occurs, the code generator computes the
% values for M, N, K, LDA, LDB, and LDC and insert them into the
% generated code.
55-141
55 Code Replacement Customization for MATLAB Code
addEntry(hTable, op_entry);
9 Create the entry for the second mapping.
% Create table entry for cblas_dgemv
op_entry = RTW.TflCBlasEntryGenerator;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 100, ...
'ImplementationName', 'cblas_dgemv', ...
'ImplementationHeaderFile', 'cblas.h', ...
'ImplementationHeaderPath', LibPath, ...
'AdditionalIncludePaths', {LibPath}, ...
'GenCallback', 'RTW.copyFileToBuildDir', ...
'SideEffects', true);
55-142
Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement
addEntry(hTable, op_entry);
10 Save the table definition file. Use the name of the table definition function to name
the file.
To test this example, create a model that uses two Product blocks. For example:
1 Create a model that includes two Product blocks, such as the following:
55-143
55 Code Replacement Customization for MATLAB Code
• On the Solver pane, select a fixed-step, discrete solver with a fixed-step size such
as 0.1.
• On the Code Generation pane, select an ERT-based system target file.
• On the Code Generation > Interface pane, select the code replacement library
that contains your addition operation entry.
3 For each Product block, set the block parameter Multiplication to the value
Matrix(*).
4 In the Model Explorer, configure the Signal Attributes for the In1, In2, and In3
source blocks. For In1 and In2, set Port dimensions to [3 3] and set the Data
type to double. For In3, set Port dimensions to [3 1] and set the Data type to
double.
5 Generate code and a code generation report.
6 Review the code replacements.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Small Matrix Operation to Processor Code Replacement” on page 55-128
• “Matrix Multiplication Operation to MathWorks BLAS Code Replacement” on page
55-132
• “Remap Operator Output to Function Input” on page 55-146
• “Customize Match and Replacement Process” on page 55-113
55-144
See Also
55-145
55 Code Replacement Customization for MATLAB Code
For example, for a sum operation, the code generator produces code similar to:
If you remap the output to the first input, the code generator produces code similar to:
The following table definition file for a sum operation remaps operator output y1 as the
first function input argument.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create an entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
55-146
Remap Operator Output to Function Input
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the getTflArgFromString and
addConceptualArg functions to create and add the arguments.
arg = getTflArgFromString(hTable, 'y1', 'uint8');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(op_entry, arg);
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the getTflArgFromString
function to create the arguments. When defining the implementation function return
argument, create a new void output argument, for example, y2. When defining the
implementation function argument for the conceptual output argument (y1), set the
operator output argument as an additional input argument. Mark its IOType as
output. Make its type a pointer type. The convenience methods setReturn and
addArgument specify whether an argument is a return value or argument and adds
the argument to the entry’s array of implementation arguments.
% Create new void output y2
arg = getTflArgFromString(hTable, 'y2', 'void');
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);
% Set y1 as first input arg, mark IOType as output, and use pointer type
arg=getTflArgFromString(hTable, 'y1', 'uint8*');
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.addArgument(arg);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
To test this example, create a model that uses an Add block. For example:
55-147
55 Code Replacement Customization for MATLAB Code
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Develop a Code Replacement Library” on page 55-15
55-148
Fixed-Point Operator Code Replacement
55-149
55 Code Replacement Customization for MATLAB Code
createAndAddConceptualArg
function:
55-150
Fixed-Point Operator Code Replacement
createAndAddConceptualArg
function:
createAndAddConceptualArg
function:
55-151
55 Code Replacement Customization for MATLAB Code
V = V% = SQ + B
•
V is an arbitrarily precise real-world value.
•
V% is the approximate real-world value that results from fixed-point representation.
•
Q is an integer that encodes V% , referred to as the quantized integer.
•
S is a coefficient of Q , referred to as the slope.
•
B is an additive correction, referred to as the bias.
The general equation for an operation between fixed-point operands is:
Addition
The operation V0 = V1 + V2 implies that
ÊS ˆ ÊS ˆ Ê B + B2 - B0 ˆ
Q0 = Á 1 ˜ Q1 + Á 2 ˜ Q2 + Á 1 ˜
Ë S0 ¯ Ë S0 ¯ Ë S0 ¯
If an addition replacement function is defined such that the scaling on the operands and
sum are equal and the net bias
55-152
Fixed-Point Operator Code Replacement
Ê B1 + B2 - B0 ˆ
Á ˜
Ë S0 ¯
is zero (for example, a function s8_add_s8_s8 that adds two signed 8-bit values and
produces a signed 8-bit result), then the operator entry must set the operator entry
parameters SlopesMustBeTheSame and MustHaveZeroNetBias to true. To match for
replacement, the slopes must be the same for all addition conceptual arguments. (For
parameter descriptions, see the reference page for the function
setTflCOperationEntryParameters.)
Subtraction
The operation V0 = V1 − V2 implies that
ÊS ˆ ÊS ˆ Ê B1 - B2 - B0 ˆ
Q0 = Á 1 ˜ Q1 - Á 2 ˜ Q2 + Á ˜
Ë S0 ¯ Ë S0 ¯ Ë S0 ¯
If a subtraction replacement function is defined such that the scaling on the operands and
difference are equal and the net bias
Ê B1 - B2 - B0 ˆ
Á ˜
Ë S0 ¯
is zero (for example, a function s8_sub_s8_s8 that subtracts two signed 8-bit values and
produces a signed 8-bit result), then the operator entry must set the operator entry
parameters SlopesMustBeTheSame and MustHaveZeroNetBias to true. To match for
replacement, the slopes must be the same for all subtraction conceptual arguments. (For
parameter descriptions, see the reference page for the function
setTflCOperationEntryParameters.)
Multiplication
There are different ways to specify multiplication replacements. The most direct way is to
specify an exact match of the input and output types. This is feasible if a model contains
only a few (known) slope and bias combinations. Use the TflCOperationEntry class
and specify the exact values of slope and bias on each argument. For scenarios where
55-153
55 Code Replacement Customization for MATLAB Code
there are numerous slope/bias combinations, it is not feasible to specify each value with a
different entry. Use a net slope entry or create a custom entry.
It is common to replace all multiplication operations that have a net slope of 1.0 with a
function that performs C-style multiplication. For example, to replace all signed 8-bit
multiplications that have a net scaling of 1.0 with the s8_mul_s8_u8_ replacement
function, the operator entry must define a net slope factor, F2E. You specify the values for
F and E using operator entry parameters NetSlopeAdjustmentFactor and
NetFixedExponent. For the s8_mul_s8_u8 function, set
NetSlopeAdjustmentFactor to 1 and NetFixedExponent to 0.0. Also, set the
operator entry parameters SlopesMustBeTheSame and MustHaveZeroNetBias to
true. To match for replacement, the biases must be zero for all multiplication conceptual
arguments. (For parameter descriptions, see the reference page for the function
setTflCOperationEntryParameters.)
Division
There are different ways to specify division replacements. The most direct way is to
specify an exact match of the input and output types. This is feasible if a model contains
only a few (known) slope and bias combinations. For this, use the TflCOperationEntry
class and specify the exact values of slope and bias on each argument. For scenarios
where there are numerous slope/bias combinations, it is not feasible to specify each value
with a different entry. For this, use a net slope entry or create a custom entry (see
“Customize Match and Replacement Process” on page 54-159).
55-154
Fixed-Point Operator Code Replacement
ÊSQ ˆ
S0Q0 = Á 1 1 ˜
Ë S2Q2 ¯
ÊQ ˆ
Q0 = S n Á 1 ˜
Ë Q2 ¯
It is common to replace all division operations that have a net slope of 1.0 with a function
that performs C-style division. For example, to replace all signed 8-bit divisions that have
a net scaling of 1.0 with the s8_mul_s8_u8_ replacement function, the operator entry
must define a net slope factor, F2E. You specify the values for F and E using operator
entry parameters NetSlopeAdjustmentFactor and NetFixedExponent. For the
s16_netslope0p5_div_s16_s16 function, you would set
NetSlopeAdjustmentFactor to 1 and NetFixedExponent to 0.0. Also, set the
operator entry parameters SlopesMustBeTheSame and MustHaveZeroNetBias to
true. To match for replacement, the biases must be zero for all division conceptual
arguments. (For parameter descriptions, see the reference page for the function
setTflCOperationEntryParameters.)
ÊS ˆ
Q0 = Á 1 ˜ Q1
Ë S0 ¯
Q0 = S nQ1
where Sn is the net slope. Set the operator entry parameters SlopesMustBeTheSame and
MustHaveZeroNetBias to true. To match for replacement, the biases must be zero for
55-155
55 Code Replacement Customization for MATLAB Code
all cast conceptual arguments. (For parameter descriptions, see the reference page for
the function setTflCOperationEntryParameters.)
Shift
The shift left or shift right operation V0 = (V1 / 2n) implies, for binary-point-only scaling,
that
ÊSQ ˆ
S0Q0 = Á 1 n 1 ˜
Ë 2 ¯
Ê S ˆ ÊQ ˆ
Q0 = Á 1 ˜ + Á n1 ˜
Ë S0 ¯ Ë 2 ¯
ÊQ ˆ
Q0 = S n Á n1 ˜
Ë2 ¯
where Sn is the net slope. Set the operator entry parameters SlopesMustBeTheSame and
MustHaveZeroNetBias to true. To match for replacement, the biases must be zero for
all shift conceptual arguments. (For parameter descriptions, see the reference page for
the function setTflCOperationEntryParameters.)
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Binary-Point-Only Scaling Code Replacement” on page 55-158
• “Slope Bias Scaling Code Replacement” on page 55-161
• “Net Slope Scaling Code Replacement” on page 55-164
• “Equal Slope and Zero Net Bias Code Replacement” on page 55-170
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 55-173
• “Shift Left Operations and Code Replacement” on page 55-177
55-156
See Also
55-157
55 Code Replacement Customization for MATLAB Code
This example creates a code replacement entry for multiplication of fixed-point data
types. You specify arguments using binary-point-only scaling. The example defines the
function mapping programmatically. Alternatively, you can use the Code Replacement
Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as multiplication, the saturation mode as saturate on integer overflow,
rounding modes as unspecified, and the name of the replacement function as
s32_mul_s16_s16_binarypoint.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 90, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'}, ...
'ImplementationName', 's32_mul_s16_s16_binarypoint', ...
'ImplementationHeaderFile', 's32_mul_s16_s16_binarypoint.h', ...
'ImplementationSourceFile', 's32_mul_s16_s16_binarypoint.c');
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call. Each argument specifies that the data type is fixed-point, the mode is
binary-point-only scaling, and its derived slope and bias values must exactly match
the call-site slope and bias values. The output argument is 32 bits, signed, with a
55-158
Binary-Point-Only Scaling Code Replacement
fraction length of 28. The input arguments are 16 bits, signed, with fraction lengths
of 15 and 13.
createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', true, ...
'WordLength', 32, ...
'FractionLength', 28);
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the
createAndSetCImplementationReturn and
createAndAddImplementationArg functions to create and add implementation
arguments to the entry. Implementation arguments must describe fundamental
numeric data types (not fixed-point data types). In this case, the output argument is
32 bits and signed (int32). The input arguments are 16 bits and signed (int16).
createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', true, ...
'WordLength', 32, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
55-159
55 Code Replacement Customization for MATLAB Code
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Fixed-Point Operator Code Replacement” on page 55-149
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 55-173
• “Shift Left Operations and Code Replacement” on page 55-177
• “Remap Operator Output to Function Input” on page 55-146
• “Customize Match and Replacement Process” on page 55-113
• “Develop a Code Replacement Library” on page 55-15
55-160
Slope Bias Scaling Code Replacement
This example creates a code replacement entry for division of fixed-point data types. You
specify arguments using slope bias scaling. The example defines the function mapping
programmatically. Alternatively, you can use the Code Replacement Tool to define the
same mapping.
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_fixed_s16divslopebias
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as division, the saturation mode as saturate on integer overflow, rounding
modes as round to ceiling, and the name of the replacement function as
s16_div_s16_s16_slopebias.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_DIV', ...
'Priority', 90, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_CEILING'}, ...
'ImplementationName', 's16_div_s16_s16_slopebias', ...
'ImplementationHeaderFile', 's16_div_s16_s16_slopebias.h', ...
'ImplementationSourceFile', 's16_div_s16_s16_slopebias.c');
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call. Each argument specifies that the data type is fixed-point, the mode is
slope bias scaling, and its specified slope and bias values must exactly match the call-
site slope and bias values. The output argument and input arguments are 16 bits,
signed, each with specific slope bias specifications.
55-161
55 Code Replacement Customization for MATLAB Code
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
55-162
See Also
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Fixed-Point Operator Code Replacement” on page 55-149
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 55-173
• “Shift Left Operations and Code Replacement” on page 55-177
• “Remap Operator Output to Function Input” on page 55-146
• “Customize Match and Replacement Process” on page 55-113
• “Develop a Code Replacement Library” on page 55-15
55-163
55 Code Replacement Customization for MATLAB Code
This example creates a code replacement entry for division of fixed-point data types,
using wrap on overflow saturation mode and a net slope. The example defines the
function mapping programmatically. Alternatively, you can use the Code Replacement
Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntryGenerator_Netslope function, which provides access
to the fixed-point parameters NetSlopeAdjustmentFactor and
NetFixedExponent.
wv = [16,32];
for iy = 1:2
for inum = 1:2
for iden = 1:2
hTable = getDivOpEntry(hTable, ...
fixdt(1,wv(iy)),fixdt(1,wv(inum)),fixdt(1,wv(iden)));
end
end
end
%---------------------------------------------------------
function hTable = getDivOpEntry(hTable,dty,dtnum,dtden)
%---------------------------------------------------------
% Create an entry for division of fixed-point data types where
% arguments are specified using Slope and Bias scaling
% Saturation on, Rounding unspecified
funcStr = sprintf('user_div_%s_%s_%s',...
typeStrFunc(dty),...
typeStrFunc(dtnum),...
typeStrFunc(dtden));
55-164
Net Slope Scaling Code Replacement
op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as division, the saturation mode as wrap on overflow, rounding modes as
unspecified, and the name of the replacement function as user_div_*.
NetSlopeAdjustmentFactor and NetFixedExponent specify the F and E parts of
the net slope F2E.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_DIV', ...
'Priority', 90, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW',...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'},...
'NetSlopeAdjustmentFactor', 1.0, ...
'NetFixedExponent', 0.0, ...
'ImplementationName', funcStr, ...
'ImplementationHeaderFile', [funcStr,'.h'], ...
'ImplementationSourceFile', [funcStr,'.c']);
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call. Specify each argument as fixed-point and signed. Also, for each
argument, specify that code replacement request processing does not check for an
exact match to the call-site slope and bias values.
createAndAddConceptualArg(op_entry, ...
'RTW.TflArgNumeric', ...
'Name', 'y1',...
'IOType', 'RTW_IO_OUTPUT',...
'CheckSlope', false,...
'CheckBias', false,...
'DataTypeMode', 'Fixed-point: slope and bias scaling',...
'IsSigned', dty.Signed,...
'WordLength', dty.WordLength,...
'Bias', 0);
createAndAddConceptualArg(op_entry, ...
'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT',...
'CheckSlope', false,...
'CheckBias', false,...
'DataTypeMode', 'Fixed-point: slope and bias scaling',...
'IsSigned', dtnum.Signed,...
'WordLength', dtnum.WordLength,...
'Bias', 0);
createAndAddConceptualArg(op_entry, ...
'RTW.TflArgNumeric', ...
'Name', 'u2', ...
55-165
55 Code Replacement Customization for MATLAB Code
'IOType', 'RTW_IO_INPUT',...
'CheckSlope', false,...
'CheckBias', false,...
'DataTypeMode', 'Fixed-point: slope and bias scaling',...
'IsSigned', dtden.Signed,...
'WordLength', dtden.WordLength,...
'Bias', 0);
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the getTflArgFromString
function to create the arguments. Implementation arguments must describe
fundamental numeric data types (not fixed-point data types). The convenience
methods setReturn and addArgument specify whether an argument is a return
value or argument. These methods add the argument to the entry array of
implementation arguments.
arg = getTflArgFromString(hTable, 'y1', typeStrBase(dty));
op_entry.Implementation.setReturn(arg);
addEntry(hTable, op_entry);
8 Define functions that determine the data type word length.
%-------------------------------------------------------------
function str = typeStrFunc(dt)
%-------------------------------------------------------------
if dt.Signed
sstr = 's';
else
sstr = 'u';
end
str = sprintf('%s%d',sstr,dt.WordLength);
%-------------------------------------------------------------
function str = typeStrBase(dt)
%-------------------------------------------------------------
if dt.Signed
sstr = ;
else
sstr = 'u';
end
str = sprintf('%sint%d',sstr,dt.WordLength);
55-166
Net Slope Scaling Code Replacement
9 Save the table definition file. Use the name of the table definition function to name
the file.
This example creates a code replacement entry for division of fixed-point data types,
using the ceiling rounding mode and a net slope scaling factor. The example defines the
function mapping programmatically. Alternatively, you can use the Code Replacement
Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntryGenerator_Netslope function, which provides access
to the fixed-point parameters NetSlopeAdjustmentFactor and
NetFixedExponent.
op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as division, the saturation mode as saturation off, rounding modes as round
to ceiling, and the name of the replacement function as s16_div_s16_s16.
NetSlopeAdjustmentFactor and NetFixedExponent specify the F and E parts of
the relative scaling factor F2E.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_DIV', ...
'Priority', 90, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_CEILING'}, ...
'NetSlopeAdjustmentFactor', 1.0, ...
'NetFixedExponent', 0.0, ...
55-167
55 Code Replacement Customization for MATLAB Code
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call. Specify each argument as fixed-point, 16 bits, and signed. Also, for each
argument, specify that code replacement request processing does not check for an
exact match to the call-site slope and bias values.
createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataType', 'Fixed', ...
'IsSigned', true, ...
'WordLength', 16);
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the
createAndSetCImplementationReturn and
createAndAddImplementationArg functions to create and add implementation
arguments to the entry. Implementation arguments must describe fundamental
numeric data types (not fixed-point data types). In this case, the output and input
arguments are 16 bits and signed (int16).
createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
55-168
See Also
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 0);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Fixed-Point Operator Code Replacement” on page 55-149
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 55-173
• “Shift Left Operations and Code Replacement” on page 55-177
• “Remap Operator Output to Function Input” on page 55-146
• “Customize Match and Replacement Process” on page 55-113
• “Develop a Code Replacement Library” on page 55-15
55-169
55 Code Replacement Customization for MATLAB Code
This example creates a code replacement entry for addition of fixed-point data types.
Slopes must be equal and net bias must be zero across the operator inputs and output.
The example defines the function mapping programmatically. Alternatively, you can use
the Code Replacement Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_fixed_slopeseq_netbiaszero
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntryGenerator function, which provides access to the fixed-
point parameters SlopesMustBeTheSame and MustHaveZeroNetBias.
op_entry = RTW.TflCOperationEntryGenerator;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as addition, the saturation mode as saturation off, rounding modes as
unspecified, and the name of the replacement function as
u16_add_SameSlopeZeroBias. SlopesMustBeTheSame and
MustHaveZeroNetBias are set to true, indicating that slopes must be equal and
net bias must be zero across the addition inputs and output.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 90, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'}, ...
'SlopesMustBeTheSame', true, ...
'MustHaveZeroNetBias', true, ...
'ImplementationName', 'u16_add_SameSlopeZeroBias', ...
'ImplementationHeaderFile', 'u16_add_SameSlopeZeroBias.h', ...
'ImplementationSourceFile', 'u16_add_SameSlopeZeroBias.c');
5 Create conceptual arguments y1, u1, and u2. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
55-170
Equal Slope and Zero Net Bias Code Replacement
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the
createAndSetCImplementationReturn and
createAndAddImplementationArg functions to create and add implementation
arguments to the entry. Implementation arguments must describe fundamental
numeric data types (not fixed-point data types). In this case, the output and input
arguments are 16 bits and unsigned (uint16).
createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', false, ...
'WordLength', 16, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 16, ...
'FractionLength', 0);
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
55-171
55 Code Replacement Customization for MATLAB Code
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Fixed-Point Operator Code Replacement” on page 55-149
• “Data Type Conversions (Casts) and Operator Code Replacement” on page 55-173
• “Shift Left Operations and Code Replacement” on page 55-177
• “Remap Operator Output to Function Input” on page 55-146
• “Customize Match and Replacement Process” on page 55-113
• “Develop a Code Replacement Library” on page 55-15
55-172
Data Type Conversions (Casts) and Operator Code Replacement
This example creates a code replacement entry that replaces int32 to int16 data type
conversion (cast) operations. The example defines the function mapping
programmatically. Alternatively, you can use the Code Replacement Tool to define the
same mapping.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as cast, the saturation mode as saturate on integer overflow, rounding
modes as toward negative infinity, and the name of the replacement function as
my_sat_cast.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_CAST', ...
'Priority', 50, ...
'ImplementationName', 'my_sat_cast', ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_FLOOR'}, ...
'ImplementationHeaderFile', 'some_hdr.h', ...
'ImplementationSourceFile', 'some_hdr.c');
55-173
55 Code Replacement Customization for MATLAB Code
6 Create the int32 argument as conceptual and implementation argument u1. This
example uses calls to the getTflArgFromString and addConceptualArg
functions to create the conceptual argument and add it to the entry. Convenience
method addArgument specifies the argument as implementation input argument.
arg = getTflArgFromString(hTable, 'u1', 'int32');
addConceptualArg(op_entry, arg);
op_entry.Implementation.addArgument(arg);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hLib, hEnt);
8 Save the table definition file. Use the name of the table definition function to name
the file.
You can use code replacement entries to replace code that the code generator produces
for data type conversion (cast) operations.
This example creates a code replacement entry to replace data type conversions (casts) of
fixed-point data types by using a net slope. The example defines the function mapping
programmatically. Alternatively, you can use the Code Replacement Tool to define the
same mapping.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntryGenerator_Netslope function, which provides access
to the fixed-point parameters NetSlopeAdjustmentFactor and
NetFixedExponent
op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as cast, the saturation mode as saturate on integer overflow, rounding
modes as toward negative infinity, and the name of the replacement function as
55-174
Data Type Conversions (Casts) and Operator Code Replacement
55-175
55 Code Replacement Customization for MATLAB Code
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', InSgn, ...
'WordLength', InWL, ...
'FractionLength', 0);
7 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
8 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
• “Define Code Replacement Mappings” on page 55-29
• “Fixed-Point Operator Code Replacement” on page 55-149
• “Shift Left Operations and Code Replacement” on page 55-177
• “Remap Operator Output to Function Input” on page 55-146
• “Customize Match and Replacement Process” on page 55-113
• “Develop a Code Replacement Library” on page 55-15
55-176
Shift Left Operations and Code Replacement
This example creates a code replacement entry to replace shift left operations for int16
data. The example defines the function mapping programmatically. Alternatively, you can
use the Code Replacement Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_shift_left_int16
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntry function.
op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as shift left and the name of the replacement function as my_shift_left.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_SL', ...
'Priority', 50, ...
'ImplementationName', 'my_shift_left', ...
'ImplementationHeaderFile', 'some_hdr.h', ...
'ImplementationSourceFile', 'some_hdr.c');
5 Create the int16 argument as conceptual argument y1 and the implementation
return value. There are multiple ways to set up the conceptual and implementation
arguments. This example uses calls to the getTflArgFromString and
addConceptualArg functions to create the conceptual argument and add it to the
entry. Convenience method setReturn specifies the argument as the implementation
return value.
arg = getTflArgFromString(hTable, 'y1', 'int16');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(op_entry, arg);
op_entry.Implementation.setReturn(arg);
6 Create the int16 argument as conceptual and implementation argument u1. This
example uses calls to the getTflArgFromString and addConceptualArg
functions to create the conceptual argument and add it to the entry. Convenience
method addArgument specifies the argument as an implementation input argument.
55-177
55 Code Replacement Customization for MATLAB Code
7 Create the int8 argument as conceptual and implementation argument u2. This
example uses calls to the getTflArgFromString and addConceptualArg
functions to create the conceptual argument and add it to the entry. This argument
specifies the number of bits to shift the previous input argument. Because the
argument type is not relevant, the example disables type checking by setting the
CheckType property to false. Convenience method addArgument specifies the
argument as implementation input argument.
arg = getTflArgFromString(hTable, 'u2', 'int8');
arg.CheckType = false;
addConceptualArg(op_entry, arg);
op_entry.Implementation.addArgument(arg);
addEntry(hTable, op_entry);
• Save the table definition file. Use the name of the table definition function to name the
file.
You can use code replacement entries to replace code that the code generator produces
for shift (<<) operations.
This example creates a code replacement entry to replace shift left operations for fixed-
point data using a net slope. The example defines the function mapping programmatically.
Alternatively, you can use the Code Replacement Tool to define the same mapping.
1 Create a table definition file that contains a function definition. For example:
hTable = RTW.TflTable;
3 Create the entry for the operator mapping with a call to the
RTW.TflCOperationEntryGenerator_Netslope function. This function provides
access to the fixed-point parameters NetSlopeAdjustmentFactor and
NetFixedExponent.
55-178
Shift Left Operations and Code Replacement
op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The parameters specify the type of
operation as shift left, the saturation mode as saturate on integer overflow, rounding
modes as toward negative infinity, and the name of the replacement function as
my_fxp_shift_left. NetSlopeAdjustmentFactor and NetFixedExponent
specify the F and E parts of the net slope F2E.
InFL = 2;
InWL = 16;
InSgn = true;
OutFL = 4;
OutWL = 32;
OutSgn = true;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_SL', ...
'Priority', 50, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_FLOOR'}, ...
'NetSlopeAdjustmentFactor', 1.0, ...
'NetFixedExponent', (OutFL - InFL),...
'ImplementationName', 'my_fxp_shift_left', ...
'ImplementationHeaderFile', 'some_hdr.h', ...
'ImplementationSourceFile', 'some_hdr.c');
5 Create conceptual arguments y1 and u1. There are multiple ways to set up the
conceptual arguments. This example uses calls to the
createAndAddConceptualArg function to create and add an argument with one
function call. Each argument is specified as fixed-point and signed. Each argument
specifies that code replacement request processing does not check for an exact
match to the call-site slope and bias values.
createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', OutSgn, ...
'WordLength', OutWL, ...
'FractionLength',OutFL);
55-179
55 Code Replacement Customization for MATLAB Code
6 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the
createAndSetCImplementationReturn and
createAndAddImplementationArg functions to create and add implementation
arguments to the entry. Implementation arguments must describe fundamental
numeric data types (not fixed-point data types).
createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', OutSgn, ...
'WordLength', OutWL, ...
'FractionLength', 0);
7 Create the int8 argument as conceptual and implementation argument u2. This
example uses calls to the getTflArgFromString and addConceptualArg
functions to create the conceptual argument and add it to the entry. This argument
specifies the number of bits to shift the previous input argument. Because the
argument type is not relevant, type checking is disabled by setting the CheckType
property to false. Convenience method addArgument specifies the argument as
implementation input argument.
arg = getTflArgFromString(hTable, 'u2', 'uint8');
arg.CheckType = false;
addConceptualArg(op_entry, arg);
op_entry.Implementation.addArgument(arg);
8 Add the entry to a code replacement table with a call to the addEntry function.
addEntry(hTable, op_entry);
9 Save the table definition file. Use the name of the table definition function to name
the file.
See Also
More About
• “Code You Can Replace from MATLAB Code” on page 55-5
55-180
See Also
55-181
Performance
183
56
56-2
Increase Code Generation Speed
The amount of time it takes to generate code for a model depends on the size and
configuration settings of the model. For instance, if you are working with a large model, it
can take awhile to generate code. To decrease the amount of time for code generation of
a model, try one or more of the following methods:
56-3
56 Optimizations for Generated Code in Simulink Coder
across the cores of a multicore host computer. If you have MATLAB Distributed
Computing Server software, you can distribute code generation and compilation for each
referenced model across remote workers in your MATLAB Distributed Computing Server
configuration.
The performance gain realized by using parallel builds for referenced models depends on
several factors, including:
• How many models can be built in parallel for a given model referencing hierarchy
• The size of the referenced models
• Parallel computing resources such as the number of local and remote workers
available
• The hardware attributes of the local and remote machines (amount of RAM, number of
cores, and so on)
For more information, see “Reduce Build Time for Referenced Models” (Simulink Coder).
You can improve code generation speed by specifying the maximum number of elements
that data vectors can have for the code generator to copy this data to model.rtw. When
a data vector exceeds the specified size, the code generator places a reference key in
model.rtw. The TLC uses this key to access the data from Simulink and format it into the
generated code. Reference keys result in maintaining only one copy of large data vectors
in memory.
The default value above which the code generator uses reference keys in place of actual
data values is 10 elements. You can verify this value. In the Command Window, type the
following command:
get_param(0, 'RTWDataReferencesMinSize')
56-4
See Also
To set the threshold to a different value, in the Command Window, type the following
set_param function:
Provide an integer value for size that specifies the number of data elements above which
the code generator uses reference keys in place of actual data values.
On the Code Generation pane in the Model Configuration Parameters dialog box, you
can specify that the build process generate only code by selecting the Generate code
only parameter. You can specify that the code generation process build a makefile by
selecting the Configuration Parameters > Code Generation > Build process >
Makefile configuration > Generate makefile parameter.
See Also
Related Examples
• “Enable parallel model reference builds” (Simulink)
• “MATLAB worker initialization for builds” (Simulink)
• “Reduce Build Time for Referenced Models” on page 43-45
56-5
56 Optimizations for Generated Code in Simulink Coder
The default setting is Optimizations off (faster builds). Selecting the value
Custom enables the Custom compiler optimization flags field, in which you can enter
custom compiler optimization flags (for example, -O2).
Note If you specify compiler options for your makefile build using OPT_OPTS, MEX_OPTS
(except MEX_OPTS="-v"), or MEX_OPT_FILE, the value of Compiler optimization level
is ignored and a warning is issued about the ignored parameter.
For more information about the Compiler optimization level parameter and its values,
see “Compiler optimization level” (Simulink Coder) and “Custom compiler optimization
flags” (Simulink Coder).
See Also
Related Examples
• “Template Makefiles and Make Options” on page 43-26
• “Configure a System Target File” on page 33-2
• “Support Compiler Optimization Level Control” on page 74-96
56-6
Optimization Tools and Techniques
Before running the Model Advisor, select the target you plan to use for code generation.
The Model Advisor works most effectively with ERT and ERT-based system target files.
Use the following examples to investigate optimizing models for code generation using
the Model Advisor:
• rtwdemo_advisor1
• rtwdemo_advisor2
• rtwdemo_advisor3
For more information on using the Model Advisor, see “Run Model Checks” (Simulink).
For more information about the checks, see “Simulink Coder Checks” (Simulink Coder).
This restriction prevents long parameter lists from appearing in the code generated for a
graphical function. You can access local data that resides in the same chart as the
graphical function. For more information, see “Reuse Logic Patterns Using Graphical
Functions” (Stateflow).
56-7
56 Optimizations for Generated Code in Simulink Coder
When you use a graphical function in a Stateflow chart, select Inline or Function for
the property Function Inline Option. Otherwise, the code generated for a graphical
function may not appear as you want. For more information, see “Specify Graphical
Function Properties” (Stateflow).
When you use a bus object, you reduce the number of parameters in the parameter list of
a generated function. This guideline also applies to output signals of a chart. For more
information, see “Define Stateflow Structures” (Stateflow).
When you use a bus object, you reduce the number of parameters in the parameter list of
a generated function. This guideline also applies to output signals of a chart. For more
information, see “Define Stateflow Structures” (Stateflow).
The code generated for discrete charts that are not inside a triggered or enabled
subsystem uses integer counters to track time instead of Simulink provided time. This
allows for more efficient code generation in terms of overhead and memory, as well as
enabling this code for use in Software-in-the-Loop(SIL) and Processor-in-the-Loop(PIL)
simulation modes.
• For Embedded Coder users, if your application uses only integer arithmetic, clear the
Support floating-point numbers parameter in the Software environment section
of the Interface pane so that the generated code contains no floating-point data or
operations. When this parameter is cleared, an error is raised if noninteger data or
expressions are encountered during code generation. The error message reports the
offending blocks and parameters.
• Disable the Configuration Parameters > Code Generation > Interface >
Advanced parameters > MAT-file loggingparameter. Deselecting this parameter
eliminates extra code and memory usage for initializing, updating, and cleaning-up
56-8
Optimization Tools and Techniques
logging variables. In addition, the code generated to support MAT-file logging invokes
malloc, which can be undesirable for your application.
• Use the Upgrade Advisor to upgrade older models (saved by prior versions or the
current version) to use current features. For details, see “Model Upgrades” (Simulink).
• Before building, set optimization flags for the compiler (for example, -O2 for gcc, -Ot
for the Microsoft Visual C++ compiler).
• Directly inline C/C++ S-functions into the generated code by writing a TLC file for the
S-function. For more information, see “Accelerate Simulation, Reuse Code, or Protect
Intellectual Property by Using S-Function Target” (Simulink Coder) and see “Inline C
MEX S-Functions” (Simulink Coder).
• Use a Simulink data type other than double when possible. The available data types
are Boolean, signed and unsigned 8-, 16-, and 32-bit integers, and 32- and 64-bit
floats (a double is a 64-bit float). For more information, see “About Data Types in
Simulink” (Simulink). For a block-by-block summary, click
showblockdatatypetable or type the command in the Command Window.
• For tunable block parameters that you configure to store in memory in the generated
code, you can match parameter data types with signal data types to eliminate
unnecessary typecasts and C shifts. Where possible, store parameter values in small
integer data types. See “Parameter Data Types in the Generated Code” on page 22-
156.
• Remove repeated values in lookup table data.
• Use the Merge block to merge the output of signals wherever possible. This block is
particularly helpful when you need to control the execution of function-call subsystems
with a Stateflow chart. The following model shows an example of how to use the
Merge block.
56-9
56 Optimizations for Generated Code in Simulink Coder
When more than one signal connected to a Merge block has a non-Auto storage class,
all non-Auto signals connected to that block must be identically labeled and have the
same storage class. When Merge blocks connect directly to one another, these rules
apply to the signals connected to any of the Merge blocks in the group.
See Also
Related Examples
• “Increase Code Generation Speed” on page 56-3
• “Execution Profiling for Generated Code” on page 56-12
• “Optimization Pane” (Simulink Coder)
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
56-10
Control Memory Allocation for Time Counters
The size of the time counters in generated code is 8, 16, 32, or 64 bits. The size is set
automatically to the minimum that can accommodate the duration value specified by
Application lifespan (days) given the step size specified in the Configuration
Parameters Solver pane. To minimize the amount of RAM used by time counters, specify
the smallest lifespan possible and the largest step size possible.
An application runs to its specified lifespan. It may be able to run longer. For example,
running a model with a step size of one millisecond (0.001 seconds) for one day requires a
32-bit timer, which could continue running without overflow for 49 days more.
To maximize application lifespan, specify Application lifespan (days) as inf. This value
allocates 64 bits (two uint32 words) for each timer. Using 64 bits to store timing data
would allow a model with a step size of 0.001 microsecond (10E-09 seconds) to run for
more than 500 years, which would rarely be required. 64-bit counters do not violate the
usual code generator length limitation of 32 bits because the value of a time counter does
not provide the value of a signal, state, or parameter.
See Also
“Application lifespan (days)” (Simulink)
Related Examples
• “Absolute and Elapsed Time Computation” (Simulink Coder)
• “Timers in Asynchronous Tasks” (Simulink Coder)
56-11
56 Optimizations for Generated Code in Simulink Coder
• Determine whether the generated code meets execution time requirements for real-
time deployment on your target hardware.
• Identify code sections that require performance improvements.
The following tasks represent a general workflow that uses code execution profiling:
• If the algorithm code easily meets the requirements, consider enhancing your
algorithm to exploit available processing power.
• If the code cannot be executed in real time, look for ways to reduce execution
time.
Identify the tasks that require the most time. For these tasks, investigate whether
trade-offs between functionality and speed are possible.
To find information about code execution profiling with Simulink products, use the
following table.
56-12
Execution Profiling for Generated Code
56-13
56 Optimizations for Generated Code in Simulink Coder
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “SIL and PIL Simulations” on page 67-2
56-14
Optimize Generated Code by Combining Multiple for Constructs
In the model, rtwdemo_forloop, the Switch block and MATLAB Function block represent
for constructs. In the In1 Block Parameters dialog box, the Port dimensions parameter
is set to 10 .
56-15
56 Optimizations for Generated Code in Simulink Coder
Generate Code
In the model, there are no data dependencies across the for loop iterations. Therefore,
the code generator combines all for loops into one loop. Build the model and view the
generated code.
### Starting build procedure for model: rtwdemo_forloop
### Successful completion of build procedure for model: rtwdemo_forloop
The generated file, rtwdemo_forloop.c, contains the code for the single for loop.
56-16
See Also
/* '<S1>:1:5' */
for (k = 0; k < 10; k++) {
/* Switch: '<Root>/Switch' incorporates:
* Gain: '<Root>/G1'
* Gain: '<Root>/G3'
* Inport: '<Root>/In1'
* Sum: '<Root>/Sum1'
* Sum: '<Root>/Sum2'
* UnitDelay: '<Root>/Delay'
*/
if (3.0 * rtwdemo_forloop_U.In1[k] >= 0.0) {
rtwdemo_forloop_DW.Delay_DSTATE[k] = rtwdemo_forloop_U.In1[k] -
rtwdemo_forloop_DW.Delay_DSTATE[k];
} else {
rtwdemo_forloop_DW.Delay_DSTATE[k] = (rtwdemo_forloop_DW.Delay_DSTATE[k] -
rtwdemo_forloop_U.In1[k]) * 5.0;
}
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Configure Loop Unrolling Threshold” on page 56-50
56-17
56 Optimizations for Generated Code in Simulink Coder
56-18
Subnormal Number Performance
Using subnormal numbers provides precision beyond the normal representation by using
leading zeros in the significand to represent smaller values after the representation
reaches the minimum exponent. As the value approaches 0.0, you trade off precision for
extended range. Subnormal numbers are useful if your application requires extra range.
• In your model, manually flush to zero any incoming or computed subnormal values at
inputs and key operations, such as washouts and filters. For an example, see “Flush
Subnormal Numbers to Zero” on page 56-21.
56-19
56 Optimizations for Generated Code in Simulink Coder
For more information, see the IEEE Standard 754, IEEE Standard for Floating-Point
Arithmetic.
56-20
Subnormal Number Performance
56-21
56 Optimizations for Generated Code in Simulink Coder
• MATLAB function block log2 generates the base 2 logarithm of the Repeating
Sequence Stair output. Specifically, log2 generates the numbers 0 through
-165.
2 On the Simulation > Stepping Options pane:
56-22
See Also
See Also
Related Examples
• “Data Types Supported by Simulink” (Simulink)
• “Numerical Consistency of Model and Generated Code Simulation Results”
(Simulink Coder)
• “Specify Single-Precision Data Type for Embedded Application” on page 22-111
56-23
56 Optimizations for Generated Code in Simulink Coder
This example shows how to remove code for out-of-range floating-point to integer
conversions. Without this code, there might be a mismatch between simulation and code
generation results. Standard C does not define the behavior of out-of-range floating-point
to integer conversions, while these conversions are well-defined during simulation. In
Standard C and during simulation, floating-point to integer conversions are well-defined
for input values in the range of the output type.
If the input values in your application are in the range of the output type, remove code for
out-of-range floating-point to integer conversions. Removing this code reduces the size
and increases the speed of the generated code.
Example Model
In this model, a Data Type Conversion block converts an input signal from a double to a
uint8. A uint8 can support values from 0 to 255. If the input signal has a value outside
of this range, an out-of-range conversion occurs. In this example, the model is named
conversion_ex.
1 Use Inport, Outport, and Data Type Conversion blocks to create the example model.
2 Open the Inport Block Parameters dialog box and select the Signal Attributes tab.
For the Data Type parameter, select double.
56-24
Remove Code From Floating-Point to Integer Conversions That Wraps Out-of-Range Values
3 Open the Data Type Conversion dialog box. For the Output data type parameter,
select uint8.
4 For the signal feeding into the Data Type Conversion block, open the Signal
Properties dialog box. Enter the name U. On the Code Generation tab, for the
Storage Class parameter, select ImportedExtern.
5 For the signal leaving the Data Type Conversion block, open the Signal Properties
dialog box. Enter the name Y. On the Code Generation tab, for the Storage Class
parameter, select ImportedExtern.
/* DataTypeConversion:
'<Root>/Data Type Conversion' incorporates:
Inport: '<>/In1'
*/
tmp = floor(U);
if (rtIsNaN(tmp) || rtIsInf(tmp)) {
tmp = 0.0;
} else {
tmp = fmod(tmp, 256.0);
}
Y = (uint8_T)
(tmp < 0.0 ?
(int32_T)
56-25
56 Optimizations for Generated Code in Simulink Coder
(uint8_T)-(int8_T)
(uint8_T)-tmp :
(int32_T)
(uint8_T) tmp);
The generated code is more efficient without this protective code, but it is possible that
the execution of generated code does not produce the same results as simulation for
values not in the range of 0 to 255.
See Also
“Remove code from floating-point to integer conversions that wraps out-of-range values”
(Simulink Coder)
Related Examples
• “hisl_0053: Configuration Parameters > Code Generation > Optimization > Remove
code from floating-point to integer conversions that wraps out-of-range values”
(Simulink)
• “Optimization Tools and Techniques” on page 56-7
• “Remove Code That Maps NaN to Integer Zero” on page 56-27
56-26
Remove Code That Maps NaN to Integer Zero
This example shows how to remove code that maps NaN to integer zero. For floating-point
to integer conversions involving saturation, Simulink converts NaN to integer zero during
simulation. If your model contains an input value of NaN, you can specify that the code
generator produce code that maps NaN to zero. Without this code, there is a mismatch
between simulation and code generation results because in Standard C, every condition
involving NaN evaluates to false.
If there are no input values of NaN in your application, you can remove code that maps
NaN to integer zero. Removing this code reduces the size and increases the speed of the
generated code.
Example Model
In this model, a Data Type Conversion block converts an input signal from a double to a
uint8. In this example, the model is named conversion_ex.
1 Use Inport, Outport, and Data Type Conversion blocks to create the example model.
2 Open the Inport Block Parameters dialog box and click the Signal Attributes tab.
For the Data Type parameter, select double.
3 Open the Data Type Conversion dialog box. For the Output data type parameter,
select uint8.
56-27
56 Optimizations for Generated Code in Simulink Coder
4 Select Saturate on integer overflow. Selecting this parameter specifies that an out-
of-range signal value equals either the minimum or maximum value that the data type
can represent.
5 For the signal feeding into the Data Type Conversion block, open the Signal
Properties dialog box. Enter a name of U. On the Code Generation tab, for the
Storage Class parameter, select ImportedExtern.
6 For the signal leaving the Data Type Conversion block, open the Signal Properties
dialog box. Enter a name of Y. On the Code Generation tab, for the Storage Class
parameter, select ImportedExtern.
Generate Code
1 Set the Configuration Parameters > Solver > Solver options > Type parameter
to Fixed-step .
2 Disable the Configuration Parameters > Optimization > Advanced parameters
> Remove code from floating-point to integer conversions with saturation
that maps NaN to zero parameter.
3 Enable the Configuration Parameters > Code Generation > Report > Create
code generation report parameter.
4 Enable the Configuration Parameters > Code Generation > Build process >
Generate code only parameter. Then, in the model window, press Ctrl+B. When
code generation is complete, an HTML code generation report opens.
5 In the Code Generation report, select the nan_int_ex.c file and view the model
step function. For an input value of NaN, there is agreement between the generated
code and simulation because NaN maps to integer zero.
56-28
See Also
Y = MAX_uint8_T;
} else {
Y = 0U;
}
See Also
“Remove code from floating-point to integer conversions with saturation that maps NaN
to zero” (Simulink Coder)
56-29
56 Optimizations for Generated Code in Simulink Coder
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Remove Code From Floating-Point to Integer Conversions That Wraps Out-of-Range
Values” on page 56-24
56-30
Disable Nonfinite Checks or Inlining for Math Functions
You can use code replacement library (CRL) customization entries to:
• Selectively disable nonfinite checks for math functions. This can improve the execution
speed of the generated code.
• Selectively disable inlining of math functions. This can increase code readability and
decrease code size.
The functions for which these customizations are supported include the following:
• Floating-point only: atan2, copysign, fix, hypot, log, log10, round, sincos, and
sqrt
• Floating-point and integer: abs, max, min, mod, rem, saturate, and sign
The general workflow for disabling nonfinite number checking and/or inlining is as
follows:
1 If you can disable nonfinite number checking for a particular math function, or if you
want to disable inlining for a particular math function and instead generate a
function invocation, you can copy the following MATLAB function code into a
MATLAB file with an .m file name extension, for example,
crl_table_customization.m.
function hTable = crl_table_customization
hTable = RTW.TflTable;
56-31
56 Optimizations for Generated Code in Simulink Coder
% registerCustomizationEntry(hTable, ...
% Priority, numInputs, key, inType, outType, Inline, SNF);
registerCustomizationEntry(hTable, ...
100, 2, 'atan2', 'double', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'atan2', 'single', 'single', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sincos', 'double', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sincos', 'single', 'single', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'abs', 'double', 'double', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'abs', 'single', 'single', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'abs', 'int32', 'int32', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'abs', 'int16', 'int16', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'abs', 'int8', 'int8', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'abs', 'integer','integer',true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'abs', 'uint32', 'uint32', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'abs', 'uint16', 'uint16', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'abs', 'uint8', 'uint8', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'hypot', 'double', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'hypot', 'single', 'single', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'log', 'double', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'log', 'single', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'log10', 'double', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'log10', 'single', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'min', 'double', 'double', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'min', 'single', 'single', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
56-32
Disable Nonfinite Checks or Inlining for Math Functions
registerCustomizationEntry(hTable, ...
100, 2, 'max', 'double', 'double', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'max', 'single', 'single', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'max', 'int32', 'int32', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'max', 'int16', 'int16', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'max', 'int8', 'int8', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'max', 'uint32', 'uint32', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'max', 'uint16', 'uint16', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'max', 'uint8', 'uint8', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'max', 'integer','integer',true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'mod', 'double', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'mod', 'single', 'single', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'mod', 'int32', 'int32', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'mod', 'int16', 'int16', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'mod', 'int8', 'int8', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'mod', 'uint32', 'uint32', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'mod', 'uint16', 'uint16', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'mod', 'uint8', 'uint8', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'rem', 'double', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'rem', 'single', 'single', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
56-33
56 Optimizations for Generated Code in Simulink Coder
registerCustomizationEntry(hTable, ...
100, 1, 'round', 'double', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'round', 'single', 'single', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 3, 'saturate', 'double', 'double', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 3, 'saturate', 'single', 'single', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 3, 'saturate', 'int32', 'int32', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 3, 'saturate', 'int16', 'int16', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 3, 'saturate', 'int8', 'int8', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 3, 'saturate', 'uint32', 'uint32', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 3, 'saturate', 'uint16', 'uint16', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 3, 'saturate', 'uint8', 'uint8', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 3, 'saturate', 'integer','integer',true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sign', 'double', 'double', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sign', 'single', 'single', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sign', 'int32', 'integer', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sign', 'int16', 'integer', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sign', 'int8', 'integer', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sign', 'uint32', 'uint32', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sign', 'uint16', 'uint16', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sign', 'uint8', 'uint8', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sign', 'integer','integer', true, 'UNSPECIFIED');
56-34
Disable Nonfinite Checks or Inlining for Math Functions
registerCustomizationEntry(hTable, ...
100, 1, 'sqrt', 'double', 'double', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'sqrt', 'single', 'single', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'fix', 'double', 'double', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'fix', 'single', 'single', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'copysign', 'double', 'double', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 1, 'copysign', 'single', 'single', true, 'UNSPECIFIED');
2 To reduce the size of the file, you can delete the registerCustomizationEntry
lines for functions for which the default nonfinite number checking and inlining
behavior is acceptable.
3 For each remaining entry,
• Set the Inline argument to true if the function should be inlined or false if it
should not be inlined.
• Set the SNF argument to ENABLE if nonfinite checking should be generated,
DISABLE if nonfinite checking should not be generated, or UNSPECIFIED to
accept the default behavior based on the model option settings.
Note For the example below, specify the argument 'RTW' if a GRT target is selected
for your model, otherwise omit the argument.
56-35
56 Optimizations for Generated Code in Simulink Coder
function rtwTargetInfo(cm)
% rtwTargetInfo function to register a code replacement library (CRL)
You can edit the Name field to specify the library name that appears in the Code
replacement library drop-down list. Also, the file name in the TableList field must
match the name of the file you created in step 1.
To register your changes, with both of the MATLAB files you created present in the
MATLAB path, enter the following command at the MATLAB command line:
sl_refresh_customizations
7 Create or open a model that generates function code corresponding to one of the
math functions for which you specified a change in nonfinite number checking or
inlining behavior.
8 Open the Configuration Parameters dialog box, go to the Code Generation >
Interface pane, and use the Code replacement library drop-down list to select the
code replacement entry you registered in step 6, for example, CRL Customization
Example.
9 Generate code for the model and examine the generated code to verify that the math
functions are generated as expected.
56-36
Minimize Computations and Storage for Intermediate Results at Block Outputs
Expression Folding
Expression folding optimizes code to minimize the computation of intermediate results at
block outputs and the storage of such results in temporary buffers or variables. When
expression folding is on, the code generator collapses (folds) block computations into a
single expression, instead of generating separate code statements and storage
declarations for each block in the model. Most Simulink blocks support expression
folding.
Expression folding improves the efficiency of generated code, frequently achieving results
that compare favorably to hand-optimized code. In many cases, entire groups of model
computations fold into a single, highly optimized line of code.
You can use expression folding in your own inlined S-function blocks. For more
information, see “S-Functions That Support Expression Folding” (Simulink Coder).
Example Model
56-37
56 Optimizations for Generated Code in Simulink Coder
Generate Code
With expression folding off, in the explfld.c file, the code generator generates this
code.
There are separate code statements for both Gain blocks. Before final output, these code
statements compute temporary results for the Gain blocks.
Enable Optimization
Expression folding is on by default. To see if expression folding is on for an existing
model:
1 Expression folding is available only when the Configuration Parameters > Signal
storage reuse parameter is selected because expression folding operates only on
expressions involving local variables. Enable the Signal storage reuse parameter.
2 When you select Signal storage reuse, the Enable local block outputs, Reuse
local block outputs, and Eliminate superfluous local variables (expression
folding) parameters are all on by default.
56-38
See Also
For an example of expression folding in the context of a more complex model, click
rtwdemo_slexprfold , or at the command prompt, type:
rtwdemo_slexprfold
For more information, see “Enable and Reuse Local Block Outputs in Generated Code”
(Simulink Coder)
See Also
“Signal storage reuse” (Simulink) | “Reuse local block outputs” (Simulink Coder) |
“Enable local block outputs” (Simulink Coder) | “Eliminate superfluous local variables
(Expression folding)” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements” on
page 22-81
56-39
56 Optimizations for Generated Code in Simulink Coder
An invariant signal is a block output signal that does not change during Simulink
simulation. For example, the signal S3 is an invariant signal. An invariant signal is not the
same as an invariant constant. The two constants (1 and 2) and the gain value of 3 are
invariant constants. To inline invariant constants, set Default parameter behavior to
Inlined.
Example Model
model = 'rtwdemo_inline_invariant_signals';
open_system(model);
56-40
Inline Invariant Signals
Generate Code
Create a temporary folder (in your system temporary folder) for the build and inspection
process.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild(model)
View the generated code without the optimization. These lines of code are in
rtwdemo_inline_invariant_signals.c.
cfile = fullfile(cgDir,'rtwdemo_inline_invariant_signals_grt_rtw',...
'rtwdemo_inline_invariant_signals.c');
rtwdemodbtype(cfile,'/* Output and update for atomic system',...
'/* Model output', 1, 0);
56-41
56 Optimizations for Generated Code in Simulink Coder
Enable Optimization
Alternatively, you can use the command-line API to enable the optimization:
The generated code uses the numerical values of the folded constants instead of creating
an additional structure (rtwdemo_inline_invariant_ConstB).
rtwbuild(model)
View the generated code with the optimization. These lines of code are in
rtwdemo_minmax.c.
rtwdemodbtype(cfile,...
'/* Output and update for atomic system', '/* Model output', 1, 0);
56-42
See Also
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Inline invariant signals” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Inline Numeric Values of Block Parameters” on page 56-44
56-43
56 Optimizations for Generated Code in Simulink Coder
This optimization determines whether numeric block parameters occupy global memory
in the generated code. The optimization can:
Open the example model rtwdemo_paraminline and configure it to show the generated
names of blocks.
load_system('rtwdemo_paraminline')
set_param('rtwdemo_paraminline','HideAutomaticNames','off')
open_system('rtwdemo_paraminline')
56-44
Inline Numeric Values of Block Parameters
The output of the block G2, and the outputs of blocks upstream of G2, change only if you
tune the values of the block parameters during simulation or during code execution.
When you update the model diagram, these blocks and signal lines appear magenta in
color.
Several blocks use Simulink.Parameter objects in the base workspace to set the
values of their parameters. The parameter objects all use the storage class Auto, which
means that you can configure the generated code to inline the parameter values.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
set_param('rtwdemo_paraminline','DefaultParameterBehavior','Tunable')
rtwbuild('rtwdemo_paraminline')
In the code generation report, view the source file rtwdemo_paraminline_data.c. The
code defines a global structure that contains the block parameter values. Each block
parameter in the model, such as a lookup table array, breakpoint set, or gain, appears as
a field of the structure.
cfile = fullfile(...
cgDir,'rtwdemo_paraminline_grt_rtw','rtwdemo_paraminline_data.c');
rtwdemodbtype(cfile,'/* Block parameters (default storage) */', '};', 1, 1);
56-45
56 Optimizations for Generated Code in Simulink Coder
/* Variable: SLIDER_POS
* Referenced by: '<Root>/Constant1'
*/
0.0,
/* Variable: T1Break
* Referenced by: '<Root>/1D Lookup'
*/
{ -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 },
/* Variable: T1Data
* Referenced by: '<Root>/1D Lookup'
*/
{ -1.0, -0.99, -0.98, -0.96, -0.76, 0.0, 0.76, 0.96, 0.98, 0.99, 1.0 },
/* Variable: T2Break
* Referenced by: '<Root>/2D Lookup'
*/
{ 1.0, 2.0, 3.0 },
/* Variable: T2Data
* Referenced by: '<Root>/2D Lookup'
*/
{ 4.0, 16.0, 10.0, 5.0, 19.0, 18.0, 6.0, 20.0, 23.0 },
/* Expression: 2
* Referenced by: '<Root>/G1'
*/
2.0,
/* Expression: -2
* Referenced by: '<Root>/G2'
*/
-2.0,
56-46
Inline Numeric Values of Block Parameters
You can tune the structure fields during code execution because they occupy global
memory. However, at each step of the generated algorithm, the code must calculate the
output of each block, including the outputs of the block G2 and the upstream blocks. View
the algorithm in the model step function in the file rtwdemo_paraminline.c.
cfile = fullfile(cgDir,'rtwdemo_paraminline_grt_rtw','rtwdemo_paraminline.c');
rtwdemodbtype(...
cfile,'/* Model step function */','/* Model initialize function */',1,0);
set_param('rtwdemo_paraminline','DefaultParameterBehavior','Inlined')
56-47
56 Optimizations for Generated Code in Simulink Coder
rtwbuild('rtwdemo_paraminline')
In the code generation report, view the algorithm in the file rtwdemo_paraminline.c.
rtwdemodbtype(...
cfile,'/* Model step function */','/* Model initialize function */',1,0);
The code does not allocate memory for block parameters or for parameter objects that
use the storage class Auto. Instead, the code generator uses the parameter values from
the model, and from the parameter objects, to calculate and inline the constant output of
the block G2, 150.0. The generator also inlines the value of the Gain parameter of the
Gain block G1, 2.0.
With the optimization, the generated code leaves out computationally expensive
algorithmic code for blocks such as the lookup tables. The optimized code calculates the
output of a block only if the output can change during execution. For this model, only the
outputs of the Inport block In1, the Gain block G1, and the Sum block can change.
bdclose('rtwdemo_paraminline')
rtwdemoclean;
cd(currentDir)
When you set Default parameter behavior to Inlined, you can preserve block
parameter tunability by creating Simulink.Parameter objects for individual
parameters. You can configure each object to appear in the code as a tunable field of the
56-48
See Also
global parameter structure or as an individual global variable. You can change parameter
values during code execution and interface the generated code with your own
handwritten code. For more information, see “Create Tunable Calibration Parameter in
the Generated Code” (Simulink Coder).
You can select the Inline invariant signals code generation option (which also places
constant values in the generated code) only when you set Default parameter behavior
to Inlined. See “Inline Invariant Signals” (Simulink Coder).
See Also
“Default parameter behavior” (Simulink Coder)
Related Examples
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
56-49
56 Optimizations for Generated Code in Simulink Coder
Assume that the loop unrolling threshold value is set to the default, 5.
If myGainVec is declared as
myGainVec = [1:10];
56-50
See Also
{
int32_T i1;
/* Gain: '<Root>/Gain' */
for(i1=0; i1<10; i1++) {
myGainVec_B.Gain_f[i1] = rtb_foo *
myGainVec_P.Gain_Gain[i1];
}
}
If myGainVec is declared as
myGainVec = [1:3];
/* Gain: '<Root>/Gain' */
myGainVec_B.Gain_f[0] = rtb_foo * myGainVec_P.Gain_Gain[0];
myGainVec_B.Gain_f[1] = rtb_foo * myGainVec_P.Gain_Gain[1];
myGainVec_B.Gain_f[2] = rtb_foo * myGainVec_P.Gain_Gain[2];
See “Explore Variable Names and Loop Rolling” (Simulink Coder) for more information on
loop rolling.
Note When a model includes Stateflow charts or MATLAB Function blocks, you can apply
a set of Stateflow optimizations on the Optimization pane. The settings you select for the
Stateflow options also apply to MATLAB Function blocks in the model. This is because the
MATLAB Function blocks and Stateflow charts are built on top of the same technology
and share a code base. You do not need a Stateflow license to use MATLAB Function
blocks.
See Also
“Loop unrolling threshold” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
56-51
56 Optimizations for Generated Code in Simulink Coder
56-52
Use memcpy Function to Optimize Generated Code for Vector Assignments
In this section...
“Example Model” on page 56-54
“Generate Code” on page 56-55
“Generate Code with Optimization” on page 56-55
You can use the Use memcpy for vector assignment parameter to optimize generated
code for vector assignments by replacing for loops with memcpy function calls. The
memcpy function is more efficient than for-loop controlled element assignment for large
data sets. This optimization improves execution speed.
Selecting the Use memcpy for vector assignment parameter enables the associated
parameter Memcpy threshold (bytes), which allows you to specify the minimum array
size in bytes for which memcpy function calls should replace for loops in the generated
code. For more information, see “Use memcpy for vector assignment” (Simulink Coder)
and “Memcpy threshold (bytes)” (Simulink Coder). In considering whether to use this
optimization,
1 Consider first generating code without this optimization and measuring its execution
speed, to establish a baseline for evaluating the optimized assignment.
2 Select Use memcpy for vector assignment and examine the setting of Memcpy
threshold (bytes), which by default specifies 64 bytes as the minimum array size for
which memcpy function calls replace for loops. Based on the array sizes used in your
application's signal vector assignments, and target environment considerations that
might bear on the threshold selection, accept the default or specify another array
size.
3 Generate code, and measure its execution speed against your baseline or previous
iterations. Iterate on steps 2 and 3 until you achieve an optimal result.
56-53
56 Optimizations for Generated Code in Simulink Coder
Note The memcpy optimization may not occur under certain conditions, including when
other optimizations have a higher precedence than the memcpy optimization, or when the
generated code is originating from Target Language Compiler (TLC) code, such as a TLC
file associated with an S-function block.
Note If you are licensed for Embedded Coder software, you can use a code replacement
library (CRL) to provide your own custom implementation of the memcpy function to be
used in generated model code. For more information, see “Memory Function Code
Replacement” on page 54-99.
Example Model
To examine the result of using the Use memcpy for vector assignment parameter on
the generated vector assignment code, create a model that generates signal vector
assignments. For example,
1 Use In, Out, and Selector blocks to create the following model.
2 Open Model Explorer and configure the Signal Attributes for the In1 and In2
source blocks. For each, set Port dimensions to [1,100], and set Data type to
int32. Apply the changes and save the model. In this example, the model has the
name vectorassign.
56-54
Use memcpy Function to Optimize Generated Code for Vector Assignments
3 For each Selector block, set the Index parameter to 1:50. Set the Input port size
parameter to 100.
Generate Code
1 The Use memcpy for vector assignment parameter is on by default. To turn off the
parameter, go to the Optimization pane and clear the Use memcpy for vector
assignment parameter.
2 Go to the Code Generation > Report pane of the Configuration Parameters dialog
box and select the Create code generation report. Then go to the Code
Generation pane, select the Generate code only option, and generate code for the
model. When code generation completes, the HTML code generation report is
displayed.
3 In the HTML code generation report, click the vectorassign.c section and inspect
the model step function. Notice that the vector assignments are implemented using
for loops.
/* Model step function */
void vectorassign_step(void)
{
int32_T i;
for (i = 0; i < 50; i++) {
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/In1'
*/
vectorassign_Y.Out1[i] = vectorassign_U.In1[i];
56-55
56 Optimizations for Generated Code in Simulink Coder
See Also
“Use memcpy for vector assignment” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Vector Operation Optimization” on page 56-110
• “Convert Data Copies to Pointer Assignments” on page 60-25
56-56
Generate Target Optimizations Within Algorithm Code
The following table lists integration options to customize generated algorithm code with
target-specific optimizations.
56-57
56 Optimizations for Generated Code in Simulink Coder
56-58
Remove Code for Blocks That Have No Effect on Computational Results
Example
In the model rtwdemo_blockreduction, a Gain block of value 1.0 is in between Inport and
Outport blocks.
model = 'rtwdemo_blockreduction';
open_system(model);
Generate Code
currentDir=pwd;
[~,cgDir]=rtwdemodir();
set_param(model,'BlockReduction','off');
rtwbuild(model)
56-59
56 Optimizations for Generated Code in Simulink Coder
cfile = fullfile(cgDir,'rtwdemo_blockreduction_ert_rtw','rtwdemo_blockreduction.c');
rtwdemodbtype(cfile, '/* Model step function */',...
'/* Model initialize function */', 1, 0);
Enable Optimization
set_param(model,'BlockReduction','on');
rtwbuild(model)
cfile = fullfile(cgDir,'rtwdemo_blockreduction_ert_rtw','rtwdemo_blockreduction.c');
rtwdemodbtype(cfile, '/* Model step function */',...
'/* Model initialize function */', 1, 0);
56-60
See Also
*/
rtwdemo_blockreduction_Y.Out1 = rtwdemo_blockreduction_U.In1;
}
Because multiplying the input signal by a value of 1.0 does not impact computational
results, the code generator excludes the Gain block from the generated code. Close the
model and clean up.
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Block reduction” (Simulink)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Inline Numeric Values of Block Parameters” on page 56-44
• “Minimize Computations and Storage for Intermediate Results at Block Outputs” on
page 56-37
56-61
56 Optimizations for Generated Code in Simulink Coder
Example
In the model rtwdemo_deadpathElim, the signal leaving the Sum block divides into two
separate code paths. The top path is not a dead code path. If the user disables the
Assertion block, the bottom path becomes a dead code path.
model = 'rtwdemo_deadpathElim';
open_system(model);
56-62
Eliminate Dead Code Paths in Generated Code
void rtwdemo_deadpathElim_step(void)
{
/* Sum: '<Root>/Sum1' incorporates:
* Constant: '<Root>/Constant1'
* Inport: '<Root>/In1'
*/
rtwdemo_deadpathElim_Y.Out1 = rtwdemo_deadpathElim_U.In1 + 1.0;
Disable the Assertion block to generate a dead code path. The code generator detects the
dead code path and eliminates it from the generated code.
1 For the Assertion block, open the Block Parameters dialog box.
2 Deselect the Enable assertion box.
56-63
56 Optimizations for Generated Code in Simulink Coder
void rtwdemo_deadpathElim_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Constant: '<Root>/Constant1'
* Inport: '<Root>/In1'
* Sum: '<Root>/Sum1'
*/
rtwdemo_deadpathElim_Y.Out1 = rtwdemo_deadpathElim_U.In1 + 1.0;
}
bdclose(model)
rtwdemoclean;
cd(currentDir)
For another example of how the code generator eliminates dead code paths in the
generated code, see rtwdemo_deadpath.
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Remove Code for Blocks That Have No Effect on Computational Results” on page
56-59
56-64
Floating-Point Multiplication to Handle a Net Slope Correction
Example
Generate Code
56-65
56 Optimizations for Generated Code in Simulink Coder
rtwbuild(model)
cfile = fullfile(cgDir,'rtwdemo_float_mul_for_net_slope_correction_ert_rtw',...
'rtwdemo_float_mul_for_net_slope_correction.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
Enable Optimization
Alternatively, you can use the command-line API to enable the optimization.
rtwbuild(model)
In the optimized code, the code generator multiplies the input signal by the reciprocal of
3.0F , that is 0.333333343F .
56-66
See Also
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Use floating-point multiplication to handle net slope corrections” (Simulink)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Remove Code From Floating-Point to Integer Conversions That Wraps Out-of-Range
Values” on page 56-24
• “Subnormal Number Performance” on page 56-19
56-67
56 Optimizations for Generated Code in Simulink Coder
Example Model
In this example, switch paths are conditionally executed. If Switch1 control input is true,
Switch1 executes blocks grouped in the Switch1:Path1 branch. If Switch1 control
input is false, Switch1 executes blocks grouped in the Switch1:Path2 branch. If
Switch1 executes blocks in the Switch1:Path2 branch and Switch2 control input is
true, Switch2 executes blocks in the Switch2:Path1 branch. If Switch2 control input
is false, Switch2 executes blocks in the Switch2:Path2 branch. The pseudo code shows
this logic.
model='rtwdemo_condinput';
open_system(model);
56-68
Use Conditional Input Branch Execution
56-69
56 Optimizations for Generated Code in Simulink Coder
Generate Code
currentDir=pwd;
[~,cgDir]=rtwdemodir();
rtwbuild(model)
View the generated code without the optimization. These lines of code are in the
rtwdemo_condinput.c file.
cfile = fullfile(cgDir,'rtwdemo_condinput_grt_rtw','rtwdemo_condinput.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
56-70
Use Conditional Input Branch Execution
The generated code contains an if-else statement for the Switch1 block and an if
statement for the Switch2 block. Therefore, the generated code for Switch1:Path2
executes even if the if statement for Switch1:Path1 evaluates to true.
Enable Optimization
set_param(model, 'ConditionallyExecuteInputs','on');
rtwbuild(model)
cfile = fullfile(cgDir,'rtwdemo_condinput_grt_rtw','rtwdemo_condinput.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
56-71
56 Optimizations for Generated Code in Simulink Coder
The generated code contains one if statement. The generated code for Switch1:Path2
only executes if the if statement evaluates to false.
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Conditional input branch execution” (Simulink) | Multiport Switch | Switch
56-72
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Eliminate Dead Code Paths in Generated Code” on page 56-62
56-73
56 Optimizations for Generated Code in Simulink Coder
• Expression Folding: Gain and Sum operations on the complex signal are folded into a
single expression.
• For-loop fusion: Two separate for-loops, one for the complex signal and one for
noncomplex signal, are combined into a single for-loop.
• Inlined block parameters: The value of Gain block "pi" is inlined in the expression of
the complex Gain-Sum.
Because of optimizations such as these, the code generated for complex and noncomplex
signals is equally efficient.
Example Model
model='rtwdemo_complex';
open_system(model);
56-74
See Also
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
56-75
56 Optimizations for Generated Code in Simulink Coder
56-76
Speed Up Linear Algebra in Code Generated from a MATLAB Function Block
The code generator uses the LAPACK library that you specify. Specify a LAPACK library
that is optimized for your execution environment. See www.netlib.org/lapack/
faq.html#_what_and_where_are_the_lapack_vendors_implementations.
The callback class must derive from the abstract class coder.LAPACKCallback. Use
this example callback class as a template.
56-77
56 Optimizations for Generated Code in Simulink Coder
buildInfo.addIncludePaths(fullfile(pwd,'include'));
libName = 'mylapack';
libPath = fullfile(pwd,'lib');
[~,linkLibExt] = buildctx.getStdLibInfo();
buildInfo.addLinkObjects([libName linkLibExt], libPath, ...
'', true, true);
buildInfo.addDefines('HAVE_LAPACK_CONFIG_H');
buildInfo.addDefines('LAPACK_COMPLEX_STRUCTURE');
end
end
end
If your compiler supports only complex data types that are represented as structures,
include these lines in the updateBuildInfo method.
buildInfo.addDefines('HAVE_LAPACK_CONFIG_H');
buildInfo.addDefines('LAPACK_COMPLEX_STRUCTURE');
56-78
Speed Up Linear Algebra in Code Generated from a MATLAB Function Block
7 Set the Configuration Parameters > Code Generation > Advanced parameters
> Custom LAPACK library callback parameter to useMyLAPACK.
If the input to mysvd is large enough, the code generator produces a LAPACK call for
svd. An example of a call to the LAPACK library function for svd is:
To specify the rpath linker option, you can use the build information addLinkFlags
method in the updateBuildInfo method of your coder.LAPACKCallback class. For
example, for a GCC compiler:
buildInfo.addLinkFlags(sprintf('-Wl,-rpath,"%s"',libPath));
56-79
56 Optimizations for Generated Code in Simulink Coder
See Also
coder.LAPACKCallback
More About
• “LAPACK Calls for Linear Algebra in a MATLAB Function Block” (Simulink)
External Websites
• www.netlib.org/lapack
• www.netlib.org/lapack/
faq.html#_what_and_where_are_the_lapack_vendors_implementations
56-80
Speed Up Fast Fourier Transforms in Code Generated from a MATLAB Function Block
When you simulate a model that includes a MATLAB Function block that calls MATLAB
fast Fourier transform (FFT) functions, the simulation software uses the library that
MATLAB uses for FFT algorithms. If you generate C/C++ code for this model, by default,
the code generator produces code for the FFT algorithms instead of producing FFT
library calls. To increase the speed of fast Fourier transforms in generated code, specify
that the code generator produce calls to a specific installed FFTW library.
The code generator produces FFTW library calls when all of these conditions are true:
• A MATLAB Function block calls one of these MATLAB functions:fft, fft2, fftn,
ifft, ifft2, or ifftn.
• You generate C/C++ code from a model that includes the MATLAB Function block.
• You have access to an FFTW library installation, version 3.2 or later.
• You specify the FFTW library installation in an FFT library callback class that derives
from coder.fftw.StandaloneFFTW3Interface.
• You set the Custom FFT library callback configuration parameter to the name of the
callback class.
For a Linux platform or a Mac platform, consider using a package manager to install the
FFTW library.
For a Windows platform, in addition to .dll files, you must have .lib import libraries, as
described in the Windows installation notes on the FFTW website.
See the installation instructions for your platform on the FFTW website.
56-81
56 Optimizations for Generated Code in Simulink Coder
methods (Static)
function th = getNumThreads
coder.inline('always');
th = int32(coder.const(1));
end
%Double
libName1 = 'libfftw3-3';
[~, libExt] = ctx.getStdLibInfo();
libName1 = [libName1 libExt];
addLinkObjects(buildInfo, libName1, libPath, 1000, true, true);
%Single
libName2 = 'libfftw3f-3';
[~, libExt] = ctx.getStdLibInfo();
libName2 = [libName2 libExt];
addLinkObjects(buildInfo, libName2, libPath, 1000, true, true);
end
end
end
56-82
Speed Up Fast Fourier Transforms in Code Generated from a MATLAB Function Block
function y = myfft()
t = 0:1/50:10-1/50;
x = sin(2*pi*15*t) + sin(2*pi*20*t);
y = fft(x);
end
4 Connect the blocks.
5 Indicate that the code generator produce calls to the FFTW library specified in the
FFT library callback class useMyFFTW. In the Configuration Parameters dialog box,
set Custom FFT library callback to useMyFFTW.
The FFTW library must be available in your execution environment. If the FFTW library is
shared, use environment variables or linker options to specify the location of the library.
56-83
56 Optimizations for Generated Code in Simulink Coder
To specify the rpath linker option, you can use the build information addLinkFlags
method in the updateBuildInfo method of your
coder.fftw.StandaloneFFTW3Interface class. For example, for a GCC compiler:
buildInfo.addLinkFlags(sprintf('-Wl,-rpath,"%s"',libPath));
See Also
coder.fftw.StandaloneFFTW3Interface
More About
• “Synchronize Multithreaded FFTW Planning in Code Generated from a MATLAB
Function Block” (Simulink Coder)
External Websites
• www.fftw.org
56-84
Synchronize Multithreaded FFTW Planning in Code Generated from a MATLAB Function Block
The code generator produces FFTW library calls when all of these conditions are true:
• A MATLAB Function block calls one of these functions:fft, fft2, fftn, ifft, ifft2,
or ifftn.
• You generate C/C++ code for a model that includes the MATLAB Function block.
• You have access to an FFTW library installation, version 3.2 or later.
• You specify the FFTW library installation in an FFT library callback class that derives
from coder.fftw.StandaloneFFTW3Interface.
• You set the Custom FFT library callback configuration parameter to the name of the
callback class.
If you integrate the code that contains the FFTW calls with external code that runs on
multiple threads, then you must prevent concurrent access to the FFTW planning process.
In your FFT library callback class, implement the lock and unlock methods. You must
also provide C code that manages a lock or mutex. Many libraries, such as OpenMP,
pthreads, and the C++ standard library (C++ 11 and later), provide locks. This example
shows how to implement the lock and unlock methods and provide supporting C code.
To manage a lock, this example uses the OpenMP library.
Prerequisites
Before you start, for the basic workflow for generating FFTW library calls for fast Fourier
transforms in a MATLAB Function block, see “Speed Up Fast Fourier Transforms in Code
Generated from a MATLAB Function Block” (Simulink Coder).
56-85
56 Optimizations for Generated Code in Simulink Coder
function y = mycustomfft()
t = 0:1/50:10-1/50;
x = sin(2*pi*15*t) + sin(2*pi*20*t);
y = fft(x);
for k = 1:100
y = y + ifft(x+k);
end
3 Add an outport block and connect it to the MATLAB Function block.
#include "mylock.h"
#include "omp.h"
void mylock_initialize(void)
{
omp_init_nest_lock(&lockVar);
}
void mylock(void)
56-86
Synchronize Multithreaded FFTW Planning in Code Generated from a MATLAB Function Block
{
omp_set_nest_lock(&lockVar);
}
void myunlock(void)
{
omp_unset_nest_lock(&lockVar);
}
void mylock_initialize(void);
void mylock(void);
void myunlock(void);
#endif
Use this class as a template. Replace fftwLocation with the location of your FFTW
library installation.
classdef myfftcb < coder.fftw.StandaloneFFTW3Interface
methods (Static)
function th = getNumThreads
coder.inline('always');
th = int32(coder.const(1));
end
function lock()
coder.cinclude('mylock.h', 'InAllSourceFiles', true);
coder.inline('always');
coder.ceval('mylock');
end
56-87
56 Optimizations for Generated Code in Simulink Coder
function unlock()
coder.cinclude('mylock.h', 'InAllSourceFiles', true);
coder.inline('always');
coder.ceval('myunlock');
end
%Double
libName1 = 'libfftw3-3';
[~, libExt] = ctx.getStdLibInfo();
libName1 = [libName1 libExt];
addLinkObjects(buildInfo, libName1, libPath, 1000, true, true);
%Single
libName2 = 'libfftw3f-3';
[~, libExt] = ctx.getStdLibInfo();
libName2 = [libName2 libExt];
addLinkObjects(buildInfo, libName2, libPath, 1000, true, true);
end
end
end
56-88
See Also
See Also
coder.fftw.StandaloneFFTW3Interface
More About
• “Speed Up Fast Fourier Transforms in Code Generated from a MATLAB Function
Block” (Simulink Coder)
External Websites
• www.fftw.org
56-89
56 Optimizations for Generated Code in Simulink Coder
• Input and output signals. Variable-size input and output signals must have an upper
bound.
• Parameters or global variables. Parameters and global variables must be fixed-size.
• Fields of bus arrays. Bus arrays cannot have variable-size fields.
• Discrete state properties of System objects associated with a MATLAB System block.
Dynamic memory allocation and the freeing of this memory can result in slower execution
of the generated code. To control the use of dynamic memory allocation for variable-size
arrays in a MATLAB Function block, you can:
56-90
See Also
If you disable dynamic memory allocation, you must provide upper bounds for variable-
size arrays.
• Disable dynamic memory allocation for smaller arrays. For smaller arrays, static
memory allocation can speed up generated code. However, static memory allocation
can lead to unused storage space. You can decide that the unused storage space is not
a significant consideration for smaller arrays.
• Enable dynamic memory allocation for larger arrays. For larger arrays, when you use
dynamic memory allocation, you can significantly reduce storage requirements.
The default value of the dynamic memory allocation threshold is 64 kilobytes. To change
the threshold, in the Configuration Parameters dialog box, set the Dynamic memory
allocation threshold in MATLAB Function blocks parameter.
To use dynamic memory allocation for all variable-size arrays, set the threshold to 0.
See Also
More About
• “Code Generation for Variable-Size Arrays” (Simulink)
• “Specify Upper Bounds for Variable-Size Arrays” (Simulink)
56-91
56 Optimizations for Generated Code in Simulink Coder
56-92
Optimize Memory Usage for Time Counters
The code generator represents time counters as unsigned integers. The word size of time
counters is based on the setting of the model configuration parameter Application
lifespan (days), which specifies the expected maximum duration of time the application
runs. You can use this parameter to prevent time counter overflows. The default size is 64
bits.
The number of bits that a time counter uses depends on the setting of the Application
lifespan (days) parameter. For example, if a time counter increments at a rate of 1 kHz,
to avoid an overflow, the counter has the following number of bits:
A 64-bit time counter does not overflow for 590 million years.
56-93
56 Optimizations for Generated Code in Simulink Coder
The model consists of three subsystems SS1, SS2, and SS3. On the Math and Data
Types pane, the Application lifespan (days) parameter is set to the default, which is
inf.
56-94
Optimize Memory Usage for Time Counters
The three subsystems contain a discrete-time integrator that requires elapsed time as
input to compute its output value. The subsystems vary as follows:
• SS1 - Clocked at 1 kHz. Does not require a time counter. Sample time type
parameter for trigger port is set to periodic. Elapsed time is inlined as 0.001.
• SS2 - Clocked at 100 Hz. Requires a time counter. Based on a lifespan of 1 day, a 32-bit
counter stores the elapsed time.
• SS3 - Clocked at 0.5 Hz. Requires a time counter. Based on a lifespan of 1 day, a 16-bit
counter stores the elapsed time.
Simulate the model. By default, the model is configured to show sample times in different
colors. Discrete sample times for the three subsystems appear red, green, and blue.
Triggered subsystems are blue-green.
2. Configure the model for the code generator to use the GRT system target file and a
lifespan of inf days.
struct tag_RTM_rtwdemo_abstime_T {
const char_T *errorStatus;
/*
* Timing:
* The following substructure contains information regarding
* the timing information for the model.
*/
struct {
uint32_T clockTick1;
56-95
56 Optimizations for Generated Code in Simulink Coder
uint32_T clockTickH1;
uint32_T clockTick2;
uint32_T clockTickH2;
struct {
uint16_T TID[3];
uint16_T cLimit[3];
} TaskCounters;
} Timing;
};
/*-
* The generated code includes comments that allow you to trace directly
* back to the appropriate location in the model. The basic format
* is <system>/block_name, where system is the system number (uniquely
* assigned by Simulink) and block_name is the name of the block.
*
* Use the MATLAB hilite_system command to trace the generated code back
* to the model. For example,
*
* hilite_system('<S3>') - opens system 3
* hilite_system('<S3>/Kp') - opens and selects block Kp which resides in S3
*
* Here is the system hierarchy for this model
*
* '<Root>' : 'rtwdemo_abstime'
* '<S1>' : 'rtwdemo_abstime/SS1'
* '<S2>' : 'rtwdemo_abstime/SS2'
56-96
Optimize Memory Usage for Time Counters
* '<S3>' : 'rtwdemo_abstime/SS3'
*/
#endif /* RTW_HEADER_rtwdemo_abstime_h_ */
struct tag_RTM_rtwdemo_abstime_T {
const char_T *errorStatus;
/*
* Timing:
* The following substructure contains information regarding
* the timing information for the model.
*/
struct {
uint32_T clockTick1;
uint16_T clockTick2;
struct {
uint16_T TID[3];
uint16_T cLimit[3];
} TaskCounters;
} Timing;
};
56-97
56 Optimizations for Generated Code in Simulink Coder
/*-
* The generated code includes comments that allow you to trace directly
* back to the appropriate location in the model. The basic format
* is <system>/block_name, where system is the system number (uniquely
* assigned by Simulink) and block_name is the name of the block.
*
* Use the MATLAB hilite_system command to trace the generated code back
* to the model. For example,
*
* hilite_system('<S3>') - opens system 3
* hilite_system('<S3>/Kp') - opens and selects block Kp which resides in S3
*
* Here is the system hierarchy for this model
*
* '<Root>' : 'rtwdemo_abstime'
* '<S1>' : 'rtwdemo_abstime/SS1'
* '<S2>' : 'rtwdemo_abstime/SS2'
* '<S3>' : 'rtwdemo_abstime/SS3'
*/
#endif /* RTW_HEADER_rtwdemo_abstime_h_ */
The new setting for the Application lifespan (days) parameter instructs the code
generator to set aside less memory for the time counters. The regenerated code includes:
• 32-bit unsigned integer, clockTick1, for storing the elapsed time of the task for SS2
• 16-bit unsigned integer, clockTick2, for storing the elapsed time of the task for SS3
Related Information
56-98
See Also
See Also
More About
• “Optimization Tools and Techniques” on page 56-7
• “Control Memory Allocation for Time Counters” on page 56-11
• “Access Timers Programmatically” (Simulink Coder)
• “Generate Code for an Elapsed Time Counter” (Simulink Coder)
• “Absolute Time Limitations” (Simulink Coder)
56-99
56 Optimizations for Generated Code in Simulink Coder
The optimization:
Example Model
56-100
Optimize Generated Code Using Boolean Data for Logical Signals
Generate Code
Create a temporary folder (in your system temporary folder) for the build and inspection
process.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild(model)
View the generated code without the optimization. These lines of code are in
rtwdemo_logicalAsBoolean.h.
hfile = fullfile(cgDir,'rtwdemo_logicalAsBoolean_ert_rtw',...
'rtwdemo_logicalAsBoolean.h');
rtwdemodbtype(hfile,'/* External outputs','/* Parameters (default storage) */',1,0);
Enable Optimization
Alternatively, you can use the command-line API to enable the optimization:
set_param(model,'BooleanDataType','on');
The generated code stores the logical signal output as Boolean data.
56-101
56 Optimizations for Generated Code in Simulink Coder
rtwbuild(model)
View the generated code with the optimization. These lines of code are in
rtwdemo_logicalAsBoolean.h.
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Implement logic signals as Boolean data (vs. double)” (Simulink)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Data Types Supported by Simulink” (Simulink)
• “Use Conditional Input Branch Execution” on page 56-68
• “Bitfields” on page 14-89
56-102
Reduce Memory Usage for Boolean and State Configuration Variables
• Use bitsets for storing state configuration — Reduces the amount of memory
that stores state configuration variables. However, it can increase the amount of
memory that stores target code if the target processor does not include
instructions for manipulating bitsets.
• Use bitsets for storing Boolean data — Reduces the amount of memory that
stores Boolean variables. However, it can increase the amount of memory that
stores target code if the target processor does not include instructions for
manipulating bitsets.
Note You cannot use bitsets when you generate code for these cases:
See Also
“Use bitsets for storing state configuration” (Simulink Coder) | “Use bitsets for storing
Boolean data” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Optimize Generated Code Using Boolean Data for Logical Signals” on page 56-100
• “Bitfields” on page 14-89
56-103
56 Optimizations for Generated Code in Simulink Coder
The default setting for “Maximum stack size (bytes)” (Simulink Coder) is Inherit from
target. In this case, the value of the maximum stack size is the smaller value of the
following: the default value set by the code generator (200,000 bytes) or the value of the
TLC variable MaxStackSize found in the system target file (ert.tlc).
To specify a smaller stack size for your application, select the Specify a value option
of the Maximum stack size (bytes) parameter and enter a positive integer value. To
specify a smaller stack size at the command line, use:
Note For overall executable stack usage metrics, you might want to do a target-specific
measurement, such as using runtime (empirical) analysis or static (code path) analysis
with object code.
It is recommended that you use the Maximum stack size (bytes) parameter to control
stack space allocation instead of modifying the TLC variable, MaxStackSize, in the
system target file. However, a target author might want to set the TLC variable,
MaxStackSize, for a target. To set MaxStackSize, use assign statements in the
system target file (ert.tlc), as in the following example.
Write your %assign statements in the Configure RTW code generation settings
section of the system target file. The %assign statement is described in “Target
Language Compiler” (Simulink Coder).
56-104
See Also
See Also
“Maximum stack size (bytes)” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Enable and Reuse Local Block Outputs in Generated Code” on page 56-113
• “Minimize Computations and Storage for Intermediate Results at Block Outputs” on
page 56-37
• “Inline Numeric Values of Block Parameters” on page 56-44
56-105
56 Optimizations for Generated Code in Simulink Coder
If your compiler and target CPU both represent floating-point zero with the integer bit
pattern 0, consider setting this parameter to gain execution and ROM efficiency.
NOTE: The command-line values are the reverse of the settings values. 'on' in the
command line corresponds to clearing the setting. 'off' in the command line
corresponds to selecting the setting.
This optimization:
Example Model
model = 'rtwdemo_memset';
open_system(model);
Generate Code
The code generator uses a loop to initialize the Constant block values.
Create a temporary folder (in your system temporary folder) for the build and inspection
process.
56-106
Optimize Generated Code Using memset Function
currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild(model)
View the generated code without the optimization. These lines of code are in
rtwdemo_memset.c.
cfile = fullfile(cgDir,'rtwdemo_memset_grt_rtw','rtwdemo_memset.c');
rtwdemodbtype(cfile,'/* Model initialize function */',...
'/* Model terminate function */',1,0);
/* external outputs */
{
int32_T i;
for (i = 0; i < 50; i++) {
rtwdemo_memset_Y.Out1[i] = 0.0;
}
}
{
int32_T i;
56-107
56 Optimizations for Generated Code in Simulink Coder
Enable Optimization
1 Open the Configuration Parameters dialog box.
2 Clear the Use memset to initialize floats and doubles to 0.0 parameter.
Alternatively, you can use the command-line API to enable the optimization:
set_param(model,'InitFltsAndDblsToZero','off');
The code generator uses the memset function to initialize the Constant block values.
View the generated code with the optimization. These lines of code are in
rtwdemo_memset.c.
rtwdemodbtype(cfile,'/* Model initialize function */',...
'/* Model terminate function */',1,0);
/* external outputs */
(void) memset(&rtwdemo_memset_Y.Out1[0], 0,
50U*sizeof(real_T));
{
int32_T i;
56-108
See Also
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Use memset to initialize floats and doubles to 0.0” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Use memcpy Function to Optimize Generated Code for Vector Assignments” on
page 56-53
• “Vector Operation Optimization” on page 56-110
• “Remove Initialization Code” on page 59-4
56-109
56 Optimizations for Generated Code in Simulink Coder
Example Model
In the model, rtwdemo_VectorOptimization, the output of Gain blocks G1 and G2 are the
vector signals tmp1 and tmp2. These vectors have a width of 10.
model = 'rtwdemo_VectorOptimization';
open_system(model);
set_param(model, 'SimulationCommand', 'update')
Generate Code
Create a temporary folder (in your system temporary folder) for the build and inspection
process.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild(model)
56-110
Vector Operation Optimization
/* Outport: '<Root>/Out2' */
rtwdemo_VectorOptimization_Y.Out2[i] = rtb_Sum3;
56-111
56 Optimizations for Generated Code in Simulink Coder
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Minimize Computations and Storage for Intermediate Results at Block Outputs” on
page 56-37
• “Use memcpy Function to Optimize Generated Code for Vector Assignments” on
page 56-53
56-112
Enable and Reuse Local Block Outputs in Generated Code
In this section...
“Example Model” on page 56-113
“Generate Code Without Optimization” on page 56-114
“Enable Local Block Outputs and Generate Code” on page 56-114
“Reuse Local Block Outputs and Generate Code” on page 56-115
This example shows how to specify block output as local variables. The code generator
can potentially reuse these local variables in the generated code. Declaring block output
as local variables conserves ROM consumption. Reusing local variables conserves RAM
consumption, reduces data copies, and increases execution speed.
Example Model
1 Use Inport, Outport, Gain, and Switch blocks to create the following model. In this
example, the model is named local_variable_ex.
2 For G2, open the Gain Block Parameters dialog box. Enter a value of 2.
3 For G1, enter a value of 3.
4 For the Switch block, open the Block Parameters dialog box. For the Criteria for
passing first input parameter, select u2>=Threshold.
56-113
56 Optimizations for Generated Code in Simulink Coder
/* Outport: '<Root>/Out1' */
local_variable_ex_Y.Out1 = local_variable_ex_B.G2;
} else {
/* Gain: '<Root>/G1' */
local_variable_ex_B.G1 = 3.0 * local_variable_ex_U.In1;
/* Outport: '<Root>/Out1' */
local_variable_ex_Y.Out1 = local_variable_ex_B.G1;
}
56-114
Enable and Reuse Local Block Outputs in Generated Code
/* Outport: '<Root>/Out1' */
local_variable_ex_Y.Out1 = rtb_Switch;
56-115
56 Optimizations for Generated Code in Simulink Coder
/* Outport: '<Root>/Out1' */
local_variable_ex_Y.Out1 = rtb_G2;
The extra temporary variable rtb_Switch and the associated data copy is not in the
generated code.
See Also
“Enable local block outputs” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Customize Stack Space Allocation” on page 56-104
• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50
56-116
57
Before generating and deploying code, get familiar with the Hardware Implementation
pane of the Configuration Parameters dialog box. By default, target hardware
microprocessor device details are hidden. To view the details, click the Device details
arrow. See “Hardware Implementation Pane” (Simulink) and “Configure Run-Time
Environment Options” (Simulink Coder) for more information.
You can use the example “Configure Target Hardware Characteristics” (Simulink Coder)
to determine characteristics of your C or C++ compiler and target hardware. By using
the example model with your target development system and debugger, you can observe
the behavior of the code as it executes on the target hardware. You can then use the
information to refine hardware target device parameters for your model.
57-2
58
To tune your application and choose tradeoffs for execution speed and memory usage, you
can choose a global variable reference optimization for the generated code.
On the Configuration Parameters dialog box, in the Optimize global data access drop-
down list, three parameter options control global variable usage optimizations.
• None. Use default optimizations. This choice works well for most models. The code
generator balances the use of local and global variables. It generates code which
balances RAM and ROM consumption and execution speed.
• Use global to hold temporary results. Reusing global variables improves
code efficiency and readability. This optimization reuses global variables, which results
in the code generator defining fewer variables. It reduces RAM and ROM consumption
and data copies.
• Minimize global data access. Using local variables to cache global data reduces
ROM consumption by reducing code size in certain cases, such as when the global
variables are scalars. This optimization improves execution speed because the code
uses fewer instructions for local variable references than for global variable
references.
Minimizing the use of global variables by using local variables interacts with stack
usage control. For example, stack size can determine the number of local and global
variables that the code generator can allocate in the generated code. For more
information, see “Customize Stack Space Allocation” (Simulink Coder).
58-2
Optimize Global Variable Usage
Example Model
model = 'rtwdemo_optimize_global_ebf';
load_system('rtwdemo_optimize_global_ebf')
1 In the Configuration Parameters dialog box, verify that the Signal storage reuse
parameter is selected.
2 In the Configuration Parameters dialog box, for the Optimize global access
parameter, select None or enter the following command in the MATLAB Command
Window:
set_param('rtwdemo_optimize_global_ebf','GlobalVariableUsage','None');
In your system's temporary folder, create a folder for the build and inspection process:
currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild(model);
58-3
58 Data Copy Reduction in Embedded Coder
cfile = fullfile(cgDir,'rtwdemo_optimize_global_ebf_ert_rtw',...
'rtwdemo_optimize_global_ebf.c');
rtwdemodbtype(cfile,'/* Model step','/* Model initialize',1, 0);
rtb_Assignment[1] = rtU.In1;
The code assigns values to the local vector rtb_Assignment. The last statement copies
the values in the local vector rtb_Assignment to the global vector rtY.Out1. Fewer
global variable references result in improved execution speed. The code uses more
instructions for global variable references than for local variable references.
In the Static Code Metrics Report, examine the Global Variables section.
1 In the Code Generation Report window, select Static Code Metrics Report.
2 Scroll down to the Global Variables section.
3 Select the [+] sign before each variable to expand it.
58-4
Optimize Global Variable Usage
In the Configuration Parameters dialog box, for the Optimize global access parameter,
select Use global to hold temporary results, or enter the following command in
the MATLAB Command Window:
set_param('rtwdemo_optimize_global_ebf',...
'GlobalVariableUsage','Use global to hold temporary results');
58-5
58 Data Copy Reduction in Embedded Coder
rtY.Out1[1] = rtU.In1;
The code assigns values to the global vector rtY.Out1 without using a local variable.
This assignment improves ROM and RAM consumption and reduces data copies. The code
places the value in the destination variable for each assignment instead of copying the
value at the end. In the Static Code Metrics Report, examine the Global Variables section.
58-6
Optimize Global Variable Usage
As a result of using global variables to hold local results, the total number of reads and
writes for global variables has increased from 2 to 5. This optimization reduces data
copies by reusing global variables.
rtwdemoclean;
cd(currentDir)
Example Model
model = 'rtwdemo_optimize_global';
load_system('rtwdemo_optimize_global')
58-7
58 Data Copy Reduction in Embedded Coder
1 In the Configuration Parameters dialog box, verify that the Signal storage reuse
parameter is selected.
2 In the Configuration Parameters dialog box, for the Optimize global access
parameter, select None or enter the following command in the MATLAB Command
Window:
set_param('rtwdemo_optimize_global','GlobalVariableUsage','None');
In your system's temporary folder, create a folder for the build and inspection process.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
58-8
Optimize Global Variable Usage
rtwbuild(model);
cfile = fullfile(cgDir,'rtwdemo_optimize_global_ert_rtw',...
'rtwdemo_optimize_global.c');
rtwdemodbtype(cfile,'/* Model step','/* Model initialize',1, 0);
case 2:
/* Outport: '<Root>/Out1' incorporates:
* Constant: '<Root>/Constant1'
*/
rtY.Out1 = 2.0;
break;
case 3:
/* Outport: '<Root>/Out1' incorporates:
* Constant: '<Root>/Constant2'
*/
rtY.Out1 = 3.0;
break;
default:
/* Outport: '<Root>/Out1' incorporates:
* Constant: '<Root>/Constant3'
*/
rtY.Out1 = 4.0;
58-9
58 Data Copy Reduction in Embedded Coder
break;
}
In the Static Code Metrics Report, examine the Global Variables section.
1 In the Code Generation Report window, select Static Code Metrics Report.
2 Scroll down to the Global Variables section.
3 Select the [+] sign before each variable to expand it.
In the Configuration Parameters dialog box, for the Optimize global data access
parameter, select Minimize global data access or enter the following command in
the MATLAB Command Window:
set_param('rtwdemo_optimize_global',...
'GlobalVariableUsage','Minimize global data access');
rtwbuild(model);
58-10
Optimize Global Variable Usage
case 2:
/* Outport: '<Root>/Out1' incorporates:
* Constant: '<Root>/Constant1'
*/
tmp_Out1 = 2.0;
break;
case 3:
/* Outport: '<Root>/Out1' incorporates:
* Constant: '<Root>/Constant2'
*/
tmp_Out1 = 3.0;
break;
default:
/* Outport: '<Root>/Out1' incorporates:
* Constant: '<Root>/Constant3'
*/
tmp_Out1 = 4.0;
58-11
58 Data Copy Reduction in Embedded Coder
break;
}
/* Outport: '<Root>/Out1' */
rtY.Out1 = tmp_Out1;
}
In the Static Code Metrics Report, examine the Global Variables section. As a
result of minimizing global data accesses, the total number of reads and writes for global
variables has decreased from 5 to 2.
rtwdemoclean;
cd(currentDir)
See Also
“Optimize global data access” (Simulink Coder)
58-12
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Minimize Computations and Storage for Intermediate Results at Block Outputs” on
page 56-37
• “Customize Stack Space Allocation” on page 56-104
• “Reuse Global Block Outputs in the Generated Code” on page 58-14
58-13
58 Data Copy Reduction in Embedded Coder
Example
1 On the Configuration Parameters dialog box, verify that Signal storage reuse is
selected.
2 Clear Reuse global block outputs and click Apply.
3 On the Code Generation > Report pane, select Static code metrics.
4 In your system's temporary folder, create a folder for the build and inspection
process.
58-14
Reuse Global Block Outputs in the Generated Code
The generated code contains a data copy to the global variable rtDW.Delay_DSTATE.
Open the Static Code Metrics Report. The total number of reads and writes for global
variables is 8. The total size is 32 bytes.
1 On the Configuration Parameters dialog box, select Reuse global block outputs
and click Apply.
2 Generate code.
3 View the generated code with the optimization. Here is a portion of
rtwdemo_reuse_global.c.
58-15
58 Data Copy Reduction in Embedded Coder
The code generator eliminates a data copy, reduces two statements to one statement and
three global variables to two global variables.
Open the Static Code Metrics Report. For global variables, this optimization reduces the
total number of reads and writes for global variables from 8 to 5 and the total size from
32 bytes to 24 bytes.
See Also
“Reuse global block outputs” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Minimize Computations and Storage for Intermediate Results at Block Outputs” on
page 56-37
• “Optimize Global Variable Usage” on page 58-2
58-16
Virtualized Output Ports Optimization
Consider the model in the following block diagram. The signal exportedSig has
exportedGlobal storage class.
In the default case, the output of the Gain block is written to the signal storage location,
exportedSig. The code generator does not generate code or data for the Out1 block,
which has become a virtual block.
The following code fragment was generated with MAT-file logging enabled. The output
port is represented as a member of the external outputs vector VirtOutPortLogON_Y.
The Gain block output value is copied to exportedSig and to the external outputs vector.
Data maintenance in the external outputs vector can be significant for smaller models
that perform benchmarks.
You can force root output ports to be stored in the external outputs vector (regardless of
the setting of MAT-file logging) by setting the TLC variable FullRootOutputVector to
1. Add the statement
58-17
58 Data Copy Reduction in Embedded Coder
%assign FullRootOutputVector = 1
to the Embedded Coder system target file. Alternatively, you can enter the assignment
from the MATLAB command line using the set_param command, the model parameter
TLCOptions, and the TLC option -a. For more information, see “Specify TLC for Code
Generation” (Simulink Coder) and “Configure TLC” (Simulink Coder).
For more information on how to control signal storage in generated code, see “How
Generated Code Stores Internal Signal, State, and Parameter Data” on page 22-50 and
“Apply Storage Classes to Individual Signal, State, and Parameter Data Elements” on page
22-81.
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Specify Buffer Reuse by Using Simulink.Signal Objects” on page 58-19
• “Optimize Global Variable Usage” on page 58-2
58-18
Specify Buffer Reuse by Using Simulink.Signal Objects
You can specify buffer reuse on signals that include a pair of root inport and outport
signals. You can also specify buffer reuse on just a pair of root inport and outport signals.
This optimization reduces ROM and RAM consumption because there are less global
variables and data copies in the generated code. Code execution speed also increases.
Example Model
model ='rtwdemo_reusable_csc';
open_system(model);
1 In the model, open the Model Data Editor (View > Model Data Editor).
2 In the Model Data Editor, on the Signals tab, from the Change view drop-down list,
select Code.
3 Click the Show/refresh additional information button. Now, the Model Data Editor
shows information about variables and objects in workspaces such as the base
workspace.
4 Next to the Filter contents box, activate the Filter using selection button.
58-19
58 Data Copy Reduction in Embedded Coder
5 In the model, select the RCSC_REAL signal line. The Model Data Editor shows two
rows: One that represents the signal line and one that represents a
Simulink.Signal object in the base workspace.
6 For the row that represents the signal line, inspect the Resolve column. The check
box is selected, which means the signal line resolves to the Simulink.Signal
object, acquiring code generation settings from that object.
7 For the row that represents the signal object, inspect the Storage Class column. The
signal object uses the storage class Reusable, which means the object appears in
the generated code as a global variable named RCSC_REAL.
8 In the model, navigate into the DeltaSubsystem subsystem.
9 Select the RCSC_REAL signal line in this subsystem. This signal also resolves to the
signal object in the base workspace.
With the Reusable storage class, the generated code can store the output of the
Complex to Real-Imag block (at the root level of the model) and the output of the
DeltaX block (in the subsystem) in the RCSC_REAL global variable.
Generate Code
For buffer reuse, the rtwdemo_reusable_csc.c file contains these global variables:
58-20
Specify Buffer Reuse by Using Simulink.Signal Objects
58-21
58 Data Copy Reduction in Embedded Coder
rtY.Out1[i].re = RCSC_REAL2[i];
rtY.Out1[i].im = RCSC_IMAG2[i];
}
The variables RCSC_REAL and RCSC_IMAG hold the outputs of the Complex to Real-Image
block and DeltaX. These variables hold the inputs to the DeltaY block. The variables
RCSC_REAL2 and RCSC_IMAG2 hold the outputs of Downsample and DeltaY. These
variables hold the inputs to the DeltaX block. By interleaving buffers in this way, you
eliminate global variables in the generated code.
To remove the signal objects from the signal lines and regenerate code, in the MATLAB
Command Window, enter these commands:
portHandles = get_param(...
'rtwdemo_reusable_csc/Complex to Real-Imag','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');
portHandles = get_param(...
'rtwdemo_reusable_csc/Downsample','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');
portHandles = get_param(...
'rtwdemo_reusable_csc/DeltaSubsystem/DeltaX','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');
portHandles = get_param(...
'rtwdemo_reusable_csc/DeltaSubsystem/DeltaY','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');
rtwbuild(model);
58-22
Specify Buffer Reuse by Using Simulink.Signal Objects
rtwdemodbtype(cfile,...
'/* Output and update for atomic system: ''<Root>/DeltaSubsystem'' */',...
'/* Output and update for atomic system: ''<Root>/Downsample'' */',1,0);
rtwdemodbtype(cfile,...
'/* Model step function */','/* Model initialize function */',1,0);
58-23
58 Data Copy Reduction in Embedded Coder
rtY.Out1[i].im = rtDWork.z2[i];
}
The generated code contains two additional global variables for holding block inputs and
outputs.
Note: You can specify buffer reuse on signals that the code generator cannot implement.
For those cases, use two new diagnostics to specify the message type that the model
displays. In the Configuration Parameters dialog box, these diagnostics are Detect non-
reused custom storage classes and Detect ambiguous custom storage class final
values.
bdclose(model)
rtwdemoclean;
cd(currentDir)
1 Use the same reusable custom storage class specification for a pair of input and state
arguments or a pair of output and state arguments of a Unit Delay block or a Delay
block.
2 In the Model Data Editor, select the States tab and from the Change view drop-
down list, select Code.
3 Use the Name column to set the name of the target Unit Delay or Delay block states.
Specify the name of the signal object that you want to reuse.
4 For each state, check the box in the Resolve column.
For Delay blocks, you must set the Delay length parameter to 1 and Initial condition >
Source to Dialog. To access these parameters, in the model, open the Property
Inspector (View > Property Inspector) and click the block in the model.
These limitations apply to a model in which you specify buffer reuse for a pair of root
inport and outport signals:
58-24
See Also
• If the code generator cannot reuse the same buffer in a top model, the generated code
contains additional buffers. If the top model is a reference model, the code generator
reports an error. To resolve the error, remove the Simulink.signal specification from
the signal that connects to the outport port.
• When you run the executable that the code generator produces, and you reuse a pair
of root inport and outport signals, when the root input value is zero, the root output
value must also be zero. If the output value is nonzero and you reuse the signals, then
the results from the simulation can differ from the results that the executable
produces.
These limitations apply to a model in which you specify buffer reuse for signals:
• Signals that you specify for reuse must have the same data types and sampling rates.
• For user-specified buffer reuse, blocks that modify a signal specified for reuse must
execute before blocks that use the original signal value. Sometimes the code generator
has to change the block operation order so that buffer reuse can occur. For models in
which the code generator is unable to reorder block operations, buffer reuse does not
occur.
• For models in which the code generator reorders block operations so that
Simulink.Signal reuse can occur, you can observe the difference in the sorted
order. In the model window, select Display > Blocks > Sorted Execution Order. To
display the sorted execution order during simulation, select Simulation > Update
Diagram. To display the execution order in the generated code, select Code > C/C++
Code > Build Model.
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements”
(Simulink Coder)
• “Choose a Storage Class for Controlling Data Representation in the Generated
Code” on page 22-69
• “Virtualized Output Ports Optimization” on page 58-17
58-25
58 Data Copy Reduction in Embedded Coder
• “Design Data Interface by Configuring Inport and Outport Blocks” on page 22-206
58-26
Specify Buffer Reuse for MATLAB Function Blocks in a Path
You can specify buffer reuse across MATLAB Function blocks by using the same variable
name for the input and output arguments. The code generator tries to reuse the output of
one MATLAB Function block as the input to the next MATLAB Function block. This
optimization conserves RAM and ROM consumption and reduces data copies.
Example Model
1 Use Inport, Outport, and MATLAB Function blocks to create the model mf_inplace.
2 Open each MATLAB Function block and copy the following code:
function y = fcn(y)
%#codegen
y=y+4;
3 Open the Configuration Parameters dialog box. On the Code Generation tab, change
the System target file to ert.tlc.
4 On the Solver tab, change the Type parameter to Fixed-step.
58-27
58 Data Copy Reduction in Embedded Coder
void mf_inplace_step(void)
{
real_T rtb_y_p5;
rtb_y_p5 = mf_inplace_U.In1;
mf_inplace_MATLABFunction(&rtb_y_p5);
mf_inplace_MATLABFunction(&rtb_y_p5);
mf_inplace_MATLABFunction(&rtb_y_p5);
mf_inplace_Y.Out1 = rtb_y_p5;
mf_inplace_MATLABFunction(&mf_inplace_Y.Out1);
}
The code generator reuses the variable rtb_y_p5 for the input and output arguments of
each MATLAB Function block.
Note On the Code Generation tab in the Subsystem Block Parameters dialog box, if the
Function packaging parameter is set to Nonreusable function and the Function
interface parameter is set to Allow arguments, the code generator cannot reuse the
input and output arguments.
See Also
Related Examples
• “What Is a MATLAB Function Block?” (Simulink)
• “Specify Buffer Reuse by Using Simulink.Signal Objects” on page 58-19
58-28
Remove Data Copies by Reordering Block Operations in the Generated Code
Example Model
In the model ex_optimizeblockorder, the signal that leaves the Sum block enters a
Subtract block and a Concatenate block. The signal that leaves the Subtract block enters
a Product block and a Sum of Elements block.
58-29
58 Data Copy Reduction in Embedded Coder
/* Sum: '<Root>/SumOfElements' */
rtY.Out2 = -0.0;
58-30
Remove Data Copies by Reordering Block Operations in the Generated Code
/* Sum: '<Root>/Sum2x3' */
rtb_Sum2x3[i] = rtb_Sum2x3_d;
/* Sum: '<Root>/SumOfElements' */
rtY.Out2 += rtb_Subtract;
}
With the default order, the generated code contains three buffers, rtb_Sum2x3[6],
rtb_Sum2x3_d, and rtb_Subtract. The generated code contains these temporary
variables and associated data copies because the Matrix Concatenate block must use the
output from the Sum block and the Sum of Elements block must use the output from the
Subtract block.
58-31
58 Data Copy Reduction in Embedded Coder
58-32
Remove Data Copies by Reordering Block Operations in the Generated Code
* Inport: '<Root>/In1'
* Inport: '<Root>/In2'
*/
for (i = 0; i < 6; i++) {
rtY.Out1[i] = rtU.In1[i] + rtU.In2;
}
/* Sum: '<Root>/SumOfElements' */
rtY.Out2 = -0.0;
for (i = 0; i < 6; i++) {
/* Sum: '<Root>/Subtract' incorporates:
* Inport: '<Root>/In3'
*/
rtY.Out1[i] -= rtU.In3;
/* Sum: '<Root>/SumOfElements' */
rtY.Out2 += rtY.Out1[i];
To implement buffer reuse, the code generator does not violate user-specified block
priorities.
58-33
58 Data Copy Reduction in Embedded Coder
See Also
“Optimize block operation order in the generated code” (Simulink Coder)
Related Examples
• “Improve Execution Efficiency by Reordering Block Operations in the Generated
Code” on page 59-65
• “Data Copy Reduction”
58-34
Data Copy Reduction for Data Store Read and Data Store Write Blocks
Example Model
In the Configuration Parameters dialog box, deselect the Reuse buffers for Data Store
Read and Data Store Write blocks parameter or at the MATLAB command prompt,
enter this command:
58-35
58 Data Copy Reduction in Embedded Coder
set_param(model,'OptimizeDataStoreBuffers','off');
currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild(model)
cfile = fullfile(cgDir,'rtwdemo_optimizedatastorebuffers_ert_rtw',...
'rtwdemo_optimizedatastorebuffers.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* DataStoreRead: '<Root>/DSR' */
rtb_DSR_last = mem.last;
58-36
Data Copy Reduction for Data Store Read and Data Store Write Blocks
/* DataStoreWrite: '<Root>/DSW' */
mem.last = rtb_SimFuncCall_o1;
mem.max = rtb_Sum_p;
The generated code contains data copies for the Data Store Read and Data Store Write
blocks, respectively.
In the Configuration Parameters dialog box, clear the Reuse buffers for Data Store
Read and Data Store Write blocks parameter or at the MATLAB command prompt,
enter this command:
set_param(model,'OptimizeDataStoreBuffers','on');
rtwbuild(model)
cfile = fullfile(cgDir,'rtwdemo_optimizedatastorebuffers_ert_rtw',...
'rtwdemo_optimizedatastorebuffers.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
58-37
58 Data Copy Reduction in Embedded Coder
/* DataStoreRead: '<Root>/DSR' */
rtb_DSR_last = mem.last;
The data copy for the Data Store Write block is not in the generated code. The code
contains the data copy for the Data Store Read block because the Sum block executes
after the Data Store Write block. The generated code contains the variable
rtb_DSR_last to hold the output of the Sum block. Therefore, the Sum block gets the
values that SimFuncCall calculates at the start of the time step rather than those values
at the next time step. If the priority of the Sum block is lower than SimFuncCall, the
code generator can remove the data copy for the Data Store Read block. Some other
cases in which the code generator might not eliminate data copies are:
58-38
See Also
• The Data Store Read and Data Store Write blocks occur on the same block unless that
block is a Bus Assignment block or an Assignment block.
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Reuse buffers for Data Store Read and Data Store Write blocks” (Simulink Coder)
Related Examples
• “Reuse Local Block Outputs and Generate Code” (Simulink Coder)
58-39
58 Data Copy Reduction in Embedded Coder
Example Model
For example, in bus_assignoptim, a bus signal containing six elements feeds into a Bus
Assignment block and a Bus Selector block. The Bus Assignment block assigns new values
to the bus element a1_real_array. This bus signal feeds into Out1.
void bus_assignoptim_step(void)
{
real_T rtb_Assignment[36];
int32_T i;
58-40
Reduce Data Copies for Bus Assignment Blocks
The generated code contains the temporary array rtb_Assignment for holding data
before this data is assigned to bus_assignoptim_Y.Out.a1_real_array.
58-41
58 Data Copy Reduction in Embedded Coder
The generated code does not contain the temporary array rtb_Assignment1 for holding
data. The generated code directly assigns this data to
bus_assignoptim_Y.Out.a1_real_array.
See Also
“Perform inplace updates for Bus Assignment blocks” (Simulink Coder)
Related Examples
• “Improve Execution Efficiency by Reordering Block Operations in the Generated
Code” on page 59-65
• “Data Copy Reduction”
58-42
Optimize Generated Code by Using Signal Labels to Guide Buffer Reuse
Specifying buffer reuse improves execution speed and may reduce RAM consumption.
Example Model
The model rtwdemo_label_guided_reuse demonstrates how you can use signal labels
to request buffer reuse for block input and output signals. For this model, the code
generator can use the same variable for the Atomic Subsystem and either the Gain or
Saturation block outputs. The generated code uses the same variable for the Saturation
and Atomic Subsystem block outputs because those signals contain the same label and
the Use Signal Labels to Guide Buffer Reuse parameter is selected.
58-43
58 Data Copy Reduction in Embedded Coder
2 In the Configuration Parameters dialog box, clear the Use Signal Labels to Guide
Buffer Reuse parameter.
3 Build the model. The rtwdemo_label_guided_reuse_step function contains this
code:
void rtwdemo_label_guided_reuse_step(void)
{
real_T rtb_Saturation[4];
real_T rtb_Bias[4];
int32_T i;
AtomicSubsystem(rtU.In1, rtb_Bias);
for (i = 0; i < 4; i++) {
if (rtb_Bias[i] > 10.0) {
rtb_Saturation[i] = 10.0;
} else if (rtb_Bias[i] < -10.0) {
rtb_Saturation[i] = -10.0;
} else {
rtb_Saturation[i] = rtb_Bias[i];
}
rtb_Bias[i] *= 3.0;
}
By default, within the for loop, the Gain block executes after the Saturation block.
The generated code uses the same variable for the output of the Atomic Subsystem
and the Gain blocks. As a result, the generated code contains two local variables
rtb_Saturation and rtb_Bias for holding intermediate results.
58-44
Optimize Generated Code by Using Signal Labels to Guide Buffer Reuse
The code generator changed the block execution order so that within the for loop, the
Saturation block executes after the Gain block. The generated code contains one local
variable rtb_Gain1 for holding intermediate results.
In addition to requesting which buffers to reuse, another possible use case is to request
buffer reuse for block input and output signals that are complex.
• Signal labels are not observation points in the generated code, so using them does not
block other optimizations such as dead code elimination and expression folding.
• The code generator does not force a signal with a label to be a global variable in the
generated code. The signal can be a local or global variable.
• Signals with labels can reuse buffers with signals that do not have labels, so reuse
among local and global variables is possible.
Using signal labels is a more conservative method of specifying reuse than using
Reusable custom storage classes. The code generator does not implement label-based
reuse when it can implement reuse by using Reusable custom storage classes in these
cases:
• Reuse that can potentially prevent other optimizations from occurring in the
generated code.
58-45
58 Data Copy Reduction in Embedded Coder
See Also
“Use signal labels to guide buffer reuse” (Simulink Coder)
Related Examples
• “Improve Execution Efficiency by Reordering Block Operations in the Generated
Code” on page 59-65
• “Remove Data Copies by Reordering Block Operations in the Generated Code” on
page 58-29
• “Specify Buffer Reuse by Using Simulink.Signal Objects” on page 58-19
• “Data Copy Reduction”
58-46
59
When the Enable local block outputs parameter is on, where possible the code
generator declares block outputs as local variables instead of global variables. Replacing
global variables with local variables improves execution speed and reduces RAM/ROM
consumption. Creating more local variables can increase stack usage. Some of the global
variables that the code generator can localize include:
When the Reuse local block outputs parameter is on, wherever possible the code
generator reuses local (function) variables for block outputs. When you select Reuse
global block outputs, the code generator reuses global (function) variables wherever
possible.
• None
• Use global to hold temporary results
• Minimize global data access
When you select None, the code generator uses the default optimizations. The setting Use
global to hold temporary results maximizes the use of global variables. The
setting Minimize global data access minimizes the use of global variables by using
local variables to hold intermediate values.
59-2
See Also
Clearing Signal storage reuse makes all block outputs global and unique, which often
significantly increases RAM and ROM usage.
The code generator does not localize global variables for MATLAB system objects or
AUTOSAR.
See Also
Related Examples
• “Enable and Reuse Local Block Outputs in Generated Code” (Simulink Coder)
• “Reuse Global Block Outputs in the Generated Code” on page 58-14
• “Optimize Global Variable Usage” on page 58-2
59-3
59 Execution Speed in Embedded Coder
Example Model
Open the model rtwdemo_internal_init. The model contains an enabled subsystem whose
initial output is zero. The subsystem contains a Unit Delay block whose initial condition is
0.
59-4
Remove Initialization Code
/* states (dwork) */
(void) memset((void *)&rtDWork, 0,
sizeof(D_Work));
/*
Enable Optimization
Open the Configuration Parameters dialog box. On the Optimization pane, select
Remove internal data zero initialization.
Alternatively, you can use the command prompt to enable the optimization. To enable the
optimization, set the model parameter ZeroInternalMemoryAtStartup to 'off'.
set_param(model, 'ZeroInternalMemoryAtStartup', 'off');
This code is in the rtwdemo_internal_init.c file. The generated code does not
initialize internal data by assignment to zero.
59-5
59 Execution Speed in Embedded Coder
void rtwdemo_internal_init_initialize(void)
{
/* (no initialization code required) */
}
/*
If you select the Remove internal data zero initialization parameter, be aware that
memory might not be in a known state each time the generated code executes. This
means that running a model (or a generated S-function) multiple times can result in
different answers for each run. This behavior is sometimes desirable. For example, you
can select the Remove internal data zero initialization parameter if you want to test
the behavior of your design during a warm boot (that is, a restart without full system
reinitialization). For models in which you select the Remove internal data zero
initialization parameter but still want to get the same answer on every run from an S-
function, you can use either of the following commands before each run:
clear SFcnName
Example Model
59-6
Remove Initialization Code
Generate Code
In your system temporary folder, create a temporary folder for the build and inspection
process.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
set_param(model, 'ZeroExternalMemoryAtStartup','on');
rtwbuild(model)
cfile = fullfile(cgDir,'rtwdemo_rootlevel_zero_initialization_ert_rtw',...
'rtwdemo_rootlevel_zero_initialization.c');
rtwdemodbtype(cfile, 'rtwdemo_rootlevel_zero_initialization_initialize',...
'trailer for generated code', 1, 0);
void rtwdemo_rootlevel_zero_initialization_initialize(void)
{
/* Registration code */
/* external inputs */
59-7
59 Execution Speed in Embedded Coder
sig1 = 0;
sig1_b = -3;
sig2 = false;
sig2_b = -3;
/* external outputs */
(void) memset((void *)&rtY, 0,
sizeof(ExternalOutputs));
}
/*
Enable Optimization
The optimized code does not contain initialization code for the input signals sig1, sig2,
and the four output signals, because their initial values are bitwise zero.
void rtwdemo_rootlevel_zero_initialization_initialize(void)
{
/* Registration code */
59-8
See Also
/* external inputs */
sig1_b = -3;
sig2_b = -3;
}
/*
bdclose(model)
rtwdemoclean;
cd(currentDir)
Additional Information
• You can use the Use memset to initialize floats and doubles parameter to control
the representation of zero during initialization. See “Use memset to initialize floats
and doubles to 0.0” (Simulink Coder).
• The code still initializes data structures whose value is not zero when you select
Remove internal data zero initialization and Remove root level I/O zero
initialization.
• The data of ImportedExtern or ImportedExternPointer storage classes are not
initialized, regardless of the settings of the Remove internal data zero
initialization and Remove root level I/O zero initialization parameters.
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Optimize Generated Code Using memset Function” on page 56-106
59-9
59 Execution Speed in Embedded Coder
The generated code might have multiply operations when indexing an element of an array.
You can select the optimization parameter “Simplify array indexing” (Simulink Coder) to
replace multiply operations in the array index with a temporary variable. This
optimization can improve execution speed by reducing the number of times the multiply
operation executes.
Example Model
If you have the following model:
59-10
Simplify Multiply Operations in Array Indexing
Generate Code
Building the model with the Simplify array indexing parameter turned off generates the
following code:
int32_T i;
int32_T i_0;
int32_T i_1;
59-11
59 Execution Speed in Embedded Coder
int32_T i;
int32_T i_0;
int32_T i_1;
int32_T tmp;
int32_T tmp_0;
int32_T tmp_1;
tmp = 0;
tmp_0 = 0;
for (i = 0; i < 2; i++) {
tmp_1 = 0;
for (i_1 = 0; i_1 < 3; i_1++) {
for (i_0 = 0; i_0 < 5; i_0++) {
ex_arrayindex_Y.Out[(i_0 + tmp_1) + tmp] =
ex_arrayindex_P.Constant1_Value[(i_0 + tmp_1) + tmp_0];
}
tmp_1 += 5;
}
tmp += 70;
tmp_0 += 15;
}
tmp = 0;
tmp_0 = 0;
for (i = 0; i < 2; i++) {
tmp_1 = 0;
for (i_1 = 0; i_1 < 2; i_1++) {
for (i_0 = 0; i_0 < 5; i_0++) {
ex_arrayindex_Y.Out[((i_0 + tmp_1) + tmp) + 15] =
ex_arrayindex_P.Constant2_Value[(i_0 + tmp_1) + tmp_0];
}
tmp_1 += 5;
}
tmp += 70;
tmp_0 += 10;
}
tmp = 0;
tmp_0 = 0;
for (i = 0; i < 2; i++) {
59-12
See Also
tmp_1 = 0;
for (i_1 = 0; i_1 < 9; i_1++) {
for (i_0 = 0; i_0 < 5; i_0++) {
ex_arrayindex_Y.Out[((i_0 + tmp_1) + tmp) + 25] =
ex_arrayindex_P.Constant3_Value[(i_0 + tmp_1) + tmp_0];
}
tmp_1 += 5;
}
tmp += 70;
tmp_0 += 45;
}
See Also
“Simplify array indexing” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Use memcpy Function to Optimize Generated Code for Vector Assignments” on
page 56-53
• “Vector Operation Optimization” on page 56-110
59-13
59 Execution Speed in Embedded Coder
• int8
• uint8
• intn
To match the integer word size for the production hardware, replace n with 8, 16, or 32 .
Example Model
The model ex_bool contains two blocks that output boolean values and two blocks that
take boolean values as inputs. This example shows how to replace the data type
boolean with the integer data type int32 in the code generated for a 32-bit hardware
target.
59-14
Replace boolean with Specific Integer Data Type
/*===========================================================================*
* Generic type definitions: boolean_T, char_T, byte_T, int_T, uint_T, *
* real_T, time_T, ulong_T. *
*===========================================================================*/
typedef double real_T;
typedef double time_T;
typedef unsigned char boolean_T;
typedef int int_T;
typedef unsigned int uint_T;
typedef unsigned long ulong_T;
59-15
59 Execution Speed in Embedded Coder
View the generated file ex_bool.c. The code declares boolean variables by using the
type boolean_T.
mybool = Simulink.AliasType;
mybool.BaseType = 'int32';
2 In the Configuration Parameters dialog box, specify the Replacement Name field for
the data type boolean as mybool.
59-16
Replace boolean with Specific Integer Data Type
View the generated file rtwtypes.h. The code maps the identifier mybool to the native
integer type of the target hardware by creating typedef statements.
/* Generic type definitions ... */
...
typedef int boolean_T;
...
/* Define Simulink Coder replacement data types. */
typedef boolean_T mybool; /* User defined replacement datatype for boolean_T */
View the generated file ex_bool.c. The code declares boolean variables that use the
type mybool.
/* External inputs (root inport signals with auto storage) */
typedef struct {
real_T In1; /* '<Root>/In1' */
real_T In2; /* '<Root>/In2' */
mybool In3; /* '<Root>/In3' */
mybool In4; /* '<Root>/In4' */
real_T In5; /* '<Root>/In5' */
} ExtU_ex_bool_T;
59-17
59 Execution Speed in Embedded Coder
See Also
Simulink.AliasType
Related Examples
• “Model Configuration Parameters: Code Generation Data Type Replacement”
59-18
Remove Code That Guards Against Division Exceptions for Integers and Fixed-Point Data
This optimization:
NOTE: If you enable this optimization, it is possible that simulation results and results
from generated code are not in bit-for-bit agreement. This example requires an Embedded
Coder® license.
Example Model
In the model rtwdemo_nzcheck, two signals of type int8 feed into a divide block.
model = 'rtwdemo_nzcheck';
open_system(model);
Generate Code
In your system's temporary folder, create a temporary folder for the build and inspection
process.
59-19
59 Execution Speed in Embedded Coder
currentDir = pwd;
[~,cgDir] = rtwdemodir();
cfile = fullfile(cgDir,'rtwdemo_nzcheck_ert_rtw','rtwdemo_nzcheck.c');
rtwdemodbtype(cfile,'/* Real-time model','/* Model step function',1, 1);
/* Real-time model */
RT_MODEL_rtwdemo_nzcheck rtwdemo_nzcheck_M_;
RT_MODEL_rtwdemo_nzcheck *const rtwdemo_nzcheck_M = &rtwdemo_nzcheck_M_;
int32_T div_s32(int32_T numerator, int32_T denominator)
{
int32_T quotient;
uint32_T tempAbsQuotient;
if (denominator == 0) {
quotient = numerator >= 0 ? MAX_int32_T : MIN_int32_T;
return quotient;
}
Enable Optimization
59-20
See Also
2 On the Optimization pane, select Remove code that protects against division
arithmetic exceptions.
Alternatively, you may use the command-line API to enable the optimization:
The optimized code does not contain code that checks for whether or not the divisor has a
value of zero.
rtwbuild(model);
/* Real-time model */
RT_MODEL_rtwdemo_nzcheck rtwdemo_nzcheck_M_;
RT_MODEL_rtwdemo_nzcheck *const rtwdemo_nzcheck_M = &rtwdemo_nzcheck_M_;
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Remove code that protects against division arithmetic exceptions” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
59-21
59 Execution Speed in Embedded Coder
59-22
Division Arithmetic Exceptions in Generated Code
When the parameter is selected, the generated code does not contain code that guards
against these types of exceptions. This produces smaller, more efficient code, however it
can affect numerical results. Select the parameter if you are sure that your model would
not encounter these exceptions to optimize the efficiency of the generated code.
When the parameter is not selected, the generated code does not contain code that
guards against division arithmetic exceptions. The added protection code checks that
there is a numerical match between simulation and code generation for division
operations at a cost of code size and performance.
Division by Zero
Division by zero is undefined and results in a runtime error in the generated code. When
the Remove code that protects against division arithmetic exceptions parameter is
selected, the code generator does not produce code that protects against division by zero.
Select this option only when you are sure that your model will not produce such a division
operation.
INT_MIN/-1
When you divide the minimum representable value of a signed integer by negative one,
the ideal result is equal to the maximum representable value plus one (INT_MAX + 1),
which is not representable. This exception may cause the application to unexpectedly halt
or crash at run-time. When the Remove code that protects against division
arithmetic exceptions parameter is selected, the code generator does not produce code
that protects against this situation. Select this option only when you are sure that your
model will not produce such a division operation.
59-23
59 Execution Speed in Embedded Coder
The ideal quotient of this operation is 2147483648, but this is not representable in an
int32 data type, resulting in an exception at runtime.
Rounding and overflow modes also affect the size and efficiency of the generated code.
For more information, see “Optimize Generated Code with the Model Advisor” (Fixed-
Point Designer).
See Also
“Remove code that protects against division arithmetic exceptions” (Simulink Coder)
Related Examples
• “Remove Code That Guards Against Division Exceptions for Integers and Fixed-Point
Data” on page 59-19
• “Optimization Tools and Techniques” on page 56-7
59-24
Optimize Generated Code by Consolidating Redundant If-Else Statements
Example
The model rtwdemo_controlflow_opt contains three Switch blocks. The Constant block
provides the control input to the Switch blocks. The variable named Cond determines the
value of the Constant block.
model = 'rtwdemo_controlflow_opt';
open_system(model);
59-25
59 Execution Speed in Embedded Coder
Generate Code
These lines of rtwdemo_controlflow_opt.c code show that in the generated code, two
if-else statements and one else-if statement represent the three Switch blocks.
59-26
Optimize Generated Code by Consolidating Redundant If-Else Statements
cfile = fullfile(cgDir,'rtwdemo_controlflow_opt_ert_rtw',...
'rtwdemo_controlflow_opt.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
59-27
59 Execution Speed in Embedded Coder
Enable Optimization
In the optimized code, the code generator consolidates the two if-else statements and
one else-if statement into one if-else statement. The code generator consolidates
these statements because they all share the same condition. There is no intervening code
that affects the outcomes of these statements.
rtwbuild(model)
59-28
See Also
*/
rtY.Out1 = rtU.In2;
}
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Preserve condition expression in if statement”
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Eliminate Dead Code Paths in Generated Code” on page 56-62
59-29
59 Execution Speed in Embedded Coder
Example Model
In the model rtwdemo_fixptdiv, two fixed point signals connect to a Divide block. The
Number of inputs parameter has the value /*.
model='rtwdemo_fixptdiv';
load_system(model)
set_param(model,'HideAutomaticNames','off','SimulationCommand','Update')
open_system(model);
59-30
Optimize Generated Code for Fixed-Point Data Operations
Generate Code
59-31
59 Execution Speed in Embedded Coder
cfile = fullfile(cgDir,'rtwdemo_fixptdiv_ert_rtw','rtwdemo_fixptdiv.c');
rtwdemodbtype(cfile,'/* Model step','/* Model initialize', 1, 0);
The generated code contains a highly efficient right shift operation instead of an
expensive division operation. The generated code also contains the precomputed value for
the constant input to the Product block.
Note that the resulting operation also includes the adjustment in signal scaling from 2^-3
to 2^-5.
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Fixed Point” (Simulink)
59-32
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
• Optimization for a specific run-time environment, including, but not limited to, specific
target hardware
• Integration with existing application code
• Compliance with a standard, such as AUTOSAR
• Modification of code behavior, such as enabling or disabling nonfinite or inline support
• Application- or project-specific code requirements, such as use of BLAS or elimination
of math.h, system header files, or calls to memcpy or memset.
You can configure a model such that the code generator uses a code replacement library
that MathWorks® provides. If you have an Embedded Coder® license, you can develop
your own code replacement library interactively with the Code Replacement Tool or
programmatically.
This example uses models to show a variety of ways you can define code replacement
mappings programmatically. Each model includes buttons that you can use to
• View the code replacement library table definitions from the Code Replacement
Viewer
• Open the library table definition file in the editor
• Open the library registration file in the editor
• View the model configuration
• Generate code
For more information, see “Define Code Replacement Mappings” on page 54-43 and
“Register Code Replacement Mappings” on page 54-70.
59-33
59 Execution Speed in Embedded Coder
2 Prepare for code replacement library development (for example, identify or develop
models to test your library).
3 Define code replacement mappings.
4 Specify build information for replacement code.
5 Register code replacement mappings.
6 Verify code replacements.
7 Deploy the library.
For more information, see “Quick Start Code Replacement Library Development -
Simulink®” on page 54-28.
This example defines and registers code replacement mappings for math functions. You
can define code replacement mappings for a variety of functions (see “Code You Can
Replace From Simulink Models” on page 54-7).
Open the model rtwdemo_crlmath and use the buttons at the bottom of the model
window to explore the files that define and register the code replacement library
mappings.
For more information, see “Math Function Code Replacement” on page 54-97.
open_system('rtwdemo_crlmath')
59-34
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
59-35
59 Execution Speed in Embedded Coder
This example shows how to define and register code replacement mappings for addition
(+) and subtraction (-) operations. When defining entries for addition and subtraction
operations, you can specify which of the following algorithms (EntryInfoAlgorithm)
your library functions implement:
1. Open the model rtwdemo_crladdsub. The model shows how to define and register
code replacement mappings for scalar addition subtraction (-) operations on two operands
with the following pairings of built-in integer data types:
• int8, uint8
• int16, uint16
• int32, uint32
open_system('rtwdemo_crladdsub')
59-36
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
59-37
59 Execution Speed in Embedded Coder
2. Use the buttons at the bottom of the model window to explore the files that define and
register the code replacement library mappings.
3. Explore the differences between the CBO and CAO algorithms by opening the model
rtwdemo_crl_cbo_cao. The model shows two SUM blocks, each demonstrating one of
the algorithm settings to match a corresponding code replacement entry.
open_system('rtwdemo_crl_cbo_cao')
59-38
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
4. Use the buttons at the bottom of the model window to explore the files that define and
register the code replacement library mappings.
For more information on addition and subtraction operator replacement, see “Addition
and Subtraction Operator Code Replacement” on page 54-177. For more information on
the addition and subtraction algorithm (EntryInfoAlgorithm) options, see
setTflCOperationEntryParameters.
59-39
59 Execution Speed in Embedded Coder
This example defines and registers code replacement mappings for scalar multiplication
(*) and division (/) operations. The operations take two operands with the following
pairings of built-in integer data types:
• int8, uint8
• int16, uint16
• int32, uint32
Open the model rtwdemo_crlmuldiv and use the buttons at the bottom of the model
window to explore the files that define and register the code replacement library
mappings.
open_system('rtwdemo_crlmuldiv')
59-40
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
59-41
59 Execution Speed in Embedded Coder
This example defines and registers code replacement mappings for scalar operations:
addition, subtraction, multiplication, complex conjugate, cast, arithmetic shift right, and
arithmetic shift left.
• single, double
• int8, uint8
• int16, uint16
• int32, uint32
• csingle, cdouble
• cint8, cuint8
• cint16, cuint16
• cint32, cuint32
• fixed-point integers
• mixed types (different type on each input)
Open the model rtwdemo_crlscalarops and use the buttons at the bottom of the model
window to explore the files that define and register the code replacement library
mappings.
CBO, the default algorithm for addition and subtraction operations, is assumed.
open_system('rtwdemo_crlscalarops')
59-42
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
59-43
59 Execution Speed in Embedded Coder
This example defines and registers code replacement mappings for matrix operations:
addition, subtraction, multiplication, transposition, conjugate, and Hermitian.
• single, double
• int8, uint8
• int16, uint16
• int32, uint32
• csingle, cdouble
• cint8, cuint8
• cint16, cuint16
• cint32, cuint32
• fixed-point integers
• mixed types (different type on each input)
Open the model rtwdemo_crlmatops, which shows some of these replacements. Use the
buttons at the bottom of the model window to explore the files that define and register the
code replacement library mappings.
For more information on matrix operator replacement, see “Small Matrix Operation to
Processor Code Replacement” on page 54-182.
CBO, the default algorithm for addition and subtraction operations, is assumed.
open_system('rtwdemo_crlmatops')
59-44
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
59-45
59 Execution Speed in Embedded Coder
This example defines and registers code replacement mappings for Basic Linear Algebra
Subroutines (BLAS) subroutines xGEMM and xGEMV. You can map the following operations
to a BLAS subroutine:
• Matrix multiplication
• Matrix multiplication with transpose on single or both inputs
• Matrix multiplication with Hermitian operation on single or both inputs
Open the model rtwdemo_crlblas and use the buttons at the bottom of the model
window to explore the files that define and register the code replacement library
mappings.
For more information on matrix multiplication replacement for BLAS, see “Matrix
Multiplication Operation to MathWorks BLAS Code Replacement” on page 54-186.
open_system('rtwdemo_crlblas')
59-46
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
59-47
59 Execution Speed in Embedded Coder
This example defines and registers code replacement mappings for scalar addition (+),
subtraction (-), multiplication (*), and division (/) operations. The operations take two
operands with fixed-point data types.
Open the model rtwdemo_crlfixpt and use the buttons at the bottom of the model
window to explore the files that define and register the code replacement library
mappings.
• By default, for addition and subtraction operator code replacements, the code
generator assumes that replacement code implements a cast-before-operation (CBO)
algorithm.
• Using fixed-point data types in a model requires a Fixed-Point Designer™ license.
For more information about fixed-point operator code replacement, see “Fixed-Point
Operator Code Replacement” on page 54-204.
open_system('rtwdemo_crlfixpt')
59-48
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
59-49
59 Execution Speed in Embedded Coder
This example defines and registers code replacement mappings for custom entries. You
can create your own entry by subclassing from RTW.TflCFunctionEntryML or
RTW.TflCOperationEntryML. Your entry class must implement a do_match method
that customizes your matching logic or modifies the matched entry. The do_match
method must have a fixed preset signature.
Open the model rtwdemo_crlcustomentry. The model shows how to modify the
matched entry by injecting constants as additional implementation function arguments.
DTC1, Trigonometric Function, and Product show custom entry code replacement
for:
• Cast operation that demonstrates how to extract the fraction lengths from types and
pass them into the implementation function - Out1 = custom_cast(In1, 2, 4).
• Sine that demonstrates how to pass a constant value to the implementation function -
Out2=custom_sin(In2, 1).
• Multiplication operation that demonstrates how to compute the net slope of an
operation and pass that into the implementation function -
Out3=custom_multiply_shift_right(In3,In4,3).
Use the buttons at the bottom of the model window to explore the files that define and
register the code replacement mappings.
For more information on custom entries, see “Customize Match and Replacement
Process” on page 54-159.
open_system('rtwdemo_crlcustomentry')
59-50
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
59-51
59 Execution Speed in Embedded Coder
This example defines and registers code replacement mappings for MATLAB® functions
specified in the MATLAB Function block. The function can be opted for replacement by
specifying coder.replace within it. This feature supports replacement of MATLAB®
functions with the following:
• single, double
• int8, uint8
• int16, uint16
• int32, uint32
• csingle, cdouble
• cint8, cuint8
• cint16, cuint16
• cint32, cuint32
• Fixed-point integers
• Mixed types (different type on each input)
Use the buttons at the bottom of the model window to explore the files that define and
register the code replacement mappings.
open_system('rtwdemo_crlcoderreplace')
59-52
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
This example shows how to specify the alignment of matrix operands passed into a
replacement function. Some target-specific function implementations require data to be
aligned to optimize application performance. To configure data alignment for a function
implementation:
• Specify the data alignment requirements in a table entry. You can specify alignment
for implementation function arguments individually or collectively.
59-53
59 Execution Speed in Embedded Coder
• Specify the data alignment capabilities and syntax for your compiler. Attach an
AlignmentSpecification object to the TargetCharacteristics object of the
registry entry specified in your rtwTargetInfo.m file.
Open the model rtwdemo_crlalign. The model shows three data alignment code
replacement scenarios:
• Add - Alignment of exported and imported signals. You can specify an exact value for
the alignment in the Signal Properties dialog box or allow the code generator to
determine the best alignment based on usage by leaving the alignment value set to -1.
• Product - Alignment of virtual and nonvirtual bus types. You can specify an exact
value for the alignment for the Alignment property of the Simulink.Bus object or
allow the code generator to determine the best alignment based on usage by leaving
the Alignment property set to -1.
• EML_MMUL - Alignment of local variables, global variables, and block parameters.
Use the buttons at the bottom of the model window to explore the files that define and
register the code replacement mappings. Note that the model is configured to use a GCC,
Clang, MSVC, or MinGW compiler.
For more information on specifying data alignment for code replacement, see “Data
Alignment for Code Replacement” on page 54-136.
open_system('rtwdemo_crlalign')
59-54
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
59-55
59 Execution Speed in Embedded Coder
This example shows how code replacement data alignment can accelerate execution of a
generated executable by enabling deployment of SIMD operations in generated code.
perf = 'rtwdemo_crlalignperf';
open_system(perf)
cc = rtwprivate('getCompilerForModel',perf);
isDaDemoSupported = strcmpi(cc.comp.Manufacturer,'GNU') || ...
strcmpi(cc.comp.Manufacturer,'Apple') || ...
strcmpi(cc.comp.Manufacturer,'Microsoft');
if ~isDaDemoSupported
recMsg = ['Use "mex -setup" to select either GCC, Clang,'...
'MSVC, or MinGW and restart this example'];
warning(['The model "%s" is configured to use GCC, Clang,'...
'MSVC, or MinGW to create a Data Aligned Executable. %s.'],...
perf,recMsg); %#ok<CTPCT>
end
59-56
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
59-57
59 Execution Speed in Embedded Coder
2. Use the buttons at the bottom of the model window to explore the files that define and
register the code replacement mappings.
3. Execute the example by double-clicking Start the Example. Note that the model is
configured to use a GCC, Clang, MSVC, or MinGW compiler. This example compiles the
model twice. The first compilation produces portable, ANSI-C code without data
alignment. The second compilation uses a SIMD code replacement library that does the
element-wise matrix multiply using SIMD instructions. The data on which the SIMD
instructions operate needs to be aligned on a 16-byte boundary. For both compilations,
the generated code is profiled by a profiling hook. After the compilations complete, a
figure appears to show a comparison of the execution time of the subsystem Root/
Filtering/Process/ALGORITHM with and without data alignment.
4. Generate a baseline by selecting the ANSI® library, building the model, and then
running the generated executable ten times. This model uses an element-wise matrix
multiplication operation as part of an image processing algorithm. The matrix
multiplication is executed numerous times as each pixel in the image is processed.
Profiling hooks time the execution of the executable.
if (isDaDemoSupported)
% Create a temporary folder (in your system's temporary folder) for the
% build and inspection process.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
set_param(perf, 'CodeReplacementLibrary','None'...
, 'TargetLangStandard','C89/C90 (ANSI)');
rtwbuild(perf);
iterations = 10;
T1 = zeros(iterations, 1);
for idx = 1:iterations
evalc(['!', fullfile('.', perf)]);
evalc(['load ', fullfile('.','rtwdemo_crlalignperf.mat')]);
T1(idx) = rt_yout.signals(1).values;
end
if exist('rtwdemo_crlalignperf_ANSI', 'dir')
rmdir('rtwdemo_crlalignperf_ANSI', 's');
end
movefile('rtwdemo_crlalignperf_ert_rtw', 'rtwdemo_crlalignperf_ANSI');
else
warning('Unable to build model "%s". %s.', perf,recMsg);
end
59-58
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
if (isDaDemoSupported)
crl=getCorrectCrlForSelectedCompiler(perf);
set_param(perf,'CodeReplacementLibrary',crl);
rtwbuild(perf);
T2 = zeros(iterations, 1);
for idx=1:iterations
evalc(['!', fullfile('.', perf)]);
evalc(['load ', fullfile('.','rtwdemo_crlalignperf.mat')]);
T2(idx) = rt_yout.signals(1).values;
end
if exist('rtwdemo_crlalignperf_SIMD', 'dir')
rmdir('rtwdemo_crlalignperf_SIMD','s');
end
movefile('rtwdemo_crlalignperf_ert_rtw', 'rtwdemo_crlalignperf_SIMD');
else
warning(...
'The Data Aligned Executable for the model "%s" could not be generated. %s.'...
,perf,recMsg);
end
6. Compare timing results of the baseline and data-aligned executables. The timing data
captured from running the baseline and data-aligned executables is displayed in a graph.
The graph illustrates that using SIMD operations with data alignment can effectively
speed up execution of data-parallel operations.
if (isDaDemoSupported)
T1(T1<0) = NaN; % The profile counter may overflow.
T2(T2<0) = NaN;
t = [min(T1), min(T2)];
h = figure;
59-59
59 Execution Speed in Embedded Coder
59-60
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
This example shows Code Replacement Viewer. You can use the Code Replacement
Viewer to:
The following commands open the Code Replacement Viewer for code replacement table
crl_tablemuldiv:
59-61
59 Execution Speed in Embedded Coder
crl = crl_table_muldiv;
crviewer(crl);
daRoot = DAStudio.Root;
me = daRoot.find('-isa', 'DAStudio.Explorer');
For more information on the Code Replacement Viewer, see “Verify Code Replacements”
on page 54-79.
Build Information
For each entry in a code replacement table, you can specify build information such as the
following, for replacements functions:
Note: Models in this example are configured for code generation only because the
implementations for the replacement functions are not provided.
For more information on specifying build information, see “Specify Build Information for
Replacement Code” on page 54-61.
Reserved Identifiers
59-62
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®
For more information on specifying reserved identifiers, see “Reserved Identifiers and
Code Replacement” on page 54-157.
When you finish using the example models, remove the example code replacement
libraries and close the example models with these commands:
rmpath(fullfile(matlabroot,'toolbox','rtw','rtwdemos','crl_demo'));
sl_refresh_customizations;
close_system('rtwdemo_crladdsub', 0)
close_system('rtwdemo_crl_cbo_cao', 0)
close_system('rtwdemo_crlmuldiv', 0)
close_system('rtwdemo_crlfixpt', 0)
close_system('rtwdemo_crlmath', 0)
close_system('rtwdemo_crlmatops', 0)
close_system('rtwdemo_crlblas', 0)
close_system('rtwdemo_crlscalarops', 0)
close_system('rtwdemo_crlcustomentry', 0)
close_system('rtwdemo_crlcoderreplace', 0)
close_system('rtwdemo_crlalign', 0)
close_system(perf, 0)
drawnow;
if exist('h','var') && ishghandle(h)
close(h);
end
if ~isempty(me)
me(end).delete;
end
clear h;
clear crl;
clear codersrc;
clear codercurdir;
clear n1;
clear me;
clear cfg;
clear t;
clear cc;
clear recMsg;
clear isDaDemoSupported;
59-63
59 Execution Speed in Embedded Coder
clear T1;
clear T2;
clear idx;
clear iterations;
clear rt_tout;
clear rt_yout;
clear crl;
clear perf;
rtwdemoclean;
cd(currentDir)
59-64
Improve Execution Efficiency by Reordering Block Operations in the Generated Code
• Eliminate data copies for blocks that perform inplace operations (that is, use the same
input and output variable) and contain algorithm code with unnecessary data copies.
• Combine more for loops by executing blocks together that have the same size.
• Reuse the same variable for the input, output, and state of a Unit Delay block by
executing the Unit Delay block before upstream blocks.
These optimizations improve execution speed and conserve RAM and ROM consumption.
Example Model
59-65
59 Execution Speed in Embedded Coder
The subsystem LoopFusionScheduling shows how the code generator reorders block
operations so that blocks that have the same output size execute together. This
59-66
Improve Execution Efficiency by Reordering Block Operations in the Generated Code
reordering enables for loop fusion. Set the Optimize block order in the generated
code parameter to Off.
In your system's temporary folder, create a folder for the build and inspection process and
build the model.
View the generated code without the optimization. Code for the
LoopFusionScheduling subsystem:
/* Product: '<S2>/Product' */
for (i = 0; i < 3; i++) {
for (i_0 = 0; i_0 < 3; i_0++) {
tmp = i_0 + 3 * i;
rty_Out2[tmp] = 0.0;
tmp_0 = 3 * i + i_0;
rty_Out2[tmp] = rty_Out2[tmp_0] + rtu_In2[i << 1] * rtu_In1[i_0];
rty_Out2[tmp] = rtu_In2[(i << 1) + 1] * rtu_In1[i_0 + 3] + rty_Out2[tmp_0];
}
}
59-67
59 Execution Speed in Embedded Coder
/* Product: '<S2>/Product1' */
for (i = 0; i < 3; i++) {
for (i_0 = 0; i_0 < 3; i_0++) {
tmp = i_0 + 3 * i;
rty_Out4[tmp] = 0.0;
tmp_0 = 3 * i + i_0;
rty_Out4[tmp] = rty_Out4[tmp_0] + rtu_In4[i << 1] * rtu_In3[i_0];
rty_Out4[tmp] = rtu_In4[(i << 1) + 1] * rtu_In3[i_0 + 3] + rty_Out4[tmp_0];
}
}
With the default execution order, the blocks execute from left to right and from top to
bottom. As a result, there are separate for loops for the two combinations of Gain and
Bias blocks and the Product blocks.
Generate code with the optimization. Set the Optimize block order in the generated
code parameter to Improved Execution Speed and build the model.
### Starting build procedure for model: rtwdemo_optimizeblockorder
### Successful completion of build procedure for model: rtwdemo_optimizeblockorder
59-68
Improve Execution Efficiency by Reordering Block Operations in the Generated Code
int32_T tmp_0;
for (i = 0; i < 3; i++) {
for (i_0 = 0; i_0 < 3; i_0++) {
/* Product: '<S2>/Product' incorporates:
* Product: '<S2>/Product1'
*/
tmp = i_0 + 3 * i;
rty_Out2[tmp] = 0.0;
/* Product: '<S2>/Product1' */
rty_Out4[tmp] = 0.0;
/* Product: '<S2>/Product1' */
rty_Out4[tmp] = rty_Out4[3 * i + i_0] + rtu_In4[i << 1] * rtu_In3[i_0];
/* Product: '<S2>/Product' */
rty_Out2[tmp] = rtu_In2[(i << 1) + 1] * rtu_In1[i_0 + 3] + rty_Out2[tmp_0];
/* Product: '<S2>/Product1' */
rty_Out4[tmp] = rtu_In4[(i << 1) + 1] * rtu_In3[i_0 + 3] + rty_Out4[tmp_0];
}
}
In the optimized code, blocks with the same output size execute together. The two sets of
Gain and Bias blocks have an output dimension size of 6, so they execute together. The
59-69
59 Execution Speed in Embedded Coder
Product blocks have an output dimension size of 9, so they execute together. The fusion of
for loops enables the code generator to set the value of the expression 3 * i + i_0
equal to the temporary variable tmp_0. This optimization also improves execution
efficiency.
Buffer Reuse for the Input, Output, and State of Unit Delay Blocks
The subsystem RegionScheduling shows how the code generator reorders block
operations to enable buffer reuse for the input, output, and state of Unit Delay blocks.
When computation is part of separate regions that connect only through Delay blocks, the
code generator can change the block execution order so that the downstream regions
execute before the upstream regions. This execution order enables maximum reuse of
Delay block states and input and output variables. Set the Optimize block order in the
generated code parameter to Off and build the model.
### Starting build procedure for model: rtwdemo_optimizeblockorder
### Successful completion of build procedure for model: rtwdemo_optimizeblockorder
View the generated code without the optimization. Code for the RegionScheduling
subsystem:
/* UnitDelay: '<S3>/UnitDelay2' */
rty_Out1[i] = localDW->UnitDelay2_DSTATE[i];
59-70
Improve Execution Efficiency by Reordering Block Operations in the Generated Code
* Gain: '<S3>/Gain'
*/
localDW->UnitDelay_DSTATE[i] = 2.0 * rtu_In2[i];
With the default execution order, the generated code contains the extra, temporary
variable rtb_Sum and a data copy.
Generate code with the optimization. Set the Optimize block order in the generated
code parameter to Improved Execution Speed and build the model.
### Starting build procedure for model: rtwdemo_optimizeblockorder
### Successful completion of build procedure for model: rtwdemo_optimizeblockorder
59-71
59 Execution Speed in Embedded Coder
*/
localDW->UnitDelay_DSTATE[i] = 2.0 * rtu_In2[i];
}
}
In the optimized code, the blocks in Regions 3, 2, and 1 execute in that order. With that
execution order, the generated code does not contain the temporary variable rtb_Sum
and the corresponding data copy.
The subsystem InplaceScheduling shows how the code generator reorders block
operations to eliminate data copies for blocks that perform inplace operations. In the
Configuration Parameters dialog box, set the Optimize block order in the generated
code parameter to Off and build the model.
View the generated code without the optimization. Code for the InplaceScheduling
subsystem:
/* MinMax: '<S1>/Max' */
if (2.0 > localDW->UnitDelay_DSTATE[idx1]) {
rtb_Max[idx1] = 2.0;
} else {
rtb_Max[idx1] = localDW->UnitDelay_DSTATE[idx1];
59-72
Improve Execution Efficiency by Reordering Block Operations in the Generated Code
/* Switch: '<S1>/Switch' */
if (rtu_In2[k] > 0.0) {
/* Update for UnitDelay: '<S1>/Unit Delay' */
localDW->UnitDelay_DSTATE[k] = 0.0;
} else {
/* Update for UnitDelay: '<S1>/Unit Delay' */
localDW->UnitDelay_DSTATE[k] = rtb_Max[k];
}
With the default execution order, the Max block executes before the Product block. To
hold the Sum block output, the generated code contains two variables,
UnitDelay_DSTATE and rtb_Max.
59-73
59 Execution Speed in Embedded Coder
Generate code with the optimization. Set the Optimize block order in the generated
code parameter to Improved Execution Speed and build the model.
### Starting build procedure for model: rtwdemo_optimizeblockorder
### Successful completion of build procedure for model: rtwdemo_optimizeblockorder
/* MinMax: '<S1>/Max' */
if (2.0 > localDW->UnitDelay_DSTATE[idx1]) {
localDW->UnitDelay_DSTATE[idx1] = 2.0;
}
59-74
See Also
The optimized code does not contain the variable rtb_Max or the data copy. The
generated code contains one variable, UnitDelay_DSTATE, for holding the Sum block
output. The Product block reads from UnitDelay_DSTATE and the Max block reads from
and writes to UnitDelay_DSTATE.
To implement buffer reuse, the code generator does not violate user-specified block
priorities.
See Also
“Optimize block operation order in the generated code” (Simulink Coder)
Related Examples
• “Remove Data Copies by Reordering Block Operations in the Generated Code” on
page 58-29
• “Optimization Tools and Techniques” on page 56-7
59-75
60
• “Optimize Generated Code Using Minimum and Maximum Values” on page 60-2
• “Flat Structures for Reusable Subsystem Parameters” on page 60-9
• “Reduce Global Variables in Nonreusable Subsystem Functions” on page 60-13
• “Optimize Generated Code By Packing Boolean Data Into Bitfields” on page 60-16
• “Optimize Generated Code By Passing Reusable Subsystem Outputs as Individual
Arguments” on page 60-20
• “Convert Data Copies to Pointer Assignments” on page 60-25
• “Reuse Buffers of Different Sizes and Dimensions” on page 60-30
• “Remove Reset and Disable Functions from the Generated Code” on page 60-37
60 Memory Usage in Embedded Coder
In the Configuration Parameters dialog box, on the Optimization tab, when you select
the Optimize using specified minimum and maximum values check box, the
software uses the minimum and maximum values to derive range information for
downstream signals in the model. It then uses this derived range information to
determine if it is possible to streamline the generated code by:
60-2
Optimize Generated Code Using Minimum and Maximum Values
simulation. You can simulate your model with simulation range checking enabled. If
errors or warnings occur, fix these issues before generating code.
Overview
The specified minimum and maximum values usually represent environmental limits, such
as temperature, or mechanical and electrical limits, such as output ranges of sensors.
This optimization uses these values to streamline the generated code. For example, it
reduces expressions to constants or removes dead branches of conditional statements.
NOTE: Make sure the minimum and maximum values that you specify are valid limits.
Otherwise, this optimization might result in numerical mismatch with simulation.
Consider the model rtwdemo_minmax. In this model, there are minimum and maximum
values specified on Inports and on the gain parameter of the Gain block.
60-3
60 Memory Usage in Embedded Coder
model = 'rtwdemo_minmax';
open_system(model);
First, generate code for this model without considering the min and max values.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwconfiguredemo(model,'ERT')
rtwbuild(model)
60-4
Optimize Generated Code Using Minimum and Maximum Values
cfile = fullfile(cgDir,'rtwdemo_minmax_ert_rtw','rtwdemo_minmax.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
60-5
60 Memory Usage in Embedded Coder
Alternatively, you can enable this optimization by setting the command-line parameter.
In the model, with the specified minimum and maximum values for U1 and U2, the sum of
U1 and U2 has a minimum value of 50. Considering the range of U3 and the specified
minimum and maximum values for the Gain block parameter, the maximum value of the
Gain block's output is 40.
The output of the Relational Operator block remains false, and the output of the Switch
block remains the product of the three inputs.
rtwconfiguredemo(model,'ERT')
rtwbuild(model)
cfile = fullfile(cgDir,'rtwdemo_minmax_ert_rtw','rtwdemo_minmax.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
60-6
Optimize Generated Code Using Minimum and Maximum Values
rtY.Out1 = U1 * U2 * U3;
}
bdclose(model)
rtwdemoclean;
cd(currentDir)
Limitations
• This optimization does not take into account minimum and maximum values for:
• Merge block inputs. To work around this issue, use a Simulink.Signal object on
the Merge block output and specify the range on this object.
• Bus elements.
• Conditionally-executed subsystem (such as a triggered subsystem) block outputs
that are directly connected to an Outport block.
Polyspace Code Prover automatically captures some minimum and maximum values
specified in the MATLAB workspace, for example, for Simulink.Signal and
Simulink.Parameter objects. In this example, to provide range information to the
Polyspace software, use a Simulink.Signal object on the input of the division and
specify a range that does not include zero.
Polyspace Code Prover stores these values in a Data Range Specification (DRS) file.
However, they do not capture all minimum and maximum values in your Simulink
model. To provide additional minimum and maximum information to Polyspace, you
can manually define a DRS file.
60-7
60 Memory Usage in Embedded Coder
• If you are using double-precision data types and the Code Generation > Interface >
Support non-finite numbers configuration parameter is selected, this optimization
does not occur.
• If your model contains multiple instances of a reusable subsystem and each instance
uses input signals with different minimum and maximum values, this optimization
might result in different generated code for each subsystem so code reuse does not
occur. Without this optimization, code is generated once for the subsystem and shares
this code among the multiple instances of the subsystem.
• The Model Advisor DO-178C/DO-331 check Check safety-related optimization
settings generates a warning if this option is selected. For many safety-critical
applications, removing dead code automatically is unacceptable because doing so
might make code untraceable. For more information about using the check to comply
with DO-178C/DO-331, see Check safety-related optimization settings (Simulink
Check).
See Also
“Optimize using the specified minimum and maximum values” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Signal Ranges” (Simulink)
60-8
Flat Structures for Reusable Subsystem Parameters
By default, the code generated for reusable subsystems contains a single flat parameter
data structure. You can generate code for reusable subsystems that contains separate
structures to define the parameters that each subsystem uses. If you use nested reusable
subsystems, the generated code creates a hierarchy of nested parameter structures.
Hierarchies of structures can reduce code efficiency due to compiler padding between
word boundaries in memory.
This optimization is for only ERT-based targets. You must set the configuration parameter
Default parameter behavior to Inlined.
The model contains two nested reusable subsystems. Each subsystem uses two of the
parameters A, B, C, and D that are defined in the base workspace.
Create a temporary folder to contain the model build files. Generate code for the model
using the default hierarchical data structure for reusable subsystems.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild(model)
In the code generation report, view the parameter structure definitions in the file
rtwdemo_paramstruct.h.
cfile = fullfile(cgDir,'rtwdemo_paramstruct_ert_rtw','rtwdemo_paramstruct.h');
rtwdemodbtype(cfile,'/* Parameters for system: ''<S1>/SubsysZ''',...
'/* Parameters (default storage)', 1, 0);
60-9
60 Memory Usage in Embedded Coder
The code defines a parameter structure for each reusable subsystem and nests the
structures.
Enable Optimization
Open the Configuration Parameters dialog box. On the Optimization pane, select
Nonhierarchical in the Parameter structure drop-down list.
Generate code for the model using a flat parameter structure for reusable subsystems.
rtwbuild(model)
60-10
See Also
In the code generation report, view the parameter structure definition in the file
rtwdemo_paramstruct.h.
The code stores all of the parameters for the reusable subsystems in a single flat
structure.
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Parameter structure” (Simulink Coder)
60-11
60 Memory Usage in Embedded Coder
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Optimize Generated Code By Passing Reusable Subsystem Outputs as Individual
Arguments” on page 60-20
• “Reduce Global Variables in Nonreusable Subsystem Functions” on page 60-13
• “Standard Data Structures in the Generated Code” on page 22-26
60-12
Reduce Global Variables in Nonreusable Subsystem Functions
Global variables can increase memory requirements and reduce execution speed. To
reduce global RAM for a nonreusable subsystem, you can generate a function interface
that passes data through arguments instead of global variables. The Subsystem block
parameter “Function interface” (Simulink) provides this option. To compare the outputs
for the Function interface options, first generate a function for a subsystem with a
void-void interface, and then generate a function with arguments.
In the code generation report, in rtwdemo_roll.c, the generated code for subsystem
RollAngleReference contains a void-void function definition:
60-13
60 Memory Usage in Embedded Coder
void rtwdemo_roll_RollAngleReference(void)
{
...
}
In the static code metrics report, navigate to Global Variables. With the void_void
option, the number of bytes for global variables is 55.
Next, generate the same function with the Allow arguments option to compare the
results.
60-14
See Also
In the code generation report, in rtwdemo_roll.c, the generated code for subsystem
RollAngleReference now has arguments:
In the static code metrics report, navigate to Global Variables. With the Allow
arguments option set, the total number of bytes for global variables is now 47 bytes.
See Also
“Function interface” (Simulink)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Generate Subsystem Code as Separate Function and Files” on page 3-11
• “Flat Structures for Reusable Subsystem Parameters” on page 60-9
• “Optimize Generated Code By Passing Reusable Subsystem Outputs as Individual
Arguments” on page 60-20
60-15
60 Memory Usage in Embedded Coder
Example Model
model = 'rtwdemo_pack_boolean';
open_system(model);
Disable Optimization
60-16
Optimize Generated Code By Packing Boolean Data Into Bitfields
2 On the Optimization > Signals and Parameters pane, clear Pack Boolean data
into bitfields.
Alternatively, you can use the command-line API to disable the optimization:
set_param(model,'BooleansAsBitfields','off');
Create a temporary folder (in your system temporary folder) for the build and inspection
process.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
View the generated code without the optimization. These lines of code are in
rtwdemo_pack_boolean.h.
hfile = fullfile(cgDir,'rtwdemo_pack_boolean_ert_rtw','rtwdemo_pack_boolean.h');
rtwdemodbtype(hfile,'/* Block signals and states','/* External inputs',1,0);
Enable Optimization
1 Open the Configuration Parameters dialog box.
2 On the Optimization > Signals and Parameters pane, select Pack Boolean data
into bitfields.
60-17
60 Memory Usage in Embedded Coder
Alternatively, you can use the command-line API to enable the optimization:
set_param(model,'BooleansAsBitfields','on');
rtwbuild(model)
View the generated code with the optimization. These lines of code are in
rtwdemo_pack_boolean.h.
hfile = fullfile(cgDir,'rtwdemo_pack_boolean_ert_rtw','rtwdemo_pack_boolean.h');
rtwdemodbtype(hfile,'/* Block signals and states','/* External inputs',1,0);
Selecting Pack Boolean data into bitfields enables model configuration parameter
Bitfield declarator type specifier. To optimize your code further, select uchar_t.
However, the optimization benefit of the Bitfield declarator type specifier setting
depends on your choice of target.
60-18
See Also
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Pack Boolean data into bitfields” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Optimize Generated Code Using Boolean Data for Logical Signals” on page 56-100
• “Replace boolean with Specific Integer Data Type” on page 59-14
• “Data Types Supported by Simulink” (Simulink)
60-19
60 Memory Usage in Embedded Coder
Example Model
Generate code for this model while passing subsystem outputs as a structure reference.
Create a temporary folder for the build and inspection process.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
60-20
Optimize Generated Code By Passing Reusable Subsystem Outputs as Individual Arguments
rtwbuild(model)
cfile = fullfile(cgDir,'rtwdemo_reusable_sys_outputs_ert_rtw',...
'rtwdemo_reusable_sys_outputs.c');
rtwdemodbtype(cfile,'/* Output and update for atomic system',...
'/* Model initialize', 1, 0);
/* Gain: '<S1>/Gain1' */
localDW->Gain1 = 6.0 * rtu_In2;
/* Gain: '<S1>/Gain2' */
localDW->Gain2 = 7.0 * rtu_In3;
}
/* Outport: '<Root>/Out1' */
rtY.Out1 = rtDW.ReusableSubsystem_d.Gain;
60-21
60 Memory Usage in Embedded Coder
/* Outport: '<Root>/Out2' */
rtY.Out2 = rtDW.ReusableSubsystem_d.Gain1;
/* Outport: '<Root>/Out3' */
rtY.Out3 = rtDW.ReusableSubsystem_d.Gain2;
}
Alternatively, you can use the command-line API to enable the optimization:
With this optimization, the ReusableSubsystem function has three output arguments,
which are direct references to the external outputs. The rtDW global structure no longer
exists, and the data copies from this structure to the rtY (external outputs) structure are
not in the generated code.
rtwbuild(model)
60-22
See Also
/* Gain: '<S1>/Gain1' */
*rty_Out2 = 6.0 * rtu_In2;
/* Gain: '<S1>/Gain2' */
*rty_Out3 = 7.0 * rtu_In3;
}
bdclose(model)
rtwdemoclean;
cd(currentDir)
See Also
“Pass reusable subsystem outputs as” (Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Flat Structures for Reusable Subsystem Parameters” on page 60-9
• “Virtualized Output Ports Optimization” on page 58-17
• “Reduce Global Variables in Nonreusable Subsystem Functions” on page 60-13
60-23
60 Memory Usage in Embedded Coder
60-24
Convert Data Copies to Pointer Assignments
Example Model
60-25
60 Memory Usage in Embedded Coder
60-26
Convert Data Copies to Pointer Assignments
* Inport: '<Root>/In1'
*/
for (i = 0; i < 100; i++) {
if (rtU.In1) {
rtb_dataX[i] = rtCP_Constant_Value[i];
rtb_dataY[i] = rtCP_Constant1_Value[i];
} else {
rtb_dataX[i] = rtCP_Constant2_Value[i];
rtb_dataY[i] = rtCP_Constant3_Value[i];
}
}
Without the optimization, the generated code contains for loop controlled element
assignments.
1 In the Configuration Parameter dialog box, select the Use memcpy for vector
assignment parameter.
2 Generate code.
60-27
60 Memory Usage in Embedded Coder
60-28
See Also
Because the setting of the Memcpy threshold (bytes) parameter is below the array
sizes in the generated code, the optimized code contains pointer assignments for the
vector signal assignments.
See Also
“Use memcpy for vector assignment” (Simulink Coder) | “Memcpy threshold (bytes)”
(Simulink Coder)
Related Examples
• “Optimization Tools and Techniques” on page 56-7
• “Use memcpy Function to Optimize Generated Code for Vector Assignments” on
page 56-53
• “Vector Operation Optimization” on page 56-110
60-29
60 Memory Usage in Embedded Coder
Example Model
In the Configuration Parameters dialog box, set Reuse buffers of different sizes and
dimension parameter to off or in the MATLAB Command Window, enter:
set_param('rtwdemo_differentsizereuse','DifferentSizesBufferReuse','off');
View the generated code without the optimization. The D_Work structure is:
60-30
Reuse Buffers of Different Sizes and Dimensions
#include "rtwdemo_differentsizereuse.h"
D_Work rtDWork;
ExternalInputs rtU;
ExternalOutputs rtY;
RT_MODEL rtM_;
RT_MODEL *const rtM = &rtM_;
static void Downsample(const real_T rtu_u[16384], real_T rty_z[4096]);
static void DeltaX(const real_T rtu_u[4096], real_T rty_z[4032]);
static void DeltaY(const real_T rtu_u[4032], real_T rty_z[3969]);
static void NoninplaceableSS1(void);
static void NoninplaceableSS2(void);
static void NoninplaceableSS3(void);
static void Downsample(const real_T rtu_u[16384], real_T rty_z[4096])
{
int32_T x;
int32_T y;
for (x = 0; x < 64; x++) {
for (y = 0; y < 64; y++) {
rty_z[x + (y << 6)] = (((rtu_u[(((((1 + y) << 1) - 2) << 7) + ((1 + x) <<
1)) - 2] + rtu_u[(((((1 + y) << 1) - 2) << 7) + ((1 + x) << 1)) - 1]) +
60-31
60 Memory Usage in Embedded Coder
60-32
Reuse Buffers of Different Sizes and Dimensions
void rtwdemo_differentsizereuse_step(void)
{
int32_T i;
for (i = 0; i < 16384; i++) {
rtDWork.ComplextoRealImag_o1[i] = rtU.ComplexData[i].re;
rtDWork.ComplextoRealImag_o2[i] = rtU.ComplexData[i].im;
}
NoninplaceableSS1();
NoninplaceableSS2();
NoninplaceableSS3();
for (i = 0; i < 3969; i++) {
rtY.Out1[i].re = rtDWork.z_i[i];
rtY.Out1[i].im = rtDWork.z[i];
}
}
The D_work structure contains eight global variables for holding the inputs and outputs
of Downsample, DeltaX, and DeltaY. These variables have different sizes.
1 In the Configuration Parameters dialog box, verify that Signal storage reuse is
selected.
2 Set the Reuse buffers of different sizes and dimensions parameter to on or in
the MATLAB Command Window, enter:
set_param('rtwdemo_differentsizereuse','DifferentSizesBufferReuse','on');
set_param('rtwdemo_differentsizereuse','GenerateComments','off');
rtwbuild(model);
View the generated code without the optimization. The D_Work structure is:
60-33
60 Memory Usage in Embedded Coder
#include "rtwdemo_differentsizereuse.h"
D_Work rtDWork;
ExternalInputs rtU;
ExternalOutputs rtY;
RT_MODEL rtM_;
RT_MODEL *const rtM = &rtM_;
static void Downsample(const real_T rtu_u[16384], real_T rty_z[4096]);
static void DeltaX(const real_T rtu_u[4096], real_T rty_z[4032]);
static void DeltaY(const real_T rtu_u[4032], real_T rty_z[3969]);
static void NoninplaceableSS1(void);
static void NoninplaceableSS2(void);
static void NoninplaceableSS3(void);
static void Downsample(const real_T rtu_u[16384], real_T rty_z[4096])
{
int32_T x;
int32_T y;
for (x = 0; x < 64; x++) {
for (y = 0; y < 64; y++) {
rty_z[x + (y << 6)] = (((rtu_u[(((((1 + y) << 1) - 2) << 7) + ((1 + x) <<
1)) - 2] + rtu_u[(((((1 + y) << 1) - 2) << 7) + ((1 + x) << 1)) - 1]) +
rtu_u[(((((1 + y) << 1) - 1) << 7) + ((1 + x) << 1)) - 2]) + rtu_u
[(((((1 + y) << 1) - 1) << 7) + ((1 + x) << 1)) - 1]) / 4.0;
}
}
}
60-34
Reuse Buffers of Different Sizes and Dimensions