0% found this document useful (0 votes)
761 views

Embedded Coder Users Guide R2018a PDF

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
761 views

Embedded Coder Users Guide R2018a PDF

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3766

Embedded Coder®

User's Guide

R2018a
How to Contact MathWorks

Latest news: www.mathworks.com

Sales and services: www.mathworks.com/sales_and_services

User community: www.mathworks.com/matlabcentral

Technical support: www.mathworks.com/support/contact_us

Phone: 508-647-7000

The MathWorks, Inc.


3 Apple Hill Drive
Natick, MA 01760-2098
Embedded Coder® User's Guide
© COPYRIGHT 2011–2018 by The MathWorks, Inc.
The software described in this document is furnished under a license agreement. The software may be used
or copied only under the terms of the license agreement. No part of this manual may be photocopied or
reproduced in any form without prior written consent from The MathWorks, Inc.
FEDERAL ACQUISITION: This provision applies to all acquisitions of the Program and Documentation by,
for, or through the federal government of the United States. By accepting delivery of the Program or
Documentation, the government hereby agrees that this software or documentation qualifies as commercial
computer software or commercial computer software documentation as such terms are used or defined in
FAR 12.212, DFARS Part 227.72, and DFARS 252.227-7014. Accordingly, the terms and conditions of this
Agreement and only those rights specified in this Agreement, shall pertain to and govern the use,
modification, reproduction, release, performance, display, and disclosure of the Program and
Documentation by the federal government (or other entity acquiring for or through the federal government)
and shall supersede any conflicting contractual terms or conditions. If this License fails to meet the
government's needs or is inconsistent in any respect with federal procurement law, the government agrees
to return the Program and Documentation, unused, to The MathWorks, Inc.
Trademarks
MATLAB and Simulink are registered trademarks of The MathWorks, Inc. See
www.mathworks.com/trademarks for a list of additional trademarks. Other product or brand
names may be trademarks or registered trademarks of their respective holders.
Patents
MathWorks products are protected by one or more U.S. patents. Please see
www.mathworks.com/patents for more information.
Revision History
April 2011 Online only New for Version 6.0 (Release 2011a)
September 2011 Online only Revised for Version 6.1 (Release 2011b)
March 2012 Online only Revised for Version 6.2 (Release 2012a)
September 2012 Online only Revised for Version 6.3 (Release 2012b)
March 2013 Online only Revised for Version 6.4 (Release 2013a)
September 2013 Online only Revised for Version 6.5 (Release 2013b)
March 2014 Online only Revised for Version 6.6 (Release 2014a)
October 2014 Online only Revised for Version 6.7 (Release 2014b)
March 2015 Online only Revised for Version 6.8 (Release 2015a)
September 2015 Online only Revised for Version 6.9 (Release 2015b)
October 2015 Online only Rereleased for Version 6.8.1 (Release
2015aSP1)
March 2016 Online only Revised for Version 6.10 (Release 2016a)
September 2016 Online only Revised for Version 6.11 (Release 2016b)
March 2017 Online only Revised for Version 6.12 (Release 2017a)
September 2017 Online only Revised for Version 6.13 (Release 2017b)
March 2018 Online only Revised for Version 7.0 (Release 2018a)
Check Bug Reports for Issues and Fixes
Software is inherently complex and is not free of errors. The output of a code generator
might contain bugs, some of which are not detected by a compiler. MathWorks reports
critical known bugs brought to its attention on its Bug Report system at
www.mathworks.com/support/bugreports/. Use the Saved Searches and Watched Bugs
tool with the search phrase "Incorrect Code Generation" to obtain a report of known bugs
that produce code that might compile and execute, but still produce wrong answers.

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

Model Architecture and Design

Modeling Environment for Embedded Coder


1
Design Models for Generated Embedded Code
Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2
Application Algorithms and Run-Time Environments . . . . 1-2
Software Execution Framework for Generated Code . . . . 1-3
Map Embedded System Architecture to Simulink Modeling
Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5
Model Templates for Code Generation . . . . . . . . . . . . . 1-14

Model Single-Core, Single-Tasking Platform


Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-16

Model Single-Core, Multitasking Platform Execution . . 1-21

Model Concurrent Execution for Symmetric Multicore


CPU Platforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-26

Model Explicit Function Invocation with Atomic


Subsystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-34

Model Explicit Function Invocation with Function-Call


Subsystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-39

Modeling Patterns for AUTOSAR Runnables . . . . . . . . . . 1-44

vii
Modeling in Simulink Coder
2
Configure a Model for Code Generation . . . . . . . . . . . . . . 2-2

Blocks and Products Supported for C Code


Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-4
Related Products . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-4
Simulink Built-In Blocks That Support Code
Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-7
Simulink Block Data Type Support Table . . . . . . . . . . . . 2-30
Block Set Support for Code Generation . . . . . . . . . . . . . 2-30

Modeling Semantic Considerations . . . . . . . . . . . . . . . . . 2-31


Data Propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-31
Sample Time Propagation . . . . . . . . . . . . . . . . . . . . . . . 2-33
Latches for Subsystem Blocks . . . . . . . . . . . . . . . . . . . . 2-34
Block Execution Order . . . . . . . . . . . . . . . . . . . . . . . . . 2-35
Algebraic Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-36

Modeling Guidelines for Blocks . . . . . . . . . . . . . . . . . . . . 2-39

Modeling Guidelines for Subsystems . . . . . . . . . . . . . . . . 2-40

Modeling Guidelines for Charts . . . . . . . . . . . . . . . . . . . . 2-43

Modeling Guidelines for MATLAB Functions . . . . . . . . . 2-45

Modeling Guidelines for Model Configuration . . . . . . . . 2-46

Subsystems in Simulink Coder


3
Control Generation of Subsystem Functions . . . . . . . . . . . 3-2
What is a Subsystem Function? . . . . . . . . . . . . . . . . . . . . 3-2
Options for Controlling Generation of Subsystem Function
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
Subsystem Function Dependence . . . . . . . . . . . . . . . . . . 3-2

viii Contents
Generate Code and Executables for Individual
Subsystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-4
Subsystem Build Limitations . . . . . . . . . . . . . . . . . . . . . . 3-6

Inline Subsystem Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-8


Configure Subsystem to Inline Code . . . . . . . . . . . . . . . . 3-8
Exceptions to Inlining . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-9

Generate Subsystem Code as Separate Function and


Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-11

Optimize Code for Identical Nested Subsystems . . . . . . 3-12

Code Generation of Constant Parameters . . . . . . . . . . . . 3-13

Referenced Models in Simulink Coder


4
Code Generation of Referenced Models . . . . . . . . . . . . . . 4-2

Generate Code for Referenced Models . . . . . . . . . . . . . . . 4-4


About Generating Code for Referenced Models . . . . . . . . 4-4
Create and Configure the Subsystem . . . . . . . . . . . . . . . 4-4
Convert Model to Use Model Referencing . . . . . . . . . . . . 4-7
Generate Model Reference Code for a GRT Target . . . . 4-10
Work with Code Generation Folders . . . . . . . . . . . . . . . 4-12

Configure Referenced Models . . . . . . . . . . . . . . . . . . . . . 4-14

Build Model Reference Targets . . . . . . . . . . . . . . . . . . . . 4-15


Reduce Change Checking Time . . . . . . . . . . . . . . . . . . . 4-15

Simulink Coder Model Referencing Requirements . . . . 4-16


Configuration Parameter Requirements . . . . . . . . . . . . 4-16
Configuration Parameters Changed During
Code Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-19
Naming Requirements . . . . . . . . . . . . . . . . . . . . . . . . . 4-20
Custom Target Requirements . . . . . . . . . . . . . . . . . . . . 4-20

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

Inherited Sample Time for Referenced Models . . . . . . . 4-25

Customize Library File Suffix and File Type . . . . . . . . . . 4-27

Simulink Coder Model Referencing Limitations . . . . . . . 4-28


Customization Limitations . . . . . . . . . . . . . . . . . . . . . . 4-28
Data Logging Limitations . . . . . . . . . . . . . . . . . . . . . . . 4-28
State Initialization Limitation . . . . . . . . . . . . . . . . . . . . 4-29
Reusability Limitations . . . . . . . . . . . . . . . . . . . . . . . . . 4-29
S-Function Limitations . . . . . . . . . . . . . . . . . . . . . . . . . 4-30
Simulink Tool Limitations . . . . . . . . . . . . . . . . . . . . . . . 4-30
Subsystem Limitations . . . . . . . . . . . . . . . . . . . . . . . . . 4-30
Target Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-30
Other Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-31
Configuration Parameters Changed During Accelerated
Simulation and Code Generation . . . . . . . . . . . . . . . . 4-31

Combined Models in Simulink Coder


5
Combine Code Generated for Multiple Models . . . . . . . . . 5-2
Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2
Control Ownership of Data . . . . . . . . . . . . . . . . . . . . . . . 5-3
Combine Code Generated for Multiple Models or Multiple
Instances of a Model . . . . . . . . . . . . . . . . . . . . . . . . . . 5-3

Code Reuse for Simulink Coder


6
What Is Code Reuse? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-2

x Contents
What Is Reentrant Code? . . . . . . . . . . . . . . . . . . . . . . . . . . 6-4

Choose a Componentization Technique for Code


Reuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6

Simulink Function Blocks and Code Generation . . . . . . . 6-8


Why Generate Code from Simulink Function Blocks and
Function Callers? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-8
Implementation Options . . . . . . . . . . . . . . . . . . . . . . . . . 6-8
Choose a Modeling Pattern . . . . . . . . . . . . . . . . . . . . . . . 6-9
Specify Function Scope . . . . . . . . . . . . . . . . . . . . . . . . 6-11
Decide Whether to Generate Export Function Code . . . 6-11
Specify Function Code Interface Customizations . . . . . . 6-11
Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-12
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-12
Generate and Call Reusable Function Code . . . . . . . . . . 6-13
Generate Code for a Simulink Function and Function
Caller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-20

Generate Reentrant Code from Top Models . . . . . . . . . . 6-24


Generate Reentrant, Multi-Instance Code . . . . . . . . . . . 6-25
Share Data Between Instances . . . . . . . . . . . . . . . . . . . 6-28

Generate Reentrant Code from Simulink Function


Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-30
Identify Requirements . . . . . . . . . . . . . . . . . . . . . . . . . 6-30
Create Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-31
Configure Model and Model Elements . . . . . . . . . . . . . 6-33
Generate and Inspect C Code . . . . . . . . . . . . . . . . . . . . 6-35
Generate and Inspect C++ Code . . . . . . . . . . . . . . . . . 6-37
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-41

Generate Reentrant Code from Subsystems . . . . . . . . . . 6-42


Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-43
Determine Why Subsystem Code Is Not Reused . . . . . . 6-45

Generate Reusable Code From Referenced Models . . . . 6-50


Considerations for Subsystems that Contain Referenced
Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-50
Code Reuse and Model Blocks with Root Inport or Outport
Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-50

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

Generate Reusable Code from Stateflow Atomic


Subcharts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-64
Generate Reusable Code for Linked Atomic Subcharts . 6-64
Generate Reusable Code for Unlinked Atomic
Subcharts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-65
Generate Reusable Code for Unit Testing . . . . . . . . . . . 6-65

Generate Shared Utility Code . . . . . . . . . . . . . . . . . . . . . . 6-70


When to Generate Shared Utility Code . . . . . . . . . . . . . 6-70
Configure Naming of Generated Functions . . . . . . . . . . 6-70
Control Placement of Shared Utility Code . . . . . . . . . . . 6-71
Control Placement of rtwtypes.h for Shared Utility
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-72
Avoid Duplicate Header Files for Exported Data . . . . . . 6-73
Reduce Shared Utility Code Generation with Incremental
Builds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-73
Manage the Shared Utility Code Checksum . . . . . . . . . 6-74

Generate Shared Utility Code for Fixed-Point


Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-80

Generate Shared Utility Code for Custom Data Types . . 6-82

Shared Constant Parameters for Code Reuse . . . . . . . . . 6-84


Suppress Shared Constants in the Generated Code . . . . 6-85

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

Model Protection in Simulink Coder


8
Protect Models for Third-Party Use . . . . . . . . . . . . . . . . . . 8-2
Requirements for Protecting a Model . . . . . . . . . . . . . . . 8-3

Harness Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-4

Protected Model Report . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-5

Code Generation Support in Protected Models . . . . . . . . . 8-6


Protected Model Requirements to Support Code
Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-6

Protected Model File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-9

Create a Protected Model . . . . . . . . . . . . . . . . . . . . . . . . . 8-11

Protected Model Creation Settings . . . . . . . . . . . . . . . . . 8-16


Open Read-Only View of Model . . . . . . . . . . . . . . . . . . . 8-17
Simulate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-17
Use Generated Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-17

Create a Protected Model with Multiple Targets . . . . . . 8-19

Use a Protected Model with Multiple Targets . . . . . . . . . 8-21

Test the Protected Model . . . . . . . . . . . . . . . . . . . . . . . . . 8-22

xiii
Save Base Workspace Definitions . . . . . . . . . . . . . . . . . . . 8-24

Package a Protected Model . . . . . . . . . . . . . . . . . . . . . . . 8-25

Specify Custom Obfuscator for Protected Model . . . . . . 8-26

Define Callbacks for Protected Models . . . . . . . . . . . . . . 8-28


Creating Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-28
Defining Callback Code . . . . . . . . . . . . . . . . . . . . . . . . 8-28
Create a Protected Model with Callbacks . . . . . . . . . . . 8-29

Component Initialization, Reset, and Termination


in Simulink Coder
9
Generate Code That Responds to Initialize, Reset, and
Terminate Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-2
Generate Code for Initialize and Terminate Events . . . . . 9-2
Generate Code for Reset Events . . . . . . . . . . . . . . . . . . . 9-7
Event Names and Code Aggregation . . . . . . . . . . . . . . . . 9-9
Limitation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-12

Stateflow Blocks in Simulink Coder


10
Code Generation of Stateflow Blocks . . . . . . . . . . . . . . . . 10-2
Comparison of Code Generation Methods . . . . . . . . . . . 10-2

Generate Reusable Code for Atomic Subcharts . . . . . . . 10-6


How to Generate Reusable Code for Linked Atomic
Subcharts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-6
How to Generate Reusable Code for Unlinked Atomic
Subcharts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-7

Generate Reusable Code for Unit Testing . . . . . . . . . . . . 10-8


Goal of the Tutorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-8
Convert a State to an Atomic Subchart . . . . . . . . . . . . . 10-9

xiv Contents
Specify Code Generation Parameters . . . . . . . . . . . . . 10-10
Generate Code for Only the Atomic Subchart . . . . . . . 10-11

Inline State Functions in Generated Code . . . . . . . . . . 10-14


Inlined Generated Code for State Functions . . . . . . . . 10-14
How to Set the State Function Inline Option . . . . . . . . 10-16
Best Practices for Controlling State Function
Inlining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-16

Air-Fuel Ratio Control System with Stateflow Charts . . 10-17

Block Authoring and Code Generation for


Simulink Coder
11
S-Functions and Code Generation . . . . . . . . . . . . . . . . . . 11-2
Types of S-Functions . . . . . . . . . . . . . . . . . . . . . . . . . . 11-3
Files Required for Implementing Noninlined and Inlined S-
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-5
Guidelines for Writing S-Functions that Support Code
Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-6

Import Calls to External Code into Generated Code with


Legacy Code Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-7
Legacy Code Tool and Code Generation . . . . . . . . . . . . 11-7
Generate Inlined S-Function Files for Code
Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-8
Apply Code Style Settings to Legacy Functions . . . . . . . 11-9
Address Dependencies on Files in Different
Locations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-9
Deploy S-Functions for Simulation and Code
Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-10
Integrate External C++ Object Methods . . . . . . . . . . . 11-11
Integrate External C++ Objects . . . . . . . . . . . . . . . . . 11-14
Legacy Code Tool Examples . . . . . . . . . . . . . . . . . . . . 11-16

External Code Integration Examples . . . . . . . . . . . . . . . 11-51


Insert External C and C++ Code Into Stateflow Charts for
Code Generation . . . . . . . . . . . . . . . . . . . . . . . . . . 11-51

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

Generate S-Function from Subsystem . . . . . . . . . . . . . . 11-62


Macro Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-65

Write S-Function and TLC Files By Hand . . . . . . . . . . . 11-67


Write Noninlined S-Function and TLC Files . . . . . . . . 11-67
Write Wrapper S-Function and TLC Files . . . . . . . . . . 11-69
Write Fully Inlined S-Functions . . . . . . . . . . . . . . . . . 11-78
Write Fully Inlined S-Functions with mdlRTW
Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-79
Guidelines for Writing Inlined S-Functions . . . . . . . . . 11-87
S-Functions That Support Expression Folding . . . . . . . 11-87
S-Functions That Specify Port Scope and Reusability . 11-99
S-Functions That Specify Sample Time Inheritance
Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-103
S-Functions That Support Code Reuse . . . . . . . . . . . 11-105
S-Functions for Multirate Multitasking
Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-106

Guidelines and Standards for Embedded Coder


12
Support for Standards and Guidelines . . . . . . . . . . . . . . 12-2

MAAB Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-5

MISRA C Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-6

Secure Coding Standards . . . . . . . . . . . . . . . . . . . . . . . . . 12-8

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

Develop a Model that Complies with the IEC 61508


Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-11

IEC 62304 Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-14


Apply Simulink and Embedded Coder to the IEC 62304
Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-14
Check for IEC 62304 Standard Compliance Using the
Model Advisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-14

ISO 26262 Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-15


Apply Simulink and Embedded Coder to the ISO 26262
Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-15
Check for ISO 26262 Standard Compliance Using the
Model Advisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-15
Validate Traceability . . . . . . . . . . . . . . . . . . . . . . . . . . 12-15

EN 50128 Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-17


Apply Simulink and Embedded Coder to the EN 50128
Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-17
Check for EN 50128 Standard Compliance Using the
Model Advisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-17
Validate Traceability . . . . . . . . . . . . . . . . . . . . . . . . . . 12-17

DO-178C Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-19


Apply Simulink and Embedded Coder to the DO-178C
Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-19
Check for Standard Compliance Using the Model
Advisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-19
Validate Traceability . . . . . . . . . . . . . . . . . . . . . . . . . . 12-19

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

Evaluate Your Generated Code for MISRA C:2012


Compliance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-4

Compliance Information Summary Tables . . . . . . . . . . . 13-7


Compliance Summary Tables . . . . . . . . . . . . . . . . . . . . 13-7
Explanatory Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-17

Modeling Guidelines for MISRA C:2012 Compliance . . 13-21


High-Integrity System Modeling Guidelines for MISRA C:
2012 Compliance . . . . . . . . . . . . . . . . . . . . . . . . . . 13-21
MISRA C:2012 Rationale for Model Advisor Checks . . 13-23

Deviations Rationale . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-30


MISRA C:2012 Directive 4.7 Deviation Rationale . . . . 13-30
MISRA C:2012 Rule 13.5 Deviation Rationale . . . . . . . 13-34
MISRA C:2012 Rule 21.1 Deviation Rationale . . . . . . . 13-36

Patterns for C Code in Embedded Coder


14
Prepare a Model for Code Generation . . . . . . . . . . . . . . . 14-3
Configure Input Ports, Output Ports, and
Arbitrary Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-3
Initialize and Configure States . . . . . . . . . . . . . . . . . . . 14-4
Set Up Configuration Parameters for
Code Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-4
Set Up an Example Model With a Stateflow Chart . . . . . 14-5
Set Up an Example Model With a MATLAB Function
Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-6

xviii Contents
Definition, Initialization, and Declaration of
Parameter Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-7
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-7
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-7
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-8

Definition and Declaration of Signal Data . . . . . . . . . . . . 14-9


C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-9
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-9
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-9

Data Type Conversion . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-11


C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-11
Modeling Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-11
Modeling Pattern for Data Type Conversion — Simulink
Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-11
Modeling Pattern for Data Type Conversion — Stateflow
Chart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-12
Modeling Pattern for Data Type Conversion — MATLAB
Function Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-13
Other Type Conversions in Modeling . . . . . . . . . . . . . 14-13

Type Qualifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-14


C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-14
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-14
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-15

Relational and Logical Operators . . . . . . . . . . . . . . . . . . 14-16


Modeling Patterns for Relational and Logical
Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-16
Modeling Pattern for Relational or Logical Operators —
Simulink Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-16
Modeling Pattern for Relational and Logical Operators –
Stateflow Chart . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-17
Modeling Pattern for Relational and Logical Operators —
MATLAB Function Block . . . . . . . . . . . . . . . . . . . . . 14-18

Bitwise Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-20


Simulink Bitwise-Operator Block . . . . . . . . . . . . . . . . 14-20
Stateflow Chart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-21
MATLAB Function Block . . . . . . . . . . . . . . . . . . . . . . . 14-22

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

For Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-37


C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-37
Modeling Patterns: . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-37
Modeling Pattern for For Loop: For-Iterator Subsystem
block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-37
Modeling Pattern for For Loop: Stateflow Chart . . . . . 14-40
Modeling Pattern for For Loop: MATLAB Function
block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-41

While Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-43


C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-43
Modeling Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-43
Modeling Pattern for While Loop: While Iterator Subsystem
block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-43
Modeling Pattern for While Loop: Stateflow Chart . . . 14-46
Modeling Pattern for While Loop: MATLAB Function
Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-49

Do While Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-53


C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-53
Modeling Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-53
Modeling Pattern for Do While Loop: While Iterator
Subsystem block . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-53
Modeling Pattern for Do While Loop: Stateflow
Chart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-56

xx Contents
Function Call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-59
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-59
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-59
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-60

Function Prototyping . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-61


C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-61
Modeling Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-61
Function Call Using Graphical Functions . . . . . . . . . . 14-61
Control Function Prototype of the model_step
Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-63

External C Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-65


C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-65
Modeling Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-65
Use the Legacy Code Tool to Create S-functions . . . . . 14-65
Use a Stateflow Chart to Make Calls to C Functions . . 14-67
Using a MATLAB Function Block to Make Calls to C
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-69

Macro Definitions (#define) . . . . . . . . . . . . . . . . . . . . . . 14-71


C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-71
Export Generated Macro Definition . . . . . . . . . . . . . . 14-71
Reuse Macro from Handwritten Code . . . . . . . . . . . . . 14-72

Conditional Inclusions (#if / #endif) . . . . . . . . . . . . . . . 14-74

Typedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-75
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-75
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-75
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-76

Structures of Parameters . . . . . . . . . . . . . . . . . . . . . . . . 14-77

Structures of Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-81

Nested Structures of Signals . . . . . . . . . . . . . . . . . . . . . 14-84

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

Arrays for Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-94


C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-94
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-94
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-94

Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-96
C Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-96
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-96
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-96

Variant Systems in Embedded Coder


15
Implement Dimension Variants for Array Sizes in
Generated Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-2
Dimension Variants . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-2
Set Parameter Value Based on Variant Choice . . . . . . . 15-11
Code Generation Optimization Considerations . . . . . . 15-12
Backward Compatibility . . . . . . . . . . . . . . . . . . . . . . . 15-13
Supported Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-13
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-14

Code Generation for Variant Blocks . . . . . . . . . . . . . . . 15-18


Restrictions on Variant Subsystem Code Generation . . 15-18
Generated Code Components Not Compiled
Conditionally . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-20
Code Generation for Variant Blocks with One Variant
Choice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-20

Represent Subsystem and Model Variants in Generated


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-23
Step 1: Represent Variant Choices in Simulink . . . . . . 15-23
Step 2: Specify Conditions That Control Variant Choice
Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-27

xxii Contents
Step 3: Configure Model for Generating Preprocessor
Conditionals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-29
Step 4: Review Generated Code . . . . . . . . . . . . . . . . . 15-30
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-33

Generate Preprocessor Conditionals for Variant


Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-35
Define Variant Controls . . . . . . . . . . . . . . . . . . . . . . . 15-35
Configure Model for Generating Preprocessor Conditional
Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-36
Special Considerations for Generating Preprocessor
Conditionals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-37
Generate Variant Control Macros in Same Header
File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-38

Represent Variant Source and Sink Blocks in Generated


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-42
Represent Variant Source and Variant Sink blocks in
Simulink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-42
Specify Conditions That Control Variant Choice
Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-47
Review the Generated Code . . . . . . . . . . . . . . . . . . . . 15-47
Generate Code with Zero Active Variant Controls . . . . 15-49
Global Data Guarding Limitation . . . . . . . . . . . . . . . . 15-50
State Logging Limitation . . . . . . . . . . . . . . . . . . . . . . 15-50

Configure Dimension Variants for S-Function Blocks . 15-52


S-Function That Supports Forward Propagation of
Symbolic Dimensions . . . . . . . . . . . . . . . . . . . . . . . 15-54
S-Function That Supports Forward and Backward
Propagation of Symbolic Dimensions . . . . . . . . . . . 15-55

Generate Code for Variant Subsystem with Child


Subsystems of Different Output Signal
Dimensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-57
Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-57
Simulate Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-58
Generate Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-59

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

Access Timers Programmatically . . . . . . . . . . . . . . . . . . . 16-5


About Timer APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-5
C API for S-Functions . . . . . . . . . . . . . . . . . . . . . . . . . . 16-5
TLC API for Code Generation . . . . . . . . . . . . . . . . . . . . 16-7

Generate Code for an Elapsed Time Counter . . . . . . . . . 16-9

Absolute Time Limitations . . . . . . . . . . . . . . . . . . . . . . . 16-12

Time-Based Scheduling in Simulink Coder


17
Time-Based Scheduling and Code Generation . . . . . . . . 17-2
Sample Time Considerations . . . . . . . . . . . . . . . . . . . . . 17-2
Tasking Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-2
Model Execution and Rate Transitions . . . . . . . . . . . . . 17-4
Execution During Simulink Model Simulation . . . . . . . . 17-5
Model Execution in Real Time . . . . . . . . . . . . . . . . . . . . 17-5
Single-Tasking Versus Multitasking Operation . . . . . . . . 17-6

Modeling for Single-Tasking Execution . . . . . . . . . . . . . . 17-8


Single-Tasking Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-8
Build a Program for Single-Tasking Execution . . . . . . . . 17-8
Single-Tasking Execution . . . . . . . . . . . . . . . . . . . . . . . 17-8

Modeling for Multitasking Execution . . . . . . . . . . . . . . 17-12


Multitasking and Pseudomultitasking Modes . . . . . . . 17-12
Build a Program for Multitasking Execution . . . . . . . . 17-14
Execute Multitasking Models . . . . . . . . . . . . . . . . . . . 17-14

xxiv Contents
Multitasking Execution . . . . . . . . . . . . . . . . . . . . . . . . 17-16

Handle Rate Transitions . . . . . . . . . . . . . . . . . . . . . . . . . 17-21


Rate Transitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-21
Data Transfer Problems . . . . . . . . . . . . . . . . . . . . . . . 17-22
Data Transfer Assumptions . . . . . . . . . . . . . . . . . . . . . 17-23
Rate Transition Block Options . . . . . . . . . . . . . . . . . . 17-23
Automatic Rate Transition . . . . . . . . . . . . . . . . . . . . . 17-26
Visualize Inserted Rate Transition Blocks . . . . . . . . . . 17-27
Periodic Sample Rate Transitions . . . . . . . . . . . . . . . . 17-29
Protect Data Integrity with volatile Keyword . . . . . . . . 17-35
Separate Rate Transition Block Code and Data from
Algorithm Code and Data . . . . . . . . . . . . . . . . . . . . 17-35

Configure Time-Based Scheduling . . . . . . . . . . . . . . . . . 17-37


Configure Start and Stop Times . . . . . . . . . . . . . . . . . 17-37
Configure the Solver Type . . . . . . . . . . . . . . . . . . . . . 17-37
Configure the Tasking Mode . . . . . . . . . . . . . . . . . . . . 17-38

Time-Based Scheduling Example Models . . . . . . . . . . . 17-39


Optimize Memory Usage for Time Counters . . . . . . . . 17-39
Single-Rate Modeling (Bare Board, No OS) . . . . . . . . . 17-45
Multirate Modeling in Single-Tasking Mode (Bare Board,
no OS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-47
Multirate Modeling in Multitasking Mode (Bare Board, no
OS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-49
Trade Determinism and Data Integrity to Improve System
Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-51

Event-Based Scheduling in Simulink Coder


18
Asynchronous Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-2
Asynchronous Support . . . . . . . . . . . . . . . . . . . . . . . . . 18-2
Block Library for Calls to an Example Real-Time Operating
System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-2
Access the Block Library for RTOS Integration . . . . . . . 18-4
Generate Code Using Library Blocks for RTOS
Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-4
Examples and Additional Information . . . . . . . . . . . . . . 18-4

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

Spawn and Synchronize Execution of RTOS Task . . . . . 18-15

Pass Asynchronous Events in RTOS as Input To a


Referenced Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-32

Rate Transitions and Asynchronous Blocks . . . . . . . . . 18-40


About Rate Transitions and Asynchronous Blocks . . . . 18-40
Handle Rate Transitions for Asynchronous Tasks . . . . 18-42
Handle Multiple Asynchronous Interrupts . . . . . . . . . . 18-42
Protect Data Integrity with volatile Keyword . . . . . . . . 18-44

Timers in Asynchronous Tasks . . . . . . . . . . . . . . . . . . . . 18-46

Create a Customized Asynchronous Library . . . . . . . . . 18-49


About Implementing Asynchronous Blocks . . . . . . . . . 18-49
Async Interrupt Block Implementation . . . . . . . . . . . . 18-50
Task Sync Block Implementation . . . . . . . . . . . . . . . . 18-54
asynclib.tlc Support Library . . . . . . . . . . . . . . . . . . . . 18-56

Import Asynchronous Event Data for Simulation . . . . . 18-59


Capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-59
Input Data Format . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-59
Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-59

Asynchronous Support Limitations . . . . . . . . . . . . . . . . 18-63


Asynchronous Task Priority . . . . . . . . . . . . . . . . . . . . 18-63
Convert an Asynchronous Subsystem into a Model
Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-63

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

Optimize Multirate Multitasking Execution for RTOS Run-


Time Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19-4
Use rtmStepTask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19-4
Schedule Code for Real-time Model without an
RTOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19-4
Schedule Code for Multirate Multitasking on an
RTOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19-5
Suppress Redundant Scheduling Calls . . . . . . . . . . . . . 19-5

Representing a Software Architecture by Creating


Code Generation Definitions
20
Define Storage Classes, Memory Sections, and Function
Templates for Software Architecture . . . . . . . . . . . . . . 20-2
Create Code Definitions for Use as Default Code
Generation Settings . . . . . . . . . . . . . . . . . . . . . . . . . 20-2
Create Code Definitions to Override Default Settings . . 20-3
Avoid Maintaining Duplicate Definitions in Packages and
Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-3
Deploy Code Generation Definitions to Users . . . . . . . . 20-3
Maintain Code Generation Definitions . . . . . . . . . . . . . 20-4
Interact with Code Generation Definitions
Programmatically . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-5

Deploy Code Generation Definitions . . . . . . . . . . . . . . . . 20-6


Share Code Generation Definitions Between Multiple
Models and Users . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-6
Share Embedded Coder Dictionary Definition
Between Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-6

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

Conform to Software Architecture by Sharing and Copying


Default Code Generation Settings Between
Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-15
Tools to Copy and Share Settings . . . . . . . . . . . . . . . . 20-16
Techniques to Copy Settings . . . . . . . . . . . . . . . . . . . . 20-18
Techniques to Share Settings . . . . . . . . . . . . . . . . . . . 20-19

Migrate Memory Section and Shared Utility Settings from


Configuration Parameters to Code
Mapping Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-21
Effects of Migration . . . . . . . . . . . . . . . . . . . . . . . . . . 20-21
Considerations Before Migrating . . . . . . . . . . . . . . . . 20-22
Considerations After Migrating . . . . . . . . . . . . . . . . . . 20-23

Data, Function, and File Definition

Configuring Data and Functions in the Generated


Code
21
Environment for Configuring Model Data and Functions
for Code Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . 21-2
Software Engineer: Configure Default Settings . . . . . . . 21-4
Software Engineer: Override Default Settings . . . . . . . . 21-4
System Architect: Create Code Generation Definition
s ........................................ 21-5

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

Data Representation in Simulink Coder


22
Configure Data Accessibility for Rapid Prototyping .... 22-3
Access Signal, State, and Parameter Data During
Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .... 22-3
Configure Data Accessibility . . . . . . . . . . . . . . . . . .... 22-4
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .... 22-5

Access Signal, State, and Parameter Data During


Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-7

Standard Data Structures in the Generated Code . . . . 22-26


Control Characteristics of Data Structures (Embedded
Coder) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-27

Use the Real-Time Model Data Structure . . . . . . . . . . . 22-29

How Generated Code Exchanges Data with an


Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-33
Data Interfaces in the Generated Code . . . . . . . . . . . . 22-33
Configure Data Interface . . . . . . . . . . . . . . . . . . . . . . 22-41

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

How Generated Code Stores Internal Signal, State, and


Parameter Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-50
Internal Data in the Generated Code . . . . . . . . . . . . . 22-51
Local Variables in the Generated Code . . . . . . . . . . . . 22-61
Appearance of Test Points in the Generated Code . . . . 22-61
Appearance of Workspace Variables in the Generated
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-62
Promote Internal Data to the Interface . . . . . . . . . . . . 22-63
Control Default Representation of Internal Data
(Embedded Coder) . . . . . . . . . . . . . . . . . . . . . . . . . 22-65

Choose a Storage Class for Controlling Data


Representation in the Generated Code . . . . . . . . . . . 22-69
Specify File Names and Other Data Attributes With
Storage Class (Embedded Coder) . . . . . . . . . . . . . . 22-76
Specify Default #include Syntax for Header Files That
Declare Data (Embedded Coder) . . . . . . . . . . . . . . 22-77
Storage Class Limitations . . . . . . . . . . . . . . . . . . . . . . 22-77

Use Storage Classes in Reentrant, Multi-Instance Models


and Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-79
Directly Applied Storage Classes . . . . . . . . . . . . . . . . 22-79
Storage Classes Applied by Default . . . . . . . . . . . . . . . 22-79

Apply Storage Classes to Individual Signal, State, and


Parameter Data Elements . . . . . . . . . . . . . . . . . . . . . . 22-81
Apply Storage Classes to Data Items . . . . . . . . . . . . . . 22-81
Built-In Storage Classes You Can Choose . . . . . . . . . . 22-85
Decide Where to Store Storage Class Specification . . . 22-86
Techniques to Apply Storage Classes Interactively . . . 22-87

xxx Contents
Techniques to Apply Storage Classes
Programmatically . . . . . . . . . . . . . . . . . . . . . . . . . . 22-87
Parameter Object Configuration Quick
Reference Diagram . . . . . . . . . . . . . . . . . . . . . . . . . 22-89

Use Enumerated Data in Generated Code . . . . . . . . . . . 22-90


Enumerated Data Types . . . . . . . . . . . . . . . . . . . . . . . 22-90
Specify Integer Data Type for Enumeration . . . . . . . . 22-90
Customize Enumerated Data Type . . . . . . . . . . . . . . . 22-92
Control Enumerated Type Implementation in Generated
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-96
Type Casting for Enumerations . . . . . . . . . . . . . . . . . . 22-98
Enumerated Type Limitations . . . . . . . . . . . . . . . . . . . 22-99

Data Stores in Generated Code . . . . . . . . . . . . . . . . . . 22-100


About Data Stores . . . . . . . . . . . . . . . . . . . . . . . . . . 22-100
Generate Code for Data Store Memory Blocks . . . . . 22-100
Storage Classes for Data Store Memory Blocks . . . . . 22-101
Data Store Buffering in Generated Code . . . . . . . . . . 22-103
Data Stores Shared by Instances of a Reusable
Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-106
Structures in Generated Code Using Data Stores . . . 22-107

Specify Single-Precision Data Type for Embedded


Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-111
Use single Data Type as Default for Underspecified
Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-111

Tune Phase Parameter of Sine Wave Block During Code


Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-115

Switch Between Output Waveforms During Code


Execution for Waveform Generator Block . . . . . . . . 22-117

Create Tunable Calibration Parameter in the Generated


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-121
Represent Block Parameter as Tunable Global
Variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-121
Apply Storage Class When Block Parameter Refers to
Numeric MATLAB Variable . . . . . . . . . . . . . . . . . . 22-124
Create Storage Class That Represents Calibration
Parameters (Embedded Coder) . . . . . . . . . . . . . . . 22-125

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

Limitations for Block Parameter Tunability in the


Generated Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-135
Tunable Expression Limitations . . . . . . . . . . . . . . . . 22-135
Linear Block Parameter Tunability . . . . . . . . . . . . . . 22-137
Parameter Structures . . . . . . . . . . . . . . . . . . . . . . . . 22-137

Code Generation of Parameter Objects With Expression


Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-139
Considerations and Limitations . . . . . . . . . . . . . . . . 22-139
Expression Preservation . . . . . . . . . . . . . . . . . . . . . . 22-140

Specify Instance-Specific Parameter Values for Reusable


Referenced Model . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-142
Pass Parameter Data to Referenced Model Entry-Point
Functions as Arguments . . . . . . . . . . . . . . . . . . . . 22-142
Control Data Types of Model Arguments and Argument
Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-153

Parameter Data Types in the Generated Code . . . . . . 22-156


Significance of Parameter Data Types . . . . . . . . . . . . 22-156
Typecasts Due to Parameter Data Type Mismatches 22-157
Considerations for Other Modeling Patterns . . . . . . . 22-158

Generate Efficient Code by Specifying Data Types for


Block Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-162
Eliminate Unnecessary Typecasts and Shifts by Matching
Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-162
Reduce Memory Consumption by Storing Parameter Value
in Small Data Type . . . . . . . . . . . . . . . . . . . . . . . . 22-166

Reuse Parameter Data in Different Data


Type Contexts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-173

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

Switch Between Sets of Parameter Values During


Simulation and Code Execution . . . . . . . . . . . . . . . . 22-196

Design Data Interface by Configuring Inport and Outport


Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-206

Generate Efficient Code for Bus Signals . . . . . . . . . . . 22-212


Code Efficiency for Bus Signals . . . . . . . . . . . . . . . . 22-212
Set Bus Diagnostics . . . . . . . . . . . . . . . . . . . . . . . . . 22-213
Optimize Virtual and Nonvirtual Buses . . . . . . . . . . . 22-213

Control Signal and State Initialization in the Generated


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-216
Signal and State Initialization in the Generated
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-216
Generate Tunable Initial Conditions . . . . . . . . . . . . . 22-218
Generate Tunable Initial Condition Structure for Bus
Signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-221

Initialization of Signal, State, and Parameter Data in the


Generated Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-228
Static Initialization and Dynamic Initialization . . . . . 22-228
Real-World Ground Initialization Requiring Nonzero Bit
Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-229
Initialization of Signal and State Data . . . . . . . . . . . . 22-229
Initialization of Parameter Data . . . . . . . . . . . . . . . . 22-231
Data Initialization in the Generated Code . . . . . . . . . 22-232
Modeling Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-237

Optimize Speed and Size of Signal Processing Algorithm


by Using Fixed-Point Data . . . . . . . . . . . . . . . . . . . . 22-239

xxxiii
Optimize Generated Code Using Fixed-Point Data with
Simulink®, Stateflow®, and MATLAB® . . . . . . . . . 22-241

Declare Workspace Variables as Tunable Parameters Using


the Model Parameter Configuration Dialog Box . . . 22-243
Declare Existing Workspace Variables as Tunable
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-243
Declare New Tunable Parameters . . . . . . . . . . . . . . . 22-244
Set Tunable Parameter Code Generation Options . . . 22-244
Programmatically Declare Workspace Variables as Tunable
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-245

Share Data Between Code Generated from Simulink,


Stateflow, and MATLAB . . . . . . . . . . . . . . . . . . . . . . . 22-247

Data Definition and Declaration Management in


Embedded Coder
23
Control Placement of Global Data Definitions and
Declarations in Generated Files . . . . . . . . . . . . . . . . . . 23-2
Organize Data to Support Component-Based, Team-
Oriented Model Development . . . . . . . . . . . . . . . . . . 23-9
Specify Default Placement . . . . . . . . . . . . . . . . . . . . . 23-11
Override Default Placement for Individual Data
Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23-12
Prevent Name Clashes by Configuring Data Item
as static . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23-12
Code Generation Impact of Storage Location for Parameter
Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23-13
Specify Default #include Syntax for Data Header
Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23-13

Establish Data Ownership in a System of


Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23-15

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

Control File Placement of Custom Data Types . . . . . . . 24-23


Data Scope and Header File . . . . . . . . . . . . . . . . . . . . 24-23
Macro Guards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24-25

Replace and Rename Data Types to Conform to Coding


Standards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24-27
Inspect External C Code . . . . . . . . . . . . . . . . . . . . . . . 24-27
Explore Example Model and Default Generated
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24-27
Reuse External Data Type Definitions . . . . . . . . . . . . . 24-28
Create Meaningful Data Type Aliases for Individual Data
Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24-29
Create Single Point of Definition for Primitive Types . . 24-31
Permanently Store Data Type Objects . . . . . . . . . . . . . 24-32
Create and Maintain Objects Corresponding to Multiple C
typedef Statements . . . . . . . . . . . . . . . . . . . . . . . . . 24-32

Exchange Structured and Enumerated Data Between


Generated and External Code . . . . . . . . . . . . . . . . . . . 24-34
Inspect External Code . . . . . . . . . . . . . . . . . . . . . . . . 24-34
Create Simulink Model . . . . . . . . . . . . . . . . . . . . . . . . 24-36
Configure Generated Code to Write Output Data to
Existing Structure Variable . . . . . . . . . . . . . . . . . . . 24-38
Configure Generated Code to Define
Parameter Data . . . . . . . . . . . . . . . . . . . . . . . . . . . 24-39
Generate, Compile, and Inspect Code . . . . . . . . . . . . . 24-40
Replace Data Type Names Throughout Model . . . . . . . 24-41

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

Module Packaging Tool (MPT) Data Objects in


Embedded Coder
25
MPT Data Object Properties . . . . . . . . . . . . . . . . . . . . . . . 25-2
Specify Persistence Level for Signals and
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25-16
Register mpt User Object Types . . . . . . . . . . . . . . . . . 25-19

Custom Storage Classes in Embedded Coder


26
Reuse Parameter Data from External Code in the
Generated Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-2

Import Parameter Data with Conditionally Compiled


Dimension Length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-7

Access Structured Data Through a Pointer That External


Code Defines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-12

Apply Custom Storage Classes to Individual Signal, State,


and Parameter Data Elements . . . . . . . . . . . . . . . . . . 26-19
Built-In Custom Storage Classes . . . . . . . . . . . . . . . . . 26-19
Create Your Own Custom Storage Class . . . . . . . . . . . 26-19
Techniques to Apply Custom Storage Classes
Interactively . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-19
Techniques to Apply Custom Storage Classes
Programmatically . . . . . . . . . . . . . . . . . . . . . . . . . . 26-21
Organize Parameter Data into a Structure by Using the
Struct Custom Storage Class . . . . . . . . . . . . . . . . . 26-23
Custom Storage Class Limitations . . . . . . . . . . . . . . . 26-25

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

Finely Control Data Representation by Writing TLC Code


for a Custom Storage Class . . . . . . . . . . . . . . . . . . . . 26-39
Create Custom Attributes Class for Custom Storage
Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-39
Write TLC Code for Custom Storage Class . . . . . . . . . 26-39
Create Custom Storage Class by Using Custom Storage
Class Designer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-40

Access Data Through Functions with Custom Storage


Class GetSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-42
Access Legacy Data Using Get and Set Functions . . . . 26-42
Use GetSet with Vector Data . . . . . . . . . . . . . . . . . . . . 26-46
Use GetSet with Structured Data . . . . . . . . . . . . . . . . 26-49
Use GetSet with Matrix Data . . . . . . . . . . . . . . . . . . . 26-54
Specify Header File or Function Naming Scheme for All
Data Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-59
Access Scalar and Array Data Through Macro Instead of
Function Call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-60
GetSet Custom Storage Class Restrictions . . . . . . . . . 26-61

Integrate External Application Code with Code Generated


from PID Controller . . . . . . . . . . . . . . . . . . . . . . . . . . 26-62

Configure Generated Code According to Interface Control


Document Interactively . . . . . . . . . . . . . . . . . . . . . . . . 26-73

xxxvii
Configure Generated Code According to Interface Control
Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-83

Generate Local Variables with Localizable Custom Storage


Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-94
Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26-94
Generate Code with Localizable Storage Class . . . . . . 26-95
Generate Code Without Localizable Storage Class . . . 26-96
Additional Information . . . . . . . . . . . . . . . . . . . . . . . . 26-98

Data Object Wizard in Embedded Coder


27
Create Data Objects for Code Generation with Data Object
Wizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27-2

Entry-Point Functions and Scheduling in Simulink


Coder
28
Configure Code Generation for Model Entry-Point
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-2
What Is an Entry-Point Function? . . . . . . . . . . . . . . . . . 28-2
Categories and Types of Generated Entry-Point
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-2
Configure Whether Entry-Point Functions
Are Reusable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-3
Configure Generated Entry-Point Function
Declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-6
Configure Placement of Entry-Point Functions
in Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-7
How to Interface with Generated Entry-Point
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-7

Generate C++ Class Interface to Model or Subsystem


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-9
Generate C++ Class Interface to Model Code . . . . . . . . 28-9

xxxviii Contents
Generate C++ Class Interface to Nonvirtual Subsystem
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-10
C++ Class Interface Limitations . . . . . . . . . . . . . . . . . 28-11

Execution of Code Generated from a Model . . . . . . . . . 28-13


Program Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-14
Program Timing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-14
External Mode Communication . . . . . . . . . . . . . . . . . . 28-15
Data Logging in Single-Tasking and Multitasking Model
Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-16
Non-Real-Time Single-Tasking Systems . . . . . . . . . . . . 28-17
Non-Real-Time Multitasking Systems . . . . . . . . . . . . . 28-17
Real-Time Single-Tasking Systems . . . . . . . . . . . . . . . 28-19
Real-Time Multitasking Systems . . . . . . . . . . . . . . . . . 28-20
Multitasking Systems Using Real-Time Tasking
Primitives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-22
Rapid Prototyping and Embedded Model Execution Differe
nces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28-23

Rapid Prototyping Model Functions . . . . . . . . . . . . . . . 28-25

Function and Class Interfaces in Embedded Coder


29
Customize Generated C Function Interfaces . . . . . . . . . . 29-2
Options for Configuring Generated C
Function Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . 29-2
Function Interface Customization Limitations for Rate-
Based Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-3

Configure Names for Generated C Initialize and Step


Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-5

Configure C Step Function Arguments . . . . . . . . . . . . . . 29-9

Combine I/O Arguments in Model Step Interface . . . . . 29-13

Configure C Initialize and Step Function Interfaces


Interactively . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-16

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

Customize Generated Function Interfaces for Simulink


Function and Function Caller Blocks . . . . . . . . . . . . 29-24
Configure Generated C/C++ Function Interface for Global
Simulink Function Block . . . . . . . . . . . . . . . . . . . . . 29-24
Configure Generated C/C++ Function Interface for
Exported Scoped Simulink Function Block . . . . . . . 29-28
Simulink Function Code Interface Limitations . . . . . . . 29-30

Customize Function Interfaces for Nonvirtual


Subsystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-32

Customize Generated C++ Class Interfaces . . . . . . . . . 29-36


Simple Use of C++ Class Control . . . . . . . . . . . . . . . . 29-37
Customize C++ Class Interfaces Using Graphical
Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-44
Customize C++ Class Interfaces Programmatically . . 29-55
Configure Step Method for Model Class . . . . . . . . . . . 29-59
Specify Custom Storage Class for C++ Class Code
Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-60
Model Class Copy Constructor and Assignment
Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-61
C++ Class Interface Control Limitations . . . . . . . . . . 29-62

Generate Modular Function Code . . . . . . . . . . . . . . . . . 29-65


About Nonvirtual Subsystem Code Generation . . . . . . 29-65
Configure Subsystem for Generating Modular
Function Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-66
Modular Function Code for Nonvirtual Subsystems . . 29-70
Nonvirtual Subsystem Modular Function Code
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29-75

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

Protect Global Data with const and volatile


Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30-17
Maintain const Correctness for Arguments of Entry-Point
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30-18
Incorrect Results or Undefined Behavior When Passing
Volatile Data to a Generated Function . . . . . . . . . . . 30-18

xli
Code Generation

Configuration for Simulink Coder


31
Code Generation Configuration . . . . . . . . . . . . . . . . . . . . 31-2
Open the Model Configuration for Code Generation . . . 31-2
Configuration Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . 31-3

Configure Code Generation Parameters for Model


Programmatically . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31-5
Modify Parameters to Support Execution efficiency . . . 31-5

Use Configuration Reference to Select Code


Generation Target . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31-7

Check Model and Configuration for


Code Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31-15
Check Mode for Code Efficiency with Model Advisor . . 31-15
Check Model During Code Generation with Code
Generation Advisor . . . . . . . . . . . . . . . . . . . . . . . . . 31-16

Application Objectives Using Code Generation


Advisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31-18
High-Level Code Generation Objectives . . . . . . . . . . . 31-19
Configure Model for Code Generation Objectives Using
Code Generation Advisor . . . . . . . . . . . . . . . . . . . . 31-19
Configure Model for Code Generation Objectives by Using
Configuration Parameters Dialog Box . . . . . . . . . . . 31-21

Simulink Coder Model Advisor Checks for Standards and


Code Efficiency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31-22

Configure Code Comments . . . . . . . . . . . . . . . . . . . . . . . 31-24

Construction of Generated Identifiers . . . . . . . . . . . . . . 31-26

Identifier Name Collisions and Mangling . . . . . . . . . . . 31-27


Identifier Name Collisions with Referenced Models . . 31-27

xlii Contents
Specify Identifier Length to Avoid Naming Collisions . 31-28

Specify Reserved Names for Generated Identifiers . . . 31-29

Reserved Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31-30


C Reserved Keywords . . . . . . . . . . . . . . . . . . . . . . . . . 31-30
C++ Reserved Keywords . . . . . . . . . . . . . . . . . . . . . . 31-31
Reserved Keywords for Code Generation . . . . . . . . . . 31-31
Code Generation Code Replacement Library
Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31-32

Debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31-34

Configuration in Embedded Coder


32
Configure Model for Code Generation Objectives by Using
Code Generation Advisor . . . . . . . . . . . . . . . . . . . . . . . 32-2
High-Level Code Generation Objectives . . . . . . . . . . . . 32-3
Specify Objectives in Referenced Models . . . . . . . . . . . 32-3
Configure Model Using Code Generation Advisor . . . . . 32-4
Configure Model for Code Generation Objectives by Using
Configuration Parameters Dialog Box . . . . . . . . . . . . 32-6

Configure Code Generation Objectives


Programmatically . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32-9

Check Model and Configuration for


Code Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32-10
Check Model During Code Generation . . . . . . . . . . . . 32-10

Embedded Coder Model Advisor Checks for Standards,


Guidelines, and Code Efficiency . . . . . . . . . . . . . . . . . 32-12

Create Custom Code Generation Objectives . . . . . . . . . 32-16


Specify Parameters in Custom Objectives . . . . . . . . . . 32-16
Specify Checks in Custom Objectives . . . . . . . . . . . . . 32-17
Determine Checks and Parameters in Existing
Objectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32-17
Steps to Create Custom Objectives . . . . . . . . . . . . . . . 32-18

xliii
Configuration Variations . . . . . . . . . . . . . . . . . . . . . . . . . 32-22

Configure and Optimize Model with Configuration Wizard


Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32-23
Configuration Wizard Block Library . . . . . . . . . . . . . . 32-23
Add a Configuration Wizard Block . . . . . . . . . . . . . . . 32-24
Use Configuration Wizard Blocks to Configure
Your Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32-25
Create a Custom Configuration Wizard Block . . . . . . . 32-26

Create a Model Configured for Code Generation Using


Model Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32-32

System Target File Configuration


33
Configure a System Target File . . . . . . . . . . . . . . . . . . . . 33-2
Select a Solver That Supports Code Generation . . . . . . 33-2
Select a System Target File from STF Browser . . . . . . . 33-3
Select a System Target File Programmatically . . . . . . . 33-4
Develop Custom System Target Files . . . . . . . . . . . . . . 33-5

Configure STF-Related Code Generation Parameters . . . 33-7


Specify Generated Code Interfaces . . . . . . . . . . . . . . . . 33-7
Configure Numeric Data Support . . . . . . . . . . . . . . . . 33-12
Configure Time Value Support . . . . . . . . . . . . . . . . . . 33-12
Configure Noninlined S-Function Support . . . . . . . . . 33-13
Configure Model Function Generation and
Argument Passing . . . . . . . . . . . . . . . . . . . . . . . . . 33-13
Configure Code Reuse Support . . . . . . . . . . . . . . . . . . 33-15

Configure a Code Replacement Library . . . . . . . . . . . . . 33-17

Configure Standard Math Library for Target System . . 33-18

Compare System Target File Support . . . . . . . . . . . . . . 33-21


Evaluate Product System Target Files . . . . . . . . . . . . . 33-23
Compare Code Styles and STF Support . . . . . . . . . . . 33-25
Compare Generated Code Features by Product . . . . . . 33-26
Compare Generated Code Features by STF . . . . . . . . . 33-29

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

Internationalization Support in Embedded Coder


35
Internationalization and Code Generation . . . . . . . . . . . 35-2
Locale Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35-2
Prepare to Generate Code for Mixed Languages and
Locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35-3
Character Set Limitations . . . . . . . . . . . . . . . . . . . . . . . 35-3
XML Escape Sequence Replacements . . . . . . . . . . . . . . 35-3
CGT Files and XML Escape Sequence Replacements . . . 35-3
Generate and Review Code with Mixed Languages and
Mixed Locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35-4

Source Code Generation in Simulink Coder


36
Configure Model, Generate Code, and Simulate . . . . . . . 36-2
About This Example . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-2
Functional Design of the Model . . . . . . . . . . . . . . . . . . 36-3
View the Top Model . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-3
View the Subsystems . . . . . . . . . . . . . . . . . . . . . . . . . . 36-4
Simulation Test Environment . . . . . . . . . . . . . . . . . . . . 36-5
Run Simulation Tests . . . . . . . . . . . . . . . . . . . . . . . . . 36-10
Key Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-11
Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-12

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

Configure Data Interface . . . . . . . . . . . . . . . . . . . . . . . . 36-20


About This Example . . . . . . . . . . . . . . . . . . . . . . . . . . 36-20
Declare Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-20
Use Data Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-21
Add New Data Objects . . . . . . . . . . . . . . . . . . . . . . . . 36-24
Enable Data Objects for Generated Code . . . . . . . . . . 36-25
Effects of Simulation on Data Typing . . . . . . . . . . . . . 36-25
Manage Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-27
Key Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-28

Call External C Functions . . . . . . . . . . . . . . . . . . . . . . . . 36-29


About This Example . . . . . . . . . . . . . . . . . . . . . . . . . . 36-29
Include External C Functions in a Model . . . . . . . . . . . 36-30
Create a Block That Calls a C Function . . . . . . . . . . . . 36-30
Validate External Code in the Simulink Environment . 36-32
Validate C Code as Part of a Model . . . . . . . . . . . . . . . 36-33
Call a C Function from Generated Code . . . . . . . . . . . 36-35
Key Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-35

Reload Generated Code . . . . . . . . . . . . . . . . . . . . . . . . . . 36-36

Manage Build Process Folders . . . . . . . . . . . . . . . . . . . . 36-37


File Generation Control Parameters . . . . . . . . . . . . . . 36-37
Build Process Folders . . . . . . . . . . . . . . . . . . . . . . . . . 36-40

Manage Build Process Files . . . . . . . . . . . . . . . . . . . . . . 36-43


model.bat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-49
model.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-49
rtwtypes.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-50

Manage Build Process File Dependencies . . . . . . . . . . . 36-53


System Header Files . . . . . . . . . . . . . . . . . . . . . . . . . . 36-54

xlvi Contents
Code Generator Header Files . . . . . . . . . . . . . . . . . . . 36-57

Add Build Process Dependencies . . . . . . . . . . . . . . . . . . 36-64


File Dependency Information for the Build Process . . . 36-65
Folder Dependency Information for the Build
Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-68

Enable Build Process for Folder Names with Spaces . . 36-71


Build Process Folder Support on Windows . . . . . . . . . 36-73
Troubleshooting Errors When Folder Names Have
Spaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-74

Code Generation of Matrices and Arrays . . . . . . . . . . . . 36-77


Code Generator Matrix Parameters . . . . . . . . . . . . . . 36-79
Internal Data Storage for Complex Number Arrays . . . 36-80

Cross-Release Shared Utility Code Reuse . . . . . . . . . . . 36-82


Workflow to Reuse Shared Utility Code . . . . . . . . . . . . 36-82
Required Edits to Reuse Shared Utility Code . . . . . . . 36-83

Cross-Release Code Integration . . . . . . . . . . . . . . . . . . . 36-85


Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-85
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-88
Simulink.Bus Support . . . . . . . . . . . . . . . . . . . . . . . . . 36-89
Root-Level I/O Through Global Variables in Generated
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-92
Communicate Between Current and Previous Release
Components Through Global Data Stores . . . . . . . . 36-95
Parameter Tuning . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-96
Use Multiple Instances of Code Generated from Reusable
Referenced Model . . . . . . . . . . . . . . . . . . . . . . . . . 36-97
Compare Simulation Behavior of Model Component in
Current Release and Generated Code from Previous
Release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36-99
Import AUTOSAR Code from Previous Releases . . . . 36-100

Generate Code Using Simulink® Coder™ . . . . . . . . . . 36-101

xlvii
Source Code Generation in Embedded Coder
37
Generate Code Using Embedded Coder® . . . . . . . . . . . . 37-2

Generate Code by Using the Quick Start Tool . . . . . . . . 37-10


Quick Start Model Analysis . . . . . . . . . . . . . . . . . . . . . 37-10
Configuration Parameter Changes for Models with a
Configuration Reference . . . . . . . . . . . . . . . . . . . . . 37-12
Next Steps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37-13

Manage File Packaging of Generated Code Modules . . 37-14


Generated Code Modules . . . . . . . . . . . . . . . . . . . . . . 37-14
User-Written Code Modules . . . . . . . . . . . . . . . . . . . . 37-18
Customize Generated Code Modules . . . . . . . . . . . . . . 37-18

Generate Reentrant Code from Top-Level Models . . . . 37-21


Configure Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37-21
Share Data Between Instances . . . . . . . . . . . . . . . . . . 37-22

Report Generation in Embedded Coder


38
Reports for Code Generation . . . . . . . . . . . . . . . . . . . . . . 38-2
HTML Code Generation Report Location . . . . . . . . . . . 38-2
HTML Code Generation Report for Referenced
Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-3
HTML Code Generation Report Extensions . . . . . . . . . . 38-3

Generate a Code Generation Report . . . . . . . . . . . . . . . . 38-5

Generate Code Generation Report After Build


Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-6

Open Code Generation Report . . . . . . . . . . . . . . . . . . . . . 38-8


Limitation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-8

Generate Code Generation Report Programmatically . 38-10

xlviii Contents
View Code Generation Report in Model Explorer . . . . . 38-11

Package and Share the Code Generation Report . . . . . 38-13


Package the Code Generation Report . . . . . . . . . . . . . 38-13
View the Code Generation Report . . . . . . . . . . . . . . . . 38-14

Web View of Model in Code Generation Report . . . . . . 38-15


About Model Web View . . . . . . . . . . . . . . . . . . . . . . . . 38-15
Generate HTML Code Generation Report with Model Web
View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-15
Model Web View Limitations . . . . . . . . . . . . . . . . . . . . 38-18

Analyze the Generated Code Interface . . . . . . . . . . . . . 38-19


Code Interface Report Overview . . . . . . . . . . . . . . . . . 38-19
Generating a Code Interface Report . . . . . . . . . . . . . . 38-20
Navigating Code Interface Report Subsections . . . . . . 38-22
Interpreting the Entry-Point Functions Subsection . . . 38-23
Interpreting the Inports and Outports Subsections . . . 38-26
Interpreting the Interface Parameters Subsection . . . . 38-28
Interpreting the Data Stores Subsection . . . . . . . . . . . 38-30
Code Interface Report Limitations . . . . . . . . . . . . . . . 38-31

Static Code Metrics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-33


About Static Code Metrics . . . . . . . . . . . . . . . . . . . . . 38-33
Static Code Metrics Analysis . . . . . . . . . . . . . . . . . . . 38-34
View Static Code Metrics and Definitions Within the
Generated Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-35

Generate Static Code Metrics Report for Simulink


Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-37

Generate a Static Code Metrics Report for MATLAB


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-42
Generate a Static Code Metrics Report Using the MATLAB
Coder App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-42
Enable a Static Code Metrics Report at the Command
Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-46

Analyze Code Replacements in Generated Code . . . . . . 38-48

Document Generated Code with Simulink Report


Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38-50
Generate Code for the Model . . . . . . . . . . . . . . . . . . . 38-51

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

Get Code Description of Generated Code . . . . . . . . . . . 38-57


Get Data Interface Information . . . . . . . . . . . . . . . . . . 38-57
Get Function Interface Information . . . . . . . . . . . . . . . 38-59
Get Model Hierarchy Information . . . . . . . . . . . . . . . . 38-61

Code Appearance in Embedded Coder


39
Add Custom Comments to Generated Code . . . . . . . . . . . 39-3

Add Custom Comments for Variables in the Generated


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-5
Embed Handwritten Comments for Signals or
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-5
Generate Dynamic Comments Based on Data
Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-6

Add Global Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-8


Use a Simulink DocBlock to Add a Comment . . . . . . . . . 39-8
Use a Simulink Annotation to Add a Comment . . . . . . 39-11
Use a Stateflow Note to Add a Comment . . . . . . . . . . . 39-11
Use Sorted Notes to Add Comments . . . . . . . . . . . . . . 39-12

Customize Generated Identifier Naming Rules . . . . . . 39-14


Apply Naming Rules to Identifiers Globally . . . . . . . . . 39-14
Apply Naming Rules to Simulink Data Objects . . . . . . 39-16

Identifier Format Control . . . . . . . . . . . . . . . . . . . . . . . . 39-22


Control Case with Token Decorators . . . . . . . . . . . . . . 39-27
Control Formatting of Identifiers . . . . . . . . . . . . . . . . 39-28

Control Name Mangling in Generated Identifiers . . . . 39-30


Minimize Name Mangling . . . . . . . . . . . . . . . . . . . . . . 39-30

l Contents
Avoid Identifier Name Collisions with
Referenced Models . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-32
Use Model Advisor to Detect Identifier Names Changed
During Code Generation . . . . . . . . . . . . . . . . . . . . . 39-32

Maintain Traceability for Generated Identifiers . . . . . . 39-34

Exceptions to Identifier Formatting Conventions . . . . . 39-35

Identifier Format Control Parameters Limitations . . . . 39-36

Control Code Style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-38


Control Parentheses in Generated Code . . . . . . . . . . . 39-39
Optimize Code by Reordering Commutable
Operands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-41
Suppress Generation of Default Cases for Unreachable
Stateflow Switch Statements . . . . . . . . . . . . . . . . . 39-42
Replace Multiplication by Powers of Two with Signed
Bitwise Shifts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-45
Generate Code with Right Shifts on Signed Integers . . 39-47
Control Indentation Style in Generated Code . . . . . . . 39-48
Control Cast Expressions in Generated Code . . . . . . . 39-50
Control Newline Style in Generated Code . . . . . . . . . . 39-54

Customize Code Organization and Format . . . . . . . . . . 39-56


Custom File Processing Components . . . . . . . . . . . . . 39-56
Custom File Processing Configuration . . . . . . . . . . . . 39-57

Specify Templates For Code Generation . . . . . . . . . . . . 39-59

Code Generation Template (CGT) Files . . . . . . . . . . . . . 39-60


Default CGT file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-60
CGT File Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-60
Built-In Tokens and Sections . . . . . . . . . . . . . . . . . . . . 39-61
Subsections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-63
Format Generated Code Files Using Templates . . . . . . 39-64

Custom File Processing (CFP) Templates . . . . . . . . . . . 39-66


Custom File Processing (CFP) Template Structure . . . 39-66

Change the Organization of a Generated File . . . . . . . . 39-68

Customize Generated File Names . . . . . . . . . . . . . . . . . 39-70

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

Comparison of a Template and Its Generated File . . . . 39-81


Template and Generated File . . . . . . . . . . . . . . . . . . . 39-82

Code Template API Summary . . . . . . . . . . . . . . . . . . . . . 39-85

Generate Custom File and Function Banners . . . . . . . . 39-89


Create a Custom File and Function Banner Template . 39-90
Customize a Code Generation Template (CGT) File for File
and Function Banner Generation . . . . . . . . . . . . . . 39-91

Template Symbols and Rules . . . . . . . . . . . . . . . . . . . . . 39-97


Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-97
Template Symbol Groups . . . . . . . . . . . . . . . . . . . . . . 39-98
Template Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . 39-101
Rules for Modifying or Creating a Template . . . . . . . 39-104

Annotate Code for Justifying Polyspace Checks . . . . . 39-106

Enhance Readability of Code for Flow Charts . . . . . . . 39-108


Appearance of Generated Code for Flow Charts . . . . 39-108
Convert If-Elseif-Else Code to Switch-Case
Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-111
Example of Converting Code to Switch-Case
Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-113

Generate Inlined Subsystem Code . . . . . . . . . . . . . . . . 39-122


Configure Subsystem to Inline Code . . . . . . . . . . . . . 39-122
Exceptions to Inlining . . . . . . . . . . . . . . . . . . . . . . . . 39-123
See Also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39-123

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

Choose a Code Replacement Library . . . . . . . . . . . . . . . . 40-8


About Choosing a Code Replacement Library . . . . . . . . 40-8
Explore Available Code Replacement Libraries . . . . . . . 40-8
Explore Code Replacement Library Contents . . . . . . . . 40-8

Replace Code Generated from Simulink Models . . . . . 40-10

Code Replacement for Simulink Models in


Embedded Coder
41
What Is Code Replacement? . . . . . . . . . . . . . . . . . . . . . . . 41-2
Code Replacement Libraries . . . . . . . . . . . . . . . . . . . . . 41-2
Code Replacement Terminology . . . . . . . . . . . . . . . . . . 41-4
Code Replacement Limitations . . . . . . . . . . . . . . . . . . . 41-7

Choose a Code Replacement Library . . . . . . . . . . . . . . . . 41-8


About Choosing a Code Replacement Library . . . . . . . . 41-8
Explore Available Code Replacement Libraries . . . . . . . 41-8
Explore Code Replacement Library Contents . . . . . . . . 41-8

Replace Code Generated from Simulink Models . . . . . 41-10

liii
Deployment

External Code Integration in Simulink Coder


42
What Is External Code Integration? . . . . . . . . . . . . . . . . . 42-3

Choose an External Code Integration Workflow . . . . . . . 42-4


Choose a Software Execution Framework . . . . . . . . . . . 42-4
Evaluate Characteristics of External Code . . . . . . . . . . 42-7
Identify Integration Requirements . . . . . . . . . . . . . . . . 42-8
Choose a Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-10

Call Reusable External Algorithm Code for Simulation and


Code Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-13
Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-13
Choose an Integration Approach . . . . . . . . . . . . . . . . . 42-14
Insert External Code into Stateflow Charts . . . . . . . . . 42-24

Place External C/C++ Code in Generated Code . . . . . . 42-27


Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-27
Choose an Integration Approach . . . . . . . . . . . . . . . . . 42-28
Integrate External Code by Using Custom Code
Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-30
Integrate External Code by Using Model Configuration
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-33
Integrate External C Code Into Generated Code By Using
Custom Code Blocks and Model Configuration
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-35

Call External Device Drivers . . . . . . . . . . . . . . . . . . . . . . 42-39

Apply Function and Operator Code Replacements . . . . 42-41

Build Integrated Code Within the Simulink


Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-42
Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-42
Configure Parameters for Integrated Code
Build Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-43
Preserve External Code Files in Build Folder . . . . . . . 42-45

liv Contents
Build Support for S-Functions . . . . . . . . . . . . . . . . . . 42-45

Generate Component Source Code for Export to External


Code Base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-52
Modeling Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-52
Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-53
Limitations for Export-Function Subsystems . . . . . . . . 42-54
Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-55
Choose an Integration Approach . . . . . . . . . . . . . . . . . 42-56
Generate C Function Code for Export-Function
Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-58
Generate C++ Function and Class Code for Export-
Function Model . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-64
Generate Code for Export-Function Subsystems . . . . . 42-69

Generate Shared Library for Export to External Code


Base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-73
About Generated Shared Libraries . . . . . . . . . . . . . . . 42-73
Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-73
Generate Shared Libraries . . . . . . . . . . . . . . . . . . . . . 42-74
Create Application Code That Uses Generated Shared
Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-75
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-78
Interface to a Development Computer Simulator By Using
a Shared Library . . . . . . . . . . . . . . . . . . . . . . . . . . 42-79

Build Integrated Code Outside the Simulink


Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-83

Exchange Data Between External C/C++ Code and


Simulink Model or Generated Code . . . . . . . . . . . . . . 42-90
Import External Code into Model . . . . . . . . . . . . . . . . 42-90
Export Generated Code to External Environment . . . . 42-92
Simulink Representations of C Data Types and
Constructs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-92
Considerations for Other Modeling Goals . . . . . . . . . 42-100

Exchange Data Between External Calling Code and


Generated Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-102
Data Exchange for Reentrant Generated Code . . . . . 42-102
Data Exchange for Nonreentrant Generated Code . . 42-103

lv
Generate Code That Matches Appearance of External
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42-106

Program Building, Interaction, and Debugging in


Simulink Coder
43
Select C or C++ Programming Language . . . . . . . . . . . . 43-2

Select and Configure C or C++ Compiler or IDE . . . . . . 43-3


Language Standards Compliance . . . . . . . . . . . . . . . . . 43-3
Programming Language Considerations . . . . . . . . . . . . 43-4
C++ Language Support Limitations . . . . . . . . . . . . . . . 43-5
Code Generator Assumes Wrap on Signed Integer Overflo
ws . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-6
Choose and Configure Compiler . . . . . . . . . . . . . . . . . . 43-6
Include S-Function Source Code . . . . . . . . . . . . . . . . . . 43-7

Troubleshoot Compiler Issues . . . . . . . . . . . . . . . . . . . . . 43-9


Compiler Version Mismatch Errors . . . . . . . . . . . . . . . . 43-9
Results for Model Simulation and Program Execution Diff
er . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-9
Generates Expected Code and Produces Unexpected
Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-10
Compile-Time Issues . . . . . . . . . . . . . . . . . . . . . . . . . . 43-11
LCC Compiler Does Not Support Ampersands in Source
Folder Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-12
LCC Compiler Might Not Support Line Lengths of Rapid
Accelerator Code . . . . . . . . . . . . . . . . . . . . . . . . . . 43-13

Choose Build Approach and Configure Build Process . 43-14


Toolchain Approach . . . . . . . . . . . . . . . . . . . . . . . . . . 43-14
Upgrade Model to Use Toolchain Approach . . . . . . . . . 43-16
Template Makefile Approach . . . . . . . . . . . . . . . . . . . 43-20
Specify TLC for Code Generation . . . . . . . . . . . . . . . . 43-24

Template Makefiles and Make Options . . . . . . . . . . . . . 43-26


Types of Template Makefiles . . . . . . . . . . . . . . . . . . . . 43-26
Specify Template Makefile Options . . . . . . . . . . . . . . . 43-27
Template Makefiles for UNIX Platforms . . . . . . . . . . . 43-27

lvi Contents
Template Makefiles for the Microsoft Visual C+
+ Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-28
Template Makefiles for the LCC Compiler . . . . . . . . . . 43-30

Build Process Workflow for Real-Time Systems . . . . . . 43-32


Working Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-32
Build Folder and Code Generation Folders . . . . . . . . . 43-32
Set Model Parameters for Code Generation . . . . . . . . 43-33
Configure Build Process . . . . . . . . . . . . . . . . . . . . . . . 43-34
Set Code Generation Parameters . . . . . . . . . . . . . . . . 43-35
Build and Run a Program . . . . . . . . . . . . . . . . . . . . . . 43-36
Contents of the Build Folder . . . . . . . . . . . . . . . . . . . . 43-38
Customized Makefile Generation . . . . . . . . . . . . . . . . 43-39

Rebuild a Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-41

Control Regeneration of Top Model Code . . . . . . . . . . . 43-43


Regeneration of Top Model Code . . . . . . . . . . . . . . . . 43-43
Force Regeneration of Top Model Code . . . . . . . . . . . . 43-44

Reduce Build Time for Referenced Models . . . . . . . . . . 43-45


Parallel Building for Large Model Reference
Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-45
Parallel Building Configuration Requirements . . . . . . . 43-46
Build Models in a Parallel Computing Environment . . . 43-46
Locate Parallel Build Logs . . . . . . . . . . . . . . . . . . . . . 43-48
View Build Process Status . . . . . . . . . . . . . . . . . . . . . 43-50
Apply Build Process Status to Improve Parallel
Builds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-51

Relocate Code to Another Development


Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-56
Code Relocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-56
Package Code Using the User Interface . . . . . . . . . . . 43-56
Package Code Using the Command-Line Interface . . . 43-58
Build Integrated Code Outside the Simulink
Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43-61
packNGo Function Limitations . . . . . . . . . . . . . . . . . . 43-67

Executable Program Generation . . . . . . . . . . . . . . . . . . 43-69

Profile Code Performance . . . . . . . . . . . . . . . . . . . . . . . . 43-72


Use the Profile Hook Function Interface . . . . . . . . . . . 43-72

lvii
Profile Hook Function Interface Limitation . . . . . . . . . 43-75

Host/Target Communication in Simulink Coder


44
Host-Target Communication with External Mode
Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-2

External Mode Simulation with XCP Communication . . 44-8


Run XCP External Mode Simulation From Simulink
Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-8
Target Application Arguments . . . . . . . . . . . . . . . . . . 44-12
Graphical Controls for XCP External Mode
Simulations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-13
Run XCP External Mode Simulation From Command
Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-16
XCP External Mode Limitations . . . . . . . . . . . . . . . . . 44-17

Customize XCP Slave Software . . . . . . . . . . . . . . . . . . . . 44-22


External Mode Abstraction Layer . . . . . . . . . . . . . . . . 44-23
XCP Slave Protocol Layer . . . . . . . . . . . . . . . . . . . . . . 44-27
XCP Slave Transport Layer . . . . . . . . . . . . . . . . . . . . . 44-27
XCP Platform Abstraction Layer . . . . . . . . . . . . . . . . . 44-27

External Mode Simulation with TCP/IP or Serial


Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-36
Create and Configure Model . . . . . . . . . . . . . . . . . . . . 44-36
Build Target Executable . . . . . . . . . . . . . . . . . . . . . . . 44-38
Run Target Program . . . . . . . . . . . . . . . . . . . . . . . . . . 44-40
Tune Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-44
Control Memory Allocation for Communication Buffers
in Target . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-46
Pure Integer Code with External Mode . . . . . . . . . . . . 44-46
Control External Mode Simulation Through Editor
Toolbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-47
Control External Mode Simulation Through External Mode
Control Panel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-48
Configure Host Monitoring of Target Program
Signal Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44-52

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

Create a Transport Layer for TCP/IP or Serial External


Mode Communication . . . . . . . . . . . . . . . . . . . . . . . . . 44-90
Design of External Mode . . . . . . . . . . . . . . . . . . . . . . 44-90
External Mode Communications Overview . . . . . . . . . 44-93
External Mode Source Files . . . . . . . . . . . . . . . . . . . . 44-94
Implement a Custom Transport Layer . . . . . . . . . . . . . 44-98

Logging in Simulink Coder


45
Log Program Execution Results . . . . . . . . . . . . . . . . . . . . 45-2
Log Data for Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . 45-2
Configure State, Time, and Output Logging . . . . . . . . . 45-9
Log Data with Scope and To Workspace Blocks . . . . . . 45-11
Log Data with To File Blocks . . . . . . . . . . . . . . . . . . . . 45-11
Data Logging Differences Between Single- and
Multitasking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45-12

Data Interchange Using the C API in Simulink


Coder
46
Exchange Data Between Generated and External Code
Using C API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46-2
Generated C API Files . . . . . . . . . . . . . . . . . . . . . . . . . 46-2

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

Use C API to Access Model Signals and States . . . . . . . 46-24

Use C API to Access Model Parameters . . . . . . . . . . . . . 46-30

ASAP2 Data Measurement and Calibration in


Simulink Coder
47
Export ASAP2 File for Data Measurement and
Calibration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47-2
What You Should Know . . . . . . . . . . . . . . . . . . . . . . . . . 47-3
Targets Supporting ASAP2 . . . . . . . . . . . . . . . . . . . . . . 47-3
Define ASAP2 Information . . . . . . . . . . . . . . . . . . . . . . 47-3
Generate an ASAP2 File . . . . . . . . . . . . . . . . . . . . . . . . 47-9
Structure of the ASAP2 File . . . . . . . . . . . . . . . . . . . . 47-12
Create a Host-Based ASAM-ASAP2 Data Definition File for
Data Measurement and Calibration . . . . . . . . . . . . 47-13

Direct Memory Access to Generated Code for


Simulink Coder
48
Access Memory in Generated Code Using Global Data
Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48-2

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

Run Rapid Simulations Over Range of Parameter


Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49-35

Run Batch Simulations Without Recompiling Generated


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49-43

Use MAT-Files to Feed Data to Inport Blocks for Rapid


Simulations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49-51

Accelerate Simulation, Reuse Code, or Protect Intellectual


Property by Using S-Function Target . . . . . . . . . . . . . 49-59
About the S-Function Target . . . . . . . . . . . . . . . . . . . . 49-59
Create S-Function Blocks from a Subsystem . . . . . . . . 49-63
Tunable Parameters in Generated S-Functions . . . . . . 49-67
System Target File . . . . . . . . . . . . . . . . . . . . . . . . . . . 49-68
Checksums and the S-Function Target . . . . . . . . . . . . 49-68
Generated S-Function Compatibility . . . . . . . . . . . . . . 49-69
S-Function Target Limitations . . . . . . . . . . . . . . . . . . . 49-70

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

Real-Time Systems in Simulink Coder


51
Deploy Algorithm Model for Real-Time Rapid
Prototyping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51-2
About Real-Time Rapid Prototyping . . . . . . . . . . . . . . . 51-2
Goals of Real-Time Rapid Prototyping . . . . . . . . . . . . . . 51-2
Refine Code With Real-Time Rapid Prototyping . . . . . . . 51-3

Deploy Environment Model for Real-Time Hardware-In-


the-Loop (HIL) Simulation . . . . . . . . . . . . . . . . . . . . . . 51-5
About Hardware-In-the-Loop Simulation . . . . . . . . . . . . 51-5
Set Up and Run HIL Simulations . . . . . . . . . . . . . . . . . 51-6

Real-Time and Embedded Systems in Embedded


Coder
52
Deploy Generated Standalone Executable Programs To
Target Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52-2
Generate a Standalone Program . . . . . . . . . . . . . . . . . . 52-2
Standalone Program Components . . . . . . . . . . . . . . . . . 52-3
Main Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52-3
rt_OneStep and Scheduling Considerations . . . . . . . . . . 52-4
Static Main Program Module . . . . . . . . . . . . . . . . . . . 52-11
Rate Grouping Compliance and Compatibility Issues . 52-17

lxii Contents
Generate Code That Dereferences Data from a Literal
Memory Address . . . . . . . . . . . . . . . . . . . . . . . . . . 52-21

Deploy Generated Component Software to Application


Target Platforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52-31
Interface to an Example Real-Time Operating System
(VxWorks®) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52-31
Multirate Modeling in Multitasking Mode (VxWorks®
OS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52-33

Export Code Generated from Model to External


Application in Embedded Coder
53
Control Generation of Function Interfaces . . . . . . . . . . . 53-2

Control Generation of C++ Class Interfaces . . . . . . . . . . 53-4

Code Replacement Customization for Simulink


Models in Embedded Coder
54
What Is Code Replacement Customization? . . . . . . . . . . 54-3
Code Replacement Match and Replacement Process . . . 54-3
Code Replacement Customization Limitations . . . . . . . . 54-4

Code You Can Replace From Simulink Models . . . . . . . . 54-7


Math Functions – Simulink Support . . . . . . . . . . . . . . . 54-7
Math Functions – Stateflow Support . . . . . . . . . . . . . . 54-14
Memory Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-19
Nonfinite Functions . . . . . . . . . . . . . . . . . . . . . . . . . . 54-20
Mutex and Semaphore Functions . . . . . . . . . . . . . . . . 54-20
Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-21

Develop a Code Replacement Library . . . . . . . . . . . . . . 54-27

lxiii
Quick Start Code Replacement Library Development -
Simulink® . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-28

Identify Code Replacement Requirements . . . . . . . . . . 54-39


Mapping Information Requirements . . . . . . . . . . . . . . 54-39
Build Information Requirements . . . . . . . . . . . . . . . . . 54-40
Registration Information Requirements . . . . . . . . . . . 54-40

Prepare for Code Replacement Library Development . 54-42

Define Code Replacement Mappings . . . . . . . . . . . . . . . 54-43


Choose an Approach for Defining Code Replacement
Mappings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-43
Define Mappings Interactively with the Code
Replacement Tool . . . . . . . . . . . . . . . . . . . . . . . . . . 54-44
Define Mappings Programmatically . . . . . . . . . . . . . . 54-47

Specify Build Information for Replacement Code . . . . 54-61


Build Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-61
Choose an Approach for Specifying Build
Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-61
Specify Build Information Interactively with the Code
Replacement Tool . . . . . . . . . . . . . . . . . . . . . . . . . . 54-62
Specify Build Information Programmatically . . . . . . . . 54-64

Register Code Replacement Mappings . . . . . . . . . . . . . 54-70


Choose an Approach for Creating the Registration
File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-70
Create Registration File Interactively with the Code
Replacement Tool . . . . . . . . . . . . . . . . . . . . . . . . . . 54-71
Create Registration File Programmatically . . . . . . . . . 54-73
Register a Code Replacement Library . . . . . . . . . . . . . 54-75
Register a Library that Includes Multiple Code
Replacement Tables . . . . . . . . . . . . . . . . . . . . . . . . 54-76
Registration Files That Define Code Replacement Library
Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-76

Troubleshoot Code Replacement Library


Registration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-78

Verify Code Replacements . . . . . . . . . . . . . . . . . . . . . . . 54-79


Code Replacement Hits and Misses . . . . . . . . . . . . . . 54-79
Validate Table Definition File . . . . . . . . . . . . . . . . . . . 54-80

lxiv Contents
Review Library Content . . . . . . . . . . . . . . . . . . . . . . . 54-80
Review Table Content . . . . . . . . . . . . . . . . . . . . . . . . . 54-82
Review Code Replacements . . . . . . . . . . . . . . . . . . . . 54-85

Troubleshoot Code Replacement Misses . . . . . . . . . . . . 54-89


Miss Reason Messages . . . . . . . . . . . . . . . . . . . . . . . . 54-89
Analyze and Correct Code Replacement Misses . . . . . 54-90

Deploy Code Replacement Library . . . . . . . . . . . . . . . . . 54-96

Math Function Code Replacement . . . . . . . . . . . . . . . . . 54-97

Memory Function Code Replacement . . . . . . . . . . . . . . 54-99

Nonfinite Function Code Replacement . . . . . . . . . . . . 54-102

Semaphore and Mutex Function Replacement . . . . . . 54-105

Algorithm-Based Code Replacement . . . . . . . . . . . . . . 54-112

Lookup Table Function Code Replacement . . . . . . . . . 54-115


Lookup Table Algorithm Replacement . . . . . . . . . . . . 54-115
Lookup Table Function Signatures . . . . . . . . . . . . . . 54-115
Interactive Mapping with Code Replacement Tool . . . 54-121
Programmatic Specification . . . . . . . . . . . . . . . . . . . 54-126
Sample Code Replacement Definition for the
lookup2D Function . . . . . . . . . . . . . . . . . . . . . . . . 54-133

Data Alignment for Code Replacement . . . . . . . . . . . . 54-136


Code Replacement Data Alignment . . . . . . . . . . . . . . 54-136
Specify Data Alignment Requirements for Function
Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-136
Provide Data Alignment Specifications for Compilers 54-138
Basic Example of Code Replacement Data Alignment 54-143

Replace MATLAB Functions with Custom Code Using


coder.replace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-146

Replace coder.ceval Calls to External Functions . . . . 54-147


Example Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-147
Interactive External Function Call Replacement
Specification with Code Replacement Tool . . . . . . 54-148

lxv
Programmatic External Function Call Replacement Specifi
cation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-150

Replace MATLAB Functions Specified in MATLAB


Function Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-153

Reserved Identifiers and Code Replacement . . . . . . . . 54-157

Customize Match and Replacement Process . . . . . . . . 54-159


Customize Code Match and Replacement for
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-160
Customize Code Match and Replacement for Nonscalar
Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-163
Customize Code Match and Replacement for Scalar
Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-167

Scalar Operator Code Replacement . . . . . . . . . . . . . . . 54-174

Addition and Subtraction Operator Code


Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-177
Algorithm Options . . . . . . . . . . . . . . . . . . . . . . . . . . 54-177
Interactive Specification with Code
Replacement Tool . . . . . . . . . . . . . . . . . . . . . . . . . 54-177
Programmatic Specification . . . . . . . . . . . . . . . . . . . 54-178
Algorithm Classification . . . . . . . . . . . . . . . . . . . . . . 54-178
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-180

Small Matrix Operation to Processor Code


Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-182

Matrix Multiplication Operation to MathWorks BLAS Code


Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-186

Matrix Multiplication Operation to ANSI/ISO C BLAS Code


Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-194

Remap Operator Output to Function Input . . . . . . . . . 54-201

Fixed-Point Operator Code Replacement . . . . . . . . . . 54-204


Common Ways to Match Fixed-Point Operator
Entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-204
Fixed-Point Numbers and Arithmetic . . . . . . . . . . . . 54-207
Addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-207

lxvi Contents
Subtraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-208
Multiplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-208
Division . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-209
Data Type Conversion (Cast) . . . . . . . . . . . . . . . . . . 54-210
Shift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-211

Binary-Point-Only Scaling Code Replacement . . . . . . 54-213

Slope Bias Scaling Code Replacement . . . . . . . . . . . . 54-217

Net Slope Scaling Code Replacement . . . . . . . . . . . . . 54-221


Multiplication and Division with Saturation . . . . . . . 54-221
Multiplication and Division with Rounding Mode and
Additional Implementation Arguments . . . . . . . . . 54-224

Equal Slope and Zero Net Bias Code Replacement . . 54-228

Data Type Conversions (Casts) and Operator Code


Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54-232
Casts from int32 To int16 . . . . . . . . . . . . . . . . . . . . . 54-232
Casts Using Net Slope . . . . . . . . . . . . . . . . . . . . . . . 54-233

Shift Left Operations and Code Replacement . . . . . . . 54-236


Shift Lefts for int16 Data . . . . . . . . . . . . . . . . . . . . . 54-236
Shift Lefts Using Net Slope . . . . . . . . . . . . . . . . . . . 54-237

Code Replacement Customization for MATLAB


Code
55
What Is Code Replacement Customization? . . . . . . . . . . 55-3
Code Replacement Match and Replacement Process . . . 55-3
Code Replacement Customization Limitations . . . . . . . . 55-4

Code You Can Replace from MATLAB Code . . . . . . . . . . . 55-5


Math Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-5
Memory Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-10
Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-10

Develop a Code Replacement Library . . . . . . . . . . . . . . 55-15

lxvii
Quick Start Library Development . . . . . . . . . . . . . . . . . . 55-16

Identify Code Replacement Requirements . . . . . . . . . . 55-25


Mapping Information Requirements . . . . . . . . . . . . . . 55-25
Build Information Requirements . . . . . . . . . . . . . . . . . 55-26
Registration Information Requirements . . . . . . . . . . . 55-26

Prepare for Code Replacement Library Development . 55-28

Define Code Replacement Mappings . . . . . . . . . . . . . . . 55-29


Choose an Approach for Defining Code Replacement
Mappings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-29
Define Mappings Interactively with the Code
Replacement Tool . . . . . . . . . . . . . . . . . . . . . . . . . . 55-30
Define Mappings Programmatically . . . . . . . . . . . . . . 55-33

Specify Build Information for Replacement Code . . . . 55-47


Build Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-47
Choose an Approach for Specifying Build
Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-47
Specify Build Information Interactively with the Code
Replacement Tool . . . . . . . . . . . . . . . . . . . . . . . . . . 55-48
Specify Build Information Programmatically . . . . . . . . 55-50

Register Code Replacement Mappings . . . . . . . . . . . . . 55-56


Choose an Approach for Creating the Registration
File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-56
Create Registration File Interactively with the Code
Replacement Tool . . . . . . . . . . . . . . . . . . . . . . . . . . 55-57
Create Registration File Programmatically . . . . . . . . . 55-59
Register a Code Replacement Library . . . . . . . . . . . . . 55-61
Registration Files That Define Multiple Code Replacement
Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-62
Registration Files That Define Code Replacement Library
Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-62

Troubleshoot Code Replacement Library


Registration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-64

Verify Code Replacements . . . . . . . . . . . . . . . . . . . . . . . 55-65


Code Replacement Hits and Misses . . . . . . . . . . . . . . 55-65
Validate a Table Definition File . . . . . . . . . . . . . . . . . . 55-66
Review Library Content . . . . . . . . . . . . . . . . . . . . . . . 55-66

lxviii Contents
Review Table Content . . . . . . . . . . . . . . . . . . . . . . . . . 55-68
Review Code Replacements . . . . . . . . . . . . . . . . . . . . 55-71

Troubleshoot Code Replacement Misses . . . . . . . . . . . . 55-74


Miss Reason Messages . . . . . . . . . . . . . . . . . . . . . . . . 55-74
Analyze and Correct Code Replacement Misses . . . . . 55-75

Deploy Code Replacement Library . . . . . . . . . . . . . . . . . 55-78

Math Function Code Replacement . . . . . . . . . . . . . . . . . 55-79

Memory Function Code Replacement . . . . . . . . . . . . . . 55-81

Specify In-Place Code Replacement . . . . . . . . . . . . . . . . 55-83


Argument Specification Requirements . . . . . . . . . . . . 55-83
Interactive Argument Replacement Specification with Code
Replacement Tool . . . . . . . . . . . . . . . . . . . . . . . . . . 55-83
Programmatic Argument Replacement Specification . . 55-86

Data Alignment for Code Replacement . . . . . . . . . . . . . 55-88


Code Replacement Data Alignment . . . . . . . . . . . . . . . 55-88
Specify Data Alignment Requirements for Function
Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-88
Provide Data Alignment Specifications for Compilers . 55-90
Specify Data Alignment in MATLAB Code for Imported
Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-95
Replacing Math Functions and Operators with
Implementations that require Data Alignment -
MATLAB® . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-96

Array Layout and Code Replacement . . . . . . . . . . . . . . 55-102

Replace MATLAB Functions with Custom Code Using


coder.replace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-105

Replace coder.ceval Calls to External Functions . . . . 55-106


Example Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-106
Interactive External Function Call Replacement
Specification with Code Replacement Tool . . . . . . 55-107
Programmatic External Function Call Replacement Specifi
cation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-109

Reserved Identifiers and Code Replacement . . . . . . . . 55-111

lxix
Customize Match and Replacement Process . . . . . . . . 55-113
Customize Match and Replacement Process for
Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-114

Scalar Operator Code Replacement . . . . . . . . . . . . . . . 55-121

Addition and Subtraction Operator Code


Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-123
Algorithm Options . . . . . . . . . . . . . . . . . . . . . . . . . . 55-123
Interactive Specification with Code
Replacement Tool . . . . . . . . . . . . . . . . . . . . . . . . . 55-123
Programmatic Specification . . . . . . . . . . . . . . . . . . . 55-124
Algorithm Classification . . . . . . . . . . . . . . . . . . . . . . 55-124
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-126

Small Matrix Operation to Processor Code


Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-128

Matrix Multiplication Operation to MathWorks BLAS Code


Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-132

Matrix Multiplication Operation to ANSI/ISO C BLAS Code


Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-139

Remap Operator Output to Function Input . . . . . . . . . 55-146

Fixed-Point Operator Code Replacement . . . . . . . . . . 55-149


Common Ways to Match Fixed-Point Operator
Entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-149
Fixed-Point Numbers and Arithmetic . . . . . . . . . . . . 55-152
Addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-152
Subtraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-153
Multiplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-153
Division . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-154
Data Type Conversion (Cast) . . . . . . . . . . . . . . . . . . 55-155
Shift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-156

Binary-Point-Only Scaling Code Replacement . . . . . . 55-158

Slope Bias Scaling Code Replacement . . . . . . . . . . . . 55-161

Net Slope Scaling Code Replacement . . . . . . . . . . . . . 55-164


Multiplication and Division with Saturation . . . . . . . 55-164

lxx Contents
Multiplication and Division with Rounding Mode and
Additional Implementation Arguments . . . . . . . . . 55-167

Equal Slope and Zero Net Bias Code Replacement . . 55-170

Data Type Conversions (Casts) and Operator Code


Replacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55-173

Shift Left Operations and Code Replacement . . . . . . . 55-177

Performance

Optimizations for Generated Code in Simulink


Coder
56
Increase Code Generation Speed . . . . . . . . . . . . . . . . . . . 56-3
Build a Model in Increments . . . . . . . . . . . . . . . . . . . . . 56-3
Build Large Model Reference Hierarchies in Parallel . . 56-3
Minimize Memory Requirements During Code
Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-4
Generate Only Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-5
No Creation of a Code Generation Report . . . . . . . . . . . 56-5

Control Compiler Optimizations . . . . . . . . . . . . . . . . . . . 56-6

Optimization Tools and Techniques . . . . . . . . . . . . . . . . . 56-7


Use the Model Advisor to Optimize a Model for Code
Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-7
Design Tips for Optimizing Generated Code for Stateflow
Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-7
Additional Optimization Techniques . . . . . . . . . . . . . . . 56-8

Control Memory Allocation for Time Counters . . . . . . . 56-11

Execution Profiling for Generated Code . . . . . . . . . . . . 56-12

lxxi
Optimize Generated Code by Combining Multiple for
Constructs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-15

Subnormal Number Performance . . . . . . . . . . . . . . . . . 56-19


Simulation Time With and Without Subnormal
Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-20
Flush Subnormal Numbers to Zero . . . . . . . . . . . . . . . 56-21

Remove Code From Floating-Point to Integer Conversions


That Wraps Out-of-Range Values . . . . . . . . . . . . . . . . 56-24
Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-24
Generate Code Without Optimization . . . . . . . . . . . . . 56-25
Generate Code with Optimization . . . . . . . . . . . . . . . . 56-26

Remove Code That Maps NaN to Integer Zero . . . . . . . 56-27


Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-27
Generate Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-28
Generate Code with Optimization . . . . . . . . . . . . . . . . 56-29

Disable Nonfinite Checks or Inlining for Math


Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-31

Minimize Computations and Storage for Intermediate


Results at Block Outputs . . . . . . . . . . . . . . . . . . . . . . 56-37
Expression Folding . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-37
Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-37
Generate Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-38
Enable Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . 56-38
Generate Code with Optimization . . . . . . . . . . . . . . . . 56-39

Inline Invariant Signals . . . . . . . . . . . . . . . . . . . . . . . . . 56-40


Optimize Generated Code Using Inline Invariant
Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-40

Inline Numeric Values of Block Parameters . . . . . . . . . 56-44

Configure Loop Unrolling Threshold . . . . . . . . . . . . . . . 56-50

Use memcpy Function to Optimize Generated Code for


Vector Assignments . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-53
Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-54
Generate Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-55
Generate Code with Optimization . . . . . . . . . . . . . . . . 56-55

lxxii Contents
Generate Target Optimizations Within Algorithm
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-57

Remove Code for Blocks That Have No Effect on


Computational Results . . . . . . . . . . . . . . . . . . . . . . . . 56-59

Eliminate Dead Code Paths in Generated Code . . . . . . 56-62

Floating-Point Multiplication to Handle a Net Slope


Correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-65

Use Conditional Input Branch Execution . . . . . . . . . . . 56-68

Optimize Generated Code for Complex Signals . . . . . . 56-74

Speed Up Linear Algebra in Code Generated from a


MATLAB Function Block . . . . . . . . . . . . . . . . . . . . . . . 56-77
Specify LAPACK Library . . . . . . . . . . . . . . . . . . . . . . . 56-77
Write LAPACK Callback Class . . . . . . . . . . . . . . . . . . . 56-77
Generate LAPACK Calls by Specifying a LAPACK Callback
Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-78
Locate LAPACK Library in Execution Environment . . . 56-79

Speed Up Fast Fourier Transforms in Code Generated from


a MATLAB Function Block . . . . . . . . . . . . . . . . . . . . . 56-81
Install an FFTW Library . . . . . . . . . . . . . . . . . . . . . . . 56-81
Write FFT Callback Class . . . . . . . . . . . . . . . . . . . . . . 56-82
Generate FFTW Calls by Specifying an FFT Callback
Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-83

Synchronize Multithreaded FFTW Planning in Code


Generated from a MATLAB Function Block . . . . . . . 56-85
Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-85
Create a Model with a MATLAB Function Block That Calls
an FFT Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-86
Write Supporting C Code . . . . . . . . . . . . . . . . . . . . . . 56-86
Create an FFT Library Callback Class . . . . . . . . . . . . . 56-87
Configure Code Generation Parameters and Build
the Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-88

Control Memory Allocation for Variable-Size Arrays in a


MATLAB Function Block . . . . . . . . . . . . . . . . . . . . . . . 56-90
Provide Upper Bounds for Variable-Size Arrays . . . . . . 56-90

lxxiii
Disable Dynamic Memory Allocation for MATLAB Function
Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-91
Modify the Dynamic Memory Allocation Threshold . . . 56-91

Optimize Memory Usage for Time Counters . . . . . . . . . 56-93

Optimize Generated Code Using Boolean Data for Logical


Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-100

Reduce Memory Usage for Boolean and State


Configuration Variables . . . . . . . . . . . . . . . . . . . . . . 56-103

Customize Stack Space Allocation . . . . . . . . . . . . . . . . 56-104

Optimize Generated Code Using memset Function . . 56-106

Vector Operation Optimization . . . . . . . . . . . . . . . . . . . 56-110

Enable and Reuse Local Block Outputs in Generated


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-113
Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56-113
Generate Code Without Optimization . . . . . . . . . . . . 56-114
Enable Local Block Outputs and Generate Code . . . . 56-114
Reuse Local Block Outputs and Generate Code . . . . . 56-115

Configuration in Embedded Coder


57
Set Hardware Implementation Parameters . . . . . . . . . . . 57-2

Data Copy Reduction in Embedded Coder


58
Optimize Global Variable Usage . . . . . . . . . . . . . . . . . . . . 58-2
Use Global to Hold Temporary Results . . . . . . . . . . . . . 58-2
Minimize Global Data Access . . . . . . . . . . . . . . . . . . . . 58-7

lxxiv Contents
Reuse Global Block Outputs in the Generated Code . . 58-14

Virtualized Output Ports Optimization . . . . . . . . . . . . . 58-17

Specify Buffer Reuse by Using Simulink.Signal


Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-19

Specify Buffer Reuse for MATLAB Function Blocks in


a Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-27
Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-27
Generate Code with Optimization . . . . . . . . . . . . . . . . 58-27

Remove Data Copies by Reordering Block Operations in


the Generated Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-29
Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-29
Generate Code without Optimization . . . . . . . . . . . . . 58-30
Generate Code with Optimization . . . . . . . . . . . . . . . . 58-32

Data Copy Reduction for Data Store Read and Data Store
Write Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-35

Reduce Data Copies for Bus Assignment Blocks . . . . . 58-40


Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-40
Generate Code Without Optimization . . . . . . . . . . . . . 58-40
Generate Code with Optimization . . . . . . . . . . . . . . . . 58-41

Optimize Generated Code by Using Signal Labels to Guide


Buffer Reuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-43
Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-43
Generate Code Without Optimization . . . . . . . . . . . . . 58-43
Generate Code with Optimization . . . . . . . . . . . . . . . . 58-44
Using Label-Based Reuse Versus Reusable Custom Storage
Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58-45

Execution Speed in Embedded Coder


59
Reduce Memory Usage for Signals . . . . . . . . . . . . . . . . . 59-2

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

Simplify Multiply Operations in Array Indexing . . . . . . 59-10


Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59-10
Generate Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59-11
Generate Code with Optimization . . . . . . . . . . . . . . . . 59-11

Replace boolean with Specific Integer Data Type . . . . . 59-14


Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59-14
Generate Code That Contains the Default boolean Data
Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59-15
Generate Code That Contains the Target boolean Data
Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59-16

Remove Code That Guards Against Division Exceptions for


Integers and Fixed-Point Data . . . . . . . . . . . . . . . . . . 59-19

Division Arithmetic Exceptions in Generated Code . . . 59-23


Division by Zero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59-23
INT_MIN/-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59-23
Other Factors Affecting Generated Code of Division
Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59-24

Optimize Generated Code by Consolidating Redundant If-


Else Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59-25

Optimize Generated Code for Fixed-Point Data


Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59-30

Optimize Generated Code By Developing and Using Code


Replacement Libraries - Simulink® . . . . . . . . . . . . . 59-33

Improve Execution Efficiency by Reordering Block


Operations in the Generated Code . . . . . . . . . . . . . . . 59-65

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

Flat Structures for Reusable Subsystem Parameters . . . 60-9

Reduce Global Variables in Nonreusable Subsystem


Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60-13
Generate void-void Function . . . . . . . . . . . . . . . . . . . . 60-13
Generate Function with Arguments . . . . . . . . . . . . . . 60-14

Optimize Generated Code By Packing Boolean Data Into


Bitfields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60-16

Optimize Generated Code By Passing Reusable Subsystem


Outputs as Individual Arguments . . . . . . . . . . . . . . . 60-20

Convert Data Copies to Pointer Assignments . . . . . . . . 60-25

Reuse Buffers of Different Sizes and Dimensions . . . . 60-30

Remove Reset and Disable Functions from the Generated


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60-37
Example Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60-37
Generate Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60-38
Enable Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . 60-39

Code Execution Profiling in Embedded Coder


61
Code Execution Profiling with SIL and PIL . . . . . . . . . . . 61-2
Configure Code Execution Profiling . . . . . . . . . . . . . . . 61-3

lxxvii
Profiling for Atomic Subsystems and Model Reference
Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61-4

View and Compare Code Execution Times . . . . . . . . . . . . 61-7


Code Execution Profiling Report . . . . . . . . . . . . . . . . . . 61-9

Analyze Code Execution Data . . . . . . . . . . . . . . . . . . . . . 61-16

Tips and Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61-19


Triggered Model Block . . . . . . . . . . . . . . . . . . . . . . . . 61-19
Outliers in Execution-Time Profiles . . . . . . . . . . . . . . . 61-19
Hardware-Specific Timer . . . . . . . . . . . . . . . . . . . . . . 61-21
Task Context Switching Due to Preemption . . . . . . . . . 61-21
Subsystem Code Reuse . . . . . . . . . . . . . . . . . . . . . . . . 61-21
Cannot Load Execution-Time Measurements from Previous
Release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61-22

Code Execution Profiling for MATLAB Coder


62
Execution Time Profiling for SIL and PIL . . . . . . . . . . . . 62-2

Generate Execution Time Profile . . . . . . . . . . . . . . . . . . . 62-3

View Execution Times . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62-4

Analyze Execution Time Data . . . . . . . . . . . . . . . . . . . . . . 62-7


Extract Execution Time Data for Kalman Estimator
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62-7

lxxviii Contents
Verification

Simulation and Code Comparison in Simulink


Coder
63
Simulation and Code Comparison . . . . . . . . . . . . . . . . . . 63-2
Configure Signal Data for Logging . . . . . . . . . . . . . . . . 63-2
Log Simulation Data . . . . . . . . . . . . . . . . . . . . . . . . . . . 63-3
Run Executable and Load Data . . . . . . . . . . . . . . . . . . . 63-5
Visualize and Compare Results . . . . . . . . . . . . . . . . . . . 63-6
Compare States for Simulation and Code Generation . . 63-8

Code Tracing in Embedded Coder


64
Verify Generated Code by Using Code Tracing . . . . . . . . 64-2
Traceable Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . 64-2
Traceability in Code Generation Report . . . . . . . . . . . . 64-3
Traceability Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64-4
Operator Traceability . . . . . . . . . . . . . . . . . . . . . . . . . . 64-5
Traceability Limitations . . . . . . . . . . . . . . . . . . . . . . . . 64-6

Trace Simulink Model Elements in Generated Code . . . 64-8


Code-to-Model Traceability . . . . . . . . . . . . . . . . . . . . . . 64-8
Model-to-Code Traceability . . . . . . . . . . . . . . . . . . . . . 64-10

Trace Stateflow Elements in Generated Code . . . . . . . . 64-13


Inline Traceability for Stateflow Elements . . . . . . . . . . 64-13
Bidirectional Traceability for States and Transitions . . 64-15
Bidirectional Traceability for State Transition Tables . 64-17
Bidirectional Traceability for Truth Table Blocks . . . . . 64-20
Bidirectional Traceability for Graphical Functions . . . 64-22
Code-to-Model Traceability for Events . . . . . . . . . . . . 64-23
Model-to-Code Traceability for Junctions . . . . . . . . . . 64-24
Format of Traceability Comments for Stateflow
Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64-25

lxxix
Link Generated Code to Requirements . . . . . . . . . . . . . 64-29

Reload Existing Traceability Information . . . . . . . . . . . 64-34

Customize Traceability Reports . . . . . . . . . . . . . . . . . . . 64-36


Generate a Traceability Matrix . . . . . . . . . . . . . . . . . . 64-38

Component Verification in Embedded Coder


65
Component Verification in Target Environment . . . . . . . 65-2
Goals of Component Verification . . . . . . . . . . . . . . . . . . 65-2
Run Component Tests . . . . . . . . . . . . . . . . . . . . . . . . . . 65-4

Component Verification With a Real-Time Target


Environment in Embedded Coder
66
Real-Time Software Component Verification . . . . . . . . . . 66-2

Real-Time Software Component Testing . . . . . . . . . . . . . 66-6

Numerical Equivalence Checking in Embedded


Coder
67
SIL and PIL Simulations . . . . . . . . . . . . . . . . . . . . . . . . . . 67-2
What Are SIL and PIL Simulations? . . . . . . . . . . . . . . . 67-2
Why Use SIL and PIL . . . . . . . . . . . . . . . . . . . . . . . . . . 67-2
How SIL and PIL Simulations Work . . . . . . . . . . . . . . . . 67-4
Comparison of SIL and PIL Simulations . . . . . . . . . . . . 67-5
Code Interfaces for SIL and PIL . . . . . . . . . . . . . . . . . . 67-6
Scheduling Considerations . . . . . . . . . . . . . . . . . . . . . . 67-8

lxxx Contents
Imported Data and Function Definitions . . . . . . . . . . . 67-10

Choose a SIL or PIL Approach . . . . . . . . . . . . . . . . . . . . 67-12


Test Top-Model Code . . . . . . . . . . . . . . . . . . . . . . . . . 67-13
Test Referenced Model Code . . . . . . . . . . . . . . . . . . . 67-14
Test Subsystem Code . . . . . . . . . . . . . . . . . . . . . . . . . 67-14
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67-14

Configure and Run SIL Simulation . . . . . . . . . . . . . . . . 67-16


Simulation with Top Model . . . . . . . . . . . . . . . . . . . . . 67-16
Simulation with Model Blocks . . . . . . . . . . . . . . . . . . . 67-18
Simulation with Blocks From Subsystems . . . . . . . . . . 67-19
Configure Hardware Implementation Settings . . . . . . 67-20
Log Internal Signals of a Component . . . . . . . . . . . . . 67-23
Prevent Code Changes in Multiple Simulations . . . . . . 67-24
Speed Up Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67-25
Simulation with Function Calls . . . . . . . . . . . . . . . . . . 67-26

Configure and Run PIL Simulation . . . . . . . . . . . . . . . . 67-28


Simulation with Top Model . . . . . . . . . . . . . . . . . . . . . 67-28
Simulation with Model Blocks . . . . . . . . . . . . . . . . . . . 67-30
Simulation with Blocks From Subsystems . . . . . . . . . . 67-31
Log Internal Signals of a Component . . . . . . . . . . . . . 67-32
Prevent Code Changes in Multiple Simulations . . . . . . 67-33
Speed Up Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67-34
Simulation with Function Calls . . . . . . . . . . . . . . . . . . 67-35

Simulation Mode Override Behavior in Model Reference


Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67-37

Debug Generated Code During SIL Simulation . . . . . . 67-39

Create PIL Target Connectivity Configuration


for Simulink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67-42
Target Connectivity Configurations for PIL . . . . . . . . . 67-42
Create a Target Connectivity API Implementation . . . . 67-43
Register a Connectivity API Implementation . . . . . . . . 67-45
Verify Target Connectivity Configuration . . . . . . . . . . 67-45
Target Connectivity API Examples . . . . . . . . . . . . . . . 67-45

Host-Target Communication for PIL . . . . . . . . . . . . . . . 67-48


Communications rtiostream API . . . . . . . . . . . . . . . . . 67-48
Synchronize Host and Target . . . . . . . . . . . . . . . . . . . 67-49

lxxxi
Test an rtiostream Driver . . . . . . . . . . . . . . . . . . . . . . 67-50
Word Addressable Target Hardware . . . . . . . . . . . . . . 67-52

Specify Hardware Timer . . . . . . . . . . . . . . . . . . . . . . . . . 67-54

PIL Simulation Sequence . . . . . . . . . . . . . . . . . . . . . . . . 67-57

Verification of Code Generation Assumptions . . . . . . . . 67-60

View SIL and PIL Files in Code Generation Report . . . 67-65

SIL and PIL Limitations . . . . . . . . . . . . . . . . . . . . . . . . . 67-68


About SIL and PIL Limitations . . . . . . . . . . . . . . . . . . 67-68
General SIL and PIL Limitations . . . . . . . . . . . . . . . . . 67-68
Top-Model SIL/PIL Limitations . . . . . . . . . . . . . . . . . . 67-78
Model Block SIL/PIL Limitations . . . . . . . . . . . . . . . . . 67-80
SIL/PIL Block Limitations . . . . . . . . . . . . . . . . . . . . . . 67-81

Check Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67-83

Verify Numerical Equivalence with CGV . . . . . . . . . . . . 67-85

Verify Numerical Equivalence Between Two Modes of


Execution of a Model . . . . . . . . . . . . . . . . . . . . . . . . . . 67-87
Configure the Model . . . . . . . . . . . . . . . . . . . . . . . . . . 67-87
Execute the Model . . . . . . . . . . . . . . . . . . . . . . . . . . . 67-88
Compare All Output Signals . . . . . . . . . . . . . . . . . . . . 67-89
Compare Individual Output Signals . . . . . . . . . . . . . . 67-90
Plot Output Signals . . . . . . . . . . . . . . . . . . . . . . . . . . 67-91

Using Code Generation Verification API . . . . . . . . . . . . 67-93

Numerical Consistency between Model and


Generated Code
68
Numerical Consistency of Model and Generated Code
Simulation Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68-2
Numerical Consistency . . . . . . . . . . . . . . . . . . . . . . . . . 68-2
Numerical Consistency in Complex Systems . . . . . . . . . 68-3

lxxxii Contents
Reasons for Block-Level Numerical Differences . . . . . . 68-5

Software-in-the-Loop Execution for MATLAB


Coder
69
Code Verification Through Software-in-the-Loop and
Processor-in-the-Loop Execution . . . . . . . . . . . . . . . . . 69-2

Software-in-the-Loop Execution with the MATLAB Coder


App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69-4

Software-in-the-Loop Execution From Command


Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69-6
SIL Execution of Code Generated for a Kalman
Estimator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69-6

Debug Generated Code During SIL Execution . . . . . . . . 69-9

Create PIL Target Connectivity Configuration


for MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69-12
Target Connectivity Configurations for PIL . . . . . . . . . 69-12
Create a Target Connectivity API Implementation . . . . 69-13
Register Target Connectivity Configuration . . . . . . . . 69-14
Verify Target Connectivity Configuration . . . . . . . . . . 69-15

Host-Target Communication for PIL . . . . . . . . . . . . . . . 69-16


Communications rtiostream API . . . . . . . . . . . . . . . . . 69-16
Synchronize Host and Target . . . . . . . . . . . . . . . . . . . 69-17
Test an rtiostream Driver . . . . . . . . . . . . . . . . . . . . . . 69-18

Specify Hardware Timer . . . . . . . . . . . . . . . . . . . . . . . . . 69-22

Processor-in-the-Loop Execution with the MATLAB Coder


App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69-25

Processor-in-the-Loop Execution From Command


Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69-28
PIL Execution of Code Generated for a Kalman
Estimator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69-28

lxxxiii
Verification of Code Generation Assumptions . . . . . . . . 69-34

SIL/PIL Execution Support and Limitations . . . . . . . . . 69-35

Speed Up SIL/PIL Execution by Disabling Constant Input


Checking and Global Data Synchronization . . . . . . . 69-38
Disable Constant Input Checking or Global Data
Synchronization at the Command Line . . . . . . . . . . 69-38
Disable Constant Input Checking or Global Data
Synchronization in the MATLAB Coder App . . . . . . 69-38

Code Coverage in Embedded Coder


70
Simulink Code Coverage Metrics . . . . . . . . . . . . . . . . . . . 70-2
Statement Coverage for Code Coverage . . . . . . . . . . . . 70-2
Condition Coverage for Code Coverage . . . . . . . . . . . . . 70-3
Decision Coverage for Code Coverage . . . . . . . . . . . . . 70-3
Modified Condition/Decision Coverage (MCDC) for Code
Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70-4
Cyclomatic Complexity for Code Coverage . . . . . . . . . . 70-5
Relational Boundary for Code Coverage . . . . . . . . . . . . 70-5

Code Coverage for Models in Software-in-the-Loop (SIL)


Mode and Processor-in-the-Loop (PIL) Mode . . . . . . . 70-7
Enable SIL or PIL Code Coverage for a Model . . . . . . . 70-7
Simulink Coverage Code Coverage Measurement Workflo
ws . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70-8
Review the Coverage Results for Models in SIL or PIL
Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70-9
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70-10

Configure Code Coverage with Third-Party Tools . . . . . 70-11

View Code Coverage Information at the End of SIL or PIL


Simulations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70-14
View LDRA Testbed Results . . . . . . . . . . . . . . . . . . . . 70-14
View BullseyeCoverage Results . . . . . . . . . . . . . . . . . 70-16

Configure Code Coverage Programmatically . . . . . . . . . 70-18

lxxxiv Contents
Code Coverage Summary and Annotations . . . . . . . . . . 70-20
LDRA Testbed Coverage . . . . . . . . . . . . . . . . . . . . . . . 70-20
BullseyeCoverage Information . . . . . . . . . . . . . . . . . . 70-23

Code Coverage Tool Support . . . . . . . . . . . . . . . . . . . . . . 70-26

Tips and Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70-27


Model Build and SIL/PIL Blocks Not Supported . . . . . 70-27
BullseyeCoverage License Wait . . . . . . . . . . . . . . . . . . 70-27
Current Working Folder Cannot be UNC Path . . . . . . . 70-27
Characters in matlabroot and File Path . . . . . . . . . . . . 70-27
Header Files with Identical Names . . . . . . . . . . . . . . . 70-27
Code Coverage for Source Files in Shared Utility
Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70-27
BullseyeCoverage Behavior with Inline Macros . . . . . . 70-28
SIL and PIL Simulations with Open LDRA Testbed . . . 70-28
Minor SIL and PIL Differences for LDRA Testbed . . . . 70-29
PIL Zero Coverage LDRA Testbed Annotations . . . . . . 70-29
PIL Support for BullseyeCoverage . . . . . . . . . . . . . . . 70-30
Modify Legacy Code . . . . . . . . . . . . . . . . . . . . . . . . . . 70-30
IDE Link Does Not Support LDRA Testbed . . . . . . . . . 70-30

Embedded IDEs and Embedded Targets

Getting Started with Embedded Targets in


Embedded Coder
71
Embedded Coder Supported Hardware . . . . . . . . . . . . . . 71-2

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

Build Process Integration in Simulink Coder


73
Control Build Process Compiling and Linking . . . . . . . . 73-2

Cross-Compile Code Generated on Microsoft


Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73-4

Control Library Location and Naming During Build . . . 73-7


Library Control Parameters . . . . . . . . . . . . . . . . . . . . . 73-7
Specify the Location of Precompiled Libraries . . . . . . . 73-8
Control the Location of Model Reference Libraries . . . 73-10
Control the Suffix Applied to Library File Names . . . . 73-10

Recompile Precompiled Libraries . . . . . . . . . . . . . . . . . 73-13

Customize Post-Code-Generation Build Processing . . . 73-14


Workflow for Setting Up Customizations . . . . . . . . . . . 73-14
Build Information Object . . . . . . . . . . . . . . . . . . . . . . 73-15
Program a Post Code Generation Command . . . . . . . . 73-15
Define a Post Code Generation Command . . . . . . . . . . 73-16
Customize Build Process with PostCodeGenCommand and
Relocate Generated Code to an External
Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73-17
Suppress Makefile Generation . . . . . . . . . . . . . . . . . . 73-20

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

Use makecfg to Customize Generated Makefiles for S-


Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73-24

Use rtwmakecfg.m API to Customize Generated Makefile


s .......................................... 73-26
About the rtwmakecfg Function . . . . . . . . . . . . . . . . . 73-26
Create the rtwmakecfg Function . . . . . . . . . . . . . . . . 73-26
Modify the Template Makefile for rtwmakecfg . . . . . . 73-29

Customize Build Process with STF_make_rtw_hook


File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73-31
STF_make_rtw_hook File . . . . . . . . . . . . . . . . . . . . . . 73-31
Conventions for Using the STF_make_rtw_hook File . . 73-31
STF_make_rtw_hook.m Function Prototype and
Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73-31
Applications for STF_make_rtw_hook.m . . . . . . . . . . . 73-34
Control Code Regeneration Using
STF_make_rtw_hook.m . . . . . . . . . . . . . . . . . . . . . . 73-34
Use STF_make_rtw_hook.m for Your Build
Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73-35

Customize Build Process with sl_customization.m . . . . 73-36


The sl_customization.m File . . . . . . . . . . . . . . . . . . . . 73-36
Register Build Process Hook Functions Using
sl_customization.m . . . . . . . . . . . . . . . . . . . . . . . . . 73-38
Variables Available for sl_customization.m Hook
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73-38
Example of Build Process Customization with
sl_customization.m . . . . . . . . . . . . . . . . . . . . . . . . . 73-39

Replace STF_rtw_info_hook Supplied Target Data . . . . 73-41

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

Sample Custom Targets . . . . . . . . . . . . . . . . . . . . . . . . . . 74-9

Target Development Folders, Files, and Builds . . . . . . . 74-11


Folder and File Naming Conventions . . . . . . . . . . . . . 74-11
Components of a Custom Target . . . . . . . . . . . . . . . . . 74-11
Key Folders Under Target Root (mytarget) . . . . . . . . . 74-16
Key Files in Target Folder (mytarget/mytarget) . . . . . . 74-19
Additional Files for Externally Developed Targets . . . . 74-22
Target Development and the Build Process . . . . . . . . . 74-23

Customize System Target Files . . . . . . . . . . . . . . . . . . . . 74-28


Control Code Generation With the System Target
File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74-28
System Target File Naming and Location
Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74-28
System Target File Structure . . . . . . . . . . . . . . . . . . . 74-29
Define and Display Custom Target Options . . . . . . . . . 74-36
Tips and Techniques for Customizing Your STF . . . . . . 74-45
Create a Custom Target Configuration . . . . . . . . . . . . 74-48

Customize Template Makefiles . . . . . . . . . . . . . . . . . . . . 74-62


Template Makefiles and Tokens . . . . . . . . . . . . . . . . . 74-62
Invoke the make Utility . . . . . . . . . . . . . . . . . . . . . . . 74-70
Structure of the Template Makefile . . . . . . . . . . . . . . . 74-71
Customize and Create Template Makefiles . . . . . . . . . 74-74

Custom Target Optional Features . . . . . . . . . . . . . . . . . 74-80

Support Toolchain Approach with Custom Target . . . . 74-82

Support Model Referencing . . . . . . . . . . . . . . . . . . . . . . 74-84


About Model Referencing with a Custom Target . . . . . 74-84
Declaring Model Referencing Compliance . . . . . . . . . 74-85
Providing Model Referencing Support in the TMF . . . . 74-85

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

Support Compiler Optimization Level Control . . . . . . . 74-96


About Compiler Optimization Level Control and Custom
Targets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74-96
Declaring Compiler Optimization Level Control
Compliance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74-96
Providing Compiler Optimization Level Control Support in
the Target Makefile . . . . . . . . . . . . . . . . . . . . . . . . 74-97

Support C Function Prototype Control . . . . . . . . . . . . . 74-98


About C Function Prototype Control and Custom
Targets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74-98
Declaring C Function Prototype Control Compliance . . 74-98
Providing C Function Prototype Control Support in the
Custom Static Main Program . . . . . . . . . . . . . . . . . 74-99

Support C++ Class Interface Control . . . . . . . . . . . . . 74-100


About C++ Class Interface Control and Custom
Targets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74-100
Declaring C++ Class Interface Control Compliance . 74-100
Providing C++ Class Interface Control Support in the
Custom Static Main Program . . . . . . . . . . . . . . . . 74-101

Support Concurrent Execution of Multiple Tasks . . . . 74-102

Interface to Development Tools . . . . . . . . . . . . . . . . . . 74-104


About Interfacing to Development Tools . . . . . . . . . . 74-104
Template Makefile Approach . . . . . . . . . . . . . . . . . . 74-104
Interface to an Integrated Development
Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74-105

Device Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74-114

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

XMakefiles for Software Build Tool Chains . . . . . . . . . . . 75-8


What is the XMakefile Feature . . . . . . . . . . . . . . . . . . . 75-8
Using Makefiles to Generate and Build Software . . . . 75-10
Making an XMakefile Configuration Operational . . . . . 75-12
Creating a New XMakefile Configuration . . . . . . . . . . 75-13
XMakefile User Configuration dialog . . . . . . . . . . . . . 75-19

Verification and Profiling Generated Code in


Embedded Coder
76
PIL Simulation for IDE and Toolchain Targets . . . . . . . . 76-2
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76-2
PIL Approaches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76-3
Communications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76-7
Running Your PIL Application to Perform Simulation and
Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76-10
Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76-11
PIL Issues and Limitations . . . . . . . . . . . . . . . . . . . . . 76-11

Code Execution Profiling for IDE and


Toolchain Targets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76-13
Execution-Time Profiling . . . . . . . . . . . . . . . . . . . . . . . 76-13
Stack Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76-13

Perform Execution-Time Profiling for IDE and Toolchain


Targets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76-16
Execution-Time Profiling During Standalone
Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76-16

xc Contents
Execution-Time Profiling During PIL Simulation . . . . . 76-19

Perform Stack Profiling with IDE and


Toolchain Targets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76-22

Processor-Specific Optimizations for Embedded


Targets in Embedded Coder
77
Replace Code for Embedded Targets . . . . . . . . . . . . . . . . 77-2
Using a Processor-Specific Code Replacement Library to
Optimize Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77-2
Process of Determining Optimization Effects Using Real-
Time Profiling Capability . . . . . . . . . . . . . . . . . . . . . 77-2

Code Generation from MATLAB Code

Build Configuration for Code Generation from


MATLAB Code
78
Specify Comment Style for C/C++ Code . . . . . . . . . . . . . 78-2
Specify Comment Style Using the MATLAB Coder
App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-2
Specify Comment Style Using the Command-Line
Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-3

Specify Indent Style for C/C++ Code . . . . . . . . . . . . . . . . 78-4


Specify Indent Style Using the MATLAB Coder App . . . 78-5
Specify Indent Style Using the Command-Line
Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-5

Generate Custom File and Function Banners for C/C++


Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-6

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

Customize Generated Identifiers . . . . . . . . . . . . . . . . . . 78-21


Customize Identifiers by Using the MATLAB
Coder App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-21
Customize Generated Identifiers by Using the Command-
Line Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-22

Control Signed Left Shifts in Generated Code . . . . . . . 78-24


Control Signed Left Shifts Using the MATLAB Coder
App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-24
Control Signed Left Shifts Using the Command-Line
Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-25

Control Data Type Casts in Generated Code . . . . . . . . . 78-26


Specify Casting Mode Using the MATLAB Coder App . 78-28
Specify Casting Mode Using the Command-Line
Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-28

Simplify Multiply Operations for Array Indexing in


Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-30

Increase Likelihood of Generating MISRA C Compliant


Code from MATLAB Code . . . . . . . . . . . . . . . . . . . . . . 78-31
Configure Code Generation Configuration Object
Properties to Increase Likelihood of MISRA C Compliant
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78-31
Configure MATLAB Coder App Settings to Increase
Likelihood of MISRA C Compliant Code . . . . . . . . . 78-32

Code Replacement for MATLAB Code


79
What Is Code Replacement? . . . . . . . . . . . . . . . . . . . . . . . 79-2
Code Replacement Libraries . . . . . . . . . . . . . . . . . . . . . 79-2
Code Replacement Terminology . . . . . . . . . . . . . . . . . . 79-4
Code Replacement Limitations . . . . . . . . . . . . . . . . . . . 79-7

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

Replace Code Generated from MATLAB Code . . . . . . . . 79-10

Storage Classes for Code Generation from


MATLAB Code
80
Storage Classes for Code Generation from MATLAB
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80-2

Control Declarations and Definitions of Global Variables


in Code Generated from MATLAB Code . . . . . . . . . . . . 80-5

Verification of Code Generated from MATLAB


Code
81
Highlight Potential Data Type Issues in a Report . . . . . . 81-2
Enable Highlight Option Using the MATLAB Coder
App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81-2
Enable Highlight Option Using the Command Line
Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81-3

Find Potential Data Type Issues in Generated Code . . . . 81-4


Data Type Issues Overview . . . . . . . . . . . . . . . . . . . . . . 81-4
Enable Highlighting of Potential Data Type Issues . . . . 81-5
Find and Address Cumbersome Operations . . . . . . . . . . 81-5
Find and Address Expensive Rounding . . . . . . . . . . . . . 81-6
Find and Address Expensive Comparison Operations . . 81-7
Find and Address Multiword Operations . . . . . . . . . . . . 81-8

xciii
PIL Execution with ARM Cortex-A at the Command
Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81-10

PIL Execution with ARM Cortex-A by Using the MATLAB


Coder App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81-12

Interactively Trace Between MATLAB Code and Generated


C/C++ Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81-14
Create the MATLAB Source Code . . . . . . . . . . . . . . . . 81-14
Prepare for Code Generation . . . . . . . . . . . . . . . . . . . 81-18
Produce a Code Generation Report with Traceability . 81-19
Access Trace Mode in the Report . . . . . . . . . . . . . . . . 81-19
Trace Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81-20
View Multiple Traces . . . . . . . . . . . . . . . . . . . . . . . . . 81-23
View Traces to Different Files . . . . . . . . . . . . . . . . . . . 81-23
Switch the Locations of the Source and Generated
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81-24
Enable Code Tooltips and Links . . . . . . . . . . . . . . . . . 81-24
Disable Traceability . . . . . . . . . . . . . . . . . . . . . . . . . . 81-25

Polyspace Verification of C/C++ Code Generated by


MATLAB Coder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81-26
Run Polyspace Analysis in the MATLAB Coder App . . . 81-26
Run Polyspace Analysis on Code Generated by
codegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81-26
Review Analysis Results . . . . . . . . . . . . . . . . . . . . . . . 81-27

xciv Contents
Model Architecture and Design

95
1

Modeling Environment for


Embedded Coder

• “Design Models for Generated Embedded Code Deployment” on page 1-2


• “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 Modeling Environment for Embedded Coder

Design Models for Generated Embedded Code


Deployment
When using Embedded Coder to generate code for an embedded system architecture, it is
important to design your Simulink models with code generation in mind from the very
beginning of the design process. Think about relevant design factors and issues such as:

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

Application Algorithms and Run-Time Environments


Use Simulink to design models that represent application algorithms and run-time
environments from which you intend to generate deployable code. Depending on your
application, you might deploy code to an execution environment that consists of a
combination of:

Execution Environment Choices


Components
Hardware • Development computer
• Rapid-prototyping board
• Microprocessor
• Microcontroller
• FPGA
• ASIC
Cores • Single
• Multiple
Operating system • General-purpose
• Real-time
• None (bare metal)

1-2
Design Models for Generated Embedded Code Deployment

Execution Environment Choices


Components
Scheduling • Single-tasking
• Multitasking
• Interrupt driven
• Concurrency
• Provided by operating system
• Generated from model
Application algorithm code • Generated from model
• External code

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.

Software Execution Framework for Generated Code


Part of an application execution environment is the software execution framework that is
responsible for scheduling and running the generated code. That software can preexist,
as in the case of an operating system and its scheduler, or you can code the software
manually. The level of complexity varies depending on which of the following modeling
and code generation scenarios applies:

• 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.

Single Top Model

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.

Multiple Top-Level Models

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.

Map Embedded System Architecture to Simulink Modeling


Environment
When mapping an embedded system architecture to the Simulink modeling environment,
think about the model design.

“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 Run- Framework that handles scheduling of system algorithm resources


Time and execution.
Environments” on
page 1-11

Consider the following questions regarding an embedded system architecture with


corresponding modeling capabilities and links to related information. Use the information
as a guide for mapping your architecture details to the Simulink modeling environment.
Designing a model architecture with your specific embedded system architecture in mind
can help you avoid rework and future conversion and maintenance costs.

Modeling Algorithms

Architecture Considerations Modeling Related Information


Considerations
What is the system domain? Product prerequisites • “Blocks and Products Supported
(based on domains of for C Code Generation” (Simulink
components) Coder)
• “Simulink Control Design”
• “Model Signal Processing
Systems” (Simulink)
• “Signal Generation, Manipulation,
and Analysis” (DSP System
Toolbox)
Does the system involve physical Physical systems • “Model Physical Systems”
domains, such as mechanical, (Simulink)
electrical, or hydraulic domains? • “Basic Principles of Modeling
Physical Networks” (Simscape)
• “Essential Physical Modeling
Techniques” (Simscape)
What aspects of your algorithm Block usage, creation, • “Blocks and Products Supported
can you represent with blocks and customization for C Code Generation” (Simulink
provided by MathWorks products? Coder)
What blocks do you need to • “External Code Integration”
create? (Simulink Coder)

1-6
Design Models for Generated Embedded Code Deployment

Architecture Considerations Modeling Related Information


Considerations
Does the architecture include state Event-driven system “Basic Approach for Modeling Event-
machine components? Driven Systems” (Stateflow)
Is there a need to standardize code Custom code definitions • “Define Storage Classes, Memory
that the code generator produces for data and functions Sections, and Function Templates
from multiple models? for Software Architecture” on
page 20-2
• Embedded Coder Dictionary

Modeling Interfaces

Architecture Considerations Modeling Related Information


Considerations
• What data must you represent Data representation • “Interface Design” (Simulink)
in the generated code? • “Data Representation and Access”
• How do you need to represent • “Modeling Patterns for C Code”
input and output—data type,
dimension, complexity? • “Fixed-Point Designer”

• Do the algorithms use floating-


point or fixed-point arithmetic?
• How will the data change?
Where and how is data pulled into Input • “Comparison of Signal Loading
the system and pulled within the Techniques” (Simulink)
system? • “Modeling Patterns for C Code”
• Where and how is data pushed Output • “Simulation Data Inspector in Your
within the system and out of Workflow” (Simulink)
the system? • “Apply Custom Storage Classes to
• What external triggers are Individual Signal, State, and
required? Parameter Data Elements” on
page 26-19
• What functions do you need to Functions and function • “Function and Class Interfaces”
define for each component? calls • “Function Prototyping” on page
• What is the prototype for each 14-61
entry-point function?

1-7
1 Modeling Environment for Embedded Coder

Architecture Considerations Modeling Related Information


Considerations
Can you benefit from setting up Data and function • “Configure Default Code
default code generation configuration Generation for Categories of
configurations for categories of Model Data and Functions” on
data and functions? page 21-7
• Code Mapping Editor
Do you need to export functions Function export • “Export-Function Models”
that are invoked by controlling (Simulink)
logic that is outside the model? • “Generate Component Source
Code for Export to External Code
Base” on page 42-52
Does the system monitor signals or C API and ASAP2 data • “Exchange Data Between
log data (for example, for exchange interfaces Generated and External Code
calibration)? Using C API” (Simulink Coder)
• “Export ASAP2 File for Data
Measurement and Calibration”
(Simulink Coder)
Do you need to replace code Code replacement • “What Is Code Replacement?”
generated for functions or (Simulink Coder)
operators, for example, to optimize • “What Is Code Replacement
the code for specific hardware? Customization?” on page 54-3
Do you need to control the Memory sections • “Control Data and Function
placement of data or functions in Placement in Memory by Inserting
memory? Pragmas” on page 30-2
Is there a requirement for Elaboration and future • “Interface Design” (Simulink)
elaboration and future considerations
considerations?

1-8
Design Models for Generated Embedded Code Deployment

Modeling Systems

Architecture Considerations Modeling Related Information


Considerations
• What is the scope of the Componentization • “Interface Design” (Simulink)
system? Controller? External • “Componentization Guidelines”
environment or plant? Test (Simulink)
harness?
• “Design Partitioning” (Simulink)
• How is the system partitioned
into algorithm components • “Custom Libraries and Linked
(chunks of logic)? Blocks” (Simulink)

• Which components can you • “Export-Function Models”


represent in Simulink? (Simulink)

• Can you design components for • “Custom MATLAB Algorithms”


reuse? What is the motivation (Simulink)
for reuse (for example, division • “Control Generation of Subsystem
of labor or plug-n-play)? Functions” (Simulink Coder)
• “Code Generation of Referenced
Models” (Simulink Coder)
• “Code Generation of Stateflow
Blocks” (Simulink Coder)
• Do aspects of the system Model referencing • “Overview of Model Referencing”
require unit testing? (Simulink)
• Is a team of people • “Componentization Guidelines”
collaborating on the project? (Simulink)
• Do you need to protect • “Code Generation of Referenced
intellectual property? Models” (Simulink Coder)
• “Generate Reusable Code for Unit
Testing” (Simulink Coder)
Are you modeling a client-server Simulink Function and • “Diagnostics Using a Client-Server
architecture? Caller blocks Architecture” (Simulink)
• “Simulink Functions” (Simulink)
Is relevant legacy or custom code External code “External Code Integration” (Simulink
available? integration Coder)

1-9
1 Modeling Environment for Embedded Coder

Architecture Considerations Modeling Related Information


Considerations
Can you apply a reference Model and project • “Create a Template from a Model”
architecture or reference templates (Simulink)
components? • “Create a New Project Using
Templates” (Simulink)
Do you need to export functions Export-function models “Export-Function Models” (Simulink)
that are invoked by controlling
logic that is outside a model?
Is there a need to package the Shared object libraries “Package Generated Code as Shared
source code for a component as a (dynamic link libraries) Libraries” on page 50-2
shared object library to simplify
distribution or sharing?
Can you reuse functions? Function reuse • “Generate Reusable Code from
Library Subsystems Shared Across
Models” (Simulink Coder)
• “Generate Reusable Code from
Library Subsystems Shared Across
Models” (Simulink Coder)
• “Generate Reentrant Code from
Top Models” (Simulink Coder)
• “Generate Reentrant Code from
Subsystems” (Simulink Coder)
• “Generate Reusable Code for
Atomic Subcharts” (Simulink
Coder)

1-10
Design Models for Generated Embedded Code Deployment

Architecture Considerations Modeling Related Information


Considerations
• Do components need to share Shared data • “Local and Global Data Stores”
access to global data? (Simulink)
• Within the system, do state • “Standard Data Structures in the
changes occur? In each case, Generated Code” (Simulink Coder)
how does the result get • “Storage Classes for Signals Used
communicated? with Model Blocks” (Simulink
• Are there identifier (naming) Coder)
issues to consider? • “Code Generation of Constant
Parameters” (Simulink Coder)
• “Data Stores in Generated Code”
(Simulink Coder)
• “Customize Generated Identifier
Naming Rules” on page 39-14
Do you need to control placement Memory sections • “Control Data and Function
of data or functions in memory? Placement in Memory by Inserting
Pragmas” on page 30-2
Are you required to apply the AUTOSAR “AUTOSAR”
AUTOSAR standard? If yes, what
aspects of the architecture involve
AUTOSAR?
Does your system need to meet Standards and “Support for Standards and
other standards or guidelines? guidelines Guidelines” on page 12-2

Modeling Run-Time Environments

Architecture Considerations Modeling Related Information


Considerations
• What level of control over run- Runtime interfacing • “Execution of Code Generated
time interfacing does your from a Model” (Simulink Coder)
application require? • See Modeling Interfaces.
• How much of your system can
you represent in a model?

1-11
1 Modeling Environment for Embedded Coder

Architecture Considerations Modeling Related Information


Considerations
Is the system partitioned into Concurrency “Multicore Processor Targets”
concurrent components to (Simulink)
maximize parallelism? Which
components?
• Are components driven by an Clocks and clock rates “Interface Design” (Simulink)
external clock?
• What clock rates do system
components use?
• Do components use a single
rate or multiple rates?
• Are components in the system Time-based scheduling • “Absolute and Elapsed Time
driven by clocks? Computation” (Simulink Coder)
• What clock rates do system • “Time-Based Scheduling”
components use? (Simulink Coder)
• Do components use a single
rate or multiple rates?
• What are the priorities of
system tasks and functions?
• Are components in the system Event-based scheduling • “Absolute and Elapsed Time
driven by events (interrupts)? Computation” (Simulink Coder)
• What are the priorities of • “Event-Based Scheduling”
system tasks and functions? (Simulink Coder)
• “Basic Approach for Modeling
Event-Driven Systems” (Stateflow)
Does the system need to handle Initialization, reset, • “Customize Initialize, Reset, and
initialization, reset, or terminate termination Terminate Functions” (Simulink)
events? • “Generate Code That Responds to
Initialize, Reset, and Terminate
Events” (Simulink Coder)

1-12
Design Models for Generated Embedded Code Deployment

Architecture Considerations Modeling Related Information


Considerations
• Is the system a single-tasking Task execution • “Execution of Code Generated
or multitasking system? from a Model” (Simulink Coder)
• Are components required to • “Modeling for Single-Tasking
execute in real time? Execution” (Simulink Coder)
• What are the execution order • “Modeling for Multitasking
dependencies (sequencing) Execution” (Simulink Coder)
between components?
• What are the time constraints
for task and function
execution?
• If you know the processing Processing platforms “Multicore Processor Targets”
platform, what is it? (Simulink)
• Will the system run on a single-
core or multicore processor?
• Is the system a distributed
system?
• Is the processing platform
hybrid or heterogeneous?
• Does the architecture employ
symmetric or asymmetric
multiprocessing? If asymmetric,
how is the platform software
partitioned across CPUs?
• Do you want to generate and Kernel, operating • “Deploy Generated Standalone
run a standalone executable system Executable Programs To Target
that does not require an Hardware” on page 52-2
external real-time kernel or • “Deploy Generated Component
operating system? Software to Application Target
• Is a real-time operation system Platforms” on page 52-31
(RTOS) required? If yes, what
RTOS?

1-13
1 Modeling Environment for Embedded Coder

Model Templates for Code Generation


The code generator provides a set of built-in templates to use as a starting point to create
models for common application designs. Use the templates to create models that are
preconfigured to generate code for rapid-prototyping or embedded system applications.

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.

To create a model from a template:

1 On the MATLAB® home tab, click Simulink.


2 In the Simulink start page, expand Embedded Coder.
3 Select a template.
4 Click Create. A new model that uses the template contents and settings appears in
the Simulink Editor window.

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

Model Single-Core, Single-Tasking Platform Execution


This example shows a model designed and configured for embedded system code
generation intended to execute on a single-core, single-tasking platform. The application
algorithm is captured in a single model hierarchy, making it possible to use Simulink®
time-based, single-task scheduling to simulate the model and execute the generated code.

Periodic Multirate Model Set Up for Single-Tasking Execution

Open the example model rtwdemo_multirate_singletasking. The model is


configured to display color-coded sample times with annotations. To see them, after
opening the model, update the diagram by pressing Ctrl+D. To display the legend, press
Ctrl+J.

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

Relevant Model Configuration Parameter Settings

• Solver > Type set to Fixed-step.


• Solver > Solver set to discrete (no continuous states).
• Solver > Treat each discrete rate as a separate task cleared.

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.

Benefits of implicit rate grouping:

• Simulink does not impose architectural constraints on 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 single-tasking execution
semantics.

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 Report

Generate code and a code generation report. The example model generates a report.

Review Generated Code

From the code generation report, review the generated code.

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:

1 Include the generated header file by adding directive #include


rtwdemo_multirate_singletasking.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:

• rtU.In1_1s of data type real_T with dimension of 1


• rtU.In2_2s of data type real_T with dimension of 1

Entry-point functions:

• Initialization entry-point function, void


rtwdemo_multirate_singletasking_initialize(void). At startup, call this
function once.
• Output and update entry-point (step) function, void
rtwdemo_multirate_singletasking_step(void). Call this function periodically
at the fastest rate in the model. For this model, call the function every second. To
achieve real-time execution, attach this function to a timer.

Output ports:

1-19
1 Modeling Environment for Embedded Coder

• rtY.Out1 of data type real_T with dimension of 1


• rtY.Out2 of data type real_T with dimension of 1

More About

• “Modeling for Single-Tasking Execution” (Simulink Coder)


• “Deploy Generated Standalone Executable Programs To Target Hardware” on page 52-
2
• “Customize Code Organization and Format” on page 39-56

1-20
Model Single-Core, Multitasking Platform Execution

Model Single-Core, Multitasking Platform Execution


Use Simulink® time-based, multitask scheduling to simulate and generate code for an
application algorithm captured in a single model hierarchy. The model is designed and
configured for an embedded system intended to execute on a single-core, multitasking
platform. The model simulates and the generated code executes based on the model
configuration and a rate monotonic scheduling algorithm.

Periodic Multirate Model Set Up for Multitasking Execution

Open the example model rtwdemo_multirate_multitasking. The model is configured


to display color-coded sample times with annotations. To see them, after opening the
model, update the diagram by pressing Ctrl+D. To display the legend, press Ctrl+J.

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.

Relevant Model Configuration Parameter Settings

• Solver > Type set to Fixed-step.


• Solver > Solver set to discrete (no continuous states).
• Solver > Treat each discrete rate as a separate task selected.

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.

Benefits of implicit rate grouping:

• 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.

Simulink enforces data transfer constraints to achieve rate monotonic scheduling:

• 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 Report

Generate code and a code generation report. The example model generates a report.

Review Generated Code

From the code generation report, review the generated code.

• ert_main.c is an example main program (execution framework) for the model. This
code controls model code execution by calling the entry-point 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 Include the generated header file by adding directive #include


rtwdemo_multirate_singletasking.h.

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:

• rtU.In1_1s of data type real_T with dimension of 1


• rtU.In2_2s of data type real_T with dimension of 1

Entry-point functions:

• Initialization entry-point function, void


rtwdemo_multirate_multitasking_initialize(void). At startup, call this
function once.
• Output and update entry-point (step) function, void
rtwdemo_multirate_multitasking_step0(void). Call this function periodically
at the fastest rate in the model. For this model, call the function every second. To
achieve real-time execution, attach this function to a timer.
• Output and update entry-point function, void
rtwdemo_multirate_multitasking_step1(void). Call this function periodically
at the second fastest rate in the model. For this model, call the function every two
seconds. To achieve real-time execution, attach this function to a timer.

Output ports:

• rtY.Out1 of data type real_T with dimension of 1


• rtY.Out2 of data type real_T with dimension of 1

More About

• “Modeling for Multitasking Execution” (Simulink Coder)


• “Deploy Generated Standalone Executable Programs To Target Hardware” on page 52-
2
• “Customize Code Organization and Format” on page 39-56

1-25
1 Modeling Environment for Embedded Coder

Model Concurrent Execution for Symmetric Multicore


CPU Platforms
Use Simulink® time-based, multitask scheduling to simulate and generate code for an
application algorithm captured in a single model hierarchy. The model is designed and
configured for an embedded system intended to execute on a symmetric multicore,
multitasking platform.

Periodic Multirate Model Set Up for Multitasking Concurrent Execution

Open the example model rtwdemo_concurrent_execution. The model is configured to


display color-coded sample times with annotations. To see them, after opening the model,
update the diagram by pressing Ctrl+D. To display the legend, press Ctrl+J.

1-26
Model Concurrent Execution for Symmetric Multicore CPU Platforms

Simulink supports simulating concurrent task execution by assigning partitions of a model


to tasks that you designate to run concurrently on multicore hardware. Use an implicit or
explicit approach to designating partitions.

Simulink implicit partitioning:

• Partitions the model based on sample times specified in the model.


• Assigns a task to each sample rate and designates that the tasks run concurrently.
• Controls the granularity of partitions. For example, you cannot split a sample rate into
multiple tasks.

1-27
1 Modeling Environment for Embedded Coder

• Does not impose modeling constraints.


• Provides ready-to-use hardware solutions, such as solutions that the Simulink® Real-
Time™ product produces.
• Is not relevant to standalone production code generation due to the lack of control
over partition granularity.

Explicit partitioning:

• Use Model and Subsystem blocks to partition the model.


• Create an arbitrary number of tasks.
• Simulink assigns each partition to a task.
• Simulink imposes modeling constraints.
• Control the granularity of partitions.
• Split a sample rate into multiple tasks.
• Assign partitions to different processor cores.
• Is for standalone production code generation due to the level of control you have over
granularity of partitions.

This example shows 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.

To support concurrent execution of tasks in a multicore run-time environment, the


preceding model was modified:

• 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.

Relevant Model Configuration Parameter Settings

• Solver > Type set to Fixed-step.


• Solver > Solver set to discrete (no continuous states).
• Solver > Treat each discrete rate as a separate task selected.
• Solver > Automatically handle rate transition for data transfer selected.
Necessary because Rate Transition block was removed.
• Solver > Allow tasks to execute concurrently on target selected.

Concurrent Execution Parameter Settings

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.

Click Tasks and Mapping to review the tasks and mapping.

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.

Benefits of implicit Simulink rate grouping:

• 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.

Simulink enforces data transfer constraints:

• 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 Report

Generate code and a code generation report. The example model generates a report.

Review Generated Code

From the code generation report, review the generated code.

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:

• In1_1s of data type real_T with dimension of 1


• In2_2s of data type real_T with dimension of 1

Entry-point functions:

• Initialization entry-point function, void


rtwdemo_concurrent_execution_initialize(void). At startup, call this
function once.

1-32
Model Concurrent Execution for Symmetric Multicore CPU Platforms

• Output and update entry-point (step) function, void


PeriodicTrigger1_OneSecond_step(void). Call this function periodically for one
of two tasks that require scheduling at the fastest rate in the model. For this model,
call the function every second.
• Output and update entry-point function, void
PeriodicTrigger1_TwoSecond_step(void). Call this function periodically at the
second fastest rate in the model. For this model, call the function every two seconds.
• Output and update entry-point function, void
PeriodicTrigger2_OneSecond_step(void). Call this function periodically for the
second task that requires scheduling at the fastest rate in the model. For this model,
call the function every second.

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:

• Out1_1s of data type real_T with dimension 1


• Out2_1s of data type real_T with dimension 1

More About

• “Multicore Processor Targets” (Simulink)


• “Deploy Generated Standalone Executable Programs To Target Hardware” on page 52-
2
• “Customize Code Organization and Format” on page 39-56

1-33
1 Modeling Environment for Embedded Coder

Model Explicit Function Invocation with Atomic


Subsystems
Deploy embedded system code from Simulink® models by partitioning a model into
multiple atomic subsystems that you build separately.

Atomic Subsystem Model

Open the example model rtwdemo_explicitinvocation_atomicsubsys. The model


is configured to display color-coded sample times with annotations. To see them, after
opening the model, update the diagram by pressing Ctrl+D. To display the legend, press
Ctrl+J.

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.

Relevant Model Configuration Parameter Settings

• Solver > Type set to Fixed-step.


• Solver > Solver set to discrete (no continuous states).

1-35
1 Modeling Environment for Embedded Coder

• Solver > Treat each discrete rate as a separate task cleared.

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.

Based on ratemonotonic scheduling, your application code (execution framework) must


transfer data between subsystems Rate2s and Rate1s at a frequency of 2 seconds with
the priority of 1 second. That is, the generated function transfers data in the 1 second
task every other time prior to executing code for subsystem Rate1s.

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 Code and Report

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.

The example model generates a report.

Review Generated Code

From the code generation report, review the generated code.

• ert_main.c is an example main program (execution framework) for the subsystem.


This code controls model code execution by calling entry-point function Rate1s_step
or Rate2s_step. Use this file as a starting point for coding your execution
framework.
• Rate1s.c and Rate2s.c contain entry points for the code that implements
subsystem Rate1s and Rate2s, respectively. This file includes the rate and task
scheduling code.

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 Include the generated header file by adding directive #include


rtwdemo_explicitinvocation_atomicsusys.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, Rate1s:

• rtU.In1 of type real_T with dimension of 1


• rtU.In2 of type real_T with dimension of 1

Entry-point functions, Rate1s:

• Initialize entry-point function, void Rate1s_initialize(void). At startup, call


this function once.
• Output and update entry-point (step) function, void Rate1s_step(void). Call this
function periodically, every second.
• Termination function, void Rate1s_terminate(void). Call this function once from
your shutdown code.

Output ports, Rate1s:

• rtY.Out1 of type real_T with dimension of 1


• rtY.Out2 of type real_T with dimension of 1

Input ports, Rate2s:

• rtU.In1 of type real_T with dimension of 1

Entry-point functions, Rate2s:

1-37
1 Modeling Environment for Embedded Coder

• Initialize entry-point function, void Rate2s_initialize(void). Call this function


once at startup.
• Output and update entry-point (step), void Rate2s_step(void). Call this function
periodically, every 2 seconds.
• Termination function, void Rate2s_terminate(void). Call this function once from
your shutdown code.

Output ports, Rate2s:

• rtY.Out1 of type real_T with dimension of 1

More About

• “Generate Modular Function Code” on page 29-65


• “Deploy Generated Standalone Executable Programs To Target Hardware” on page 52-
2
• “Customize Code Organization and Format” on page 39-56

1-38
Model Explicit Function Invocation with Function-Call Subsystems

Model Explicit Function Invocation with Function-Call


Subsystems
Deploy embedded system code from Simulink® models by partitioning a model into
function-call subsystems that you build separately.

Function-Call Subsystem Model

Open the example model rtwdemo_explicitinvocation_funccallsubsys. The


model is configured to display color-coded sample times with annotations. To see them,
after opening the model, update the diagram by pressing Ctrl+D. To display the legend,
press Ctrl+J.

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

Relevant Model Configuration Parameter Settings

• Solver > Type set to Fixed-step.


• Solver > Solver set to discrete (no continuous states).
• Solver > Treat each discrete rate as a separate task selected. Simulink applies
multitasking execution because the model uses multiple sample rates.

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 Report

Generate code and a code generation report. The example model generates a report.

Review Generated Code

From the code generation report, review the generated code.

• 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:

1 Include the generated header files by adding directives #include Rate1s.h,


#include DataBuffer.h, and #include Rate2s.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:

• rtU.In1_1s of type real_T with dimension of 1


• rtU.In2_2s of type real_T with dimension of 1

Entry-point functions:

• Initialize entry-point function, void


rtwdemo_explicitinvocation_funccallsubsys_initialize(void). At
startup, call this function once.
• Exported function, void CallEvery1s(void). Call this function as needed.
• Exported function, void CallEvery1s(void). Call this function as needed.
• Exported function, void CallEvery2sAt1sPriority(void). Call this function as
needed.

Output ports:

• rtY.Out1 of type real_T with dimension of 1


• rtY.Out2 of type real_T with dimension of 1

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

• “Customize Code Organization and Format” on page 39-56

1-43
1 Modeling Environment for Embedded Coder

Modeling Patterns for AUTOSAR Runnables


Use Simulink® models, subsystems, and functions to model AUTOSAR atomic software
components and their runnable entities (runnables).

Prerequisites

The Embedded Coder Support Package for AUTOSAR Standard is required for generating
C code and arxml descriptions for AUTOSAR software components.

• Install the AUTOSAR Standard Support Package


• “Support Package Installation” (MATLAB)

Multiple Periodic Runnables Configured for Multitasking

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

Relevant Model Configuration Parameter Settings

• Solver > Type set to Fixed-step.


• Solver > Solver set to discrete (no continuous states).
• Solver > Fixed-step size (fundamental sample time) set to auto.
• Solver > Treat each discrete rate as a separate task selected.

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 Report

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.

Review Generated Code

In the code generation report, review the generated code.

• 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

• Compiler.h, Platform_Types.h, Rte_ASWC.h, Rte_Type.h, and Std_Types.h


contain stub implementations of AUTOSAR RTE functions. Use these files to test the
generated code in Simulink, for example, in software-in-the-loop (SIL) or processor-in-
the-loop (PIL) simulations of the component under test.

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:

• Require port, interface: sender-receiver of type real-T of 1 dimension


• Require port, interface: sender-receiver of type real-T of 1 dimension

Entry-point functions:

• Initialization entry-point function, void Runnable_Initialize(void). At startup,


call this function once.
• Output and update entry-point function, void Runnable_1s(void). Call this
function periodically at the fastest rate in the model. For this model, call the function
every second. To achieve real-time execution, attach this function to a timer.
• Output and update entry-point function, void Runnable_2s(void). Call this
function periodically at the second fastest rate in the model. For this model, call the
function every 2 seconds. To achieve real-time execution, attach this function to a
timer.

Output ports:

• Provide port, interface: sender-receiver of type real-T of 1 dimension


• Provide port, interface: sender-receiver of type real-T of 1 dimension

Multiple Runnables Configured as Periodic-Rate Runnable and Asynchronous


Function-Call Runnable

Open the example model rtwdemo_autosar_swc_fcncalls. The model shows the


implementation of an AUTOSAR atomic software component (ASWC). The model uses an
asynchronous function-call runnable, Runnable_Trigger, which is triggered by an
external event. The model also includes a periodic rate-based runnable, Runnable_1s.
The Rate Transition blocks represent inter-runnable variables (IRVs).

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.

Relevant Model Configuration Parameter Settings

1-48
Modeling Patterns for AUTOSAR Runnables

• Solver > Type set to Fixed-step.


• Solver > Solver set to discrete (no continuous states).
• Solver > Fixed-step size (fundamental sample time) set to 1.
• Solver > Treat each discrete rate as a separate task cleared.

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 Report

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.

Review Generated Code

In the code generation report, review the generated code.

• rtwdemo_autosar_swc_fcncalls.c contains entry points for the code that


implements the model algorithm. This file includes the rate scheduling code.
• rtwdemo_autosar_swc_fcncalls.h declares model data structures and a public
interface to the model entry points and data structures.

1-49
1 Modeling Environment for Embedded Coder

• rtwdemo_autosar_swc_fcncalls_private.h contains local define constants


and local data required by the model and subsystems.
• rtwdemo_autosar_swc_fcncalls_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_fcncalls_component.arxml,
rtwdemo_autosar_swc_fcncalls_datatype.arxml,
rtwdemo_autosar_swc_fcncalls_implementation.arxml, and
rtwdemo_autosar_swc_fcncalls_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.
• Compiler.h, Platform_Types.h, Rte_ASWC.h, Rte_Type.h, and Std_Types.h
contain stub implementations of AUTOSAR RTE functions. Use these files to test the
generated code in Simulink, for example, in software-in-the-loop (SIL) or processor-in-
the-loop (PIL) simulations of the component under test.

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:

• Require port, interface: sender-receiver of type real-T of 1 dimension

Entry-point functions:

• Initialization entry-point function, void Runnable_Initialize(void). At startup,


call this function once.
• Simulink function, void Runnable_1s(void). Call this function periodically at the
fastest rate in the model. For this model, call the function every second. To achieve
real-time execution, attach this function to a timer.
• Exported function, void Runnable_Trigger(void). Call this function at any time
from an external trigger.

Output port:

1-50
Modeling Patterns for AUTOSAR Runnables

• Provide port, interface: sender-receiver of type real-T of 1 dimension

Multiple Runnables Configured As Function-Call Subsystem and Simulink


Function

Open the example model rtwdemo_autosar_swc_slfcns. The model shows the


implementation of an AUTOSAR atomic software component (ASWC). The model includes
one periodic rate runnable, Runnable_1s, that uses a function-call subsystem, SS1. The
model also includes a Simulink function, readData, to provide a value (CurVal) to
clients that request it.

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

Use function-call subsystems:

• When it is difficult or not possible to specify system events in a Simulink model.


• To achieve complex multirate scheduling of runnables. Model each rate as a separate
function-call subsystem.

1-52
Modeling Patterns for AUTOSAR Runnables

Relevant Model Configuration Parameter Settings

• Solver > Type set to Fixed-step.


• Solver > Solver set to discrete (no continuous states).
• Solver > Fixed-step size (fundamental sample time) set to 1.
• Solver > Treat each discrete rate as a separate task selected.

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 Report

Generate code and a code generation report. The example model generates a report.

The code generator:

• 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).

Review Generated Code

In the code generation report, review the generated code.

• rtwdemo_autosar_swc_slfcns.c contains entry points for the code that


implements the model algorithm. This file includes the rate scheduling code.
• rtwdemo_autosar_swc_slfcns.h declares model data structures and a public
interface to the model entry points and data structures.
• rtwdemo_autosar_swc_slfcns_private.h contains local define constants and
local data required by the model and subsystems.

1-53
1 Modeling Environment for Embedded Coder

• rtwdemo_autosar_swc_slfcns_types.h provides forward declarations for the


real-time model data structure and the parameters data structure.
• readData.c contains code for the Simulink function.
• readData_private.h contains local define constants and local data required by
the function.
• readData.h declares data structures and a public interface for calling the function.
• rtwtypes.h defines data types, structures, and macros that the generated code
requires.
• rtwdemo_autosar_swc_slfcns_component.arxml,
rtwdemo_autosar_swc_slfcns_datatype.arxml,
rtwdemo_autosar_swc_slfcns_implementation.arxml, and
rtwdemo_autosar_swc_slfcns_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.
• Compiler.h, Platform_Types.h, Rte_ASWC.h, Rte_Type.h, and Std_Types.h
contain stub implementations of AUTOSAR RTE functions. Use these files to test the
generated code in Simulink, for example, in software-in-the-loop (SIL) or processor-in-
the-loop (PIL) simulations of the component under test.

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:

• Require port, interface: sender-receiver of type uint16-T of 1 dimension


• Require port, interface: sender-receiver of type real-T of 1 dimension Entry-point
functions:

Entry-point functions:

• Initialization entry-point function, void Runnable_Init(void). At startup, call this


function once.
• Exported function, void Runnable_1s(void). Call this function periodically, every
second.

1-54
Modeling Patterns for AUTOSAR Runnables

• Simulink function, Std_ReturnType readData(real_T Data[2]). Call this


function at any time.

Output ports:

• Provide port, interface: sender-receiver of type uint16-T of 1 dimension

Related Links

• “Model AUTOSAR Software Components”


• “AUTOSAR Component Creation”
• “AUTOSAR Code Generation”

1-55
2

Modeling in Simulink Coder

• “Configure a Model for Code Generation” on page 2-2


• “Blocks and Products Supported for C Code Generation” on page 2-4
• “Modeling Semantic Considerations” on page 2-31
• “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
• “Modeling Guidelines for Model Configuration” on page 2-46
2 Modeling in Simulink Coder

Configure a Model for Code Generation


Model configuration parameters determine the method for generating the code and the
resulting format.

1 Open rtwdemo_throttlecntrl and save a copy as throttlecntrl in a writable


location on your MATLAB path.

Note This model uses Stateflow® software.


2 Open the Configuration Parameters dialog box Solver pane. To generate code for a
model, you must configure the model to use a fixed-step solver. For this example, set
the parameters as noted in the following table.

Parameter Setting Effect on Generated


Code
Type Fixed-step Maintains a constant
(fixed) step size, which is
required for code
generation
Solver discrete (no Applies a fixed-step
continuous states) integration technique for
computing the state
derivative of the model
Fixed-step size .001 Sets the base rate; must
be the lowest common
multiple of all rates in the
system

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

Blocks and Products Supported for C Code Generation

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.

Product Extends Code Generation Capabilities for ...


Aerospace Blockset™ Aircraft, spacecraft, rocket, propulsion systems,
and unmanned airborne vehicles
Audio System Toolbox™ Audio processing systems
Automated Driving System Toolbox™ Designing, simulating, and testing ADAS and
autonomous driving systems
Communications System Toolbox™ Physical layer of communication systems
Computer Vision System Toolbox™ Video processing, image processing, and
computer vision systems
Control System Toolbox™ Linear control systems
DSP System Toolbox™ Signal processing systems
Embedded Coder Embedded systems, rapid prototyping boards,
and microprocessors in mass production
Fixed-Point Designer™ Fixed-point systems
Fuzzy Logic Toolbox™ System designs based on fuzzy logic

2-4
Blocks and Products Supported for C Code Generation

Product Extends Code Generation Capabilities for ...


HDL Verifier™ Direct programming interface (DPI) component
and transaction-level model (TLM) generation
from Simulink
IEC Certification Kit ISO 26262 and IEC 61508 certification
Model-Based Calibration Toolbox™ Developing processes for systematically
identifying optimal balance of engine
performance, emissions, and fuel economy, and
reusing statistical models for control design,
hardware-in-the-loop (HIL) testing, or powertrain
simulation
Model Predictive Control Toolbox™ Controllers that optimize performance of multi-
input and multi-output systems that are subject
to input and output constraints
Neural Network Toolbox™ Neural networks
Parallel Computing Toolbox™ Parallel builds for large Simulink models
Phased Array System Toolbox™ Sensor array systems in radar, sonar, wireless
communications, and medical imaging
applications
Polyspace® Bug Finder™ MISRA-C compliance and static analysis of
generated code
Polyspace Code Prover™ Formal analysis of generated code
Powertrain Blockset™ Real-time testing of powertrain applications
Robotics System Toolbox™ Robot Operating System (ROS) node generation
Simscape™ Systems spanning mechanical, electrical,
hydraulic, and other physical domains as
physical networks
Simscape Driveline™ Driveline (drivetrain) systems
Simscape Electronics™ Electronic and electromechanical systems
Simscape Fluids™ Hydraulic power and control systems
Simscape Multibody™ Three-dimensional mechanical systems
Simscape Power Systems™ Systems that generate, transmit, distribute, and
consume electrical power

2-5
2 Modeling in Simulink Coder

Product Extends Code Generation Capabilities for ...


Simulink 3D Animation™ Systems with 3D visualizations
Simulink Check™ Model standards compliance checking and
metrics
Simulink Code Inspector™ Automated reviews of generated code
Simulink Control Design™ Autotuning of PID controllers
Simulink Coverage™ Model and code structural coverage analysis
Simulink Design Optimization™ Systems requiring maximum overall system
performance
Simulink Desktop Real-Time™ Rapid prototyping or hardware-in-the-loop (HIL)
simulation of control system and signal
processing algorithms
Simulink Real-Time™ Rapid control prototyping, hardware-in-the-loop
(HIL) simulation, and other real-time testing
applications
Simulink Report Generator™ Automatically generating project documentation
in a standard format
Simulink Requirements™ Authoring and tracing requirements to design
and code
Simulink Test™ Software-in-the-loop (SIL), processor-in-the-loop
(PIL), and real-time hardware-in-the-loop (HIL)
testing of generated code
Stateflow State machines and flow charts
System Identification Toolbox™ Systems constructed from measured input-
output data
Vehicle Dynamics Blockset™ Modeling and simulation of vehicle dynamics in
3D environment
Vehicle Network Toolbox™ CAN blocks for Accelerator and Rapid
Accelerator simulations and code deployment on
Windows®

2-6
Blocks and Products Supported for C Code Generation

Simulink Built-In Blocks That Support Code Generation


The following tables summarize code generator support for Simulink blocks. There is a
table for each block library. For more detail, including data types each block supports, in
the MATLAB Command Window, type showblockdatatypetable, or consult the block
reference pages. For some blocks, the generated code might rely on memcpy or memset
(string.h).

• Additional Math and Discrete: Additional Discrete


• Additional Math and Discrete: Increment/Decrement
• Continuous
• Discontinuities
• Discrete
• Logic and Bit Operations
• Lookup Tables
• Math Operations
• Model Verification
• Model-Wide Utilities
• Ports & Subsystems
• Signal Attributes
• Signal Routing
• Sinks
• Sources
• User-Defined

2-7
2 Modeling in Simulink Coder

Additional Math and Discrete: Additional Discrete

Block Support Notes


Fixed-Point State-Space The code generator does not explicitly group
Transfer Fcn Direct Form II primitive blocks that constitute a nonatomic
masked subsystem block in the generated code.
Transfer Fcn Direct Form II Time Varying This flexibility allows for more efficient code
generation. In certain cases, you can achieve
grouping by configuring the masked subsystem
block to execute as an atomic unit by selecting the
Treat as atomic unit option.

Additional Math and Discrete: Increment/Decrement

Block Support Notes


Decrement Real World The code generator does not explicitly group primitive blocks that
Decrement Stored Integer constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the masked
subsystem block to execute as an atomic unit by selecting the Treat
as atomic unit option.
Decrement Time To Zero Supports code generation.
Decrement To Zero The code generator does not explicitly group primitive blocks that
Increment Real World constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
Increment Stored Integer certain cases, you can achieve grouping by configuring the masked
subsystem block to execute as an atomic unit by selecting the Treat
as atomic unit option.

2-8
Blocks and Products Supported for C Code Generation

Continuous

Block Support Notes


Derivative Not recommended for production-quality code. Relates to resource
Integrator limits and restrictions on speed and memory often found in
embedded systems. The code generated can contain dynamic
Integrator, Integrator allocation and freeing of memory, recursion, additional memory
Limited overhead, and widely-varying execution times. While the code is
PID Controller functionally valid and generally acceptable in resource-rich
environments, smaller embedded targets often cannot support such
PID Controller (2DOF)
code.
Second-Order Integrator,
Second-Order Integrator In general, consider using the Simulink Model Discretizer to map
Limited continuous blocks into discrete equivalents that support production
State-Space code generation. To start the Model Discretizer, select Analysis >
Control Design > Model Discretizer. One exception is the Second-
Transfer Fcn Order Integrator block because, for this block, the Model Discretizer
Transport Delay produces an approximate discretization.
Variable Time Delay, Variable
Transport Delay
Zero-Pole

2-9
2 Modeling in Simulink Coder

Discontinuities

Block Support Notes


Backlash Supports code generation.
Coulomb and Viscous The code generator does not explicitly group primitive blocks that
Friction constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the masked
subsystem block to execute as an atomic unit by selecting the Treat
as atomic unit option.
Dead Zone Supports code generation.
Dead Zone Dynamic The code generator does not explicitly group primitive blocks that
constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the masked
subsystem block to execute as an atomic unit by selecting the Treat
as atomic unit option.
Hit Crossing Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
Quantizer Supports code generation.
Rate Limiter Cannot use inside a triggered subsystem hierarchy.
Rate Limiter Dynamic The code generator does not explicitly group primitive blocks that
constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the masked
subsystem block to execute as an atomic unit by selecting the Treat
as atomic unit option.
Relay Support code generation.
Saturation

2-10
Blocks and Products Supported for C Code Generation

Block Support Notes


Saturation Dynamic The code generator does not explicitly group primitive blocks that
Wrap To Zero constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the masked
subsystem block to execute as an atomic unit by selecting the Treat
as atomic unit option.

2-11
2 Modeling in Simulink Coder

Discrete

Block Support Notes


Delay Supports code generation.
Difference • The code generator does not explicitly group primitive blocks that
constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the
masked subsystem block to execute as an atomic unit by selecting
the Treat as atomic unit option.
• Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and
freeing of memory, recursion, additional memory overhead, and
widely-varying execution times. While the code is functionally
valid and generally acceptable in resource-rich environments,
smaller embedded targets often cannot support such code.
Usually, blocks evolve toward being suitable for production code.
Thus, blocks suitable for production code remain suitable.
Discrete Derivative • Depends on absolute time when used inside a triggered
subsystem hierarchy.
• Supports code generation.
Discrete Filter Support code generation.
Discrete FIR Filter
PID Controller • Depends on absolute time when used inside a triggered
PID Controller (2DOF) subsystem hierarchy.
• Support code generation.
Discrete State-Space Support code generation.
Discrete Transfer Fcn
Discrete Zero-Pole
Discrete-Time Integrator Depends on absolute time when used inside a triggered subsystem
hierarchy.
Enabled Delay Supports code generation.

2-12
Blocks and Products Supported for C Code Generation

Block Support Notes


First-Order Hold Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
Memory Support code generation.
Resettable Delay
Tapped Delay
Transfer Fcn First Order The code generator does not explicitly group primitive blocks that
Transfer Fcn Lead or Lag constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
Transfer Fcn Real Zero certain cases, you can achieve grouping by configuring the masked
subsystem block to execute as an atomic unit by selecting the Treat
as atomic unit option.
Unit Delay Support code generation.
Variable Integer Delay
Zero-Order Hold

2-13
2 Modeling in Simulink Coder

Logic and Bit Operations

Block Support Notes


Bit Clear Support code generation.
Bit Set
Bitwise Operator
Combinatorial Logic
Compare to Constant
Compare to Zero
Detect Change
Detect Decrease
Detect Fall Negative
Detect Fall Nonpositive
Detect Increase
Detect Rise Nonnegative
Detect Rise Positive
Extract Bits
Interval Test
Interval Test Dynamic
Logical Operator
Relational Operator
Shift Arithmetic

2-14
Blocks and Products Supported for C Code Generation

Lookup Tables

Block Support Notes


Cosine The code generator does not explicitly group primitive blocks that
constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the masked
subsystem block to execute as an atomic unit by selecting the Treat
as atomic unit check box.
Direct Lookup Table (n-D) Support code generation.
Interpolation Using
Prelookup
1-D Lookup Table
2-D Lookup Table
n-D Lookup Table
Lookup Table Dynamic
Prelookup
Sine The code generator does not explicitly group primitive blocks that
constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the masked
subsystem block to execute as an atomic unit by selecting the Treat
as atomic unit option.

2-15
2 Modeling in Simulink Coder

Math Operations

Block Support Notes


Abs Support code generation.
Add
Algebraic Constraint Ignored during code generation.
Assignment Support code generation.
Bias
Complex to Magnitude-Angle
Complex to Real-Imag
Divide
Dot Product
Find Nonzero Elements
Gain
Magnitude-Angle to Complex
Math Function (10^u)
Math Function (conj)
Math Function (exp)
Math Function (hermitian)
Math Function (hypot)
Math Function (log)
Math Function (log10)
Math Function
(magnitude^2)
Math Function (mod)
Math Function (pow)
Math Function (reciprocal)
Math Function (rem)
Math Function (square)
Math Function (transpose)

2-16
Blocks and Products Supported for C Code Generation

Block Support Notes


Vector Concatenate, Matrix
Concatenate
MinMax
MinMax Running Resettable
Permute Dimensions
Polynomial
Product
Product of Elements
Real-Imag to Complex
Sqrt, Signed Sqrt,
Reciprocal Sqrt
Reshape
Rounding Function
Sign
Sqrt, Signed Sqrt,
Reciprocal Sqrt
Sine Wave Function • Does not refer to absolute time when configured for sample-based
operation. Depends on absolute time when in time-based
operation.
• Depends on absolute time when used inside a triggered
subsystem hierarchy.
Slider Gain Support code generation.
Sqrt
Squeeze
Subtract
Sum
Sum of Elements

2-17
2 Modeling in Simulink Coder

Block Support Notes


Trigonometric Function Functions asinh, acosh, and atanh are not supported by all
compilers. If you use a compiler that does not support those
functions, the software issues a warning for the block and the
generated code fails to link.
Unary Minus Support code generation.
Vector Concatenate, Matrix
Concatenate
Weighted Sample Time Math

2-18
Blocks and Products Supported for C Code Generation

Model Verification

Block Support Notes


Assertion Supports code generation.
Check Discrete Gradient Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
Check Dynamic Gap Support code generation.
Check Dynamic Lower
Bound
Check Dynamic Range
Check Dynamic Upper
Bound
Check Input Resolution Not recommended for production code. Relates to resource limits
Check Static Gap and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
Check Static Lower Bound of memory, recursion, additional memory overhead, and widely-
Check Static Range varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
Check Static Upper Bound
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.

2-19
2 Modeling in Simulink Coder

Model-Wide Utilities

Block Support Notes


Block Support Table Ignored during code generation.
DocBlock Uses the template symbol you specify for the Embedded Coder
Flag block parameter to add comments to generated code. Requires
an Embedded Coder license. For more information, see “Use a
Simulink DocBlock to Add a Comment” on page 39-8.
Model Info Ignored during code generation.
Timed-Based Linearization
Trigger-Based Linearization

2-20
Blocks and Products Supported for C Code Generation

Ports & Subsystems

Block Support Notes


Subsystem, Atomic Support code generation.
Subsystem, Nonvirtual
Subsystem, CodeReuse
Subsystem
Configurable Subsystem
Enable
Enabled Subsystem
Enabled and Triggered
Subsystem
For Each Subsystem
For Iterator Subsystem
Function-Call Feedback
Latch
Function-Call Generator
Function-Call Split
Function-Call Subsystem
If
If Action Subsystem
Inport (In1)
Model
Model Variants
Outport (Out1)
Resettable Subsystem
Subsystem
Switch Case
Switch Case Action
Subsystem
Trigger

2-21
2 Modeling in Simulink Coder

Block Support Notes


Triggered Subsystem
Unit System Configuration
Variant Subsystem
While Iterator Subsystem

Signal Attributes

Block Support Notes


Bus to Vector Support code generation.
Data Type Conversion
Data Type Conversion
Inherited
Data Type Duplicate
Data Type Propagation
Data Type Scaling Strip
IC Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
Probe Supports code generation.
Rate Transition • Supports code generation.
• Cannot use inside a triggered subsystem hierarchy.
Signal Conversion Support code generation.
Signal Specification
Unit Conversion
Weighted Sample Time
Width

2-22
Blocks and Products Supported for C Code Generation

Signal Routing

Block Support Notes


Bus Assignment Support code generation.
Bus Creator
Bus Selector
Data Store Memory
Data Store Read
Data Store Write
Demux
Environment Controller Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
From Support code generation.
Goto
Goto Tag Visibility
Index Vector
Manual Switch Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
Manual Variant Sink Support code generation.
Manual Variant Source

2-23
2 Modeling in Simulink Coder

Block Support Notes


Merge When multiple signals connected to a Merge block have 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 all signals
connected to Merge blocks in the group.
Multiport Switch Support code generation.
Mux
Selector
State Reader
State Writer
Switch
Variant Sink
Variant Source
Vector Concatenate

2-24
Blocks and Products Supported for C Code Generation

Sinks

Block Support Notes


Display Ignored for code generation.
Floating Scope and Scope
Viewer
Outport (Out1) Supports code generation.
Scope Ignored for code generation.
Stop Simulation • Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and
freeing of memory, recursion, additional memory overhead, and
widely-varying execution times. While the code is functionally
valid and generally acceptable in resource-rich environments,
smaller embedded targets often cannot support such code.
Usually, blocks evolve toward being suitable for production code.
Thus, blocks suitable for production code remain suitable.
• Generated code stops executing when the stop condition is true.
Terminator Supports code generation.
To File Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
To Workspace Ignored for code generation.
XY Graph

2-25
2 Modeling in Simulink Coder

Sources

Block Support Notes


Band-Limited White Noise Cannot use inside a triggered subsystem hierarchy.
Chirp Signal Not recommended for production code. Relates to resource limits
Clock and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
Constant Supports code generation.
Counter Free-Running Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
Counter Limited • The code generator does not explicitly group primitive blocks that
constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the
masked subsystem block to execute as an atomic unit by selecting
the Treat as atomic unit option.
• Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and
freeing of memory, recursion, additional memory overhead, and
widely-varying execution times. While the code is functionally
valid and generally acceptable in resource-rich environments,
smaller embedded targets often cannot support such code.
Usually, blocks evolve toward being suitable for production code.
Thus, blocks suitable for production code remain suitable.

2-26
Blocks and Products Supported for C Code Generation

Block Support Notes


Digital Clock Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
Enumerated Constant Supports code generation.
From File Not recommended for production code. Relates to resource limits
From Spreadsheet and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
From Workspace Ignored for code generation.
Ground Support code generation.
Inport (In1)
Pulse Generator Cannot use inside a triggered subsystem hierarchy. Does not refer to
absolute time when configured for sample-based operation. Depends
on absolute time when in time-based operation.
Ramp Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
Random Number Supports code generation.

2-27
2 Modeling in Simulink Coder

Block Support Notes


Repeating Sequence • Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and
freeing of memory, recursion, additional memory overhead, and
widely-varying execution times. While the code is functionally
valid and generally acceptable in resource-rich environments,
smaller embedded targets often cannot support such code.
Usually, blocks evolve toward being suitable for production code.
Thus, blocks suitable for production code remain suitable.
• Consider using the Repeating Sequence Stair or Repeating
Sequence Interpolated block instead.
Repeating Sequence • The code generator does not explicitly group primitive blocks that
Interpolated constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the
masked subsystem block to execute as an atomic unit by selecting
the Treat as atomic unit option.
• Cannot use inside a triggered subsystem hierarchy.
Repeating Sequence Stair The code generator does not explicitly group primitive blocks that
constitute a nonatomic masked subsystem block in the generated
code. This flexibility allows for more efficient code generation. In
certain cases, you can achieve grouping by configuring the masked
subsystem block to execute as an atomic unit by selecting the Treat
as atomic unit option.
Signal Builder Not recommended for production code. Relates to resource limits
Signal Generator and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.

2-28
Blocks and Products Supported for C Code Generation

Block Support Notes


Sine Wave • Depends on absolute time when used inside a triggered
subsystem hierarchy.
• Does not refer to absolute time when configured for sample-based
operation. Depends on absolute time when in time-based
operation.
Step Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.
Uniform Random Number Supports code generation.
Waveform Generator Not recommended for production code. Relates to resource limits
and restrictions on speed and memory often found in embedded
systems. Generated code can contain dynamic allocation and freeing
of memory, recursion, additional memory overhead, and widely-
varying execution times. While the code is functionally valid and
generally acceptable in resource-rich environments, smaller
embedded targets often cannot support such code. Usually, blocks
evolve toward being suitable for production code. Thus, blocks
suitable for production code remain suitable.

2-29
2 Modeling in Simulink Coder

User-Defined

Block Support Notes


Fcn Support code generation.
Function Caller
Initialize Function
Interpreted MATLAB Consider using the MATLAB Function block instead.
Function
Level-2 MATLAB S-Function If a corresponding TLC file is available, the Level-2 MATLAB S-
Function block uses the TLC file to generate code, otherwise code
generation throws an error.
MATLAB Function Support code generation.
MATLAB System
S-Function S-functions that call into MATLAB are not supported for code
S-Function Builder generation.

Simulink Function Support code generation.


Terminate Function

Simulink Block Data Type Support Table


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, in the MATLAB
Command Window, type showblockdatatypetable, or consult the block reference
pages.

Block Set Support for Code Generation


Several products that include blocks are available for you to consider for code generation.
However, before using the blocks for one of these products, consult the documentation for
that product to confirm which blocks support code generation.

2-30
Modeling Semantic Considerations

Modeling Semantic Considerations


In this section...
“Data Propagation” on page 2-31
“Sample Time Propagation” on page 2-33
“Latches for Subsystem Blocks” on page 2-34
“Block Execution Order” on page 2-35
“Algebraic Loops” on page 2-36

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.

Sample Time Propagation


Inherited sample times in source blocks (for example, a root inport) can sometimes lead
to unexpected and unintended sample time assignments. Since a block may specify an
inherited sample time, information available at the outset is often insufficient to compile a
block diagram completely.

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.

Blocks Whose Outputs Have Constant Values

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:

• You set Default parameter behavior to Tunable. By default, numeric block


parameters appear as tunable fields of a global parameter structure.
• You use a tunable parameter, such as a Simulink.Parameter object that uses a
storage class other than Auto, as the value of one or more numeric block parameters.
These block parameters are tunable regardless of the setting that you choose for
Default parameter behavior.

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.

Latches for Subsystem Blocks


When an Inport block is the signal source for a triggered or function-call subsystem, you
can use latch options to preserve input values while the subsystem executes. The Inport
block latch options include:

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

• Preserves latches in generated code regardless of optimizations that might be set


• Places the code for latches at the start of a subsystem's output/update function

For more information on these options, see the block description of Inport.

2-34
Modeling Semantic Considerations

Block Execution Order


Once the Simulink engine compiles the block diagram, it creates a model.rtw file
(analogous to an object file generated from a C or C++ file). The model.rtw file contains
the connection information of the model, as well as the signal attributes. Thus, the timing
engine in can determine when blocks with different rates should be executed.

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

“Asynchronous Events” (Simulink Coder). For more information on multirate code


generation, see “Modeling for Multitasking Execution” (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

the values of x and y cannot be directly computed.

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).

Algebraic Loops in Triggered Subsystems

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.

A similar Minimize algebraic loop occurrences option appears on the Model


Referencing pane of the Configuration Parameters dialog box. Selecting it enables the
Simulink Coder software to generate code for models containing Model blocks that are
involved in algebraic loops.

2-38
Modeling Guidelines for Blocks

Modeling Guidelines for Blocks


Code generation modeling guidelines include recommended model settings, block usage,
and block parameters. When you develop models for code generation, use these
guidelines.

For more information, see “Modeling Guidelines” (Simulink).

Code Generation “cgsl_0101: Zero-based indexing” (Simulink)


Modeling
Guidelines “cgsl_0102: Evenly spaced breakpoints in lookup tables” (Simulink)

“cgsl_0103: Precalculated signals and parameters” (Simulink)

“cgsl_0104: Modeling global shared memory using data stores”


(Simulink)

“cgsl_0105: Modeling local shared memory using data stores”


(Simulink)

“cgsl_0201: Redundant Unit Delay and Memory blocks” (Simulink)

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

Modeling Guidelines for Subsystems


When you develop models and generate code for subsystems, use the modeling guideline
recommendations.

For more information, see “Modeling Guidelines” (Simulink).

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)

“hisl_0011: Usage of Switch Case blocks and Action Subsystem blocks”


(Simulink)

“hisl_0023: Verification of model and subsystem variants” (Simulink)

2-40
Modeling Guidelines for Subsystems

MathWorks db_0040: Model hierarchy


Automotive
Advisory Board db_0042: Port block in Simulink models
(MAAB) Control
Algorithm db_0081: Unconnected signals, block inputs and block outputs
Guidelines
db_0143: Similar block types on the model levels

db_0144: Use of Subsystems

db_0146: Triggered, enabled, conditional Subsystems

jc_0111: Direction of Subsystem

jc_0201: Usable characters for Subsystem names

jc_0231: Usable characters for block names

jc_0281: Naming of Trigger Port block and Enable Port block

jc_0321: Trigger layer

jc_0331: Structure layer

jc_0351: Methods of initialization

jm_0002: Block resizing

na_0005: Port block name visibility in Simulink models

na_0006: Guidelines for mixed use of Simulink and Stateflow

na_0008: Display of labels on signals

na_0009: Entry versus propagation of signal labels

na_0012: Use of Switch vs. If-Then-Else Action Subsystem

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

Modeling Guidelines for Charts


When you develop models and generate code for charts, use the modeling guideline
recommendations.

For more information, see “Modeling Guidelines” (Simulink).

High-Integrity “hisf_0001: Mealy and Moore semantics” (Simulink)


Systems
Modeling “hisf_0002: User-specified state/transition execution order” (Simulink)
Guidelines
“hisf_0009: Strong data typing (Simulink and Stateflow boundary)”
(Simulink)

“hisf_0011: Stateflow debugging settings” (Simulink)

“hisf_0003: Usage of bitwise operations” (Simulink)

“hisf_0004: Usage of recursive behavior” (Simulink)

“hisf_0007: Usage of junction conditions (maintaining mutual


exclusion)” (Simulink)

“hisf_0013: Usage of transition paths (crossing parallel state


boundaries)” (Simulink)

“hisf_0014: Usage of transition paths (passing through states)”


(Simulink)

“hisf_0015: Strong data typing (casting variables and parameters in


expressions)” (Simulink)

2-43
2 Modeling in Simulink Coder

MathWorks db_0127: MATLAB commands in Stateflow


Automotive
Advisory Board db_0151: State machine patterns for transition actions
(MAAB) Control
Algorithm jc_0451: Use of unary minus on unsigned integers in Stateflow
Guidelines
jc_0481: Use of hard equality comparisons for floating point numbers in
Stateflow

jc_0501: Format of entries in a State block

jc_0511: Setting the return value from a graphical function

jc_0521: Use of the return value from graphical functions

jc_0531: Placement of the default transition

jc_0541: Use of tunable parameters in Stateflow

jm_0011: Pointers in Stateflow

na_0001: Bitwise Stateflow operators

na_0013: Comparison operation in Stateflow

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

Modeling Guidelines for MATLAB Functions


When you develop models and generate code for MATLAB Functions, use the modeling
guideline recommendations.

For more information, see “Modeling Guidelines” (Simulink).

High-Integrity “himl_0001: Usage of standardized MATLAB function headers”


Systems (Simulink)
Modeling
Guidelines “himl_0002: Strong data typing at MATLAB function boundaries”
(Simulink)

“himl_0003: Limitation of MATLAB function complexity” (Simulink)

“himl_0005: Usage of global variables in MATLAB functions” (Simulink)

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

Modeling Guidelines for Model Configuration


When you develop models and generate code, use the modeling guideline configuration
recommendations.

For more information, see “Modeling Guidelines” (Simulink).

Code Generation “cgsl_0301: Prioritization of code generation objectives for code


Modeling efficiency” (Simulink)
Guidelines
“cgsl_0302: Diagnostic settings for multirate and multitasking models”
(Simulink)

2-46
Modeling Guidelines for Model Configuration

High-Integrity “hisl_0043: Configuration Parameters > Diagnostics > Solver”


Systems (Simulink)
Modeling
Guidelines “hisl_0044: Configuration Parameters > Diagnostics > Sample Time”
(Simulink)

“hisl_0301: Configuration Parameters > Diagnostics > Compatibility”


(Simulink)

“hisl_0302: Configuration Parameters > Diagnostics > Data Validity >


Parameters” (Simulink)

“hisl_0303: Configuration Parameters > Diagnostics > Merge block”


(Simulink)

“hisl_0304: Configuration Parameters > Diagnostics > Model


initialization” (Simulink)

“hisl_0305: Configuration Parameters > Diagnostics > Debugging”


(Simulink)

“hisl_0306: Configuration Parameters > Diagnostics > Connectivity >


Signals” (Simulink)

“hisl_0307: Configuration Parameters > Diagnostics > Connectivity >


Buses” (Simulink)

“hisl_0308: Configuration Parameters > Diagnostics > Connectivity >


Function calls” (Simulink)

“hisl_0309: Configuration Parameters > Diagnostics > Type


Conversion” (Simulink)

“hisl_0310: Configuration Parameters > Diagnostics > Model


Referencing” (Simulink)

“hisl_0311: Configuration Parameters > Diagnostics > Stateflow”


(Simulink)

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

Subsystems in Simulink Coder

• “Control Generation of Subsystem Functions” on page 3-2


• “Generate Code and Executables for Individual Subsystems” on page 3-4
• “Inline Subsystem Code” on page 3-8
• “Generate Subsystem Code as Separate Function and Files” on page 3-11
• “Optimize Code for Identical Nested Subsystems” on page 3-12
• “Code Generation of Constant Parameters” on page 3-13
3 Subsystems in Simulink Coder

Control Generation of Subsystem Functions

What is a Subsystem Function?


A subsystem function is function code that the code generator produces for a subsystem
in a model. The function interface and how the code generator packages the code
depends on whether the subsystem is a virtual or atomic (nonvirtual) subsystem and how
you configure the subsystem block parameters. For more information, see Subsystem,
Atomic Subsystem, Nonvirtual Subsystem, CodeReuse Subsystem.

Options for Controlling Generation of Subsystem Function


Code
You can design and configure a model in a way that controls how the code generator
produces code from subsystems.

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

Subsystem Function Dependence


Code generated from subsystems can be completely independent of code generated for a
model. When generating code for a subsystem, the code can reference global data
structures of the model, even if the subsystem function code is in a separate file. Each

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

Generate Code and Executables for Individual


Subsystems
You can generate code and build an executable for a subsystem within a model. The code
generation and build process uses the code generation and build parameters of the root
model.

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.

The generated code is in a build subfolder, named subsystem_target_rtw.


subsystem is the name of the source subsystem block and target is the name of
the target configuration.

When you generate code for a subsystem, you can generate an S-function by selecting
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 Limitations


The following limitations apply to building subsystems:

• 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:

1 Copy all blocks in the subsystem to an empty model.


2 In the Configuration Parameters dialog box, on the Solver pane, set:

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:

The subsystem 'model/subsys'


is trying to generate code to an reserved file (subsys) for
the model 'subsys'...

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

Inline Subsystem Code


You can configure a nonvirtual subsystem to inline the subsystem code with the model
code. In the Subsystem Parameters dialog box, setting the Function packaging
parameter to Auto or Inline inlines the generated code of the subsystem.

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.

Configure Subsystem to Inline Code


To configure your subsystem for inlining:

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.

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


selected.
3 Click the Code Generation tab and select Auto or Inline from the Function
packaging parameter.

3-8
Inline Subsystem Code

4 Click Apply and close the dialog box.

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

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.

• If the subsystem is a function-call subsystem that is called by a noninlined S-function,


the Inline option is ignored. Noninlined S-functions make calls by using function
pointers. Therefore, the function-call subsystem must generate a function with all
arguments present.

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.

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

3-10
Generate Subsystem Code as Separate Function and Files

Generate Subsystem Code as Separate Function and


Files
To generate a separate subsystem function and a separate file for a subsystem in a model:

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

Optimize Code for Identical Nested Subsystems


The Function packaging parameter Auto option can optimize code in situations in
which identical subsystems contain other identical subsystems, by both reusing and
inlining generated code. Suppose a model, such as the one shown in “Reuse of Identical
Nested Subsystems” on page 3-12, contains identical subsystems A1 and A2. A1 contains
subsystem B1, and A2 contains subsystem B2, which are identical. In such cases, the
Auto option causes one function to be generated which is called for both A1 and A2. This
function contains one piece of inlined code to execute B1 and B2. This optimization
generates less code which improves execution speed.

Reuse of Identical Nested Subsystems

3-12
Code Generation of Constant Parameters

Code Generation of Constant Parameters


The code generator attempts to generate constant parameters to the shared utilities
folder first. If constant parameters are not generated to the shared utilities folder, they
are defined in the top model in a global constant parameter structure. The declaration of
the structure, ConstParam_model, is in model.h:

/* Constant parameters (auto storage) */


typedef struct {
/* Expression: [1 2 3 4 5 6 7]
* Referenced by: '<Root>/Constant'
*/
real_T Constant_Value[7];

/* Expression: [7 6 5 4 3 2 1]
* Referenced by: '<Root>/Gain'
*/
real_T Gain_Gain[7];
} ConstParam_model;

The definition of the constant parameters, model_constP, is in:

/* Constant parameters (auto storage) */


const ConstParam_model model_ConstP = {
/* Expression: [1 2 3 4 5 6 7]
* Referenced by: '<Root>/Constant'
*/
{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 },

/* 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 }
};

The model_constP is passed as an argument to referenced models.

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

Referenced Models in Simulink


Coder

• “Code Generation of Referenced Models” on page 4-2


• “Generate Code for Referenced Models” on page 4-4
• “Configure Referenced Models” on page 4-14
• “Build Model Reference Targets” on page 4-15
• “Simulink Coder Model Referencing Requirements” on page 4-16
• “Storage Classes for Signals Used with Model Blocks” on page 4-21
• “Inherited Sample Time for Referenced Models” on page 4-25
• “Customize Library File Suffix and File Type” on page 4-27
• “Simulink Coder Model Referencing Limitations” on page 4-28
4 Referenced Models in Simulink Coder

Code Generation of Referenced Models


This section describes model referencing considerations that apply specifically to code
generation by the Simulink Coder. This section assumes that you understand referenced
models and related terminology and requirements, as described in “Overview of Model
Referencing” (Simulink) and associated topics.

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

Generate Code for Referenced Models


In this section...
“About Generating Code for Referenced Models” on page 4-4
“Create and Configure the Subsystem” on page 4-4
“Convert Model to Use Model Referencing” on page 4-7
“Generate Model Reference Code for a GRT Target” on page 4-10
“Work with Code Generation Folders” on page 4-12

About Generating Code for Referenced Models


To generate code for referenced models, you

1 Create a subsystem in an existing model.


2 Convert the subsystem to a referenced model (Model block).
3 Call the referenced model from the top model.
4 Generate code for the top model and referenced model.
5 Explore the generated code and the code generation folder.

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

Create and Configure the Subsystem


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

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

mkdir mrexample
cd mrexample
2 Open the vdp 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.

A subsystem block replaces the selected blocks.


5 If the new subsystem block is not where you want it, move it to a preferred location.
6 Rename the block vdpmult.
7 Right-click the vdpmult block and select Block Parameters (Subsystem).

The Function Block Parameters dialog box appears.


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

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

4-5
4 Referenced Models in Simulink Coder

The block diagram should now appear as follows:

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

1 Open Model Explorer by selecting Model Explorer from the model's View menu.
2 In the Model Hierarchy pane, click the symbol preceding the model name to reveal
its components.
3 Click Configuration (Active) in the left pane.
4 In the center pane, select Solver.
5 In the right pane, under Solver 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.

Convert Model to Use Model Referencing


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

help Simulink.SubSystem.convertToModelReference

For additional information, type:

doc Simulink.SubSystem.convertToModelReference

If you want to see an example of Simulink.SubSystem.convertToModelReference


before using it yourself, type:

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).

Extract the Subsystem to a Referenced Model

To use Simulink.SubSystem.convertToModelReference to extract vdpmult and


convert it to a referenced model, type:

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

This command:

1 Extracts the subsystem vdpmult from vdptop.

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.

The converter prints progress messages and terminates with

ans =
1

The parent model vdptop now looks like this:

Note the changes in the appearance of the block vdpmult. These changes indicate that it
is now a Model block rather than a subsystem. As a Model block, it 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

Files Created and Changed by the Converter

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

File Description
vdptop 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.

Run the Converted Model

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

Generate Model Reference Code for a GRT Target


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

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


2 If the model vdptop is not open, open it. Make sure it is the active window.
3 Open Model Explorer by selecting Model Explorer from the model's View menu.
4 In the Model Hierarchy pane, click the symbol preceding the vdptop model to
reveal its components.
5 Click Configuration (Active) in the left pane.
6 In the center pane, select Data Import/Export.
7 In the pane, select Time and Output and clear Data stores. Click Apply.

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).

Work with Code Generation Folders


Model reference code is generated in your code generation folder (Simulink) and
simulation target code is generated in your simulation cache folder (Simulink). Because of
this process, there are constraints on:

• When and where model reference targets are built.


• How the model reference targets are accessed.

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

Configure Referenced Models


Minimize occurrences of algebraic loops by selecting the Minimize algebraic loop
occurrences parameter on the Model Reference pane. The setting of this option affects
only generation of code from the model. For information on how this option affects code
generation, see “Configure Run-Time Environment Options” (Simulink Coder). For more
information about direct feed through, see “Algebraic Loops” (Simulink).

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

Build Model Reference Targets


By default, the Simulink engine rebuilds simulation targets before the Simulink Coder
software generates model reference targets. You can change the rebuild criteria or
specify when the engine rebuilds targets. For more information, see “Rebuild” (Simulink).

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.

Reduce Change Checking Time


You can reduce the time that the Simulink and Simulink Coder products spend checking
whether simulation targets and model reference targets need to be rebuilt by setting
configuration parameter values as follows:

• 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

Simulink Coder Model Referencing Requirements


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

• The Simulink requirements listed in:

• “Configuration Requirements for All Referenced Model Simulation” (Simulink)


• “Define Referenced Model Inputs and Outputs” (Simulink)
• The Simulink limitations listed in “Signal Limitations” (Simulink)
• The Simulink Coder limitations listed in “Simulink Coder Model Referencing
Limitations” on page 4-28

Configuration Parameter Requirements


A referenced model uses a configuration set in the same way a top model does, as
described in “Manage a Configuration Set” (Simulink). By default, every model in a
hierarchy has its own configuration set, which it uses in the same way that it would if the
model executed independently.

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

• Where an inconsistency has no significance, the product ignores or resolves the


inconsistency without posting a warning.
• Where a nontrivial and possibly acceptable solution exists, the product resolves the
conflict silently; resolves it with a warning; or generates an error.
• If an acceptable resolution is not possible, the product generates an error. You must
then change parameter values to eliminate the problem.

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.

Configuration Requirements for Model Referencing with All System Targets

Dialog Box Pane Option Requirement


Solver Start time Some system targets require the start
time of all models to be zero.
Hardware All options Values must be the same for top and
Implementation referenced models.
Code Generation System target file Must be the same for top and
referenced models.
Language Must be the same for top and
referenced models.
Generate code only Must be the same for top and
referenced models.
Symbols Maximum identifier Cannot be longer for a referenced
length model than for its parent model.
Interface Code replacement Must be the same for top and
library referenced models.
C API options The C API check boxes must be the
same for top and referenced models.
ASAP2 interface Can be on or off in a top model, but
must be off in a referenced model. If
it is not, the Simulink Coder software
temporarily sets it to off during code
generation.

4-17
4 Referenced Models in Simulink Coder

Configuration Requirements for Model Referencing with ERT System Targets


(Requires Embedded Coder License)

Dialog Box Pane Option Requirement


Comments > Ignore custom Must be the same for top and referenced
Advanced storage classes models.
parameters
Symbols Global variables $R token must appear.
Global types
Subsystem
methods
Local temporary
variables
Constant macros
Signal naming Must be the same for top and referenced
models.
M-function If specified, must be the same for top and
referenced models.
Parameter Must be the same for top and referenced
naming models.
#define naming Must be the same for top and referenced
models.
Interface Support floating- Must be the same for both top and referenced
point numbers models
Support non- If off for top model, can be on or off for
finite numbers referenced models.

If on for top model, must be on for referenced


models.
Support complex If off for top model, can be on or off for
numbers referenced models.

If on for top model, must be on for referenced


models.

4-18
Simulink Coder Model Referencing Requirements

Dialog Box Pane Option Requirement


Suppress error If on for top model, must be on for referenced
status in real- models.
time model
Code Placement Use owner from Must be the same for top and referenced
data object for models.
data definition
placement
Signal display Must be the same for top and referenced
level models.
Parameter tune Must be the same for top and referenced
level models.

Configuration Parameters Changed During Code Generation


For referenced models, if these Configuration Parameters > Code Generation >
Symbols parameters have settings that do not contain a $R token (which represents the
name of the reference model), code generation prepends the $R token to the identifier
format:

• Global variables (CustomSymbolStrGlobalVar)


• Global types (CustomSymbolStrType)
• Subsystem methods (CustomSymbolStrFcn)
• Constant macros (CustomSymbolStrMacro)

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.

Embedded Coder Naming Requirements

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:

• The $R token must be included in the Identifier format control parameter


specifications (in addition to the $M token) except for Shared utilities identifier
format.
• The Maximum identifier length must be large enough to accommodate full
expansions of the $R and $M tokens.

See “Model Configuration Parameters: Code Generation Symbols” (Simulink Coder) for
more information.

Custom Target Requirements


If you have an Embedded Coder license, a custom target must meet various requirements
to support model referencing. For details, see “Support Model Referencing” on page 74-
84.

4-20
Storage Classes for Signals Used with Model Blocks

Storage Classes for Signals Used with Model Blocks


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

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

• 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.

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

• 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).

Storage Classes for Parameters Used with Model Blocks


Storage classes are supported for both simulation and code generation, and all except
Auto are tunable. The supported storage classes thus include

• Model default

4-21
4 Referenced Models in Simulink Coder

• ExportedGlobal
• ImportedExtern
• ImportedExternPointer
• Custom

Note the following restrictions on parameters in referenced models:

• Tunable parameters are not supported for noninlined S-functions.


• Tunable parameters set using the Model Parameter Configuration dialog box are
ignored.

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).

Signal Name Mismatches Across Model Reference Boundary


Within a parent model, the name and storage class for a signal entering or leaving a
Model block might not match those of the signal attached to the root inport or outport

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:

Relationships of Signals and Storage Classes Across Model Reference Boundary


Referenced Model Parent Model Signal Passing Signal Mismatch
Method Checking
Auto Any storage class Function argument None
Model default Any storage class Function argument Signal label
(when Code Mapping mismatch
Editor specifies
Default storage
class) or resolved to
Signal Object
Global Auto or Model Global variable Signal label
default (when mismatch
Code Mapping Editor
specifies Default
storage class)
Global Global Global variable Labels and storage
classes must be
identical (else error)

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

• 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.

• When such a signal is Model default or resolves to a Simulink.Signal object,


the Signal label mismatch diagnostic is applied.
• If a root input or output signal in a referenced model is global, it is communicated by
using direct memory access (global variable). In addition,

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

Inherited Sample Time for Referenced Models


For information about Model block sample time inheritance, see “Inherit Sample Times
for Model Referencing” (Simulink). In generated code, you can control inheriting sample
time by using ssSetModelReferenceSampleTimeInheritanceRule in different ways:

• 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:

static void mdlOutputs(SimStruct *S, int_T tid)


{
const real_T *u = (const real_T*)
ssGetInputPortSignal(S,0);
real_T *y = ssGetOutputPortSignal(S,0);
y[0] = ssGetSampleTime(S,tid) * u[0];
}

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:

static void mdlOutputs(SimStruct *S, int_T tid)


{
InputRealPtrsType enablePtrs;
int *enabled = ssGetIWork(S);

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;

for (i = 0; i < NOUTPUTS; i++) {


if (ssIsSampleHit(S,
ssGetOutputPortSampleTimeIndex(S,i), tid)) {
real_T *y = ssGetOutputPortRealSignal(S,i);
*y = signal;
}
}
}
} /* end mdlOutputs */

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

Customize Library File Suffix and File Type


You can control the library file suffix and file type extension that the Simulink Coder code
generator uses to name generated model reference libraries. Use the model configuration
parameter TargetLibSuffix to specify the scheme for the suffix and extension. The
scheme must include a period (.). If you do not set this parameter, the Simulink Coder
software names the libraries as follows:

• On Windows systems, model_rtwlib.lib


• On UNIX or Linux® systems, model_rtwlib.a

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

Simulink Coder Model Referencing Limitations


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

• The Simulink requirements listed in:

• “Configuration Requirements for All Referenced Model Simulation” (Simulink)


• “Define Referenced Model Inputs and Outputs” (Simulink)
• The Simulink limitations listed in “Model Referencing Limitations” (Simulink).
• The Simulink Coder requirements applicable to the code generation target, as listed in
“Configuration Parameter Requirements” on page 4-16.

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).

Data Logging Limitations


• To Workspace blocks, Scope blocks, and all types of runtime display, such as the
display of port values and signal values, are ignored when the Simulink Coder
software generates code for a referenced model. The resulting code is the same as if
the constructs did not exist.
• Code generated for referenced models cannot log data to MAT-files. If data logging is
enabled for a referenced model, the Simulink Coder software disables the option
before code generation and re-enables it afterwards.
• If you log states for a model that contains referenced models, the ordering of the
states in the output is determined by block sorted order, and might not match between
simulation output and generated code MAT-file logging output.

4-28
Simulink Coder Model Referencing Limitations

State Initialization Limitation


When a top model uses the Data Import/Export > Initial state parameter in the
Configuration Parameters dialog box to specify initial conditions, the Simulink Coder
software does not initialize the discrete states of the referenced models during code
generation.

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:

• Inlined but has not set the option SS_OPTION_WORKS_WITH_CODE_REUSE


• Not inlined
• The model contains a function-call subsystem that:

• Has been forced by the Simulink engine to be a function


• Is called by a wide signal

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).

Simulink Tool Limitations


• Simulink tools that require access to a model's internal data or configuration
(including the Model Coverage tool, the Simulink Report Generator product, the
Simulink debugger, and the Simulink profiler) have no effect on code generated by the
Simulink Coder software for a referenced model, or on the execution of that code.
Specifications made and actions taken by such tools are ignored and effectively do not
exist.

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.

Configuration Parameters Changed During Accelerated


Simulation and Code Generation
During model referencing simulation in accelerator and rapid accelerator mode, Simulink
temporarily sets several Configuration Parameters > Diagnostics > Data Validity
parameter settings to None, if they are set to Warning or Error. You can use the Model
Advisor to check for parameters that change. For details, see “Accelerated Simulation and
Code Generation Changes Settings” (Simulink).

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

Combined Models in Simulink Coder


5 Combined Models in Simulink Coder

Combine Code Generated for Multiple Models

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:

• Referenced models. See “Overview of Model Referencing” (Simulink) and “Generate


Code for Referenced Models” on page 4-4.
• If you have Embedded Coder software, interface the code for multiple models to a
common harness program. From the harness program, call the entry-point functions
generated for each model. The ert.tlc system target file has restrictions, relating to
embedded processing, that could be incompatible with your application.
• Generate reusable, multi-instance code that is reentrant. See “Combine Code
Generated for Multiple Models or Multiple Instances of a Model” on page 5-3.

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:

• Symbol naming consistency


• Required scheduling of the overall algorithm
• Model configuration consistency

If you combine code generated for different models (that is, without using referenced
models), consider:

• Data is global. Symbol (name) clashes can result.


• Configuration parameter settings for the models must match, including settings such
as hardware word sizes.
• Reuse and sharing of code can be suboptimal (for example, duplicate code for shared
utility functions, scheduling, and solvers).
• Scheduling can be more complex (for example, models can have periodic sample times
that are not multiples of each other, making scheduling from a common timer
interrupt more complicated)

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.

Control Ownership of Data


If you have Embedded Coder software, you can specify an owner for individual data items
such as signals, parameters, and states. The owner of a data item generates the definition
(memory allocation and initialization) for the data item. For example, if you apply a
custom storage class to a Simulink.Signal object so that it appears as a global
variable in the generated code, specify one of the combined models as the owner of the
object. The code generated for that model defines the variable.

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.

To specify an owner for a data item:

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.

Combine Code Generated for Multiple Models or Multiple


Instances of a Model
For each model for which you are combining code, generate the code.

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.

After generating source code for each 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.

Share Data Across Models

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

Data Logging and External Mode Support

A multiple-model program can log data to separate MAT-files for each model.

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

5-5
6

Code Reuse for Simulink Coder


6 Code Reuse for Simulink Coder

What Is Code Reuse?


Code reuse is a programming technique that reduces time and resources to develop
software. When you develop code for reuse, the code serves multiple purposes. The
technique involves modularization, which enables multiple individuals to develop code for
various system components independently and in parallel. The technique also simplifies
software distribution.

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.

Applications of code reuse include:

• 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

What Is Reentrant Code?


Reentrant (multi-instance) code is a reusable routine that multiple programs can invoke,
interrupt, and reinvoke simultaneously. When you want to reuse code, but associate each
instance of the shared code with unique, preserved data, use reentrant code. For
example, consider this figure that shows four instances of function sensor_read.
Although the function algorithm is the same in each case, the data associated with each
instance varies and is relative to the sensor position.

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

• “Choose a Componentization Technique for Code Reuse” on page 6-6

6-5
6 Code Reuse for Simulink Coder

Choose a Componentization Technique for Code Reuse


Key componentization techniques that you can use withSimulink and the code generator
to produce reusable code include:

• Reference models
• Subsystems
• Library subsystems
• Combinations of models, subsystems, and library subsystems

Choose componentization techniques based on your code reuse goals.

Goal Referenced Subsyst Subsystem in Library


Model em in
Model
Design for explicit √ √ √
code reuse.
Facilitate parallel √ √ √
team development.
Reuse function √
within a model or
across models.
Improve build √
performance by
generating reusable
code incrementally.
Verify reusable √
code with SIL or
PIL simulation.
Optimize generated √ √ √
code by configuring
code generator to
detect
opportunities for
code reuse.

6-6
See Also

Goal Referenced Subsyst Subsystem in Library


Model em in
Model
Maximize reuse √ √
with context-
dependent
behavior.
Develop a √
frequently used,
and infrequently
changed, utility
function.

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

Simulink Function Blocks and Code Generation

Why Generate Code from Simulink Function Blocks and


Function Callers?
Simulink Function blocks provide a mechanism for generating C or C++ code for
modeling components that represent shared resources. You define the logic as a resource
in a Simulink Function block, which separates the function interface (name and
arguments) from the implementation of the logic. Function callers (Function Caller
blocks, MATLAB Function blocks, and Stateflow charts) can then reuse the function logic
at different levels of the model hierarchy.

Simulink Function blocks provide an alternative to reusable subsystems. For example, a


consideration for using a Simulink Function block instead of a subsystem block is that a
Simulink Function block shares states between function callers. The code generator
produces one function. If the Simulink Function block contains blocks that have states,
such as a delay or memory, the states persistent between function callers. The order of
the function calls is an important consideration.

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.

Other uses of Simulink Function blocks and callers include:

• Nesting calls to a function.


• Calling a function defined in one modeling component from another modeling
component.
• Generating functions that are globally accessible or scoped.
• Producing code for a client and server application.

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

• How you represent a function and function callers in a model


• Scope of a function
• Whether to export a function from a model (requires Embedded Coder)
• Function code interface customizations (requires Embedded Coder)
• Code generation requirements
• Code generation limitations

Choose a Modeling Pattern


This table shows C code for a function that multiplies an input value times two and a
Simulink Function block that can represent that function in a Simulink model.

Function Definition Modeling Element


codegen-folder/subsystem.c Simulink Function block

#include "timestwo_sf.h"

#include "ex_slfunc_comp_sf.h"
#include "ex_slfunc_comp_sf_private.h"

void timestwo_sf(real_T rtu_x, real_T *rty_y)


{
*rty_y = 2.0 * rtu_x;
}

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

Function Call Modeling Element


codegen-folder/model.c Function Caller block

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

Specify Function Scope


A function that you define with a Simulink Function block can be global or scoped.

• 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).

Decide Whether to Generate Export Function Code


Although you can use Simulink Function blocks in a single top-model design, function
code is more reusable when you generate it as standalone, atomic components. You do
that by designing the functions in the context of export-function models.

For information, see “Generate Component Source Code for Export to External Code
Base” on page 42-52 and “Export-Function Models” (Simulink).

Specify Function Code Interface Customizations


WithEmbedded Coder, simplify integration of generated code with external code by
customizing generated function code interfaces for Simulink Function and Function
Caller blocks. You can customize the function interfaces for:

• Global Simulink Function blocks


• Scoped Simulink Function blocks that are at the root level of a model

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.

Generate and Call Reusable Function Code


This example shows how to use the Simulink Function and Function Caller blocks to
generate reusable function code. The code generator produces a global function, which
complies with code requirements so that existing external code can call the function and
a local function. The code generator also produces calls to global and local functions. The
call to the global function shows that the global function is reused (shared).

Code requirements for the global function are:

• Function names start with prefix func_.


• Names of input arguments are of the form xn, where n is a unique integer value.
• Names of output arguments are of the form yn, where n is a unique integer value.
• Input and output arguments are integers (int) and are passed by reference. The
native integer size of the target hardware is 32 bits.

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.

Inspect External Code That Calls Reusable Function

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

typedef int my_int;

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);

printf('Times 2 Value:', 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

Configure Generated Code to Reuse Custom Data Type

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.

1 Create a Simulink.AliasType object to represent the custom data type my_int.

my_int = Simulink.AliasType

my_int =

AliasType with properties:

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.Description='Custom 32-bit int representation';


my_int.DataScope='Imported';
my_int.HeaderFile='call_times2.h';
my_int.BaseType='int32';

my_int
AliasType with properties:

Description: 'Custom 32-bit int representation'


DataScope: 'Imported'
HeaderFile: 'call_times2.h'
BaseType: 'int32'
3 Configure the code generator to replace instances of type int32_T with my_int. In
the Configuration Parameters dialog box, open the Code GenerationData Type
Replacement pane.

• Select Replace data type names in the generated code.


• In the Data type names table, enter my_int for the replacement name for
int32.

6-15
6 Code Reuse for Simulink Coder

Configure Reusable, Global Function

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.

1 Open the block that represents the times2 function.

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_.

• Set Function name to func_times2.


• Set Function visibility to global.
3 Configure the function input and output arguments by setting Argument Inport and
Argument Outport block parameters. For example, the code requirements specify
that argument names be of the form xn and yn. The requirements also specify that
arguments be type my_int.

• On the Main tab, set Argument name to x1 (input) and y1 (output).


• On the Signal Attributes tab, set Data type to int32. With the data type
replacement that you specified previously, int32 appears in the generated code
as myint.
4 Configure the Simulink Function block code interface. At the top level of the model,
right-click the global function func_times2. From the menu, select C/C++
CodeConfigure C/C++ Function Interface.

• Set C/C++ function name to func_times2.


• Set C/C++ return argument to void.
• Set C/C++ Identifier Name for argument x1 to x1.

6-16
Simulink Function Blocks and Code Generation

• Set C/C++ Identifier Name for argument y1 to y1.

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 Local Function

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.

1 Open the block that represents the times3 function.


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_.

• Set Function name to func_times3.


• Set Function visibility to scoped.
3 Configure the function input and output arguments by setting Argument Inport and
Argument Outport block parameters. For example, the code requirements specify
that argument names be of the form xn and yn. The requirements also specify that
arguments be type my_int.

• On the Main tab, set Argument name to x1 (input) and y1 (output).


• On the Signal Attributes tab, set Data type to int32. With the data type
replacement that you specified previously, int32 appears in the generated code
as my_int.
4 Configure the Simulink Function block code interface. At the top level of the model,
right-click the scoped function func_times3. From the menu, select C/C++
CodeConfigure C/C++ Function Interface. In this case, the code generator
controls naming the function and arguments. The function name combines the name
of the root model and the function name that you specify for the trigger port of the
Simulink Function block. In this example, the name is
ex_slfunc_comp_func_times3.

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.

Configure Function Callers

For each function caller, configure Function Caller block parameters:

• Set Function prototype to y1 = func_times2(x1).


• Set Input argument specifications to int32(1).
• Set Output argument specifications to int32(1).

Generate and Inspect Code

Generate code for the model.

• Global function code

Source code for the global, reusable function func_times2 is in the build folder in
subsystem file, func_times2.c.
#include "func_times2.h"

/* Include model header file for global data */


#include "ex_slfunc_comp.h"
#include "ex_slfunc_comp_private.h"

void func_times2(my_int x1, my_int *y1)


{
*y1 = x1 << 1;
}
• Local function code

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

ex_slfunc_comp_func_times3. The name ex_slfunc_comp_func_times3


reflects the scope of the local function by combining the name of the model and the
name of the function.
void ex_slfunc_comp_step(void)
{
my_int rtb_FunctionCaller2;

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;
.
.
.

• Entry-point declaration for local function

The model header file ex_slfunc_comp.h includes an extern declaration for


function ex_slfunc_comp_func_times3. That statement declares the function entry
point.

extern void ex_slfunc_comp_func_times3(my_int rtu_x1, my_int *rty_y1);


• Include statements for global function

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

The subsystem header file func_times2_private.h defines macros and includes


header files that declare data and functions for the global function, func_times2.

#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"

extern void func_times2(my_int rtu_x1, my_int *rty_y1);

#endif

Generate Code for a Simulink Function and Function Caller


This example shows how to generate C code for Simulink Function and Function Caller
blocks and displays the relevant generated code.

Open the example model rtwdemo_export_functions. The model uses Stateflow


software, but this example reviews only the code generated from the referenced models.

6-20
Simulink Function Blocks and Code Generation

Generate Code for Function Definition

1 To view the contents of the subsystem, double-click rtwdemo_functions. The


Simulink Function block is the f3 subsystem defined as y = f3(u).

2 Generate code.

The code generator creates rtwdemo_functions.c. This file contains the function
definition and function initialization code.

• Initialization code for function f3:

void f3_Init(void)
{
rtDWork.Delay_DSTATE = 1;
}
• Code for function f3:

void f3(real_T rtu_u, real_T *rty_y)


{

6-21
6 Code Reuse for Simulink Coder

rtY.TicToc10 = rtDWork.Delay_DSTATE;

rtDWork.Delay_DSTATE = (int8_T)(int32_T)-(int32_T)rtY.TicToc10;

adder_h(rtB.Subtract, rtU.U2, rtu_u, rtB.FunctionCaller);

*rty_y = rtB.FunctionCaller;
}

void adder_h(real_T rtu_u1,


real_T rtu_u2,
real_T rtu_u3,
real_T *rty_y)
{
*rty_y = (rtu_u1 + rtu_u2) + rtu_u3;
}
• The shared header file f3.h contains the entry point declaration for function f3.

#include "rtwtypes.h"

extern void f3(real_T rtu_u, real_T *rty_y);

Generate Code for Function Caller

1 In the rtwdemo_export_functions model, double-click rtwdemo_caller to view


the contents of the caller subsystem.
2 Generate code.

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.

rtwdemo_caller.c calls function f3.

void rtwdemo_caller_t_10tic(const real_T *rtu_u,


real_T *rty_y)
{
f3(*rtu_u, rty_y);
}

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

Generate Reentrant Code from Top Models


By default, for top models, the code generator produces code that is not reentrant. Entry-
point functions have a void-void interface. Code communicates with other code by sharing
access to global data structures that reside in shared memory.

For applications that can benefit from reuse and require that each use or instance of the
code maintains its own unique data, configure a model such that the code generator
produces reentrant code. To generate reentrant code, set the model configuration
parameter “Code interface packaging” (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

Generate Reentrant, Multi-Instance Code


This example shows you how to configure a model for reentrant, multi-instance code
generation. Multiple programs can use reentrant code simultaneously. When you
configure a model for reentrancy, the execution (step) entry-point function uses root-level
input and output arguments instead of global data structures. After examining the
configuration settings, generate and review the generated code.

Open the Model

Open the model 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();

Examine Relevant Model Configuration Settings

1. Open the Model Configuration Parameters dialog box.

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

• Code interface packaging is set to Reusable function. This parameter setting


instructs the code generator to produce reusable, multi-instance code.
• The Reusable function parameter setting also displays the Multi-instance code
error diagnostic parameter. That parameter is set to Error, indicating that the code
generator abort if the model violates requirements for generating multi-instance code.
• Pass root-level I/O as is set to Part of model data structure. This setting
packages root-level model input and output into the real-time model data structure
(rtModel), which is an optimized data structure that replaces SimStruct as the top-
level data structure for a model.
• Remove error status field in real-time model data structure is selected. This
parameter setting reduces memory usage by omitting the error status field from the
generated real-time model data structure.

Generate and Review Code

rtwbuild(model);

### Starting build procedure for model: rtwdemo_reusable


### Successful completion of build procedure for model: rtwdemo_reusable

From the code generation report, review the generated code.

• ert_main.c is an example main program (execution framework) for the model. This
code controls model code execution by calling the entry-point 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.

1. Include the generated header file by adding directive #include


rtwdemo_reusable.h.

2. Write input data to the generated code for model Inport blocks.

6-26
Generate Reentrant Code from Top Models

3. Call the generated entry-point functions.

4. Read data from the generated code for the model Outport block.

Input ports:

• <Root>/In1 of data real_T with dimension of 1


• <Root>/In2 of data real_T with dimension of 1

Entry-point functions:

• Initialization entry-point function, void


rtwdemo_reusable_initialize(RT_MODEL *const rtM). At startup, call this
function once.
• Output and update (step) entry-point function, void
rtwdemo_reusable_step(RT_MODEL *const rtM). Call this function periodically
at the fastest rate in the model. For this model, call the function every second. To
achieve real-time execution, attach this function to a timer.

Output port:

• <Root>/Out1 of data type real_T with dimension of 1


Examine the |rtwdemo_reusable_step| function code in |rtwdemo_reusable.c|.

cfile = fullfile(cgDir,'rtwdemo_reusable_ert_rtw','rtwdemo_reusable.c');
rtwdemodbtype(cfile,'/* Model step function', '/* Model initialize function ', 1, 0);

/* Model step function */


void rtwdemo_reusable_step(RT_MODEL *const rtM)
{
Parameters *rtP = ((Parameters *) rtM->defaultParam);
D_Work *rtDWork = ((D_Work *) rtM->dwork);
ExternalInputs *rtU = (ExternalInputs *) rtM->inputs;
ExternalOutputs *rtY = (ExternalOutputs *) rtM->outputs;

/* Outport: '<Root>/Out1' incorporates:


* UnitDelay: '<Root>/Delay'
*/
rtY->Out1 = rtDWork->Delay_DSTATE;

/* Gain: '<Root>/Gain' incorporates:


* Inport: '<Root>/In1'

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.

Close the model and the code generation report.

bdclose(model)
rtwdemoclean;
cd(currentDir)

Share Data Between Instances


When your code calls a reentrant model entry-point function multiple times, each call
represents an instance of the model. By default, the code generator generates code that
assumes each instance reads from and writes to a separate copy of the signals, block
states, and parameters in the model.

• To share a piece of parameter data between the instances (for example, to share a
setpoint for a reusable PID control algorithm), use a parameter object, such as
Simulink.Parameter, 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

Generate Reentrant Code from Simulink Function Blocks


If you are using Embedded Coder, you can generate reusable, reentrant code by
representing an algorithm as a scoped Simulink Function block. Examples of when to
generate reentrant code from Simulink Function blocks are when a function shares state
between function callers within a model or for client/server applications. You can
generate code that is highly modularized by using multiple instances of a shared Simulink
Function block in an export-function model. The code generator produces function code
and associates each use or call to the function with instance-specific data. The scope of
the function depends on whether you place the function at the root level of model or in a
subsystem.

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:

• How many instances of each function are required?


• Do you need to restrict call sites for a function to the model containing the function
definition?
• Do you need for a function to interface with signals in the local environment, but keep
those signals hidden from callers?
• Do functions need to communicate directly with each other?
• Do functions need to connect to external I/O?
• Do you need to log function output?

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 referenced model, rtwdemo_func_dinteg, consists of a Simulink Function block


that defines function multiinstfunc and subsystem subsys_calc.

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 Model and Model Elements


Configure 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:

• Configure block instances with the same function name.


• Set Function visibility to scoped.

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 Function Caller Blocks

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

For this example, the prototypes are configured as follows:

• 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

• Scopes the function to the model that includes the subsystem.


• Treats the subsystem as an atomic unit.

Configure Referenced Model

Configure the referenced model that includes a Simulink Function block:

• 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 Top Model

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:

• Set Multi-instance code error diagnostic to Error.


• Set Pass root-level I/O as to Part of model data structure.

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.

Generate and Inspect C Code


Generate C code for the model.

• Function code for multi-instance Simulink Function block

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;

rtwdemo_func_dinteg_M->dwork.DiscreteIntegrator_DSTATE += 0.1 * rtu_u;


return rty_y_0;
}

6-35
6 Code Reuse for Simulink Coder

• Function code for a Simulink Function block defined in a subsystem

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;

rtwdemo_func_dinteg_M->dwork.UnitDelay_DSTATE = rtu_u * 0.07;


}

• Self-referential structure that stores multi-instance data for reusable functions

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;

• Initialization code for multi-instance referenced model

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;
}

void rtwdemo_func_dinteg_initialize(const char_T **rt_errorStatus,


RT_MODEL_rtwdemo_func_dinteg_T *const rtwdemo_func_dinteg_M)
{
{
rtmSetErrorStatusPointer(rtwdemo_func_dinteg_M, rt_errorStatus);
}
}

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)));

rtwdemo_func_dinteg_Start((&(rtwdemo_comp_M->Instance1)), &rtU->In2, &rtU->In3,


&rtY->Out2, &rtY->Out3);

rtwdemo_func_dinteg_Start((&(rtwdemo_comp_M->Instance2)), &rtU->In4, &rtU->In5,


&rtY->Out4, &rtY->Out5);
}

• Top model entry-point function declarations

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);

extern void Run(RT_MODEL_rtwdemo_comp_T *const rtwdemo_comp_M);

• Reference model entry-point function declarations

Header file slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg.h


includes extern declarations for reference model entry-point functions.
extern void rtwdemo_func_dinteg_initialize(const char_T **rt_errorStatus,
RT_MODEL_rtwdemo_func_dinteg_T *const rtwdemo_func_dinteg_M);
extern real_T rtwdemo_func_dinteg_multiinstfunc(RT_MODEL_rtwdemo_func_dinteg_T *
const rtwdemo_func_dinteg_M, const real_T rtu_u);
extern 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);

Generate and Inspect C++ Code


Generate C++ code for the model.

• Function code for multi-instance Simulink Function block

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_crtrty_Out2 = 2.0 * rtb_TmpLatchAtInOutport1;

rtwdemo_func_dinteg_c_func_calc(rtb_TmpLatchAtIn2Outport1,
rtwdemo_func_dinteg_crtrty_Out1);

rty_y_0 = rtwdemo_func_dinteg_cpprtDW.DiscreteIntegrator_DSTATE;

rtwdemo_func_dinteg_cpprtDW.DiscreteIntegrator_DSTATE += 0.1 * rtu_u;


return rty_y_0;
}

• Function code for a Simulink Function block defined in a subsystem

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;

rtwdemo_func_dinteg_cpprtDW.UnitDelay_DSTATE = rtu_u * 0.07;


}

• Self-referential structure that stores multi-instance data for reusable functions

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

• Initialization code for multi-instance referenced model

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)));

Instance1MDLOBJ0.start(&rtU.In2, &rtU.In3, &rtY.Out2, &rtY.Out3);

Instance2MDLOBJ1.start(&rtwU.In4, &rtwU.In5, &rtY.Out4, &rtY.Out5);


}
• Top model class declaration

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;
};

• Reference model class declaration

Header file slprj/ert/rtwdemo_func_dinteg/rtwdemo_func_dinteg_cpp.h


includes the class declaration for the reference model.
class rtwdemo_func_dintegModelClass {
public:
real_T multiinstfunc(const real_T rtu_u);

void start(real_T *rtu_In1, real_T *rtu_In2, real_T *rty_Out2, real_T


*rty_Out1);

rtwdemo_func_dintegModelClass();

~rtwdemo_func_dintegModelClass();

rtwdemo_func_dinteg_cp_RT_MODEL * getRTM();

void initializeRTM();

void setErrorStatusPointer(const char_T **rt_errorStatus);

private:
rtwdemo_func_dinteg_cpp_DW rtwdemo_func_dinteg_cpprtDW;

const real_T *rtwdemo_func_dinteg_cprtrtu_In1;


const real_T *rtwdemo_func_dinteg_cprtrtu_In2;
real_T *rtwdemo_func_dinteg_crtrty_Out2;
real_T *rtwdemo_func_dinteg_crtrty_Out1;

rtwdemo_func_dinteg_cp_RT_MODEL rtwdemo_func_dinteg_cpprtM;

6-40
See Also

void rtwdemo_func_dinteg_c_func_calc(real_T rtu_u, real_T *rty_y);


};

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:

• Generate code if the export-function model includes model variants.


• Call the generated code from a Stateflow chart.
• Enable the external mode data exchange interface.

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

Generate Reentrant Code from Subsystems


You can reduce the amount of code that the code generator produces for identical atomic
subsystems by configuring the subsystems as reusable functions that pass data as
arguments (for example, rtB_* for block input and output, rtDW_* for continuous states,
and rtP_* for parameters) . By default, the code generator produces subsystem code that
communicates with other code by sharing access to global data structures that reside in
shared memory. By passing data as arguments, the code can be reentrant. Each instance
of the code maintains its own unique data.

To configure subsystems for reusability and reentrancy, configure mask and block
parameters of the identical subsystems the same way. 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 configure the subsystem block parameters:

1 If a subsystem is virtual, select “Treat as atomic unit” (Simulink) to enable function


packaging parameters.
2 On the Code Generation tab, set “Function packaging” (Simulink) to Reusable
function. The code generator produces a separate function with arguments for
each subsystem. Selecting Reusable function also enables additional parameters
that you can use to control the names of the function and file that the code generator
produces for the subsystem code.
3 Set “Function name options” (Simulink). To generate reusable, reentrant code,
specify the same setting for identical subsystems.

• 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 there are multiple instances of an identical subsystem within a model reference


hierarchy, select Auto.

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.

• To let the code generator determine file naming select Auto.


• To use the subsystem name or, for a library block, the name of the library block
select Use subsystem name.
• To use the function name, as specified by Function name options select Use
function name.
• To display the “File name (no extension)” (Simulink) parameter and enter a file
name, excluding the extension (for example, .c or .cpp) select User
specified.

Other considerations:

• If there are multiple instances of an identical subsystem within a model reference


hierarchy, select Auto.
• If the code generator does not generate a separate file for a subsystem, the
function code is placed in the file generated from the subsystem's parent system.
If the parent is the model itself, the code generator places the function code in
model.c or model.cpp.
• If your generated code is under source control, specify a value other than Auto.
This specification prevents the generated file name from changing when you
modify and rebuild the model.
• If you select Use subsystem name, the code generator mangles the subsystem
file name if the model contains Model blocks, or if a model reference target is
being generated for the model. In these situations, the code generator uses the
file name modelsubsystem.c.

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

• In blocks and data objects, you use symbols to specify dimensions.


• A port has different sample times, data types, complexity, frame status, or
dimensions across subsystems.
• The output of a subsystem is marked as a global signal.
• Subsystems contain identical blocks with different names or parameter settings.
• The output of a subsystem is connected to a Merge block, and the output of the
Merge block is configured with a custom storage class that is implemented in the C
code as nonaddressable memory (for example, BitField).
• The input of a subsystem is nonscalar and is configured with a custom storage class
that is implemented in the C code as nonaddressable memory.
• A masked subsystem has a parameter that is nonscalar and is configured with a
custom storage class that is implemented in the C code as nonaddressable memory.
• A function-call subsystem uses mask parameters when you set the model
configuration parameter “Default parameter behavior” (Simulink Coder) to
Tunable. To reuse the masked function-call subsystem, place it inside a new
atomic subsystem without a mask. Then move the Trigger block from the masked
subsystem into the atomic subsystem.
• A block in a subsystem uses a partially tunable expression. Some partially tunable
expressions disable code reuse.

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

Determine Why Subsystem Code Is Not Reused


Due to the limitations described in “Generate Reentrant Code from Subsystems”
(Simulink Coder), the code generator might not reuse generated code as you expect. To
determine why code generated for a subsystem is not reused:

1 Review the Subsystems section of the code generation report.


2 Compare subsystem checksum data.

Review Subsystems Section of HTML Code Generation Report

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:

• A table that summarizes how nonvirtual subsystems were converted to generated


code.
• Diagnostic information that describes why subsystems were not generated as reusable
code.

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.

Compare Subsystem Checksum Data

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

Use the method Simulink.SubSystem.getChecksum to get the checksum for a


subsystem. Review the results to determine why code is not reused.

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.

[chksum1, chksum1_details] = ...


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

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.

Look at the structure chksum1_details.


chksum1_details

chksum1_details =
ContentsChecksum: [1x1 struct]
InterfaceChecksum: [1x1 struct]
ContentsChecksumItems: [287x1 struct]
InterfaceChecksumItems: [53x1 struct]

ContentsChecksum and InterfaceChecksum are component checksums of the


subsystem checksum. The remaining two fields, ContentsChecksumItems and
InterfaceChecksumItems, contain the checksum details.
8 Determine whether a difference exists in the subsystem contents, interface, or both.
For example:
isequal(chksum1_details.ContentsChecksum.Value,...
chksum2_details.ContentsChecksum.Value)
ans =
0

6-47
6 Code Reuse for Simulink Coder

isequal(chksum1_details.InterfaceChecksum.Value,...
chksum2_details.InterfaceChecksum.Value)
ans =
1

In this case, differences exist in the content.


9 Write a script like this script to find the differences.
idxForCDiffs=[];
for idx = 1:length(chksum1_details.ContentsChecksumItems)
if (~strcmp(chksum1_details.ContentsChecksumItems(idx).Identifier, ...
chksum2_details.ContentsChecksumItems(idx).Identifier))
disp(['Identifiers different for contents item ', num2str(idx)]);
idxForCDiffs=[idxForCDiffs, idx];
end
if (ischar(chksum1_details.ContentsChecksumItems(idx).Value))
if (~strcmp(chksum1_details.ContentsChecksumItems(idx).Value, ...
chksum2_details.ContentsChecksumItems(idx).Value))
disp(['Character vector values different for contents item ', num2str(idx)]);
idxForCDiffs=[idxForCDiffs, idx];
end
end
if (isnumeric(chksum1_details.ContentsChecksumItems(idx).Value))
if (chksum1_details.ContentsChecksumItems(idx).Value ~= ...
chksum2_details.ContentsChecksumItems(idx).Value)
disp(['Numeric values different for contents item ', num2str(idx)]);
idxForCDiffs=[idxForCDiffs, idx];
end
end
end

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 =

Handle: 'rtwdemo_ssreuse/SS1/Lookup Table'


Identifier: 'SaturateOnIntegerOverflow'
Value: 'on'

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

Generate Reusable Code From Referenced Models


Considerations for Subsystems that Contain Referenced
Models
You can generate reusable code for subsystems that contain referenced models by using
the same procedures and options described in “Control Generation of Subsystem
Functions” on page 3-2. However, consider these restrictions:

• 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).

Code Reuse and Model Blocks with Root Inport or Outport


Blocks
A reusable subsystem function with input or output connected to the root Inport or
Outport block of a referenced model can affect code reuse. This can prevent you from
reusing atomic subsystems in a reference model context the same way you might reuse
the subsystems in a standalone model.

For example, consider this subsystem:

6-50
Generate Reusable Code From Referenced Models

Suppose that you make the following changes to the subsystem block parameters:

• Select “Treat as atomic unit” (Simulink).


• On the Code Generation tab, set “Function packaging” (Simulink) to Reusable
function.

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.

void reuse_subsys1_Subsystem(real_T rtu_In1, B_Subsystem_reuse_subsys1_T *localB)


{
localB->Gain = 3.0 * rtu_In1;
}

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).

The result is a single reusable function:

6-51
6 Code Reuse for Simulink Coder

void reuse_subsys1_Subsystem(real_T rtu_In1, B_Subsystem_reuse_subsys1_T *localB)


{
localB->Gain = 3.0 * rtu_In1;
}

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

Generate Reusable Code from Library Subsystems


Shared Across Models

What Is a Reusable Library Subsystem?


A reusable library subsystem is a subsystem included in a library that is configured for
reuse. You must define a subsystem in a library and configure it for reuse to reuse the
subsystem across models.

To reuse common functionality, you can include multiple instances of a subsystem:

• 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

Reusable Library Subsystem Code Placement and Naming


The generated code of a reusable library subsystem is independent of the generated code
of the model. Code for the reusable library subsystem is generated to the shared utility
folder, slprj/target/_sharedutils, instead of the model reference hierarchy folders.
The generated code for the supporting types, which are generated to the .h file, are also
in the shared utilities folder.

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:

• Function name: RLS_mgdjlngd


• File name: RLS_mgdjlnd.c and RLS_mgdjlnd.h

Configure Reusable Library Subsystem


Set the Subsystem parameters as listed here:

• Select Treat as an atomic unit.


• On the Code Generation tab:

• Set Function packaging to Reusable function.


• Set Function name options

and File name options to Auto, Use subsystem name, or User specified.

In a model reference hierarchy, if an instance of the reusable library subsystem is in the


top model, then on the Model Referencing pane of the Configuration Parameters dialog
box, you must select the Pass fixed-size scalar root input by value for code
generation parameter. If you do not select the parameter, a separate shared function is
generated for the reusable library subsystem instance in the top model, and a reusable
function is generated for instances in the referenced models.

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).

Configure Models That Include Reusable Library Subsystems


For a model to use a reusable library subsystem, you must configure the model differently
depending on whether the model is a reference model or top model. If the subsystem is in
a referenced model hierarchy, set the configuration parameter, “Shared code placement”
(Simulink Coder) to Auto. Otherwise, for each model that uses the subsystem, set the
model configuration parameter Shared code placement to Shared location.

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.

Generate Reusable Code for Subsystems Shared Across


Models
This example shows how to configure a reusable library subsystem and generate a
reusable function for a subsystem shared across referenced models. The result is reusable
code for the subsystem, which is generated to the shared utility folder (slprj/target/
_sharedutils).

• “Create a reusable library subsystem.” on page 6-55


• “Create the example model.” on page 6-58
• “Set configuration parameters of the top model.” on page 6-60
• “Create and propagate a configuration reference.” on page 6-60
• “Generate and view the code.” on page 6-61

Create a reusable library subsystem.

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:

• Select Treat as an atomic unit.


• On the Code Generation tab:

• Set Function packaging to Reusable function.


• Set Function name options to User specified and verify that the
Function name is set to myfun.
• Set File name options to Auto.
4 Click Apply and OK.

6-57
6 Code Reuse for Simulink Coder

5 Save the reusable library subsystem as ssreuselib, which creates a file,


ssreuselib.slx.

Create the example model.

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

Set configuration parameters of the top model.

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.

Create and propagate a configuration reference.

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

2 Right-click Configuration and select Convert to Configuration Reference.


3 In the Convert Active Configuration to Reference dialog box, click OK. This action
converts the model configuration set to a configuration reference,
Simulink.ConfigSetRef, and creates the configuration reference object,
configSetObj, in the base workspace.
4 In the left navigation column, right-click Reference (Active) and select Propagate
to Referenced Models.
5 In the Configuration Reference Propagation to Referenced Models dialog box, select
the referenced models in the list. Click Propagate.

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.

Generate and view the code.

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

Generate Reusable Code from Stateflow Atomic


Subcharts
Generate Reusable Code for Linked Atomic Subcharts
To specify code generation parameters for linked atomic subcharts from the same library:
1 Open the library model that contains your atomic subchart.
2 Unlock the library.
3 Right-click the library chart and select Block Parameters.
4 In the dialog box, specify the following parameters:
a On the Main tab, select Treat as atomic unit.
b On the Code Generation tab, set Function packaging to Reusable
function.
c Set File name options to User specified.
d For File name, enter the name of the file with no extension.
e Click OK to apply the changes.
5 (OPTIONAL) Customize the generated function names for atomic subcharts:
a Open the Model Configuration Parameters dialog box.
b On the Code Generation pane, set System target file to ert.tlc.
c Navigate to the Code Generation > Symbols pane.
d For Subsystem methods, specify the format of the function names using a
combination of the following tokens:

• $R — root model name


• $F — type of interface function for the atomic subchart
• $N — block name
• $H — subsystem index
• $M — name-mangling text
e Click OK to apply the changes.

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

Generate Reusable Code for Unlinked Atomic Subcharts


To specify code generation parameters for an unlinked atomic subchart:

1 In your chart, right-click the atomic subchart and select Properties.


2 In the dialog box, specify the following parameters:

a Set Code generation function packaging to Reusable function.


b Set Code generation file name options to User specified.
c For Code generation file name, enter the name of the file with no extension.
d Click OK to apply the changes.
3 (OPTIONAL) Customize the generated function names for atomic subcharts:

a Open the Model Configuration Parameters dialog box.


b On the Code Generation pane, set System target file to ert.tlc.
c Navigate to the Code Generation > Symbols pane.
d For Subsystem methods, specify the format of the function names using a
combination of the following tokens:

• $R — root model name


• $F — type of interface function for the atomic subchart
• $N — block name
• $H — subsystem index
• $M — name-mangling text
e Click OK to apply the changes.

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.

Generate Reusable Code for Unit Testing


Convert a State to an Atomic Subchart

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

Set Up a Standalone C File for the Atomic Subchart

1 Open the properties dialog box for A.


2 Set Code generation function packaging to Reusable function.
3 Set Code generation file name options to User specified.
4 For Code generation file name, enter saturator as the name of the file.
5 Click OK.

Set Up the Code Generation Report

1 Open the Model Configuration Parameters dialog box.


2 In the Code Generation pane, set System target file to ert.tlc.
3 In the Code Generation > Report pane, select Create code generation report.

This step automatically selects Open report automatically and Code-to-model.


4 Select Model-to-code.
5 Click Apply.

6-66
Generate Reusable Code from Stateflow Atomic Subcharts

Customize the Generated Function Names

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:

• $R is the root model name.


• $N is the block name.
• $M is the mangle token.
• $F is the type of interface function for the atomic subchart.

For more information, see “Subsystem methods” (Simulink Coder).


3 Click Apply.

Generate Code for Only the Atomic Subchart

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:

• $R is the root model name, ex_reuse_states.


• $N is the block name, A.
• $M is the mangle token, which is empty.
• $F is the type of interface function for the atomic subchart, during.

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

Generate Shared Utility Code

When to Generate Shared Utility Code


Blocks in a model can require common functionality to implement their algorithms.
Consider modularizing this functionality into standalone support or helper functions. This
approach can be more efficient than inlining the code for the functionality for each block
instance. To decide about using a library or a shared utility, consider:

• 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.

Configure Naming of Generated Functions


Configure a default naming rule for generated shared utility functions by using one of
these methods.

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.

This example shows the customization of shared utility function names.

1 Open the example model rtwdemo_crlmath.


2 Set model configuration parameter Shared code placement to Shared location.
3 Set parameter Shared utilities identifier format as mymodel_$N$C. You can
customize this format with any string. However, you must include token $C.
4 Set parameter Shared checksum length to 5.
5 Generate code and a code generation report.
6 In the left navigation pane of the report, review the list generated files for shared
utilities under Shared files.

Control Placement of Shared Utility Code


Control placement of shared utility code with the model configuration parameter Shared
code placement. The default option value is Auto. For this setting, the code generator
places required code for fixed-point and other utilities in the model.c file, the
model.cpp file, or a separate file in the build folder (for example, vdp_grt_rtw) if a
model does not contain existing shared utility code or one of these blocks:

• Model blocks

6-71
6 Code Reuse for Simulink Coder

• Simulink Function blocks


• Function Caller blocks
• Calls to Simulink Functions from Stateflow or MATLAB Function blocks
• Stateflow graphical functions when you select the Export Chart Level Functions
parameter

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 for Shared Utility Code


The generated rtwtypes.h header file provides fundamental type definitions, #define
statements, and enumerations. For more information, see “rtwtypes.h” on page 36-50.

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

• Clear the Support non-inlined S-functions parameter. If you use noninlined S-


functions in the model, this option generates an error.
• Clear the Classic call interface parameter. This parameter setting disables use of the
GRT system target file.

Avoid Duplicate Header Files for Exported Data


Exported header files appear in the shared utility folder when:

• 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.

Reduce Shared Utility Code Generation with Incremental


Builds
You can specify that the model build generates C source files in a shared utilities folder.
See “Generate Shared Utility Code” (Simulink Coder). These files include C source files
that contain function definitions and header files that contain macro definitions. For this
discussion, the term functions means functions and macros.

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.

Manage the Shared Utility Code Checksum


When you set the model configuration parameter Shared code placement to Shared
location or when the model contains Model blocks, the code generator places shared
code in the shared utilities folder. The build process generates a shared utilities checksum
of the code generation configuration for the shared code.

During subsequent code generation, if the checksum file slprj/target/


_sharedutils/checksummap.mat exists relative to the current folder, the code
generator reads that file. The code generator verifies that the current model that you are
building has configuration properties that match the checksum of properties from the
shared utility model. If mismatches occur between the properties defined in
checksummap.mat and the current model properties, you see an error. Use the error
message to manage the checksum (for example, diagnose and resolve the configuration
issues with the current model).

For more information, see “Reduce Shared Utility Code Generation with Incremental
Builds” (Simulink Coder).

• “View the Shared Utility Checksum Hash Table” on page 6-75


• “Relate the Shared Utility Checksum to Configuration Parameters” on page 6-76

6-74
Generate Shared Utility Code

View the Shared Utility Checksum Hash Table

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:

1 Open the rtwdemo_lct_start_term.slx model. In the Command Window, type:


rtwdemo_lct_start_term
2 Create and move to a new working folder.
mkdir C:\Temp\demo
cd C:\Temp\demo
3 Save a copy of the model in the folder.
4 Build the model. This model is already set up to produce shared utilities.
5 Move to the _sharedutils folder created by the build process.
cd C:\Temp\demo\slprj\grt\_sharedutils
6 Load the checksummap.mat file into MATLAB.
load checksummap
7 Display the contents of hashTbl.targetInfoStruct and examine the checksum-
related property values.
hashTbl.targetInfoStruct

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'

Relate the Shared Utility Checksum to Configuration Parameters

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.

The following table describes the key-value pairs.

Key Names Model Properties


ShiftRightIntArith TargetShiftRightIntArith
ProdShiftRightIntArith ProdShiftRightIntArith
Endianess TargetEndianess
ProdEndianess ProdEndianess

6-76
Generate Shared Utility Code

Key Names Model Properties


TargetBitPerChar,
TargetBitPerShort, TargetBitPerInt,
TargetBitPerLong,
wordlengths TargetBitPerLongLong,
TargetBitPerFloat,
TargetBitPerDouble,
TargetBitPerPointer
ProdBitPerChar, ProdBitPerShort,
ProdBitPerInt, ProdBitPerLong,
Prodwordlengths ProdBitPerLongLong,
ProdBitPerFloat, ProdBitPerDouble,
ProdBitPerPointer
TargetWordSize TargetWordSize
ProdWordSize ProdWordSize
TargetHWDeviceType TargetHWDeviceType
ProdHWDeviceType ProdHWDeviceType
TargetIntDivRoundTo TargetIntDivRoundTo
ProdIntDivRoundTo ProdIntDivRoundTo
tmfName TemplateMakefile
toolchainName Toolchain
computer return value of the computer command
UseDivisionForNetSlopeComputation UseDivisionForNetSlopeComputation
PurelyIntegerCode PurelyIntegerCode
PortableWordSizes PortableWordSizes
SupportNonInlinedSFcns SupportNonInlinedSFcns
EnableUserReplacementTypes,
RTWReplacementTypes
ReplacementTypes
MaxIdInt8 MaxIdInt8
MinIdInt8 MinIdInt8
MaxIdUint8 MaxIdUint8
MaxIdInt16 MaxIdInt16

6-77
6 Code Reuse for Simulink Coder

Key Names Model Properties


MinIdInt16 MinIdInt16
MaxIdUint16 MaxIdUint16
MaxIdInt32 MaxIdInt32
MinIdInt32 MinIdInt32
MaxIdUint32 MaxIdUint32
BooleanTrueId BooleanTrueId
BooleanFalseId BooleanFalseId
TypeLimitIdReplacementHeaderFile TypeLimitIdReplacementHeaderFile
SharedCodeRepository reserved (internal use only)
TargetLang TargetLang
PreserveExternInFcnDecls PreserveExternInFcnDecls
EnableSignedRightShifts EnableSignedRightShifts
EnableSignedLeftShifts EnableSignedLeftShifts
TflName CodeReplacementLibrary
TflCheckSum reserved (internal use only)
MemSecFuncSharedUtil,
UtilMemSecName
MemSecPackage
CodeCoverageChecksum reserved (internal use only)
TargetLargestAtomicInteger TargetLargestAtomicInteger
TargetLargestAtomicFloat TargetLargestAtomicFloat
ProdLargestAtomicInteger ProdLargestAtomicInteger
ProdLargestAtomicFloat ProdLargestAtomicFloat
LongLongMode TargetLongLongMode
ProdLongLongMode ProdLongLongMode
CollapseNonTrivialExpressions reserved (internal use only)

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

Generate Shared Utility Code for Fixed-Point Functions


An important set of generated functions that the model build places in the shared utility
folder are the fixed-point support functions. Based on model and block properties, there
are many possible versions of fixed-point utilities functions that make it impractical to
provide a complete set as static files. Generating only the required fixed-point utility
functions during the code generation process is an efficient alternative.

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 property-based naming convention for the fixed-point utilities is as follows:


operation + [zero protection] + output data type + output bits +
[input1 data] + input1 bits + [input2 data type + input2 bits] +
[shift direction] + [saturate mode] + [round mode]

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.

Operation FIX2FIX FIX2FIX ACCUM_POS MUL div div


Zero protection NULL NULL NULL NULL _nzp NULL
Output data type _U _S _S _S _s _s
Output bits 12 9 30 30 16 32
Input data type _U _S _S _S [and _S] s NULL
Input bits 16 9 30 30 [and 16] 32 NULL
Shift direction NULL SR99 NULL NULL NULL NULL
Saturate mode NULL NULL NULL NULL NULL _sat
Round mode NULL NULL NULL NULL _floor _floor

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

Generate Shared Utility Code for Custom Data Types


By default, if a model employs a custom data type (such as a Simulink.AliasType
object or an enumeration class), the code generator places the corresponding type
definition (typedef) in the model_types.h file. When you generate code from multiple
models, each model duplicates the type definition. These duplicate definitions can prevent
you from compiling the bodies of generated code together.

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).

Through this mechanism, you can share:

• 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).

To share a custom data type across multiple models:

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.

For an enumeration that you define by using the Simulink.defineIntEnumType


function, set the 'DataScope' pair argument to 'Exported' and, optionally, specify
the 'HeaderFile' pair argument
3 Use the data type in the models.

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

Shared Constant Parameters for Code Reuse


You can share the generated code for constant parameters across models if either of the
following conditions applies:

• Constant parameters are shared in a model reference hierarchy.


• The model configuration parameter “Shared code placement” (Simulink Coder) is set
to Shared location.

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:

• In the shared utility folder, slprj/grt/_sharedutils, the constant parameters are


defined in const_params.c and named rtCP_pooled_ appended to a unique
checksum:
extern const real_T rtCP_pooled_lfcjjmohiecj[7];
const real_T rtCP_pooled_lfcjjmohiecj[7] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };

extern const real_T rtCP_pooled_ppphohdbfcba[7];


const real_T rtCP_pooled_ppphohdbfcba[7] = { 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 };

• In top_model_private.h or in a referenced model, ref_model_private.h, for


better readability, the constants are renamed as follows:
extern const real_T rtCP_pooled_lfcjjmohiecj[7];
extern const real_T rtCP_pooled_ppphohdbfcba[7];

#define rtCP_Constant_Value rtCP_pooled_lfcjjmohiecj /* Expression: [1 2 3 4 5 6 7]


* Referenced by: '<Root>/Constant'*/
#define rtCP_Gain_Gain rtCP_pooled_ppphohdbfcba /* Expression: [7 6 5 4 3 2 1]
* Referenced by: '<Root>/Gain' */

• In topmod.c or refmod.c, the call site might be:


for (i = 0; i < 7; i++) {
topmod_Y.Out1[i] = (topmod_U.In1 + rtCP_Constant_Value[i]) * rtCP_Gain_Gain[i];
}

6-84
Shared Constant Parameters for Code Reuse

The code generator attempts to generate constants as individual constants to the


const_params.c file in the shared utilities folder. Otherwise, constants are generated as
described in “Code Generation of Constant Parameters” on page 3-13.

Suppress Shared Constants in the Generated Code


You can choose whether the code generator produces shared constants and shared
functions. You might want to be able to keep the code and data separate between
subsystems, or you might find that sharing constants results in a memory shortage during
code generation.

You can change this setting programmatically by using the parameter


GenerateSharedConstants with set_param and get_param.

In the following example, when GenerateSharedConstants is set to on, the code


generator defines the constant values in the_sharedutils folder in the
const_params.c file. When GenerateSharedConstants is set to off, the code
generator defines the constant values in a nonshared area, in the model_ert_rtw file in
the model_data.c file.

Open the model rtwdemo_throttlecntrl:

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

Shared code placement is set to Auto, the GenerateSharedConstants setting is


ignored. If you try to set the parameter value, an error message appears. The default
value of GenerateSharedConstants is on.

In the Command Window, set GenerateSharedConstants to on:


>> set_param('rtwdemo_throttlecntrl','GenerateSharedConstants','on')

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 } ;

extern const real_T rtCP_pooled_SghuHxKVKGHD[9];


const real_T rtCP_pooled_SghuHxKVKGHD[9] = { -1.0, -0.5, -0.25, -0.05, 0.0, 0.05,
0.25, 0.5, 1.0 } ;

extern const real_T rtCP_pooled_WqWb2t17NA2R[7];


const real_T rtCP_pooled_WqWb2t17NA2R[7] = { -1.0, -0.25, -0.01, 0.0, 0.01, 0.25,
1.0 } ;

extern const real_T rtCP_pooled_Ygnal0wM3c14[7];


const real_T rtCP_pooled_Ygnal0wM3c14[7] = { 1.0, 0.25, 0.0, 0.0, 0.0, 0.25, 1.0
} ;

In the Command Window, set GenerateSharedConstants to off:


>> set_param('rtwdemo_throttlecntrl','GenerateSharedConstants','off')

You can see the unshared constants in the folder rtwdemo_throttlecntrl_grt_rtw,


in the file rtwdemo_throttlecntrl_data.c:
/* Constant parameters (auto storage) */
const ConstP_rtwdemo_throttlecntrl_T rtwdemo_throttlecntrl_ConstP = {
/* Pooled Parameter (Expression: P_OutMap)
* Referenced by:
* '<S2>/Proportional Gain Shape'
* '<S3>/Proportional Gain Shape'
*/
{ 1.0, 0.25, 0.0, 0.0, 0.0, 0.25, 1.0 },

/* Pooled Parameter (Expression: P_InErrMap)


* Referenced by:
* '<S2>/Proportional Gain Shape'
* '<S3>/Proportional Gain Shape'
*/
{ -1.0, -0.25, -0.01, 0.0, 0.01, 0.25, 1.0 },

/* Pooled Parameter (Expression: I_OutMap)


* Referenced by:

6-86
See Also

* '<S2>/Integral Gain Shape'


* '<S3>/Integral Gain Shape'
*/
{ 1.0, 0.75, 0.6, 0.0, 0.0, 0.0, 0.6, 0.75, 1.0 },

/* Pooled Parameter (Expression: I_InErrMap)


* Referenced by:
* '<S2>/Integral Gain Shape'
* '<S3>/Integral Gain Shape'
*/
{ -1.0, -0.5, -0.25, -0.05, 0.0, 0.05, 0.25, 0.5, 1.0 }
};

Shared constant Parameters Limitations

No shared constants or shared functions are generated for a model when:

• 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.

Individual constants are not shared, if:

• A constant is referenced by a non-inlined S-function.


• A constant has a user-defined type where Data Scope is not set to Exported.

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

Configure Model Parameters for


Simulink Coder
7 Configure Model Parameters for Simulink Coder

Configure Run-Time Environment Options


When you use Simulink software to create and execute a model and use the code
generator to produce C or C++ code, consider your configuration for up to three run-time
environments:

• The MATLAB development computer run-time environment that runs MathWorks


software during application development.
• The production hardware run-time environment in which you deploy an application
when it is put into production.
• The test hardware run-time environment in which you test an application under
development before deployment.

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:

• Integer and fixed-point operations performed in simulation


• Generated code run on the production hardware
• Generated code run on the test hardware

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.

Configure Production and Test Hardware


You can specify model simulation or code generation for a specific hardware board and its
device type. For example, you can set the data size, byte ordering, and compiler behavior,
such as integer rounding. You can configure:

• 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.

Configure production hardware by selecting Configuration Parameters > Hardware


Implementation. By default, the Hardware Implementation pane lists Hardware board,
Device vendor, and Device type parameter fields only. Unless you have installed
hardware support packages, Hardware board lists values None or Determine by Code
Generation system target file, and Get Hardware Support Packages. After
installing a hardware support package, the list also includes the corresponding hardware
board name. If you select a hardware board name, parameters for that board appear. To
set device details, such as data size and byte ordering, click Device details.

Configure test hardware on the Configuration Parameters > Hardware


Implementation > Advanced parameters pane. To enable parameters for configuring
test hardware details, disable the Configuration Parameters > Hardware
Implementation > Advanced parameters > Test hardware is the same as
production hardware parameter. Code generated for test hardware executes in the
environment specified by the test hardware parameters. The code behaves as if it were
executing in the environment specified for the production hardware. For more
information, see “Test Hardware Considerations” on page 7-14.

Default values and properties appear as initial values in the Hardware Implementation
pane when:

• You specify a System target file in the Code Generation pane.


• The system target file specifies a default microprocessor and its hardware properties.

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.

Hardware implementation parameters describe hardware and compiler properties to


MATLAB software. The code generator uses the information to produce code for the run-
time environment that runs as efficiently as possible. The generated code gives bit-true
agreement for the results of integer and fixed-point operations in simulation, production
code, and test code.

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 Hardware Board” on page 7-4


• “Specify Device Vendor” on page 7-5
• “Specify the Device Type” on page 7-5
• “Register More Device Vendor and Device Type Values” on page 7-6
• “Set Bit Lengths for Device Data Types” on page 7-9
• “Set Byte Ordering for Device” on page 7-10
• “Set Quotient Rounding Behavior for Signed Integer Division” on page 7-10
• “Set Arithmetic Right Shift Behavior for Signed Integers” on page 7-11
• “Update Release 14 Hardware Configuration” on page 7-12

Specify Hardware Board

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 configure test hardware, use the Configuration Parameters > Hardware


Implementation > Advanced parameters pane.

To enable parameters for configuring test hardware details, set ProdEqTarget to off.

7-4
Configure Run-Time Environment Options

Ways to Specify the Hardware Board


If Select
The menu includes the name of the The name of that hardware board.
hardware board that you want to use.
If you select a hardware board name,
parameters for that board appear.
The menu does not include the name of Get Hardware Support Packages.
the hardware board that you want to
use. That value opens the Support Package Installer.
Install the support package that you want. After
you install the support package, the menu
includes relevant hardware board names.
The model configuration uses system None.
target file ert.tlc, realtime.tlc, or
autosar.tlc. No hardware board is specified for the
hardware implementation.
The model configuration does not use Determine by Code Generation system
system target file ert.tlc, target file.
realtime.tlc, or autosar.tlc.
The code generator uses the specified system
target file to determine the hardware
implementation.

Specify Device Vendor

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.

Specify the Device Type

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.

Register More Device Vendor and Device Type Values

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

function thisDev = loc_register_device


thisDev = RTW.HWDeviceRegistry;
thisDev.Vendor = 'MyDevVendor';
thisDev.Type = 'MyDevType';
thisDev.Alias = {};
thisDev.Platform = {'Prod', 'Target'};
thisDev.setWordSizes([8 16 32 32 32]);
thisDev.LargestAtomicInteger = 'Char';
thisDev.LargestAtomicFloat = 'None';
thisDev.Endianess = 'Unspecified';
thisDev.IntDivRoundTo = 'Undefined';
thisDev.ShiftRightIntArith = true;
thisDev.setEnabled({'IntDivRoundTo'});
end

After device registration, you can select the device in the Hardware Implementation
pane.

7-6
Configure Run-Time Environment Options

To register multiple devices, specify an array of RTW.HWDeviceRegistry objects in your


sl_customization.m file. For example:

function sl_customization(cm)
cm.registerTargetInfo(@loc_register_device);
end

function thisDev = loc_register_device

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

You can specify various RTW.HWDeviceRegistry properties in the


registerTargetInfo function call in your sl_customization.m file.

7-7
7 Configure Model Parameters for Simulink Coder

Properties for registerTargetInfo Function Call

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'.

Embedded Coder software provides the utility functions


RTW.isHWDeviceTypeEq and RTW.resolveHWDeviceType.
These functions detect and resolve alias values or legacy
values when testing user-specified values for the hardware
device type.
Platform Cell array of enumerated character vector values specifying
whether this device can be listed in the Production
hardware subpane ({'Prod'}), the Test hardware subpane
({'Target'}), or both ({'Prod', 'Target'}).
setWordSizes Array of integer sizes to associate with the Number of bits
parameters char, short, int, long, and native word size,
respectively.
LargestAtomicIntege Character vector specifying an enumerated value for the
r Largest atomic size: integer parameter: 'Char',
'Short','Int', or 'Long'.
LargestAtomicFloat Character vector specifying an enumerated value for the
Largest atomic size: floating-point parameter: 'Float',
'Double', or 'None'.
Endianess Character vector specifying an enumerated value for the Byte
ordering parameter: 'Unspecified', 'Little' for little
Endian, or 'Big' for big Endian.
IntDivRoundTo Character vector specifying an enumerated value for the
Signed integer division rounds to parameter: 'Zero',
'Floor', or 'Undefined'.

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.

This property applies for the 'Endianess',


'IntDivRoundTo', and 'ShiftRightIntArith'
properties. You can apply this property to individual Number
of bits parameters by using the property names
'BitPerChar', 'BitPerShort', 'BitPerInt',
'BitPerLong', and 'NativeWordSize'.

Set Bit Lengths for Device Data Types

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.

Mapping of Integer Types from Code Generator to Simulink

Code Generator Integer Type Simulink Integer Type


boolean_T boolean
int8_T int8
uint8_T uint8
int16_T int16
uint16_T uint16
int32_T int32
uint32_T uint32

Set Byte Ordering for Device

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.

Set Quotient Rounding Behavior for Signed Integer Division

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.

The compiler quotient rounding behavior varies according to these values.

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.

Example Quotient Rounding for Zero, Floor, and Undefined

N D Ideal N/D Zero Floor Undefined


33 4 8.25 8 8 8
-33 4 -8.25 -8 -9 -8 or -9
33 -4 -8.25 -8 -9 -8 or -9
-33 -4 8.25 8 8 8 or 9

Set Arithmetic Right Shift Behavior for Signed Integers

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.

Update Release 14 Hardware Configuration

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');

This update to your model:

• Enables the Test Hardware is the same as production hardware parameter


(ProdEqTarget), setting the parameter to 'on'.
• Copies the Production device vendor and type parameter (ProdHWDeviceType)
value to the Test device vendor and type parameter (TargetHWDeviceType).

To complete the update:

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 Considerations


When you configure production hardware, consider these points:

• 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

Test Hardware Considerations


By default, the test hardware configuration is the same as the configuration for the
production hardware. You can use the generated code for testing in an environment that
is identical to the production environment.

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.

Example Production Hardware Setting That Affects Normal


Mode Simulation
Changing some production hardware settings, for example, ProdLongLongMode and
ProdIntDivRoundTo, can affect normal mode simulation results. The following example
simulates an adder with four inputs. In the first simulation, ProdLongLongMode is
disabled. In the second simulation, ProdLongLongMode is enabled. In the plot of
simulation outputs, you observe small differences between output values in the time step
range 125–175.
model = 'hwSettingEffect';
new_system(model)
open_system(model)

% 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)

pos = [75 155 105 175];


add_block('built-in/Inport',[model '/In1'],'Position',pos)
set_param([model '/In1'], 'OutDataTypeStr', ...
'int32','PortDimensions','1','SampleTime','1');
add_line(model, 'In1/1','sum_int32/1')

pos = [75 205 105 225];


add_block('built-in/Inport',[model '/In2'],'Position',pos)
set_param([model '/In2'], 'OutDataTypeStr', ...
'int32','PortDimensions','1','SampleTime','1');
add_line(model, 'In2/1','sum_int32/2')

pos = [75 255 105 275];


add_block('built-in/Inport',[model '/In3'],'Position',pos)
set_param([model '/In3'], 'OutDataTypeStr', ...
'int32','PortDimensions','1','SampleTime','1');
add_line(model, 'In3/1','sum_int32/3')

pos = [75 305 105 325];


add_block('built-in/Inport',[model '/In4'],'Position',pos)
set_param([model '/In4'], 'OutDataTypeStr', ...
'int32','PortDimensions','1','SampleTime','1');
add_line(model, 'In4/1','sum_int32/4')

pos = [275 230 305 250];


add_block('built-in/Outport',[model '/Out1'],'Position',pos)
add_line(model, 'sum_int32/1','Out1/1')

% Specify input data


t = 0:200;
peakValue = 1.5e9;
in1 = peakValue * sin(t*2*pi/100);
in2 = peakValue * cos(t*2*pi/70);
in3 = -peakValue * sin(t*2*pi/40);
in4 = -peakValue * cos(t*2*pi/30);
set = Simulink.SimulationData.Dataset;
set = set.addElement(1, timeseries(int32(in1),t,'Name','sig1'));
set = set.addElement(2, timeseries(int32(in2),t,'Name','sig2'));
set = set.addElement(3, timeseries(int32(in3),t,'Name','sig3'));
set = set.addElement(4, timeseries(int32(in4),t,'Name','sig4'));

set_param(model, 'LoadExternalInput', 'on');


set_param(model, 'ExternalInput', 'set');

set_param(model, 'StopTime', '50');

% Disable production hardware setting and run first simulation


set_param(model, 'ProdLongLongMode', 'off');
[~, ~, y1] = sim(model, 200);

7-15
7 Configure Model Parameters for Simulink Coder

% Enable production hardware setting and run second simulation


set_param(model, 'ProdLongLongMode', 'on');
[~, ~, y2] = sim(model, 200);

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

Model Protection in Simulink Coder

• “Protect Models for Third-Party Use” on page 8-2


• “Harness Model” on page 8-4
• “Protected Model Report” on page 8-5
• “Code Generation Support in Protected Models” on page 8-6
• “Protected Model File” on page 8-9
• “Create a Protected Model” on page 8-11
• “Protected Model Creation Settings” on page 8-16
• “Create a Protected Model with Multiple Targets” on page 8-19
• “Use a Protected Model with Multiple Targets” on page 8-21
• “Test the Protected Model” on page 8-22
• “Save Base Workspace Definitions” on page 8-24
• “Package a Protected Model” on page 8-25
• “Specify Custom Obfuscator for Protected Model” on page 8-26
• “Define Callbacks for Protected Models” on page 8-28
8 Model Protection in Simulink Coder

Protect Models for Third-Party Use


Protect a model when you want to share a model with a third party without revealing
intellectual property. Protecting a model does not use encryption technology unless you
use the optional password protection available for read-only view, simulation, and code
generation. If you choose password protection for one of these options, the software
protects the supporting files by using AES–256 encryption.

When you create a protected model (Simulink):

• 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.

Create a protected model by using one of these options:

• 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.

Requirements for Protecting a Model


To protect a model, the model must meet all requirements listed in “Model Referencing
Limitations” (Simulink) and these requirements:

• You must have a Simulink Coder license to create a protected model.


• The model must be available on the MATLAB path.
• The model cannot have unsaved changes.
• The model cannot use a noninlined S-function directly or indirectly.
• All protected referenced models must support simulation in Accelerator mode. The
protected referenced model creator must select Simulate in the Create Protected
Model dialog box or set the 'Mode' to 'Accelerator' or 'CodeGeneration' by
using the Simulink.ModelReference.protect function.
• All protected referenced models must use the default 'CodeInterface' setting:
'Model reference'.
• Protected referenced models cannot have password protection on simulation.
• Protected referenced models cannot have callbacks.
• The model cannot support operations that a protected referenced model does not
support or supports with password protection. For example, a protected model can
support code generation only if all protected referenced models support code
generation without password protection.
• When protecting a model for code generation, the model must use a Content type
that is compatible with the Content type of each protected referenced model. See
“Code Generation Support in Protected Models” (Simulink Coder).

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

Protected Model Report


You can generate a protected model report when you create the protected model. The
report is included as part of the protected model. The report has:

• A Summary, including the following tables:

• 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

Code Generation Support in Protected Models


You can create a protected model that supports code generation. When a protected model
includes generated code, a third party can generate code for a model that includes the
protected model. If you choose to obfuscate the code, the code is obfuscated before
compilation. The protected model file contains only headers and binaries. Source code,
such as .c and .cpp, is not present in the protected model file, although the headers are
documented in the protected model report. For more information, see “Protected Model
File” on page 8-9 and “Protected Model Report” on page 8-5.

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.

When you create a protected model that supports code generation:

• 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.

Protected Model Requirements to Support Code Generation


Contents and configuration of a model can prevent code generation support of the
protected model. Interaction between the parent model and the protected referenced
model can also prevent code generation.

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:

• The protected model must use normal, accelerator, software-in-the-loop (SIL), or


processor-in-the-loop (PIL) mode and a single target.

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.

Code Generation Content Type Compatibility

Protected Parent Model Content Compatible Protected Referenced


Type Model Content Types
Binaries • Binaries
• Obfuscated source code
Binaries with 'ObfuscateCode' set • Binaries
to 'false' • Binaries with 'ObfuscateCode'
set to 'false'
• Obfuscated source code
• Readable source code
Obfuscated source code • Obfuscated source code
Readable source code • Obfuscated source code
• Readable source code

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

Protected Model File


A protected model file (.slxp) consists of the model itself and supporting files, depending
on the options that you selected when you created the protected model.

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

Create a Protected Model


This example shows how to create a protected model for read-only viewing, simulation, or
code generation.

1 Open your model. For this example, sldemo_mdlref_basic is used as a


demonstration.
2 In the Simulink Editor, right-click the model block that references the model for
which you want to generate protected model code. In this example, right-click
CounterA.
3 From the context menu, select Block Parameters (ModelReference).
4 In the Block Parameters dialog box, in the Model name field, specify the extension
for the model, .slx. When both the model and the protected model exist in the same
folder, .slxp takes precedence over .slx. In the Model name field, if you do not
specify an extension, then the original model block in the model becomes protected.
5 Click OK.
6 Right-click the model block. From the context menu, select Subsystem & Model
Reference > Create Protected Model for Selected Model Block.

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

Note In this example, sldemo_mdlref_basic does not specify an ERT-based


system target file, therefore the Code interface options are not available on the
Create Protected Model dialog box.
9 From the Content type list, select Obfuscated source code to conceal the
source code purpose and logic of the protected model.
10 In the Create protected model in field, specify the folder path for the protected
model. The default value is the current working folder.
11 To create a harness model for the protected model, select the Create harness
model for protected model check box.
12 Click Create. An untitled harness model opens. It contains a model block, which
refers to the protected model sldemo_mdlref_counter.slxp. The Simulation
mode for the Model block is set to Accelerator. You cannot change the mode.

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

Protected Model Creation Settings


When you create a protected model, in the Create Protected Model dialog box, you can
select which settings you want configured. The settings provide certain functionality
permissions when using a protected model. The functionality choices are:

• Read-only viewing
• Simulation
• Code Generation

Password-protection is optional. You must have a minimum of four characters.

8-16
Protected Model Creation Settings

Open Read-Only View of Model


If you want to share a view-only version of your model, this option allows someone using
the protected model to open a Web view of the model. The contents and block parameters
are viewable in the model Web view.

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:

• Enables protected model Simulation Report.


• Sets Mode to Accelerator. You can run Normal Mode and Accelerator simulations.
• Displays only binaries and headers.
• Enables code obfuscation.

Use Generated Code


The Use generated code check box allows simulation and code generation for a
protected model. To generate code, the Simulate check box must also be selected. This
functionality:

• Enables protected model Simulation Report and Code Generation Report.


• Sets Mode to enable code generation.
• Enables support for simulation.
• Supports the Model block if you have an Embedded Coder license and specify an ERT
system target file (ert.tlc) for the model. From the Code interface drop-down list,
select one of the following options:

• 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

Create a Protected Model with Multiple Targets


You can create a protected model that supports multiple code generation targets. This
example shows how to use command-line functions to create a protected model that
supports code generation for GRT and ERT 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.

set_param('mdlref_counter', 'SystemTargetFile', 'ert.tlc');


save_system('mdlref_counter');
6 Add support to the protected model for the ERT target. You are prompted for the
modification password.

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 =

'ert' 'grt' 'sim'

8-20
Use a Protected Model with Multiple Targets

Use a Protected Model with Multiple Targets


When using a protected model with multiple targets, prepare your model for code
generation.

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

Test the Protected Model


To test a protected model that you created, you use the generated harness model and the
procedure described in “Simulate a Protected Model” (Simulink).

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.

1 If it is not already open, open sldemo_mdlref_basic.


2 Enable logging for the output signal of the Model block, CounterA. In the
Configuration Parameters dialog box, in the Data Import/Export pane, select the
Signal logging parameter. Click Apply and OK.
3 Right-click the output signal. From the context menu, select Properties. In the
Signal Properties dialog box, select Log signal data. Click Apply and OK. For more
information, see “Export Signal Data Using Signal Logging” (Simulink).
4 Right-click the CounterA block. From the context menu, select Block Parameters
(ModelReference). In the Block Parameters dialog box, specify the Model name
parameter with the name of the unprotected model and the extension,
sldemo_mdlref_counter.slx. Click Apply and OK. Repeat this step for
CounterB block and CounterC block.
5 In the Simulink Editor, click the Simulation Data Inspector button arrow and select
Send Logged Workspace Data to Data Inspector from the menu.
6 Simulate the model. When the simulation is complete, click the Simulation Data
Inspector button to open the Simulation Data Inspector.
7 In the Simulation Data Inspector, rename the run to indicate that it is for the
unprotected model.
8 In the Simulink Editor, right-click the CounterA block. From the context menu,
select Block Parameters (ModelReference). In the Block Parameters dialog

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

Save Base Workspace Definitions


Referenced models can use object definitions or tunable parameters that are defined in
the MATLAB base workspace. These variables are not saved with the model. When you
protect a model, you must obtain the definitions of required base workspace entities and
ship them with the model.

The following base workspace variables must be saved to a MAT-file:

• Global tunable parameter


• Global data store
• The following objects used by a signal that connects to a root-level model Inport or
Outport:

• 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

Package a Protected Model


In addition to the protected model file (.slxp), you can include additional files in the
protected model package:

• Harness model file.


• Any required definitions saved in a MAT-file. For more information, see “Save Base
Workspace Definitions” on page 8-24.
• Instructions on how to retrieve the files.

Some ways to deliver the protected model package are:

• 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

Specify Custom Obfuscator for Protected Model


When creating a protected model, you can specify your own postprocessing function for
files that the protected model creation process generates. Before packaging the protected
model files, this function is called by the Simulink.ModelReference.protect
function. You can use this functionality to run your own custom obfuscator on the
generated files by following these steps:

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)

% Get source file list information.


srcFileList = protectedModelInfo.SourceFiles;
disp('### Obfuscating...');
for i=1:length(srcFileList)
disp(['### Obfuscator: Processing ' srcFileList{i} '...']);
% call to custom obfuscator
customObfuscator(srcFileList{i});
end
end
4 Specify your postprocessing function when creating the protected model:

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

Define Callbacks for Protected Models


When you create a protected model, you can customize its behavior by defining callbacks.
Callbacks specify code that executes when you view, simulate, or generate code for the
protected model. A protected model user cannot view or modify a callback. If a model
references a protected model with callbacks, you cannot protect the model.

To create a protected model with callbacks:

1 Define Simulink.ProtectedModel.Callback objects for each callback.


2 To create your protected model, call the Simulink.ModelReference.protect
function. Use the 'Callbacks' option to specify a cell array of callbacks to include
in the protected model.

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.

Defining Callback Code


You can define the code for a callback by using either a character vector of MATLAB
commands or a script on the MATLAB path. When you write callback code, follow these
guidelines:

8-28
Define Callbacks for Protected Models

• Callbacks must use MATLAB code (.m or .p).


• The code can include protected model functions or any MATLAB command that does
not require loading the model.
• Callback code must not call out to external utilities unless those utilities are available
in the environment where the protected model is used.
• Callback code cannot reference the source protected model unless you are using
protected model functions.

You can use the Simulink.ProtectedModel.getCallbackInfo function in callback


code to get information on the protected model. The function returns a
Simulink.ProtectedModel.CallbackInfo object that provides the protected model
name and the names of submodels. If the callback is specified for 'CODEGEN'
functionality and 'Build' event, the object provides the target identifier and model code
interface type ('Top model' or 'Model reference').

Create a Protected Model with Callbacks


This example creates a protected model with a callback for code generation.

1 On the MATLAB path, create a callback script, pm_callback.m, containing:

s1 = 'Code interface is: ';


cbinfobj = Simulink.ProtectedModel.getCallbackInfo(...
'sldemo_mdlref_counter','Build','CODEGEN');
disp([s1 cbinfobj.CodeInterface]);
2 Create a callback that uses the script. If the callback code replaces the protected
model build process, set the override option.

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

Component Initialization, Reset, and


Termination in Simulink Coder
9 Component Initialization, Reset, and Termination in Simulink Coder

Generate Code That Responds to Initialize, Reset, and


Terminate Events
To generate code from a modeling component that responds to initialize, reset, and
terminate events during execution, use the blocks Initialize Function and Terminate
Function. For information on how to use these blocks, see “Customize Initialize, Reset,
and Terminate Functions” (Simulink). You can use the blocks anywhere in a model
hierarchy.

Examples of when to generate code that responds to initialize, reset, or terminate events
include:

• Starting and stopping a component.


• Calculating initial conditions.
• Saving and restoring state from nonvolatile memory.
• Generating reset entry-point functions that respond to external events.

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.

Generate Code for Initialize and Terminate Events


When you generate code for a component that includes Initialize Function and Terminate
Function blocks, the code generator:

• 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.

Consider the model rtwdemo_irt_base.

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:

• Initializes an error status.


• Allocates memory for block I/O and state parameters.
• Sets the output value
• Sets the initial condition for the discrete integrator.

The terminate function, ,rtwdemo_irt_base_terminate, requires no code.

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));

(void) memset((void *)&rtwdemo_irt_base_DW, 0,


sizeof(DW_rtwdemo_irt_base_T));

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));

(void) memset((void *)&rtwdemo_irt__initterm_DW, 0,


sizeof(DW_rtwdemo_irt__initterm_T));

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) */
}

Generate Code for Reset Events


Generate code that responds to a reset event by including an Initialize Function or
Terminate Function block in a modeling component. Configure the block for a reset by
setting the Event type parameter of its Event Listener block to Reset. Also set the Event
name parameter. The default name is reset.

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

The code generator produces reset function rtwdemo_irt_reset_reset.

void rtwdemo_irt_reset_reset(void)

{
rtwdemo_irt_reset_DW.DiscreteIntegrator_DSTATE = 5.0;
}

Event Names and Code Aggregation


Use the Initialize Function and Terminate Function blocks to define multiple initialize,
reset, and terminate functions for a component hierarchy. Define only one initialize
function and one terminate function per hierarchy level. You can define multiple reset
functions for a hierarchy level. The event names that you configure for the functions at a
given level must be unique.

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

(rtwdemo_irt_shared_reset), one for initialize


(rtwdemo_irt_shared_initialize), and one for terminate
(rtwdemo_irt_shared_terminate). Within each entry-point function, after listing code
for blocks configured with an initial condition (model_P.block_IC), the code generator
orders code for components, starting with the lowest level of the hierarchy and ending
with the root.

.
.
.
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));

(void) memset(((void *)&rtwdemo_irt_shared_DW), 0,


sizeof(DW_rtwdemo_irt_shared_T));

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

Stateflow Blocks in Simulink Coder

• “Code Generation of Stateflow Blocks” on page 10-2


• “Generate Reusable Code for Atomic Subcharts” on page 10-6
• “Generate Reusable Code for Unit Testing” on page 10-8
• “Inline State Functions in Generated Code” on page 10-14
• “Air-Fuel Ratio Control System with Stateflow Charts” on page 10-17
10 Stateflow Blocks in Simulink Coder

Code Generation of Stateflow Blocks


The code generator produces code for Stateflow blocks for rapid prototyping. If you have
an Embedded Coder license, you can generate production code for Stateflow blocks.

Comparison of Code Generation Methods


The following sections compare two ways of generating code.

Code Generation Without Atomic Subcharts

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

Code Generation With Atomic Subcharts

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

Generate Reusable Code for Atomic Subcharts


In this section...
“How to Generate Reusable Code for Linked Atomic Subcharts” on page 10-6
“How to Generate Reusable Code for Unlinked Atomic Subcharts” on page 10-7

How to Generate Reusable Code for Linked Atomic Subcharts


To specify code generation parameters for linked atomic subcharts from the same library:

1 Open the library model that contains your atomic subchart.


2 Unlock the library.
3 Right-click the library chart and select Block Parameters.
4 In the dialog box, specify the following parameters:

a On the Main tab, select Treat as atomic unit.


b On the Code Generation tab, set Function packaging to Reusable
function.
c Set File name options to User specified.
d For File name, enter the name of the file with no extension.
e Click OK to apply the changes.
5 (OPTIONAL) Customize the generated function names for atomic subcharts:

a Open the Model Configuration Parameters dialog box.


b On the Code Generation pane, set System target file to ert.tlc.
c Navigate to the Code Generation > Symbols pane.
d For Subsystem methods, specify the format of the function names using a
combination of the following tokens:

• $R — root model name


• $F — type of interface function for the atomic subchart
• $N — block name
• $H — subsystem index
• $M — name-mangling text

10-6
Generate Reusable Code for Atomic Subcharts

e Click OK to apply the changes.

When you generate code for your model, a separate file stores the code for linked atomic
subcharts from the same library.

How to Generate Reusable Code for Unlinked Atomic


Subcharts
To specify code generation parameters for an unlinked atomic subchart:

1 In your chart, right-click the atomic subchart and select Properties.


2 In the dialog box, specify the following parameters:

a Set Code generation function packaging to Reusable function.


b Set Code generation file name options to User specified.
c For Code generation file name, enter the name of the file with no extension.
d Click OK to apply the changes.
3 (OPTIONAL) Customize the generated function names for atomic subcharts:

a Open the Model Configuration Parameters dialog box.


b On the Code Generation pane, set System target file to ert.tlc.
c Navigate to the Code Generation > Symbols pane.
d For Subsystem methods, specify the format of the function names using a
combination of the following tokens:

• $R — root model name


• $F — type of interface function for the atomic subchart
• $N — block name
• $H — subsystem index
• $M — name-mangling text
e Click OK to apply the changes.

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

Generate Reusable Code for Unit Testing


In this section...
“Goal of the Tutorial” on page 10-8
“Convert a State to an Atomic Subchart” on page 10-9
“Specify Code Generation Parameters” on page 10-10
“Generate Code for Only the Atomic Subchart” on page 10-11

Goal of the Tutorial


Assume that you have the following model, and the chart has two states:

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.

Convert a State to an Atomic Subchart


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:

10-9
10 Stateflow Blocks in Simulink Coder

Specify Code Generation Parameters


Set Up a Standalone C File for the Atomic Subchart

1 Open the properties dialog box for A.


2 Set Code generation function packaging to Reusable function.
3 Set Code generation file name options to User specified.
4 For Code generation file name, enter saturator as the name of the file.
5 Click OK.

Set Up the Code Generation Report

1 Open the Model Configuration Parameters dialog box.


2 In the Code Generation pane, set System target file to ert.tlc.
3 In the Code Generation > Report pane, select Create code generation report.

This step automatically selects Open report automatically and Code-to-model.

10-10
Generate Reusable Code for Unit Testing

4 Select Model-to-code.
5 Click Apply.

Customize the Generated Function Names

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:

• $R is the root model name.


• $N is the block name.
• $M is the mangle token.
• $F is the type of interface function for the atomic subchart.

For more information, see “Subsystem methods” (Simulink Coder).


3 Click Apply.

Generate Code for Only the Atomic Subchart


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:

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:

• $R is the root model name, ex_reuse_states.


• $N is the block name, A.
• $M is the mangle token, which is empty.
• $F is the type of interface function for the atomic subchart, during.

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

Inline State Functions in Generated Code

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

Inlined Generated Code for State Functions


By default, the code generator uses an internal heuristic to determine whether to inline
generated code for state functions. The heuristic takes into consideration an inlining
threshold. As code grows and shrinks in size, generated code for state functions can be
unpredictable.

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.

What Happens When You Force Inlining

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.

What Happens When You Prevent Inlining

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.

The code generator produces this function


only when the flow chart is complex enough
to exceed the inlining threshold.

In generated code, Stateflow software calls


this function from both the
enter_internal_foo and foo functions.
foo Checks for valid outer transitions and if
none, performs during actions.
exit_atomic_foo Performs exit actions and marks foo
inactive.
exit_internal_foo Performs exit actions of the child substates
and then exits foo.

Suppose the following chart is in model M.

If you prevent inlining for state A, the code generator produces this code.

10-15
10 Stateflow Blocks in Simulink Coder

static void M_inner_default_A(void);


static void M_exit_atomic_A(void);
static void M_A(void);
static void M_enter_atomic_A(void);
static void M_enter_internal_A(void);

How to Set the State Function Inline Option


To set the function inlining property for a state:

1 Right-click inside the state and, from the context menu, select Properties.

The State properties dialog box opens.


2 In the Function Inline Option field, select one of these options.

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.

Best Practices for Controlling State Function Inlining


To Set Function Inline Option Property To
Generate a separate function for each Function for the state and each substate
action of a state and a separate function for
each action of its substates
Generate a separate function for each Function for the state and Inline for each
action of a state, but include code for the substate
associated action of its substates

10-16
Air-Fuel Ratio Control System with Stateflow Charts

Air-Fuel Ratio Control System with Stateflow Charts


Generate code for an air-fuel ratio control system designed with Simulink® and
Stateflow®.

Figures 1, 2, and 3 show relevant portions of the sldemo_fuelsys model, a closed-loop


system containing a plant and controller. The plant validates the controller in simulation
early in the design cycle. In this example, you generate code for the relevant controller
subsystem, "fuel_rate_control". Figure 1 shows the top-level simulation model.

Open sldemo_fuelsys via rtwdemo_fuelsys and compile the diagram to see the signal data
types.

rtwdemo_fuelsys
sldemo_fuelsys([],[],[],'compile');
sldemo_fuelsys([],[],[],'term');

Figure 1: Top-level model of the plant and controller

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');

Figure 2: The air-fuel ratio controller subsystem

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

Figure 3: Air-fuel rate controller logic

Close these windows.

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

Configure and Build the Model with 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');

### Starting build procedure for model: fuel_rate_control


### Successful completion of build procedure for model: fuel_rate_control

Configure and Build the Model with Embedded Coder®

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')

### Starting build procedure for model: fuel_rate_control


### Successful completion of build procedure for model: fuel_rate_control

View the air-fuel ratio control logic in the generated code.


rtwdemodbtype('fuel_rate_control_ert_rtw/fuel_rate_control.c','/* Function for Chart:',

/* Function for Chart: '<S1>/control_logic' */


static void Fueling_Mode(const int32_T *sfEvent)
{
/* This state interprets the other states in the chart to directly control the fuelin

10-20
Air-Fuel Ratio Control System with Stateflow Charts

switch (rtDW.bitsForTID0.is_Fueling_Mode) {
case IN_Fuel_Disabled:
rtDW.fuel_mode = DISABLED;

/* The fuel is completely shut off while in this state. */


switch (rtDW.bitsForTID0.is_Fuel_Disabled) {
case IN_Overspeed:
/* Inport: '<Root>/sensors' */
/* The speed is dangerously high, so shut off the fuel. */
if ((rtDW.bitsForTID0.is_Speed == IN_normal) && (rtU.sensors.speed <
603.0F)) {
if (!(rtDW.bitsForTID0.is_Fail == IN_Multi)) {
rtDW.bitsForTID0.is_Fuel_Disabled = IN_NO_ACTIVE_CHILD;
rtDW.bitsForTID0.is_Fueling_Mode = IN_Running;
switch (rtDW.bitsForTID0.was_Running) {
case IN_Low_Emissions:
if (rtDW.bitsForTID0.is_Running != IN_Low_Emissions) {
rtDW.bitsForTID0.is_Running = IN_Low_Emissions;
rtDW.bitsForTID0.was_Running = IN_Low_Emissions;
rtDW.fuel_mode = LOW;
}

switch (rtDW.bitsForTID0.was_Low_Emissions) {
case IN_Normal:
rtDW.bitsForTID0.is_Low_Emissions = IN_Normal;
rtDW.bitsForTID0.was_Low_Emissions = IN_Normal;
break;

Close the model and code generation report.

clear hDemo;
rtwdemoclean;
close_system('sldemo_fuelsys',0);

Related Examples

For related fixed-point examples that use sldemo_fuelsys, see

• Fixed-point design - “Fixed-Point Fuel Rate Control System” (Fixed-Point Designer)


• Fixed-point production C/C++ code generation - “Air-Fuel Ratio Control System
with Fixed-Point Data” (Simulink Coder)

10-21
11

Block Authoring and Code


Generation for Simulink Coder

• “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
• “External Code Integration Examples” on page 11-51
• “Generate S-Function from Subsystem” on page 11-62
• “Write S-Function and TLC Files By Hand” on page 11-67
11 Block Authoring and Code Generation for Simulink Coder

S-Functions and Code Generation

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:

• Represent custom algorithms


• Interface existing external code with Simulink and the code generator
• Represent device drivers for interfacing with hardware
• Generate highly optimized code for embedded systems
• Verify code generated for a subsystem as part of a Simulink simulation

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.

This content assumes that you understand the following concepts:

• Level 2 S-functions

11-2
S-Functions and Code Generation

• Target Language Compiler (TLC) scripting


• How the code generator produces and builds C/C++ code

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.”

Respectively, the preceding situations map to the following MathWorks terminology:

1 Noninlined S-function
2 Inlined S-function
3 Autogenerated S-function for external code

Noninlined S-Functions

A noninlined S-function is a C or C++ MEX S-function that is treated identically by the


Simulink engine and generated code. In general, you implement your algorithm once
according to the S-function API. The Simulink engine and generated code call the S-
function routines (for example, mdlOutputs) during model execution.

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)

Autogenerated S-Functions for Legacy or Custom Code

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.

Files Required for Implementing Noninlined and Inlined S-


Functions
This topic briefly describes what files and functions you need to create noninlined and
inlined S-functions.

• Noninlined S-functions require the C or C++ MEX S-function source code


(sfunction.c or sfunction.cpp).
• Fully inlined S-functions require an sfunction.tlc file. Fully inlined S-functions
produce the optimal code for a parameterized S-function. This is an S-function that
operates in a specific mode dependent upon fixed S-function parameters that do not
change during model execution. For a given operating mode, the sfunction.tlc file
specifies the exact code that is generated to implement the algorithm for that mode.
For example, the direct-index lookup table S-function in “Write Fully Inlined S-
Functions with mdlRTW Routine” on page 11-79 contains two operating modes — one
for evenly spaced x-data and one for unevenly spaced x-data.

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

Guidelines for Writing S-Functions that Support Code


Generation
• You can use C/C++ MEX, MATLAB language, and Fortran MEX S-functions with code
generation.
• You can inline S-functions for code generation by providing an inlining TLC file. See S-
Function Inlining in “Target Language Compiler” (Simulink Coder). MATLAB and
Fortran MEX S-functions must be inlined. C/C++ MEX S-functions can be inlined for
code efficiency, or noninlined.
• To automatically generate a fully inlined C MEX S-function for invoking legacy or
custom code, use the Legacy Code Tool. 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” (Simulink Coder).
• If code efficiency is not an overriding consideration, for example, if you are rapid
prototyping, you can choose not to inline a C/C++ MEX S-function. For more
information, see “Write Noninlined S-Function and TLC Files” on page 11-67.

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

Import Calls to External Code into Generated Code with


Legacy Code Tool
In this section...
“Legacy Code Tool and Code Generation” on page 11-7
“Generate Inlined S-Function Files for Code Generation” on page 11-8
“Apply Code Style Settings to Legacy Functions” on page 11-9
“Address Dependencies on Files in Different Locations” on page 11-9
“Deploy S-Functions for Simulation and Code Generation” on page 11-10
“Integrate External C++ Object Methods” on page 11-11
“Integrate External C++ Objects” on page 11-14
“Legacy Code Tool Examples” on page 11-16

Legacy Code Tool and Code Generation


You can use the Simulink Legacy Code Tool to generate fully inlined C MEX S-functions
for legacy or custom code. The S-functions are optimized for embedded components, such
as device drivers and lookup tables, and they call existing C or C++ functions.

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).

You can use the tool to:

• Compile and build the generated S-function for simulation.


• Generate a masked S-Function block that is configured to call the existing external
code.

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

sFunction_makecfg.m or rtwmakecfg.m file for the S-function. Generating the file


maintains those dependencies when you build a model that includes the S-function. For
example, for some applications, such as custom targets, you might want to locate files in a
target-specific location. The build process looks for sFunction_makecfg.m or
rtwmakecfg.m in the same folder as the S-function dynamically loadable executable and
calls the function in the file.

For more information, see “Integrate C Functions Using Legacy Code Tool” (Simulink).

Generate Inlined S-Function Files for Code Generation


Depending on the code generation requirements of your application, to generate code for
a model that uses the S-function, do either of the following:

• 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

You cannot set the singleCPPMexFile field to true if

• 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

Apply Code Style Settings to Legacy Functions


To apply the model configuration parameters for code style to a legacy function:
1 Initialize the Legacy Code Tool data structure. For example:
def = legacy_code('initialize');
2 In the data structure, set the value of the Options.singleCPPMexFile field to
true. For example:
def.Options.singleCPPMexFile = true;

To check the setting, enter:


def.Options.singleCPPMexFile

singleCPPMexFile Limitations

You cannot set the singleCPPMexFile field to true if

• 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

Address Dependencies on Files in Different Locations


By default, the Legacy Code Tool assumes that files on which an S-function depends
reside in the same folder as the dynamically loadable executable file for the S-function. If
your S-function depends on files that reside elsewhere and you are using the template
makefile build process, generate an sFunction_makecfg.m or rtwmakecfg.m file for
the S-function. For example, you might generate this file if your Legacy Code Tool data
structure defines compilation resources as path names.

To generate the sFunction_makecfg.m or rtwmakecfg.m file, call the legacy_code


function with 'sfcn_makecfg_generate' or 'rtwmakecfg_generate' as the first

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).

Deploy S-Functions for Simulation and Code Generation


You can deploy the S-functions that you generate with the Legacy Code Tool so that other
people can use them. To deploy an S-function for simulation and code generation, share
the following files:

• 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

When you use these deployed files:

• 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

Integrate External C++ Object Methods


Integrate legacy C++ object methods by using the Legacy Code Tool.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C++ MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a block TLC file and optional rtwmakecfg.m file that calls the legacy code
during code generation.

Provide the Legacy Function Specification

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();
};

The legacy source code is in the files adder_cpp.h and adder_cpp.cpp.

% 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;

Generate an S-Function for Simulation

To generate a C-MEX S-function according to the description provided by the input


argument 'def', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-function calls the legacy functions during simulation. The
source code for the S-function is in the file rtwdemo_sfun_adder_cpp.cpp.
legacy_code('sfcn_cmex_generate', def);

Compile the Generated S-Function for Simulation

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);

### Start Compiling rtwdemo_sfun_adder_cpp


mex('-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src', '-IC:\TEMP\Bdoc18a_815039_1
Building with 'Microsoft Visual C++ 2015'.
MEX completed successfully.
mex('rtwdemo_sfun_adder_cpp.cpp', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src
Building with 'Microsoft Visual C++ 2015'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_adder_cpp
### Exit

Generate a TLC Block File for Code Generation

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);

Generate an rtwmakecfg.m File for Code Generation

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);

Generate a Masked S-Function Block for Calling the Generated S-Function

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);

Show the Generated Integration with Legacy Code

The model rtwdemo_lct_cpp shows integration with the legacy code.

open_system('rtwdemo_lct_cpp')
sim('rtwdemo_lct_cpp')

11-13
11 Block Authoring and Code Generation for Simulink Coder

Integrate External C++ Objects


The Legacy Code Tool can interface with C++ functions, but not C++ objects. Using the
previous example as a starting point, here is an example of how you can work around this
limitation.

• 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;};
};

// Method wrappers implemented as macros


#define createAdder(work1) \
*(work1) = new adder

#define deleteAdder(work1) \
delete(static_cast<adder*>(*(work1)))

#define adderOutput(work1, u1) \


(static_cast<adder*> ((work1)))->add_one(u1)

#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"

int adder::add_one(int increment)


{
int_state += increment;
return int_state;
}
• Update rtwdemo_sfun_adder_cpp.cpp with the following changes:

• 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

def.OutputFcnSpec = 'int32 y1 = adderOutput(void *work1, int32 u1)';


• TerminateFcnSpec calls the macro that frees the memory.

def.TerminateFcnSpec = 'deleteAdder(void **work1)';

Legacy Code Tool Examples


Integrate External C Functions That Pass Input Arguments By Value Versus
Address

This example shows how to use the Legacy Code Tool to integrate legacy C functions that
pass their input arguments by value versus address.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C-MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a TLC block file and optional rtwmakecfg.m file that specifies how the
generated code for a model calls the legacy code.

Provide the Legacy Function Specification

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];

Generate S-Functions for Simulation

To generate C-MEX S-functions according to the description provided by the input


argument 'defs', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-functions call the legacy functions in simulation. The source
code for the S-functions is in the files rtwdemo_sfun_filterV1.c and
rtwdemo_sfun_filterV2.c.
legacy_code('sfcn_cmex_generate', defs);

Compile the Generated S-Functions for Simulation

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);

### Start Compiling rtwdemo_sfun_filterV1


mex('-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src', '-IC:\TEMP\Bdoc18a_815039_1
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.

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

### Start Compiling rtwdemo_sfun_filterV2


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_filterV2.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src',
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_filterV2
### Exit

Generate TLC Block Files for Code Generation

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);

Generate an rtwmakecfg.m File for Code Generation

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);

Generate Masked S-Function Blocks for Calling the Generated S-Functions

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);

Show the Generated Integration with Legacy Code

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

Integrate External C Functions That Pass the Output Argument As a Return


Argument

This example shows how to use the Legacy Code Tool to integrate legacy C functions that
pass their output as a return argument.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C-MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a TLC block file and optional rtwmakecfg.m file that specifies how the
generated code for a model calls the legacy code.

11-20
Import Calls to External Code into Generated Code with Legacy Code Tool

Provide the Legacy Function Specification

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 gainScalar(const FLT in, const FLT gain)

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'};

Generate an S-Function for Simulation

To generate a C-MEX S-function according to the description provided by the input


argument 'def', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-function calls the legacy functions during simulation. The
source code for the S-function is in the file rtwdemo_sfun_gain_scalar.c.

legacy_code('sfcn_cmex_generate', def);

Compile the Generated S-Function for Simulation

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);

### Start Compiling rtwdemo_sfun_gain_scalar


mex('-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src', '-IC:\TEMP\Bdoc18a_815039_1
Building with 'Microsoft Visual C++ 2015 (C)'.

11-21
11 Block Authoring and Code Generation for Simulink Coder

MEX completed successfully.


mex('rtwdemo_sfun_gain_scalar.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_gain_scalar
### Exit

Generate a TLC Block File for Code Generation

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);

Generate an rtwmakecfg.m File for Code Generation

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);

Generate a Masked S-Function Block for Calling the Generated S-Function

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

Show the Generated Integration with Legacy Code

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.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C-MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a TLC block file and optional rtwmakecfg.m file that specifies how the
generated code for a model calls the legacy code.

Provide the Legacy Function Specification

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

myFixpt is logically a fixed-point data type, which is physically a typedef to a 16-bit


integer:
myFixpt = Simulink.NumericType;
myFixpt.DataTypeMode = 'Fixed-point: binary point scaling';
myFixpt.Signed = true;
myFixpt.WordLength = 16;
myFixpt.FractionLength = 10;
myFixpt.IsAlias = true;
myFixpt.HeaderFile = 'timesFixpt.h';

The legacy source code is in the files timesFixpt.h, and timesS16.c.


% rtwdemo_sfun_times_s16
def = legacy_code('initialize');
def.SFunctionName = 'rtwdemo_sfun_times_s16';
def.OutputFcnSpec = 'myFixpt y1 = timesS16(myFixpt u1, myFixpt u2, uint8 p1)';
def.HeaderFiles = {'timesFixpt.h'};
def.SourceFiles = {'timesS16.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};

Generate an S-Function for Simulation

To generate a C-MEX S-function according to the description provided by the input


argument 'def', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-function calls the legacy functions during simulation. The
source code for the S-function is in the file rtwdemo_sfun_times_s16.c.
legacy_code('sfcn_cmex_generate', def);

Compile the Generated S-Function for Simulation

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);

### Start Compiling rtwdemo_sfun_times_s16


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_times_s16.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src',

11-24
Import Calls to External Code into Generated Code with Legacy Code Tool

Building with 'Microsoft Visual C++ 2015 (C)'.


MEX completed successfully.
### Finish Compiling rtwdemo_sfun_times_s16
### Exit

Generate a TLC Block File for Code Generation

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);

Generate an rtwmakecfg.m File for Code Generation

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);

Generate a Masked S-Function Block for Calling the Generated S-Function

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

Show the Integration of the Model with Legacy Code

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 External C Functions with Instance-Specific Persistent Memory

Integrate legacy C functions that use instance-specific persistent memory by using the
Legacy Code Tool.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C-MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a TLC block file and optional rtwmakecfg.m file that specifies how the
generated code for a model calls the legacy code.

Provide the Legacy Function Specification

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

void memory_bus_init(COUNTERBUS *mem, int32_T upper_sat, int32_T lower_sat);

void memory_bus_step(COUNTERBUS *input, COUNTERBUS *mem, COUNTERBUS


*output);

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'};

Generate an S-Function for Simulation

To generate a C-MEX S-function according to the description provided by the input


argument 'def', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-function calls the legacy functions during simulation. The
source code for the S-function is in the file rtwdemo_sfun_work.c.

legacy_code('sfcn_cmex_generate', def);

Compile the Generated S-Function for Simulation

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);

### Start Compiling rtwdemo_sfun_work


mex('-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src', '-IC:\TEMP\Bdoc18a_815039_1

11-27
11 Block Authoring and Code Generation for Simulink Coder

Building with 'Microsoft Visual C++ 2015 (C)'.


MEX completed successfully.
mex('rtwdemo_sfun_work.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src', '-IC
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_work
### Exit

Generate a TLC Block File for Code Generation

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);

Generate an rtwmakecfg.m File for Code Generation

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);

Generate a Masked S-Function Block for Calling the Generated S-Function

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

Show the Integration of the Model with Legacy Code

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 External C Functions That Use Structure Arguments

Integrate legacy C functions with structure arguments that use Simulink® buses with the
Legacy Code Tool.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C-MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a TLC block file and optional rtwmakecfg.m file that specifies how the
generated code for a model calls the legacy code.

Provide the Legacy Function Specification

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:

counterbusFcn(COUNTERBUS *u1, int32_T u2, COUNTERBUS *y1, int32_T *y2)

11-29
11 Block Authoring and Code Generation for Simulink Coder

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
counterbus.h, and counterbus.c.

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'};

Generate an S-Function for Simulation

To generate a C-MEX S-function according to the description provided by the input


argument 'def', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-function calls the legacy functions during simulation. The
source code for the S-function is in the file rtwdemo_sfun_counterbus.c.

legacy_code('sfcn_cmex_generate', def);

Compile the Generated S-Function for Simulation

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);

### Start Compiling rtwdemo_sfun_counterbus


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_counterbus.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src'
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_counterbus
### Exit

11-30
Import Calls to External Code into Generated Code with Legacy Code Tool

Generate a TLC Block File for Code Generation

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);

Generate an rtwmakecfg.m File for Code Generation

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);

Generate a Masked S-Function Block for Calling the Generated S-Function

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);

Show the Integration of the Model with Legacy Code

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.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C-MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a TLC block file and optional rtwmakecfg.m file that specifies how the
generated code for a model calls the legacy code.

Provide the Legacy Function Specification

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:

void cplx_gain(creal_T *input, creal_T *gain, creal_T *output);

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

'complex<double> p1[1], complex<double> y1[1])'];


def.HeaderFiles = {'cplxgain.h'};
def.SourceFiles = {'cplxgain.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};

Generate an S-Function for Simulation

To generate a C-MEX S-function according to the description provided by the input


argument 'def', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-function calls the legacy functions during simulation. The
source code for the S-function is in the file rtwdemo_sfun_cplx_gain.c.

legacy_code('sfcn_cmex_generate', def);

Compile the Generated S-Function for Simulation

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);

### Start Compiling rtwdemo_sfun_cplx_gain


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_cplx_gain.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src',
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_cplx_gain
### Exit

Generate a TLC Block File for Code Generation

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

Generate an rtwmakecfg.m File for Code Generation

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);

Generate a Masked S-Function Block for Calling the Generated S-Function

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);

Show the Integration of the Model with Legacy Code

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

Integrate External C Functions That Pass Arguments That Have Inherited


Dimensions

This example shows how to use the Legacy Code Tool to integrate legacy C functions
whose arguments have inherited dimensions.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C-MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a TLC block file and optional rtwmakecfg.m file that specifies how the
generated code for a model calls the legacy code.

Provide the Legacy Function Specification

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

def.OutputFcnSpec = ['void mat_add(double u1[][], double u2[][], ' ...


'int32 u3, int32 u4, double y1[size(u1,1)][size(u1,2)])'];
def.HeaderFiles = {'mat_ops.h'};
def.SourceFiles = {'mat_ops.c'};
def.IncPaths = {'rtwdemo_lct_src'};
def.SrcPaths = {'rtwdemo_lct_src'};
defs = [defs; def];

% 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];

Generate S-Functions for Simulation

To generate C-MEX S-functions according to the description provided by the input


argument 'defs', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-functions call the legacy functions during simulation. The
source code for the S-function is in the files rtwdemo_sfun_mat_add.c and
rtwdemo_sfun_mat_mult.c.
legacy_code('sfcn_cmex_generate', defs);

Compile the Generated S-Functions for Simulation

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);

### Start Compiling rtwdemo_sfun_mat_add


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_mat_add.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src', '
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.

11-36
Import Calls to External Code into Generated Code with Legacy Code Tool

### Finish Compiling rtwdemo_sfun_mat_add


### Exit

### Start Compiling rtwdemo_sfun_mat_mult


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_mat_mult.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src',
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_mat_mult
### Exit

Generate TLC Block Files for Code Generation

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);

Generate an rtwmakecfg.m File for Code Generation

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);

Generate Masked S-Function Blocks for Calling the Generated S-Functions

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

Show the Generated Integration with Legacy Code

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 External C Functions That Implement Start and Terminate Actions

Integrate legacy C functions that have start and terminate actions by using the Legacy
Code Tool.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C-MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a TLC block file and optional rtwmakecfg.m file that specifies how the
generated code for a model calls the legacy code.

Provide the Legacy Function Specification

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:

• void initFaultCounter(unsigned int *counter)


• void openLogFile(void **fid)
• void incAndLogFaultCounter(void *fid, unsigned int *counter, double time)
• void closeLogFile(void **fid)

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;

Generate an S-Function for Simulation

To generate a C-MEX S-function according to the description provided by the input


argument 'def', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-function calls the legacy functions during simulation. The
source code for the S-function is in the file rtwdemo_sfun_fault.c.

legacy_code('sfcn_cmex_generate', def);

Compile the Generated S-Function for Simulation

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);

### Start Compiling rtwdemo_sfun_fault

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

Generate a TLC Block File for Code Generation

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);

Generate an rtwmakecfg.m File for Code Generation

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);

Generate a Masked S-Function Block for Calling the Generated S-Function

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

Showing the Generated Integration with Legacy Code

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')

Integrate External C Functions That Pass Arguments as Multi-Dimensional


Signals

This example shows how to use the Legacy Code Tool to integrate legacy C functions with
multi-dimensional Signals.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C-MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a TLC block file and optional rtwmakecfg.m file that specifies how the
generated code for a model calls the legacy code.

Provide the Legacy Function Specification

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.

Generate an S-Function for Simulation

To generate a C-MEX S-function according to the description provided by the input


argument 'def', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-function calls the legacy functions during simulation. The
source code for the S-function is in the file rtwdemo_sfun_ndarray_add.c.

legacy_code('sfcn_cmex_generate', def);

Compile the Generated S-Function for Simulation

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);

### Start Compiling rtwdemo_sfun_ndarray_add


mex('-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src', '-IC:\TEMP\Bdoc18a_815039_1
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.

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

Generate a TLC Block File for Code Generation

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);

Generate an rtwmakecfg.m File for Code Generation

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);

Generate a Masked S-Function Block for Calling the Generated S-Function

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

Showing the Generated Integration with Legacy Code

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')

Integrate External C Functions with a Block Sample Time Specified, Inherited,


and Parameterized

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.

With the Legacy Code Tool, you can:

• Provide the legacy function specification.


• Generate a C-MEX S-function that calls the legacy code during simulation.
• Compile and build the generated S-function for simulation.
• Generate a TLC block file and optional rtwmakecfg.m file that specifies how the
generated code for a model calls the legacy code.

Provide the Legacy Function Specification

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 gainScalar(const FLT in, const FLT gain)

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

Generate S-Functions for Simulation

To generate C-MEX S-functions according to the description provided by the input


argument 'defs', call the function legacy_code() again with the first input set to
'sfcn_cmex_generate'. The S-functions call the legacy functions during simulation. The
source code for the S-functions is in the files rtwdemo_sfun_st_inherited.c and
rtwdemo_sfun_st_fixed.c. rtwdemo_sfun_st_parameterized.c.

legacy_code('sfcn_cmex_generate', defs);

Compile the Generated S-Functions for Simulation

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);

### Start Compiling rtwdemo_sfun_st_inherited


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_st_inherited.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_sr
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_st_inherited
### Exit

### Start Compiling rtwdemo_sfun_st_fixed


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_st_fixed.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lct_src',
Building with 'Microsoft Visual C++ 2015 (C)'.
MEX completed successfully.
### Finish Compiling rtwdemo_sfun_st_fixed
### Exit

### Start Compiling rtwdemo_sfun_st_parameterized


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_st_parameterized.c', '-IB:\matlab\toolbox\rtw\rtwdemos\rtwdemo_lc

11-47
11 Block Authoring and Code Generation for Simulink Coder

Building with 'Microsoft Visual C++ 2015 (C)'.


MEX completed successfully.
### Finish Compiling rtwdemo_sfun_st_parameterized
### Exit

Generate TLC Block Files for Code Generation

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);

Generate an rtwmakecfg.m File for Code Generation

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);

Generate Masked S-Function Blocks for Calling the Generated S-Functions

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

Show the Generated Integration with Legacy Code

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

External Code Integration Examples


This topic shows various scenarios of external code integration.

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.

%Open files my_header.h and my_function.c


eval('edit my_header.h')
eval('edit 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.

%Open Configuration Parameters dialog box


slCfgPrmDlg(model,'Open');
slCfgPrmDlg(bdroot,'TurnToPage','Simulation Target');

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.

%Open Configuration Parameters dialog box


slCfgPrmDlg(model,'Open');
slCfgPrmDlg(bdroot,'TurnToPage','Code Generation/Custom Code');

Generate Code

rtwbuild('rtwdemo_sfcustom')

### Starting build procedure for model: rtwdemo_sfcustom


### Successful completion of build procedure for model: rtwdemo_sfcustom

Call C Code from Stateflow

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

• Include Custom C Code in Simulation Targets for Library Models


• Integrate Custom C++ Code for Simulation

Close Model

rtwdemoclean;
close_system('rtwdemo_sfcustom',0);

Integrate External C Code Into Generated Code By Using


Custom Code Blocks and Model Configuration Parameters
This example shows how to place external code in generated code by using custom code
blocks and model configuration parameters.

1. Open the model rtwdemo_slcustcode.

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.

4. Close the dialog box.

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.

7. Generate code and a code generation report.

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_INT2 = -1;

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.

int_T *intPtr = &GLOBAL_INT1;

*intPtr = -1;

rtwdemo_slcustcode_Y.Output = rtwdemo_slcustcode_U.Input << 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;

Integrate External C Code Into Generated Code By Using


Custom Code Blocks and Model Configuration Parameters
This example shows how to place external code in generated code by using custom code
blocks and model configuration parameters.

1. Open the model rtwdemo_slcustcode.

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.

4. Close the dialog box.

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.

7. Generate code and a code generation report.

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_INT2 = -1;

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.

int_T *intPtr = &GLOBAL_INT1;

*intPtr = -1;

rtwdemo_slcustcode_Y.Output = rtwdemo_slcustcode_U.Input << 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.

%Open files my_header.h and my_function.c


eval('edit my_header.h')
eval('edit 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.

%Open Configuration Parameters dialog box


slCfgPrmDlg(model,'Open');
slCfgPrmDlg(bdroot,'TurnToPage','Simulation Target');

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.

%Open Configuration Parameters dialog box


slCfgPrmDlg(model,'Open');
slCfgPrmDlg(bdroot,'TurnToPage','Code Generation/Custom Code');

Generate Code

rtwbuild('rtwdemo_sfcustom')

### Starting build procedure for model: rtwdemo_sfcustom


### Successful completion of build procedure for model: rtwdemo_sfcustom

Call C Code from Stateflow

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

• Include Custom C Code in Simulation Targets for Library Models


• Integrate Custom C++ Code for Simulation

Close Model

rtwdemoclean;
close_system('rtwdemo_sfcustom',0);

11-61
11 Block Authoring and Code Generation for Simulink Coder

Generate S-Function from Subsystem


The Generate S-function feature automates the process of generating an S-function
from a subsystem. In addition, the Generate S-function feature presents a display of
parameters used within the subsystem, and lets you declare selected parameters tunable.

As an example, consider SourceSubsys, the same subsystem illustrated in the example


“Create S-Function Blocks from a Subsystem” on page 49-63. The objective is to
automatically extract SourceSubsys from the model and build an S-Function block from
it, as in the previous example. In addition, the workspace variable K , which is the gain
factor of the Gain block within SourceSubsys (as shown in the Gain block parameter
dialog box below), is declared and generated as a tunable variable.

To auto-generate an S-function from SourceSubsys with tunable parameter K,


1 With the SourceSubsys model open, click the subsystem to select it.
2 From the Code menu, select C/C++ Code > Generate S-Function. This menu item
is enabled when a subsystem is selected in the current model.

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

The upper pane of the window displays three columns:

• Variable Name: name of the parameter.


• Class: If the parameter is a workspace variable, its data type is shown. If the
parameter is a data object, its name and class is shown
• Tunable: Lets you select tunable parameters. To declare a parameter tunable,
select the check box. In the next figure, the parameter K is declared tunable.

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.

Generate S-Function Window


4 After selecting tunable parameters, click the Build button. This initiates code
generation and compilation of the S-function, using the S-function target. The Create
New Model option is automatically enabled.
5 The build process displays status messages in the MATLAB Command Window. When
the build completes, the tunable parameters window closes, and a new untitled model
window opens.

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:

• subsys_sf.c or .cpp, where subsys is the subsystem name (for example,


SourceSubsys_sf.c)
• subsys_sf.h
• subsys_sf.mexext, where mexext is a platform-dependent MEX-file extension
(for example, SourceSubsys_sf.mexw64)

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

/* Gain: '<S1>/Gain' incorporates:


* Sum: '<S1>/Sum'
*/
rtb_Gain_n[0] = (rtb_Product_p + (*(((const
real_T**)ssGetInputPortSignalPtrs(S, 2))[0]))) * (*(real_T
*)(mxGetData(K(S))));
rtb_Gain_n[1] = (rtb_Product_p + (*(((const
real_T**)ssGetInputPortSignalPtrs(S, 2))[1]))) * (*(real_T
*)(mxGetData(K(S))));

• 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.

If you specify paths and files with absolute

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

Write S-Function and TLC Files By Hand


You can choose from several approaches for writing S-function and TLC files by hand.

Write Noninlined S-Function and TLC Files


• “About Noninlined S-Functions” on page 11-67
• “Guidelines for Writing Noninlined S-Functions” on page 11-67
• “Noninlined S-Function Parameter Type Limitations” on page 11-68

About Noninlined S-Functions

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.

Guidelines for Writing Noninlined S-Functions

• The MEX-file cannot call MATLAB functions.


• If the MEX-file uses functions in the MATLAB External Interface libraries, include the
header file cg_sfun.h instead of mex.h or simulink.c. To handle this case, include
the following lines at the end of your S-function:
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif

• 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

• Use only full matrices that contain only real data.


• Do not specify a return value for calls to mxGetString . If you do specify a return
value, the MEX-file will not compile. Instead, use the function's second input
argument, which returns a pointer to a character vector.
• Make sure that the #define s-function_name statement is correct. The S-function
name that you specify must match the S-function's filename.
• Use the data types real_T and int_T instead of double and int, if possible. The
data types real_T and int_T are more generic and can be used in multiple
environments.
• Provide the build process with the names of the modules used to build the S-function.
You can do this by using a template make file, the set_param function, or the S-
function modules field of the S-Function block parameters dialog box. For
example, suppose you build your S-function with the following command:
mex sfun_main.c sfun_module1.c sfun_module2.c

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).

Noninlined S-Function Parameter Type Limitations

Parameters to noninlined S-functions can be of the following types only:

• 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

source file, compiler errors occur. See the files matlabroot/rtw/c/src/rt_matrx.h


and matlabroot/rtw/c/src/rt_matrx.c for details on supported MATLAB API
functions.

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.

Write Wrapper S-Function and TLC Files


This topic describes how to create S-functions that work seamlessly with the Simulink and
code generator products using the wrapper concept. This topic begins by describing how
to interface your algorithms in Simulink models by writing MEX S-function wrappers
(sfunction.mex). It finishes with a description of how to direct the code generator to
insert your algorithm into the generated code by creating a TLC S-function wrapper
(sfunction.tlc).

• “MEX S-Function Wrapper” on page 11-69


• “TLC S-Function Wrapper” on page 11-74
• “Code Overhead for Noninlined S-Functions” on page 11-74
• “How to Inline” on page 11-75
• “The Inlined Code” on page 11-77

MEX S-Function Wrapper

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

• Interpretive in nature (that is, highly parameterized by operating modes)


• Heavily optimized (that is, no extra tests to decide what mode the code is operating in)

then you must create a fully inlined TLC file for your S-function.

The next figure shows the wrapper S-function concept.

11-70
Write S-Function and TLC Files By Hand

Simulink Simulink Coder


Place the name of your S-function wrapper.c, the generated code,
in the S-Function block dialog box. calls mdlOutputs,
which then calls my_alg.
wrapper.mdl
wrapper.c
...
wrapsfcn *See note below MdlOutputs(...)
{
S-function ...
my_alg();
In Simulink, the S-function }
calls mdlOutputs, which
in turn calls my_alg.

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.

The following sample model includes an S-function wrapper.

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.

For more information, see “Templates for C S-Functions” (Simulink).


#define S_FUNCTION_NAME wrapsfcn
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"

extern real_T my_alg(real_T u); /* Declare my_alg as extern */

/*
* mdlInitializeSizes - initialize the sizes array
*/
static void mdlInitializeSizes(SimStruct *S)
{

ssSetNumSFcnParams( S, 0); /*number of input arguments*/

if (!ssSetNumInputPorts(S, 1)) return;


ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);

if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, 1);

ssSetNumSampleTimes( S, 1);
}

/*

11-72
Write S-Function and TLC Files By Hand

* mdlInitializeSampleTimes - indicate that this S-function runs


* at the rate of the source (driving block)
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}

/*
* 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)
{
}

#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */


#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif

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

TLC S-Function Wrapper

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')

Code Overhead for Noninlined S-Functions

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"

/* Start the model */


void mdlStart(void)
{
/* (start code not required) */
}

/* Compute block outputs */


void mdlOutputs(int_T tid)
{
/* Sin Block: <Root>/Sin */
rtB.Sin = rtP.Sin.Amplitude *
sin(rtP.Sin.Frequency * ssGetT(rtS) + rtP.Sin.Phase);

/* Level2 S-Function Block: <Root>/S-Function (wrapsfcn) */


{

11-74
Write S-Function and TLC Files By Hand

/* Noninlined S-functions create a SimStruct object and


* generate a call to S-function routine mdlOutputs
*/
SimStruct *rts = ssGetSFunction(rtS, 0);
sfcnOutputs(rts, tid);
}

/* Outport Block: <Root>/Out */


rtY.Out = rtB.S_Function;
}

/* Perform model update */


void mdlUpdate(int_T tid)
{
/* (update code not required) */
}

/* 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.

The wrapsfcn.tlc file tells


Simulink Coder how to
inline the call to my_alg
using this statement. wrapper.c
... my_alg.c
wrapsfcn.tlc mdlOutputs myalg()
... { {
%<y> = my_alg(%<u>); ... <C code here>
... y = my_alg(); }
...
}
...

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.

This is the wrapsfcn.tlc file that inlines wrapsfcn.c.


%% File : wrapsfcn.tlc
%% Abstract:
%% Example inlined tlc file for S-function wrapsfcn.c
%%

%implements "wrapsfcn" "C"

%% Function: BlockTypeSetup ====================================================


%% Abstract:
%% Create function prototype in model.h as:
%% "extern real_T my_alg(real_T u);"
%%
%function BlockTypeSetup(block, system) void
%openfile buffer
extern real_T my_alg(real_T u); /* This line is placed in wrapper.h */
%closefile buffer
%<LibCacheFunctionPrototype(buffer)>
%endfunction %% BlockTypeSetup

11-76
Write S-Function and TLC Files By Hand

%% Function: Outputs ===========================================================


%% Abstract:
%% y = my_alg( u );
%%
%function Outputs(block, system) Output
/* %<Type> Block: %<Name> */
%assign u = LibBlockInputSignal(0, "", "", 0)
%assign y = LibBlockOutputSignal(0, "", "", 0)
%% PROVIDE THE CALLING STATEMENT FOR "algorithm"
%% The following line is expanded and placed in mdlOutputs within wrapper.c
%<y> = my_alg(%<u>);

%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 Inlined Code

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);

/* S-Function Block: <Root>/S-Function */


rtB.S_Function = my_alg(rtB.Sin); /* Inlined call to my_alg */

/* Outport Block: <Root>/Out */


rtY.Out = rtB.S_Function;
}

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.

Write Fully Inlined S-Functions


Using the example from “Write Wrapper S-Function and TLC Files” (Simulink Coder), you
could eliminate the call to my_alg entirely by specifying the explicit code (that is, 2.0 *
u) in wrapsfcn.tlc. This is referred to as a fully inlined S-function. While this can
improve performance, if you are working with a large amount of C/C++ code, this can be
a lengthy task. In addition, you now have to maintain your algorithm in two places, the
C/C++ S-function itself and the corresponding TLC file. However, the performance gains
might outweigh the disadvantages. To inline the algorithm used in this example, in the
Outputs section of your wrapsfcn.tlc file, instead of writing
%<y> = my_alg(%<u>);

use
%<y> = 2.0 * %<u>;

This is the code produced in mdlOutputs:


void mdlOutputs(int_T tid)
{
/* Sin Block: <Root>/Sin */
rtB.Sin = rtP.Sin.Amplitude *
sin(rtP.Sin.Frequency * ssGetT(rtS) + rtP.Sin.Phase);

/* S-Function Block: <Root>/S-Function */


rtB.S_Function = 2.0 * rtB.Sin; /* Explicit embedding of algorithm */

/* Outport Block: <Root>/Out */


rtY.Out = rtB.S_Function;
}

The Target Language Compiler has replaced the call to my_alg with the algorithm itself.

Multiport S-Function

A more advanced multiport inlined S-function example is sfun_multiport.c and


sfun_multiport.tlc. This S-function illustrates how to create a fully inlined TLC file
for an S-function that contains multiple ports. You might find that looking at this example
helps you to understand fully inlined TLC files.

11-78
Write S-Function and TLC Files By Hand

Write Fully Inlined S-Functions with mdlRTW Routine


You can inline more complex S-functions that use the S-function mdlRTW routine. The
purpose of the mdlRTW routine is to provide the code generation process with more
information about how the S-function is to be inlined, by creating a parameter record of a
nontunable parameter for use with a TLC file. The mdlRTW routine does this by placing
information in the model.rtw file. The mdlRTW function is described in the text file
matlabroot/simulink/src/sfuntmpl_doc.c.

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:

• Error checking of S-function parameters


• Caching of information for the S-function that doesn't change during model execution
• How to use the mdlRTW function to customize the code generator to produce the
optimal code for a given set of block parameters
• How to generate an inlined TLC file for an S-function in a combination of the fully
inlined form and/or the wrapper form

• “S-Function RTWdata” on page 11-80


• “Direct-Index Lookup Table Algorithm” on page 11-80
• “Direct-Index Lookup Table Example” on page 11-82
• “Error Handling” on page 11-83
• “User Data Caching” on page 11-83

11-79
11 Block Authoring and Code Generation for Simulink Coder

• “mdlRTW Usage” on page 11-84

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')

produces this result:


ans =

field1: 'information for field1'


field2: 'information for field2'

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.

Direct-Index Lookup Table Algorithm

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

The parameters to the S-function are


XData, YData, XEvenlySpaced

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.

The following graph shows how the parameters XData=[1:6]and


YData=[1,2,7,4,5,9] are handled. For example, if the input (x-value) to the S-
Function block is 3, the output (y-value) is 7.

11-81
11 Block Authoring and Code Generation for Simulink Coder

Direct-Index Lookup Table Example

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.

The inlined TLC file is sfun_directlook.tlc, which is used to either perform a


wrapper call or embed the optimal C/C++ code for the S-function. (See the example in
“mdlRTW Usage” (Simulink Coder)).

Error Handling

In sfun_directlook.tlc, the mdlCheckParameters routine verifies that:

• The new parameter settings are valid.


• XData and YData are vectors of the same length containing real finite numbers.
• XDataEvenlySpaced is a scalar.
• The XData vector is a monotonically increasing vector and evenly spaced.

The mdlInitializeSizes function explicitly calls mdlCheckParameters after it


verifies the number of parameters passed to the S-function. After the Simulink engine
calls mdlInitializeSizes, it then calls mdlCheckParameters whenever you change
the parameters or there is a need to reevaluate them.

User Data Caching

In sfun_directlook.tlc, the mdlStart routine shows how to cache information that


does not change during the simulation (or while the generated code is executing). The
example caches the value of the XDataEvenlySpaced parameter in UserData, a field of
the SimStruct. The following line in mdlInitializeSizes tells the Simulink engine to
disallow changes to XDataEvenlySpaced.
ssSetSFcnParamTunable(S, iParam, SS_PRM_NOT_TUNABLE);

During execution, mdlOutputs accesses the value of XDataEvenlySpaced from


UserData rather than calling the mxGetPr MATLAB API function.

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.

Because xData and yData are registered as run-time parameters in


mdlSetWorkWidths, the code generator handles writing to the model.rtw file
automatically.

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"

/* External outputs (root outports fed by signals with auto storage) */


ExtY_sfun_directlook_ex_T sfun_directlook_ex_Y;

/* 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_;

/* Model output function */


void sfun_directlook_ex_output(void)
{
/* local block i/o variables */
real_T rtb_SFunction;
real_T rtb_SFunction1;

/* Sin: '<Root>/Sine Wave' */


rtb_SFunction1 = sin(sfun_directlook_ex_M->Timing.t[0]);

/* Code that is inlined for the top S-function block in the


* sfun_directlook_ex model
*/
/* S-Function (sfun_directlook): '<Root>/S-Function' */
{
const real_T *xData = sfun_directlook_ex_ConstP.SFunction_XData;
const real_T *yData = sfun_directlook_ex_ConstP.SFunction_YData;
real_T spacing = xData[1] - xData[0];

11-85
11 Block Authoring and Code Generation for Simulink Coder

if (rtb_SFunction1 <= xData[0] ) {


rtb_SFunction = yData[0];
} else if (rtb_SFunction1 >= yData[20] ) {
rtb_SFunction = yData[20];
} else {
int_T idx = (int_T)( ( rtb_SFunction1 - xData[0] ) / spacing );
rtb_SFunction = yData[idx];
}
}

/* Outport: '<Root>/Out1' */
sfun_directlook_ex_Y.Out1 = rtb_SFunction;

/* Code that is inlined for the bottom S-function block in the


* sfun_directlook_ex model
*/
/* S-Function (sfun_directlook): '<Root>/S-Function1' */
{
const real_T *xData = sfun_directlook_ex_ConstP.SFunction1_XData;
const real_T *yData = sfun_directlook_ex_ConstP.SFunction1_YData;
int_T idx;
idx = GetDirectLookupIndex(xData, 5, rtb_SFunction1);
rtb_SFunction1 = yData[idx];
}

/* Outport: '<Root>/Out2' */
sfun_directlook_ex_Y.Out2 = rtb_SFunction1;
}

/* Model update function */


void sfun_directlook_ex_update(void)
{
/* signal main to stop simulation */
{ /* Sample time: [0.0s, 0.0s] */
if ((rtmGetTFinal(sfun_directlook_ex_M)!=-1) &&
!((rtmGetTFinal(sfun_directlook_ex_M)-sfun_directlook_ex_M->Timing.t[0])
> sfun_directlook_ex_M->Timing.t[0] * (DBL_EPSILON))) {
rtmSetErrorStatus(sfun_directlook_ex_M, "Simulation finished");
}
}

/* Update absolute time for base rate */


/* The "clockTick0" counts the number of times the code of this task has
* been executed. The absolute time is the multiplication of "clockTick0"
* and "Timing.stepSize0". Size of "clockTick0" ensures timer will not
* overflow during the application lifespan selected.
* Timer of this task consists of two 32 bit unsigned integers.
* The two integers represent the low bits Timing.clockTick0 and the high bits
* Timing.clockTickH0. When the low bit overflows to 0, the high bits increment.
*/
if (!(++sfun_directlook_ex_M->Timing.clockTick0)) {
++sfun_directlook_ex_M->Timing.clockTickH0;
}

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;
}
...

Guidelines for Writing Inlined S-Functions


• Consider using the block property RTWdata (see “S-Function RTWdata” (Simulink
Coder)). This property is a structure of character vectors that you can associate with a
block. The code generator saves the structure with the model in the model.rtw file
and makes the .rtw file more readable. For example, suppose you enter the following
commands in the MATLAB Command Window:
mydata.field1 = 'information for field1';
mydata.field2 = 'information for field2';
set_param(sfun_block, 'RTWdata', mydata);

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

• Rename tunable parameters in the generated code


• Introduce nontunable parameters into a TLC file

S-Functions That Support Expression Folding


• “About S-Functions that Support Expression Folding” on page 11-87
• “Categories of Output Expressions” on page 11-88
• “Acceptance or Denial of Requests for Input Expressions” on page 11-93
• “Expression Folding in a TLC Block Implementation” on page 11-95

About S-Functions that Support Expression Folding

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:

• Writing inlined S-functions (see “S-Function Basics” (Simulink)).


• “Target Language Compiler” (Simulink Coder)

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).

The topics that follow explain

• 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.

Categories of Output Expressions

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

A trivial output expression is an expression that can be repeated, without a performance


penalty, when the output port has multiple output destinations. For example, the output of
a Unit Delay block is defined as a trivial expression because the output expression is
simply a direct access to the block's state. Because the output expression does not have
computations, it can be repeated more than once without degrading the performance of
the generated code.

A generic output expression is an expression that should be assumed to have a


performance penalty if repeated. As such, a generic output expression is not suitable for
repeating when the output port has multiple output destinations. For instance, the output
of a Sum block is a generic rather than a trivial expression because it is costly to
recompute a Sum block output expression as an input to multiple blocks.
Examples of Trivial and Generic Output Expressions

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:

* UnitDelay: <Root>/Unit Delay */


rtY.Out1 = rtDWork.Unit_Delay_DSTATE;

11-89
11 Block Authoring and Code Generation for Simulink Coder

/* Outport: <Root>/Out2 incorporates:


* UnitDelay: <Root>/Unit Delay */
rtY.Out2 = rtDWork.Unit_Delay_DSTATE;

/* Outport: <Root>/Out3 incorporates:


* UnitDelay: <Root>/Unit Delay */
rtY.Out3 = rtDWork.Unit_Delay_DSTATE;

...
}

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;

/* Sum: <Root>/Sum incorporates:


* Gain: <Root>/Gain
* Inport: <Root>/u1
* Gain: <Root>/Gain1
* Inport: <Root>/u2
*
* Regarding <Root>/Gain:
* Gain value: rtP.Gain_Gain
*
* Regarding <Root>/Gain1:
* Gain value: rtP.Gain1_Gain
*/
rtb_non_triv = (rtP.Gain_Gain * rtU.u1) + (rtP.Gain1_Gain *
rtU.u2);

/* Outport: <Root>/Out1 */
rtY.Out1 = rtb_non_triv;

/* Sin Block: <Root>/Sine Wave */

rtb_Sine_Wave = rtP.Sine_Wave_Amp *
sin(rtP.Sine_Wave_Freq * rtmGetT(rtM_model) +
rtP.Sine_Wave_Phase) + rtP.Sine_Wave_Bias;

/* Outport: <Root>/Out2 incorporates:


* Sum: <Root>/Sum1
*/
rtY.Out2 = (rtb_non_triv + rtb_Sine_Wave);
}

Specify the Category of an Output Expression

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

Types of Output Expressions


Category of When to Use
Expression
Constant Use only if block output is a direct memory access to a block
parameter.
Trivial Use only if block output is an expression that can appear multiple
times in the code without reducing efficiency (for example, a
direct memory access to a field of the DWork vector, or a literal).
Generic Use if output is an expression, but not constant or trivial.

You must declare outputs as expressions in the mdlSetWorkWidths function using


macros defined in the S-Function API. The macros have the following arguments:

• SimStruct *S: pointer to the block's SimStruct.


• int idx: zero-based index of the output port.
• bool value: pass in TRUE if the port generates output expressions.

The following macros are available for setting an output to be a constant, trivial, or
generic expression:

• void ssSetOutputPortConstOutputExprInRTW(SimStruct *S, int idx,


bool value)
• void ssSetOutputPortTrivialOutputExprInRTW(SimStruct *S, int idx,
bool value)
• void ssSetOutputPortOutputExprInRTW(SimStruct *S, int idx, bool
value)

The following macros are available for querying the status set by prior calls to the macros
above:

• bool ssGetOutputPortConstOutputExprInRTW(SimStruct *S, int idx)


• bool ssGetOutputPortTrivialOutputExprInRTW(SimStruct *S, int idx)
• bool ssGetOutputPortOutputExprInRTW(SimStruct *S, int idx)

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

is considered a trivial expression, because it is a direct memory access that can be


repeated without degrading the efficiency of the generated code.

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.

Acceptance or Denial of Requests for Input Expressions

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.

A request to output a constant expression is not denied, because there is no performance


penalty for a constant expression, and the software can take the parameter’s address.
S-Function API to Specify Input Expression Acceptance

The S-Function API provides macros that let you:

• Specify whether a block input should accept nonconstant expressions (that is, trivial or
generic expressions)
• Query whether a block input accepts nonconstant expressions

By default, block inputs do not accept 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:

• SimStruct *S: pointer to the block's SimStruct.


• int idx: zero-based index of the input port.
• bool value: pass in TRUE if the port accepts input expressions; otherwise pass in
FALSE.

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)

Denial of Block Requests to Output Expressions

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

Expression Folding in a TLC Block Implementation

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

• Input ports, as explained in “S-Function API to Specify Input Expression Acceptance”


on page 11-93.
• Output ports, as explained in “Categories of Output Expressions” on page 11-88.

This topic discusses required modifications to the TLC implementation.


Expression Folding Compliance

In the BlockInstanceSetup function of your S-function, register your block to be


compliant with expression folding. Otherwise, expression folding requested or allowed at
the block's outputs or inputs will be disabled, and temporary variables will be used.

To register expression folding compliance, call the TLC library function


LibBlockSetIsExpressionCompliant(block), which is defined in
matlabroot/rtw/c/tlc/lib/utillib.tlc. For example:
%% Function: BlockInstanceSetup ===========================================
%%
%function BlockInstanceSetup(block, system) void
%%
%<LibBlockSetIsExpressionCompliant(block)>
%%
%endfunction

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

The BlockOutputSignal function is used to generate code for a scalar output


expression or one element of a nonscalar output expression. If your block outputs an
expression, you should add a BlockOutputSignal function. The prototype of the
BlockOutputSignal is
%function BlockOutputSignal(block,system,portIdx,ucv,lcv,idx,retType) void

11-95
11 Block Authoring and Code Generation for Simulink Coder

The arguments to BlockOutputSignal are as follows:

• 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:

"Signal" specifies the contents or address of the output signal.

"SignalAddr" specifies the address of the output signal

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

%% 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 logicOperator = ParamSettings.Operator
%if ISEQUAL(logicOperator, "~=")
%assign op = "!="
elseif ISEQUAL(logicOperator, "==") %assign op = "=="
%else
%assign op = logicOperator
%endif
%assign u0 = LibBlockInputSignal(0, ucv, lcv, idx)
%assign u1 = LibBlockInputSignal(1, ucv, lcv, idx)
%return "(%<u0> %<op> %<u1>)"
%default
%assign errTxt = "Unsupported return type: %<retType>"
%<LibBlockReportError(block,errTxt)>
%endswitch
%endfunction

Expression Folding for Blocks with Multiple Outputs

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

Comments for Blocks That Are Expression-Folding-Compliant

In the past, blocks preceded their outputs code with comments of the form
/* %<Type> Block: %<Name> */

When a block is expression-folding-compliant, the initial line shown above is generated


automatically. You should not include the comment as part of the block's TLC
implementation. Additional information should be registered using the
LibCacheBlockComment function.

The LibCacheBlockComment function takes a character vector as an input, defining the


body of the comment, except for the opening header, the final newline of a single or
multiline comment, and the closing trailer.

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)>

S-Functions That Specify Port Scope and Reusability


You can use the following SimStruct macros in the mdlInitializeSizes method to
specify the scope and reusability of the memory used for your S-function's input and
output ports:

• ssSetInputPortOptimOpts: Specify the scope and reusability of the memory


allocated to an S-function input port
• ssSetOutputPortOptimOpts: Specify the scope and reusability of the memory
allocated to an S-function output port
• ssSetInputPortOverWritable: Specify whether one of your S-function's input
ports can be overwritten by one of its output ports
• ssSetOutputPortOverwritesInputPort: Specify whether an output port can
share its memory buffer with an input port

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:

1 Indicate the ports are reusable using either the SS_REUSABLE_AND_LOCAL or


SS_REUSABLE_AND_GLOBAL option in the ssSetInputPortOptimOpts and
ssSetOutputPortOptimOpts macros
2 Indicate the input port memory is overwritable using
ssSetInputPortOverWritable
3 If your S-function has multiple input and output ports, use
ssSetOutputPortOverwritesInputPort to indicate which output and input ports
share 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.

The S-function's mdlInitializeSizes method declares the input port as reusable,


local, and overwritable and the output port as reusable and local, as follows:
static void mdlInitializeSizes(SimStruct *S)
{
/* snip */
ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL);
ssSetInputPortOverWritable(S, 0, TRUE);

/* 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

/* Sin: '<Root>/Sine Wave' */


rtb_SFunction[0] = sin(((real_T)sl_directlook_DWork.counter[0] +
sl_directlook_P.SineWave_Offset) * 2.0 * 3.1415926535897931E+000 /
sl_directlook_P.SineWave_NumSamp) * sl_directlook_P.SineWave_Amp[0] +
sl_directlook_P.SineWave_Bias;
rtb_SFunction[1] = sin(((real_T)sl_directlook_DWork.counter[1] +
sl_directlook_P.SineWave_Offset) * 2.0 * 3.1415926535897931E+000 /
sl_directlook_P.SineWave_NumSamp) * sl_directlook_P.SineWave_Amp[1] +
sl_directlook_P.SineWave_Bias;

/* S-Function Block: <Root>/S-Function */


{
const real_T *xData = &sl_directlook_P.SFunction_XData[0];
const real_T *yData = &sl_directlook_P.SFunction_YData [0];
real_T spacing = xData[1] - xData[0];
if (rtb_SFunction[0] <= xData[0] ) {
rtb_SFunction[0] = yData[0];
} else if (rtb_SFunction[0] >= yData[20] ) {
rtb_SFunction[0] = yData[20];
} else {
int_T idx = (int_T)( ( rtb_SFunction[0] - xData[0] ) / spacing );
rtb_SFunction[0] = yData[idx];
}

if (rtb_SFunction[1] <= xData[0] ) {


rtb_SFunction[1] = yData[0];
} else if (rtb_SFunction[1] >= yData[20] ) {
rtb_SFunction[1] = yData[20];
} else {
int_T idx = (int_T)( ( rtb_SFunction[1] - xData[0] ) / spacing );
rtb_SFunction[1] = yData[idx];
}
}

/* 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

Scope and S-function mdlInitializeSizes Generated code


reusability code
Inputs: Local, ssSetInputPortOptimOpts(S, 0, The model.c file declares a local
SS_REUSABLE_AND_LOCAL);
reusable, variable in the output function.
overwritable ssSetInputPortOverWritable(S, 0,
/* local block i/o variables */
TRUE);
real_T rtb_SFunction[2];
Outputs: Local, ssSetOutputPortOptimOpts(S, 0,
reusable SS_REUSABLE_AND_LOCAL);

Inputs: Global, ssSetInputPortOptimOpts(S, 0, The model.h file defines a block


SS_REUSABLE_AND_GLOBAL);
reusable, signals structure with a single element
overwritable ssSetInputPortOverWritable(S, 0, to store the S-function's input and
TRUE);
output.
Outputs: Global, ssSetOutputPortOptimOpts(S, 0, /* Block signals (auto storage) */
reusable SS_REUSABLE_AND_GLOBAL); typedef struct {
real_T SFunction[2];
} BlockIO_sl_directlook;

The model.c file uses this element of


the structure in calculations of the S-
function's input and output signals.
/* Sin: '<Root>/Sine Wave' */
sl_directlook_B.SFunction[0] = sin ...
/* snip */
/*S-Function Block:<Root>/S-Function*/
{
const real_T *xData =
&sl_directlook_P.SFunction_XData[0]

Inputs: Local, not ssSetInputPortOptimOpts(S, 0, The model.c file declares local


SS_NOT_REUSABLE_AND_LOCAL);
reusable variables for the S-function's input and
ssSetInputPortOverWritable(S, 0, output in the output function
Outputs: Local, FALSE);
/* local block i/o variables */
not reusable ssSetOutputPortOptimOpts(S, 0, real_T rtb_SineWave[2];
SS_NOT_REUSABLE_AND_LOCAL); real_T rtb_SFunction[2];

11-102
Write S-Function and TLC Files By Hand

Scope and S-function mdlInitializeSizes Generated code


reusability code
Inputs: Global, ssSetInputPortOptimOpts(S, 0, The model.h file defines a block
SS_NOT_REUSABLE_AND_GLOBAL);
not reusable signal structure with individual
ssSetInputPortOverWritable(S, 0, elements to store the S-function's
Outputs: Global, FALSE);
input and output.
not reusable ssSetOutputPortOptimOpts(S, 0, /* Block signals (auto storage) */
SS_NOT_REUSABLE_AND_GLOBAL); typedef struct {
real_T SineWave[2];
real_T SFunction[2];
} BlockIO_sl_directlook;

The model.c file uses the different


elements in this structure when
calculating the S-function's input and
output.
/* Sin: '<Root>/Sine Wave' */
sl_directlook_B.SineWave[0] = sin ...
/* snip */
/*S-Function Block:<Root>/S-Function*/
{
const real_T *xData =
&sl_directlook_P.SFunction_XData[0]

S-Functions That Specify Sample Time Inheritance Rules


For the Simulink engine to determine whether a model can inherit a sample time, the S-
functions in the model need to specify how they use sample times. You can specify this
information by calling the macro
ssSetModelReferenceSampleTimeInheritanceRule from mdlInitializeSizes or
mdlSetWorkWidths. To use this macro:

1 Check whether the S-function calls any of the following macros:

• 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)

• Throwing errors if sample time


is inherited, continuous, or
constant
• Checking ssIsSampleHit
• Checking whether sample time
is inherited in either
mdlSetInputPortSampleTi
me or
mdlSetOutputPortSampleT
ime before setting

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

Note If an S-function does not set the


ssSetModelReferenceSampleTimeInheritanceRule macro, by default the Simulink
engine assumes that the S-function does not preclude the model containing that S-
function from inheriting a sample time. However, the engine issues a warning indicating
that the model includes S-functions for which this macro is not set.

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.

S-Functions That Support Code Reuse


You can reuse the generated code for identical subsystems that occur in multiple
instances within a model and across referenced models. For more information about code
generation of subsystems for code reuse, see “Control Generation of Subsystem
Functions” (Simulink Coder). If you want your S-function to support code reuse for a
subsystem, the S-function must meet the following requirements:

• The S-function must be inlined.


• Code generated from the S-function must not use static variables.
• The S-function must initialize its pointer work vector in mdlStart and not before.
• The S-function must not be a sink that logs data to the workspace.
• The S-function must register its parameters as run-time parameters in
mdlSetWorkWidths. (It must not use ssWriteRTWParameters in its mdlRTW
function for this purpose.)
• The S-function must not be a device driver.

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 for Multirate Multitasking Environments


• “About S-Functions for Multirate Multitasking Environments” on page 11-106
• “Rate Grouping Support in S-Functions” on page 11-106
• “Create Multitasking, Multirate, Port-Based Sample Time S-Functions” on page 11-107

About S-Functions for Multirate Multitasking Environments

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.

Rate Grouping Support in S-Functions

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.

Create Multitasking, Multirate, Port-Based Sample Time S-Functions

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.

Rules for Properly Handling Fast-to-Slow Transitions

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:

• File: sfun_multirate_zoh.c, Equation: y = u(tslow)


• Input: local and reusable
• Output: local and reusable
• DirectFeedthrough: yes
OutputFcn
if (ssIsSampleHit(".1")) {
if (ssIsSepcialSampleHit("1")) {
DWork = u;
}
}
if (ssIsSampleHit("1")) {
y = DWork;
}

An alternative, slightly optimized approach for simple algorithms:

• Input: local and reusable


• Output: global and not reusable because it needs to persist between special sample
hits
• DirectFeedthrough: yes

11-108
Write S-Function and TLC Files By Hand

OutputFcn
if (ssIsSampleHit(".1")) {
if (ssIsSpecialSampleHit("1")) {
y = u;
}
}

Example adding a simple algorithm:

• File: sfun_multirate_avg.c; Equation: y = average(u)


• Input: local and reusable
• Output: local and reusable
• DirectFeedthrough: yes

(Assume DWork[0:10] and DWork[mycounter] are initialized to zero)


OutputFcn
if (ssIsSampleHit(".1")) {
/* In general, processing on 'u' could be done here,
it runs on every hit of the fast rate. */
DWork[DWork[mycounter]++] = u;
if (ssIsSpecialSampleHit("1")) {
/* In general, processing on DWork[0:10] can be done
here, but it does cause the faster rate to have
nonuniform processing requirements (every 10th hit,
more code needs to be run).*/
DWork[10] = sum(DWork[0:9])/10;
DWork[mycounter] = 0;
}
}
if (ssIsSampleHit("1")) {
/* Processing on DWork[10] can be done here before
outputing. This code runs on every hit of the
slower task. */
y = DWork[10];
}

Rules for Properly Handling Slow-to-Fast Transitions

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:

• Always read input from the update function.


• Use no special sample hit checks when reading input.
• Write the input to a DWork.
• When there is a special sample hit between the rates, copy the DWork into a second
DWork in the output function.

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:

• File: sfun_multirate_delay.c, Equation: y = u(tslow-1)


• 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: local and reusable
• DirectFeedthrough: no
OutputFcn
if (ssIsSampleHit(".1") {
if (ssIsSpecialSampleHit("1") {
DWork[1] = DWork[0];
}
y = DWork[1];
}
UpdateFcn
if (ssIsSampleHit("1")) {
DWork[0] = u;
}

An alternative, optimized approach can be used by some algorithms:

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;
}

Example adding a simple algorithm:

• File: sfun_multirate_modulate.c, Equation: y = sin(tfast) + u(tslow-1)


• Input: Set to local, will be local if output/update are combined (an ERT feature)
otherwise will be global. Set to not reusable because input needs to be preserved until
the update function runs.
• Output: local and reusable
• DirectFeedthrough: no
OutputFcn
if (ssIsSampleHit(".1") {
if (ssIsSpecialSampleHit("1") {
/* Processing not likely to be done here. It causes
* the faster rate to have nonuniform processing
* requirements (every 10th hit, more code needs to
* be run).*/
DWork[1] = DWork[0];
}
/* Processing done at fast rate */
y = sin(ssGetTaskTime(".1")) + DWork[1];
}
UpdateFcn
if (ssIsSampleHit("1")) {
/* Processing on 'u' can be done here. There is a delay of
one slow rate period before the fast rate sees it.*/
DWork[0] = 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

Guidelines and Standards for


Embedded Coder

• “Support for Standards and Guidelines” on page 12-2


• “MAAB Guidelines” on page 12-5
• “MISRA C Guidelines” on page 12-6
• “Secure Coding Standards” on page 12-8
• “IEC 61508 Standard” on page 12-9
• “Develop a Model that Complies with the IEC 61508 Standard” on page 12-11
• “IEC 62304 Standard” on page 12-14
• “ISO 26262 Standard” on page 12-15
• “EN 50128 Standard” on page 12-17
• “DO-178C Standard” on page 12-19
12 Guidelines and Standards for Embedded Coder

Support for Standards and Guidelines


If your application has mission-critical development and certification goals, your models
or subsystems and the code generated for them might need to comply with one or more of
the standards and guidelines listed in the following table.

Standard or Guidelines Organization For More Information, See...


Guidelines: Use of MATLAB, MAAB • Control Algorithm Modeling
Simulink, and Stateflow Guidelines Using MATLAB,
software for control algorithm Simulink, and Stateflow
modeling – MathWorks Software: MathWorks
Automotive Advisory Board Automotive Advisory Board
(MAAB) Guidelines (MAAB) Guidelines
• Develop Models and Code that
Comply with “MAAB
Guidelines” on page 12-5
Guidelines: Use of the C Motor Industry Software • MISRA C website
Language in Critical Systems Reliability Association • Technical Solution 1-1IFP0W on
(MISRA C®a) (MISRA) the MathWorks website
• Develop Models and Code that
Comply with “MISRA C
Guidelines” on page 12-6
Standard: CERT® C Coding CERT Division of the Software • CERT C Coding Standards
Standards b Engineering Institute (SEI) publication on the Software
Engineering Institute website
• Secure Coding on the Software
Engineering Institute website
• Develop Model and Code that
Comply with “Secure Coding
Standards” on page 12-8
Standard: Common Weakness The MITRE Corporation • CWE list of software
Enumeration (CWE™c) weaknesses types
• Develop Model and Code that
Comply with “Secure Coding
Standards” on page 12-8

12-2
Support for Standards and Guidelines

Standard or Guidelines Organization For More Information, See...


Standard: ISO/IEC TS 17961 International Organization for • ISO/IEC TS 17961:2013
Standardization and standards publication
International Electrotechnical • Develop Model and Code that
Commission Comply with “Secure Coding
Standards” on page 12-8
Standard: AUTomotive Open AUTOSAR Development • Publications and specifications
System ARchitecture Partnership available from the AUTOSAR
(AUTOSAR) website
• AUTOSAR Support from
Embedded Coder on the
MathWorks website
• “AUTOSAR Standard”
• Embedded Coder “AUTOSAR”
documentation
Standard: IEC 61508, International Electrotechnical • IEC functional safety zone
Functional safety of electrical/ Commission website
electronic/programmable • IEC 61508 Support in MATLAB
electronic safety-related and Simulink
systems
• Develop Models and Code that
Comply with “IEC 61508
Standard” on page 12-9
Standard: IEC 62304, Medical International Electrotechnical • Develop Models and Code that
device software - Software life Commission Comply with “IEC 62304
cycle processes Standard” on page 12-14
Standard: ISO 26262, Road International Organization for • ISO 26262 Support in MATLAB
Vehicles - Functional Safety Standardization and Simulink
• Develop Models and Code that
Comply with “ISO 26262
Standard” on page 12-15
Standard: EN 50128, Railway European Committee for • Develop Models and Code that
applications — Software for Electrotechnical Comply with “EN 50128
railway control and protection Standardization Standard” on page 12-17
systems

12-3
12 Guidelines and Standards for Embedded Coder

Standard or Guidelines Organization For More Information, See...


Standard: DO-178C, Software Radio Technical Commission • Develop Models and Code that
Considerations in Airborne for Aeronautics (RTCA) Comply with “DO-178C
Systems and Equipment Standard” on page 12-19
Certification
a. MISRA® and MISRA C are registered trademarks of MISRA Ltd., held on behalf of the MISRA Consortium.
b. CERT is registered in the U.S. Patent and Trademark Office by Carnegie Mellon University.
c. CWE is a trademark of The MITRE Corporation.

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).

For information about MISRA C, see www.misra.org.uk.

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:

1 Open the Model Advisor.


2 Navigate to By Task > Modeling Guidelines for MISRA C:2012.
3 Run the checks in the folder.

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

Secure Coding Standards


These coding standards are for software developers to use in the development of code in
the C language:

• CERT® C — Published by the CERT Division of the Software Engineering Institute


(SEI), these guidelines help eliminate constructs with undefined behavior that can lead
to unexpected results at runtime and expose security weaknesses.
• Common Weakness Enumeration (CWE™) — Published by The MITRE Corporation,
this list identifies common software weakness types that can occur in software
architecture, design, code, or implementation. These weaknesses can lead to security
vulnerabilities.
• ISO/IEC TS 19761:2013 — Published by International Organization for
Standardization and International Electrotechnical Commission, these rules are
designed so that they can be enforced by static analysis tools without excessive false
positives.

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:

1 Open the Model Advisor.


2 Navigate to By Task > Modeling Guidelines for secure coding standards (CERT
C, CWE, ISO/IEC TS 17961) .
3 Run the checks in the folder.

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

IEC 61508 Standard


In this section...
“Apply Simulink and Embedded Coder to the IEC 61508 Standard” on page 12-9
“Check for IEC 61508 Standard Compliance Using the Model Advisor” on page 12-9
“Validate Traceability” on page 12-9

Apply Simulink and Embedded Coder to the IEC 61508


Standard
Applying Model-Based Design to a safety-critical system requires extra consideration and
rigor so that the system adheres to defined safety standards. IEC 61508, Functional
safety of electrical/electronic/programmable electronic safety related systems, is such a
standard. Because the standard was published when most software was coded by hand,
the standard needs to be mapped to Model-Based Design technologies. For further
information about MathWorks support for IEC 61508, see IEC 61508 Support in MATLAB
and Simulink.

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/.

Check for IEC 61508 Standard Compliance Using the Model


Advisor
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 selected aspects of the
IEC 61508 standard by running the Simulink Model Advisor (Simulink). Navigate to By
Task > Modeling Standards for IEC 61508 and run the “IEC 61508, IEC 62304, ISO
26262, and EN 50128 Checks” (Simulink Check).

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

Develop a Model that Complies with the IEC 61508


Standard
This example shows how to use Model Advisor checks for the IEC 61508 standard to
develop a model and code that comply with the standard.

The IEC 61508 checks identify issues with a model that impede deployment in safety-
related applications or limit traceability.

Understanding the Model

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

Apply the IEC 61508 Modeling Standard Checks

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.

To identify possible compliance issues with the model:

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.

To review the check results and make changes:

1 Review the Summary in the Report section of the right pane.


2 In the Task Hierarchy, select a check that did not pass. Review the results that
appear in the right pane for that check. For more information on the check and on
how to resolve reported issues, with the check selected, click Help.
3 Click the Generate Code Using Embedded Coder button in the model to inspect
the generated code and the traceability report.
4 Resolve the reported issues and rerun the checks.
5 Review the generated HTML report of the check results by clicking the link in the
Report box.
6 Print the generated HTML report. You can use the report as evidence in the IEC
61508 compliance example process.

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

IEC 62304 Standard

Apply Simulink and Embedded Coder to the IEC 62304


Standard
Applying Model-Based Design to a safety-critical system requires extra consideration and
rigor so that the system adheres to defined safety standards. Standard: IEC 62304,
Medical device software - Software life cycle processes, is such a 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 62304
standard. For more information, see https://www.mathworks.com/products/iec-61508/.

Check for IEC 62304 Standard Compliance Using the Model


Advisor
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 selected aspects of the
IEC 62304 standard by running the Simulink Model Advisor (Simulink). Navigate to By
Task > Modeling Standards for IEC 62304 and run the “IEC 61508, IEC 62304, ISO
26262, and EN 50128 Checks” (Simulink Check).

For more information on using the Model Advisor, see “Run Model Checks” (Simulink).

12-14
ISO 26262 Standard

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

Apply Simulink and Embedded Coder to the ISO 26262


Standard
Applying Model-Based Design to a safety-critical system requires extra consideration and
rigor so that the system adheres to defined functional safety standards. ISO 26262, Road
Vehicles - Functional Safety, is such a standard. For further information about MathWorks
support for ISO 26262, see ISO 26262 Support in MATLAB and Simulink.

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/.

Check for ISO 26262 Standard Compliance Using the Model


Advisor
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 selected aspects of the
ISO 26262 standard by running the Simulink Model Advisor (Simulink). Navigate to By
Task > Modeling Standards for ISO 26262 and run the “IEC 61508, IEC 62304, ISO
26262, and EN 50128 Checks” (Simulink Check).

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

Apply Simulink and Embedded Coder to the EN 50128


Standard
Applying Model-Based Design to a safety-critical system requires extra consideration and
rigor so that the system adheres to defined safety standards. EN 50128, Railway
applications — Software for railway control and protection systems, is such a 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 EN 50128
standard. For more information, see https://www.mathworks.com/products/iec-61508/.

Check for EN 50128 Standard Compliance Using the Model


Advisor
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 selected aspects of the
EN 50128 standard by running the Simulink Model Advisor (Simulink). Navigate to By
Task > Modeling Standards for EN 50128 and run the “IEC 61508, IEC 62304, ISO
26262, and EN 50128 Checks” (Simulink Check).

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

Apply Simulink and Embedded Coder to the DO-178C Standard


Applying Model-Based Design to a high-integrity system requires extra consideration and
rigor so that the system adheres to defined safety standards. DO-178C Software
Considerations in Airborne Systems and Equipment Certification is such a standard. A
supplement to DO-178C, DO-331, provides guidance on the use of Model-Based Design
technologies. MathWorks provides a DO Qualification Kit product that you can use to
qualify MathWorks verification tools for projects based on the DO-178C, DO-331, and
related standards. For more information, see https://www.mathworks.com/products/
do-178/.

For information about Model-Based Design and MathWorks support of aerospace and
defense industry standards, see https://www.mathworks.com/aerospace-defense/ .

Check for Standard Compliance Using the Model Advisor


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 selected aspects of the
DO-178C standard by running the Simulink Model Advisor (Simulink). Navigate to By
Product > Simulink Check > Modeling Standards > DO-178C/DO-331 Checks or
By Task > Modeling Standards for DO-178C/DO-331 and run the DO-178C/DO-331
checks (Simulink Check).

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

MISRA C:2012 Compliance and


Deviations for Code Generated by
Using Embedded Coder

• “Using This Documentation When Developing a MISRA C:2012 Compliance


Statement” on page 13-2
• “Evaluate Your Generated Code for MISRA C:2012 Compliance” on page 13-4
• “Compliance Information Summary Tables” on page 13-7
• “Modeling Guidelines for MISRA C:2012 Compliance” on page 13-21
• “Deviations Rationale” on page 13-30
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

Using This Documentation When Developing a MISRA C:


2012 Compliance Statement
As part of the model development process, it is important that C code generated by
Embedded Coder from Simulink and Stateflow complies with industry coding standards.

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 .

Disclaimer While adhering to the recommendations in the MISRA C:2012 Compliance


and Deviations for Code Generated using Embedded Coder documentation will reduce the
risk that an error is introduced during development and not be detected, it is not a
guarantee that the system being developed will be safe. Conversely, if some of the
recommendations are not followed, it does not mean that the system being developed will
be unsafe.

MathWorks Process for Identifying Violations of MISRA C:2012


Guidelines in Generated C Code
To determine any potential violations in the generated code, MathWorks maintains an
extensive set of test models that cover the standard usage of compliant blocks. For each
release, MathWorks uses these test models with the following products to evaluate the
modeling, code generation, and analysis of generated code.

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.

Use the Polyspace Bug Finder MISRA C:


2012 Checker (Polyspace Bug Finder) to
analyze the generated code against the
MISRA C:2012 Directives and Rules
(Polyspace Bug Finder) and provide
information about violations.
Polyspace Code Prover Prove absence of run-time errors.

Use the Polyspace Code Prover MISRA C:


2012 checker (Polyspace Code Prover) to
analyze the generated code against the
MISRA C:2012 Directives and Rules
(Polyspace Code Prover) and provide
information about violations.
a. MISRA C:2012 checks are available only when you have an Simulink Check or Embedded Coder license.

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

Evaluate Your Generated Code for MISRA C:2012


Compliance
It is important to check that C code generated by Embedded Coder from Simulink and
Stateflow complies with MISRA C:2012 coding standards. This workflow illustrates the
process of evaluating your generated code for compliance to MISRA C:2012 guidelines.

1 Design the model in Simulink (Simulink) or Stateflow (Stateflow)


2 Open the Model Advisor (Simulink) and run the MISRA C:2012 checks (Simulink
Check), which are available in By Task > Modeling Standards for MISRA C:2012.

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

• A shared utility folder to synchronize functions


• Data ownership to control data definitions
• Hand integration to manage code generated from various models
5 Execute the Polyspace Bug Finder MISRA C:2012 Checker (Polyspace Bug Finder).

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

Compliance Information Summary Tables

In this section...
“Compliance Summary Tables” on page 13-7
“Explanatory Notes” on page 13-17

Compliance Summary Tables


MathWorks evaluates C code generated by Embedded Coder from Simulink and Stateflow
against the MISRA C:2012 coding standards. The results from this effort are available in
these compliance summary tables. These tables identify:

• Methods used to obtain compliance:

• Compliant: Compliance to the rule/directive is achieved through adherence to the


code generation process, modeling guidelines, or Model Advisor checks. When
applicable, there are explanatory notes that provide information relevant to
compliance methods or actions that you can perform to satisfy the directive or rule.
• Deviation: The rule or directive is not compliant.
• Whether the Polyspace MISRA C:2012 Checker supports the rule or directive.

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.

"Implementation" MISRA C:2012 Directives

Directive Category Compliance Polyspace


Support?
1.1 Required Compliant: Yes,
partially
• hisl_0060 supported
• hisl_0016
• “Explanatory Note for Directive 1.1” on page
13-17

13-7
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

"Compilation and Build" MISRA C:2012 Directives

Directive Category Compliance Polyspace


Support?
2.1 Required Compliant Yes

"Requirements Traceability" MISRA C:2012 Directives

Directive Category Compliance Polyspace


Support?
3.1 Required Compliant: No

• “Explanatory Note for MISRA Directive 3.1” on


page 13-18

13-8
Compliance Information Summary Tables

"Code Design" MISRA C:2012 Directives

Directive Category Compliance Polyspace


Support?
4.1 Required Compliant: Yes

• 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

• “Explanatory Note for Directive 4.3” on page


13-18
4.6 Required Not Applicable. See “Explanatory Note for N/A
Directive 4.6” on page 13-19
4.7 Required Compliant: Yesa

• Check for missing error ports for AUTOSAR


receiver interfaces

Deviation:

• Deviation for AUTOSAR target-based code


generator - sender ports. See “MISRA C:2012
Directive 4.7 Deviation Rationale” on page 13-
30
4.10 Required Compliant Yes
4.11 Required Compliant: Yes

• “Explanatory Note for Directive 4.11” on page


13-19

13-9
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

Directive Category Compliance Polyspace


Support?
4.12 Required Compliant: No

• 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.

"Standard C Environment" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
1.1 Required Compliant Yes
1.3 Required Compliant Yes

"Unused Code" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
2.1 Required Compliant: Yes

• hisl_0053
• hisl_0101
2.2 Required Compliant Yes

"Comments" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
3.1 Required Compliant: Yes

• Check for unsupported block names


3.2 Required Compliant Yes

"Character Sets and Lexical Conventions" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
4.1 Required Compliant Yes

13-10
Compliance Information Summary Tables

"Identifiers" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
5.1 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.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

• “Explanatory Note for Rules 5.1, 5.2, 5.4, 5.5,


5.6, 5.7, and 5.8” on page 13-19
5.7 Required Compliant: Yes

• “Explanatory Note for Rules 5.1, 5.2, 5.4, 5.5,


5.6, 5.7, and 5.8” on page 13-19
5.8 Required Compliant: Yes

• “Explanatory Note for Rules 5.1, 5.2, 5.4, 5.5,


5.6, 5.7, and 5.8” on page 13-19

13-11
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

"Types" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
6.1 Required Compliant: Yes

• hisl_0060
6.2 Required Compliant: Yes

• hisl_0060

"Literals and Constants" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
7.4 Required Compliant Yes

"Declarations and Definitions" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
8.1 Required Compliant Yes
8.2 Required Compliant Yes
8.3 Required Compliant Yes
8.6 Required Compliant Yes
8.8 Required Compliant Yes
8.10 Required Compliant Yes
8.12 Required Compliant: Yes

• “Explanatory Note for Rule 8.12” on page 13-


19

13-12
Compliance Information Summary Tables

"Initialization" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
9.1 Mandatory Compliant: Yes

• hisl_0029
• Check usage of Assignment blocks
9.4 Required Compliant Yes

"Pointer Type Conversion" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
11.1 Required Compliant Yes
11.2 Required Compliant Yes
11.3 Required Compliant: Yes

• hisl_0020
11.6 Required Compliant Yes
11.7 Required Compliant Yes
11.8 Required Compliant: Yes

• hisl_0020

"Expressions" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
12.2 Required Compliant Yes

13-13
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

"Side Effects" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
13.1 Required Compliant Yes
13.2 Required Compliant: Yes

• hisl_0062
13.5 Required Compliant: Yes

• hisl_0062

Deviation:

• “MISRA C:2012 Rule 13.5 Deviation Rationale”


on page 13-34
13.6 Mandatory Compliant Yes

"Control Statement Expressions" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
14.3 Required Compliant: Yes

• hisl_0101

"Control Flow" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
15.6 Required Compliant Yes

13-14
Compliance Information Summary Tables

"Functions" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
17.1 Required Compliant Yes
17.2 Required Compliant: Yes

• hisf_0004
17.3 Mandatory Compliant Yes
17.4 Mandatory Compliant Yes
17.6 Mandatory Compliant Yes

"Pointers and Arrays" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
18.1 Required Compliant Yes
18.2 Required Compliant Yes
18.3 Required Compliant Yes
18.6 Required Compliant Yes
18.7 Required Compliant Yes
18.8 Required Compliant Yes

"Overlapping Storage" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
19.1 Mandatory Compliant Yes

13-15
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

"Preprocessing Directives" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
20.2 Required Compliant Yes
20.3 Required Compliant Yes
20.4 Required Compliant Yes
20.6 Required Compliant Yes
20.7 Required Compliant Yes
20.9 Required Compliant Yes
20.11 Required Compliant Yes
20.12 Required Compliant Yes
20.13 Required Compliant Yes
20.14 Required Compliant Yes

"Standard Libraries" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
21.1 Required Compliant Yes
21.2 Required Compliant: Yes

• 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

"Resources" MISRA C:2012 Rules

Rule Category Compliance Polyspace


Support?
22.1 Required Compliant Yes
22.2 Mandatory Compliant Yes
22.3 Required Compliant Yes
22.4 Mandatory Compliant Yes
22.5 Mandatory Compliant Yes
22.6 Mandatory Compliant Yes

Explanatory Notes
These explanatory notes are referenced from the “Compliance Information Summary
Tables” on page 13-7.

Explanatory Note for Directive 1.1

Information about the implementation-defined behavior for Embedded Coder is available


in “Configure Run-Time Environment Options” on page 7-2 . Compiler documentation is
out of scope.

Character set encoding is managed by using the SavedCharacterEncoding model


parameter. For additional information, including a list of supported character encodings,
see slCharacterEncoding.

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

Embedded Coder generates #pragma when the user:

• Selects the use of memory sections (Simulink Coder)


• Creates a custom storage class with memory sections on page 26-26

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

To enable the generation of bitfields:

1 Select at least one of these model configuration parameters:

• 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.

Explanatory Note for MISRA Directive 3.1

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).

Explanatory Note for Directive 4.1

You can use Polyspace Bug Finder to identify run-time errors and Polyspace Code Prover
to prove the absence of run-time errors.

For information about running an analysis, see:

• “Configure and Run Analysis” (Polyspace Code Prover)


• “Configure and Run Analysis” (Polyspace Bug Finder)

Explanatory Note for Directive 4.3

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.

For additional information, see:

• “External C Functions” on page 14-65


• “Code Replacement Customization”

13-18
Compliance Information Summary Tables

• “Control Data and Function Placement in Memory by Inserting Pragmas” on page 30-
2

Explanatory Note for Directive 4.6

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.

Explanatory Note for Directive 4.11

The requirements of this directive are satisfied by:

“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

Embedded Coder is configurable to limit the number of characters imposed by the


implementation. For additional information, see Maximum identifier length.

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.

Explanatory Note for Rule 8.12

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).

Explanatory Note for Rules 10.1 and 10.2

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

• Plain char type for character values


• Signed and unsigned char type for numeric values

13-20
Modeling Guidelines for MISRA C:2012 Compliance

Modeling Guidelines for MISRA C:2012 Compliance


The “Compliance Information Summary Tables” on page 13-7 identifies modeling
guidelines that are relevant to the compliance of generated C code with MISRA C:2012
coding standards. For a list of these guidelines and their corresponding Model Advisor
check, see “High-Integrity System Modeling Guidelines for MISRA C:2012 Compliance”
on page 13-21. For information about the MISRA rationale for Model Advisor checks, see
“MISRA C:2012 Rationale for Model Advisor Checks” on page 13-23.

High-Integrity System Modeling Guidelines for MISRA C:2012


Compliance
To augment the modeling guidelines developed by the MathWorks Automotive Advisory
Board (MAAB), MathWorks has published a set of modeling guidelines that focus on high-
integrity applications.

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.

High-Integrity Guideline Model Advisor Check


hisl_0001: Usage of Abs block Check usage of Math Operations
blocks
hisl_0002: Usage of Math Function blocks (rem and Check usage of Math Operations
reciprocal) blocks
hisl_0005: Usage of Product blocks Check safety-related diagnostic
settings for signal data
hisl_0006: Usage of While Iterator blocks Check usage of Ports and
Subsystem blocks
hisl_0008: Usage of For Iterator Blocks Check usage of Ports and
Subsystem blocks
hisl_0010: Usage of If blocks and If Action Check usage of Ports and
Subsystem blocks Subsystem blocks
hisl_0011: Usage of Switch Case blocks and Action Check usage of Ports and
Subsystem blocks Subsystem blocks

13-21
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

High-Integrity Guideline Model Advisor Check


hisl_0016: Usage of blocks that compute relational Check usage of Logic and Bit
operators Operations blocks
hisl_0017: Usage of blocks that compute relational Check usage of Logic and Bit
operators (2) Operations blocks
hisl_0018: Usage of Logical Operator block Check usage of Logic and Bit
Operations blocks
hisl_0019: Usage of Bitwise Operator block Not applicable
hisl_0020: Blocks not recommended for MISRA C: Check for blocks not
2012 compliance recommended for MISRA C:2012

Check for blocks not


recommended for C/C++
production code deployment.
hisl_0029: Usage of Assignment blocks Check usage of Math Operations
blocks
hisl_0045: Configuration Parameters > Code Check safety-related optimization
Generation > Optimization > Implement logic settings
signals as Boolean data (vs. double)
hisl_0053: Configuration Parameters > Code Check safety-related optimization
Generation > Optimization > Remove code from settings
floating-point to integer conversions that wraps out-
of-range values
hisl_0054: Configuration Parameters > Code Check safety-related optimization
Generation > Optimization > Remove code that settings
protects against division arithmetic exceptions
hisl_0060: Configuration parameters that improve Check configuration parameters
MISRA C:2012 compliance for MISRA C:2012.

Check for bitwise operations on


signed integers
hisl_0061: Unique identifiers for clarity Check Stateflow charts for
uniquely defined data objects

Check usage of Stateflow


constructs

13-22
Modeling Guidelines for MISRA C:2012 Compliance

High-Integrity Guideline Model Advisor Check


hisl_0062: Global variables in graphical functions Not applicable
hisl_0063: Length of user-defined object names to Not applicable
improve MISRA C:2012 compliance
hisf_0064: Shift operations for Stateflow data to Check usage of shift operations for
improve code compliance Stateflow data
hisf_0065: Type cast operations in Stateflow to Check assignment operations in
improve code compliance Stateflow charts
hisl_0101: Avoid invariant comparison operations to Not applicable
improve MISRA C:2012 compliance
hisl_0102: Data type of loop control variables to Not applicable
improve MISRA C:2012 compliance
hisl_0201: Define reserved keywords to improve Not applicable
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.

High-Integrity Guideline Model Advisor Check


hisf_0003: Usage of bitwise operations Check for bitwise operations in Stateflow
charts
hisf_0004: Usage of recursive behavior Not applicable
hisf_0064: Shift operations for Stateflow Check usage of shift operations for
data to improve code compliance Stateflow data
hisf_0065: Type cast operations in Check assignment operations in Stateflow
Stateflow to improve code compliance charts
hisf_0211: Protect against use of unary Check Stateflow charts for unary operators
operators in Stateflow Charts to improve
code compliance

MISRA C:2012 Rationale for Model Advisor Checks


This table provides MISRA C:2012 rationale for the Model Advisor checks.

13-23
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

Model Advisor Check MISRA C:2012 Rule or Directive


Check configuration parameters for MISRA C:2012
Set Model Verification block General recommendation for embedded
enabling to Disable all systems
Set System target file to and General recommendation for embedded
ERT-based target systems
Code replacement library to General recommendation for embedded
None or AUTOSAR 4.0 systems
Set Shared code placement to Prerequisite of configuration parameter
Shared location Generate shared constants
Clear Generate shared MISRA Rule 8.5: An external object or
constants function shall be declared once in one and
only one file
Clear Support non-finite MISRA C:2012 Directive 4.1: Run-time
numbers failures shall be minimized
Clear Support continuous General recommendation for embedded
time systems
Clear Support non-inlined S- General recommendation for embedded
functions systems
Clear Mat-file logging General recommendation for embedded
systems
Set Parentheses level to MISRA C:2012 Rule 12.1: The precedence of
Maximum (Specify operators within expressions should be
precedence with made explicit
parentheses)
Set Casting modes to MISRA C:2012 Rules 10.x: The essential
Standards Compliant type model

13-24
Modeling Guidelines for MISRA C:2012 Compliance

Model Advisor Check MISRA C:2012 Rule or Directive


Set System-generated MISRA C:2012 5.1: External identifiers shall
identifiers to Shortened be distinct

MISRA C:2012 5.2: Identifiers declared in


the same scope and name space shall be
distinct

MISRA C:2012 5.4: Macro identifiers shall


be distinct

MISRA C:2012 5.5: Identifiers shall be


distinct from macro names
Set Bitfield declarator type MISRA C:2012 Rule 6.1: Bit-fields shall only
specifierto uint_T be declared with an appropriate type

MISRA C:2012 Rule 6.2: Single-bit named


bit fields shall not be of a signed type
Set Signed integer division MISRA C:2012 Rule 10.1: Operands shall not
rounds to to Zero or Floor be of an inappropriate essential type.
Set Use division for fixed- MISRA C:2012 Rule 10.1: Operands shall not
point net slope computation be of an inappropriate essential type.
to on or Use division for
reciprocals of integers
only
EnableSignedLeftShifts – off MISRA C:2012 Rule 10.1: Operands shall not
be of an inappropriate essential type
Clear Allow right shifts on MISRA C:2012 Rule 10.1: Operands shall not
signed integers be of an inappropriate essential type.
Clear Use dynamic memory MISRA C:2012 Directive 4.12: Dynamic
allocation for model memory allocation shall not be used.
initialization
MISRA C:2012 Rule 21.3: The memory
allocation and deallocation functions of
<stdlib.h> shall not be used.
Set Wrap on overflow to MISRA C:2012 Directive 4.1: Run-time
warning or error failures shall be minimized

13-25
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

Model Advisor Check MISRA C:2012 Rule or Directive


Set Inf or NaN block output to MISRA C:2012 Directive 4.1: Run-time
warning or error failures shall be minimized
Clear Dynamic memory MISRA C:2012 Directive 4.12: Dynamic
allocation in MATLAB memory allocation shall not be used.
functions
MISRA C:2012 Rule 21.3: The memory
allocation and deallocation functions of
<stdlib.h> shall not be used.
Select Preserve static keyword MISRA Rule 8.7: Functions and objects
in function declarations should not be defined with external linkage
if they are referenced in only one translation
unit

MISRA Rule 8.8: The static storage class


specifier shall be used in all declarations of
objects and functions that have internal
linkage
Check for blocks not recommended for C/C General recommendation for embedded
++ production code deployment systems
Check for blocks not recommended for MISRA C:2012

13-26
Modeling Guidelines for MISRA C:2012 Compliance

Model Advisor Check MISRA C:2012 Rule or Directive


Lookup Table blocks using cubic MISRA C:2012 Rule 11.3: A cast shall not be
spline interpolation or performed between a pointer to object type
extrapolation methods and a pointer to a different object type.

MISRA C:2012 Rule 11.5: A conversion


should not be performed from pointer to
void into pointer to object.

MISRA C:2012 Rule 11.8: A cast shall not


remove any const or volatile qualification
from the type pointed to by a pointer.

MISRA C:2012 Rule 11.9: The macro NULL


shall be the only permitted form of integer
null pointer constant.

MISRA C:2012 Rule 12.1: The precedence of


operators within expressions should be
made explicit.

13-27
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

Model Advisor Check MISRA C:2012 Rule or Directive


Deprecated Lookup Table blocks MISRA C:2012 Rule 11.3: A cast shall not be
performed between a pointer to object type
and a pointer to a different object type.

MISRA C:2012 Rule 11.5: A conversion


should not be performed from pointer to
void into pointer to object.

MISRA C:2012 Rule 11.8: A cast shall not


remove any const or volatile qualification
from the type pointed to by a pointer.

MISRA C:2012 Rule 11.9: The macro NULL


shall be the only permitted form of integer
null pointer constant.

MISRA C:2012 Rule 12.1: The precedence of


operators within expressions should be
made explicit.

MISRA C:2012 Rule 12.2: The right hand


operand of a shift operator shall lie in the
range zero to one less than the width in bits
of the essential type of the left hand
operand.
S-Function Builder blocks MISRA C:2012 Rule 8.4: A compatible
declaration shall be visible when an object
or function with external linkage is defined.

MISRA C:2012 Rule 8.5: An external object


or function shall be declared once in one and
only one file.
From Workspace blocks MISRA C:2012 Rule 18.4: The +, -, += and -
= operators should not be applied to an
expression of pointer type.
Check for unsupported block names MISRA C:2012 Rule 3.1: The character
sequences /* and // shall not be used within
a comment.

13-28
Modeling Guidelines for MISRA C:2012 Compliance

Model Advisor Check MISRA C:2012 Rule or Directive


Check usage of Assignment blocks MISRA C:2012 Rule 9.1: The value of an
object with automatic storage duration shall
not be read before it has been set.
Check for switch case expressions without MISRA C:2012 Rule 16.4: Every switch
a default case statement shall have a default label.
Check for missing error ports in AUTOSAR MISRA C:2012 Directive 4.7 If a function
receiver interfaces returns error information, then that error
information shall be tested.

MISRA C:2012 Rule 17.7: The value


returned by a function having non-void
return type shall be used.
Check for bitwise operations on signed MISRA C:2012 Rule 10.1: Operands shall not
integers be of an inappropriate essential type.
Check for recursive function calls MISRA C:2012 Rule 17.2: Functions shall
not call themselves, either directly or
indirectly.
Check for equality and inequality MISRA C:2012 Directive 1.1: Any
operations on floating-point values implementation-defined behaviour on which
the output of the program depends shall be
documented and understood.
Check for missing const qualifiers in model MISRA C:2012 Rule 8.13: A pointer should
functions point to a const-qualified type whenever
possible.
Check integer word lengths MISRA C:2012 Rule 10.1: Operands shall not
be of an inappropriate essential type.
Check for bus object names that are used MISRA C:2012 Rule 10.1: Operands shall not
as bus element names be of an inappropriate essential type.

MISRA C:2012 Rule 5.6: A typedef name


shall be a unique identifier.

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:

• The guideline being deviated


• The circumstances in which the deviation is permitted
• Justification for the deviation, including a risk assessment
• Demonstration of how safety is assured
• Potential consequences of non-conformance

Deviations to the MISRA C:2012 directives and rules include:

• “MISRA C:2012 Directive 4.7 Deviation Rationale” on page 13-30


• “MISRA C:2012 Rule 13.5 Deviation Rationale” on page 13-34
• “MISRA C:2012 Rule 21.1 Deviation Rationale” on page 13-36

MISRA C:2012 Directive 4.7 Deviation Rationale


Directive Definition

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

Simulink pattern is a top-level output port that is configured as an AUTOSAR Sender


Interface.

Model Example

AUTOSAR Configuration

13-31
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

Generated Code Sample

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.

Conditions Under Which the Deviation is Requested

The deviation is requested for all instances of AUTOSAR sender ports.

Consequences of Noncompliance

The calling program cannot react when the sender operation is unsuccessful.

Actions to Control Reporting

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).

For additional information, see:

13-33
13 MISRA C:2012 Compliance and Deviations for Code Generated by Using Embedded Coder

• “Modeling Patterns for AUTOSAR Runnables” on page 1-44


• “Getting Started with AUTOSAR Code Generation”
• “Compliance Information Summary Tables” on page 13-7

MISRA C:2012 Rule 13.5 Deviation Rationale


Rule Definition

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

Generated Code Sample

In the sample code, note the use of operand && in Y1 = (U1 && (sqrt(U2) <=
3.0));.

/* Exported block signals */


boolean_T U1; /* '<Root>/U1' */
real_T U2; /* '<Root>/U2' */
boolean_T Y1; /* '<Root>/Logical Operator' */

/* Model step function */


void DEV_R1305_01main_step(void)
{
/* Logic: '<Root>/Logical Operator' incorporates:
* Constant: '<S1>/Constant'
* Inport: '<Root>/U1'
* Inport: '<Root>/U2'
* RelationalOperator: '<S1>/Compare'
* Sqrt: '<Root>/Sqrt'
*/
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.

Conditions Under Which the Deviation is Requested

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.

Actions to Control Reporting

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.

MISRA C:2012 Rule 21.1 Deviation Rationale


Rule Definition

#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.

A symbol is a variable or function name and is already defined: Flagged by compiler


warnings/errors for symbol redefinition.

A symbol is a macro name and is already defined: Flagged by compiler warnings/errors


for macro redefinition.

Conditions Under Which the Deviation is Requested

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.

Actions to Control Reporting

Review violations caused by leading underscores to check whether there is a conflict with
compiler implementation.

13-37
14

Patterns for C Code in Embedded


Coder

• “Prepare a Model for Code Generation” on page 14-3


• “Definition, Initialization, and Declaration of Parameter Data” on page 14-7
• “Definition and Declaration of Signal Data” on page 14-9
• “Data Type Conversion” on page 14-11
• “Type Qualifiers” on page 14-14
• “Relational and Logical Operators” on page 14-16
• “Bitwise Operations” on page 14-20
• “Enumeration” on page 14-23
• “If-Else” on page 14-27
• “Switch” on page 14-32
• “For Loop” on page 14-37
• “While Loop” on page 14-43
• “Do While Loop” on page 14-53
• “Function Call” on page 14-59
• “Function Prototyping” on page 14-61
• “External C Functions” on page 14-65
• “Macro Definitions (#define)” on page 14-71
• “Conditional Inclusions (#if / #endif)” on page 14-74
• “Typedef” on page 14-75
• “Structures of Parameters” on page 14-77
• “Structures of Signals” on page 14-81
• “Nested Structures of Signals” on page 14-84
• “Bitfields” on page 14-89
• “Arrays for Parameters” on page 14-92
14 Patterns for C Code in Embedded Coder

• “Arrays for Signals” on page 14-94


• “Pointers” on page 14-96

14-2
Prepare a Model for Code Generation

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:

Model Components Naming Convention


Inputs u1, u2, u3, and so on
Outputs y1, y2, y3, and so on
Parameters p1, p2, p3, and so on
States x1, x2, x3, and so on

Input ports are named to reflect the signal names that they propagate.

Configure Input Ports, Output Ports, and Arbitrary Signals


1 Create a model in Simulink. For more information, see “Model Editing Fundamentals”
(Simulink).

14-3
14 Patterns for C Code in Embedded Coder

2 In the model, select View > Model Data Editor.


3 In the Model Data Editor, on the Inports/Outports tab or the Signals tab, use the
Signal Name column or the Name column to give the target signal a name.
4 Set the Change view drop-down list to Code.
5 Use the Storage Class column to apply a storage class to the signal.

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.

Initialize and Configure States


1 In the Model Data Editor, on the States tab, use the Initial Value column to specify
initial values for a block state (such as the state of a Unit Delay block).
2 Set the Change view drop-down list to Code.
3 Use the Name column to give the state a name.
4 Use the Storage Class column to apply a storage class to the state.

Set Up Configuration Parameters for Code Generation


1 Open the Configuration Parameter dialog box by selecting Simulation > Model
Configuration parameters. You can also use the keyboard shortcut Ctrl+E.
2 Open the Solver pane and select

• Solver type: Fixed-Step


• Solver: discrete (no continuous states)
3 Open the Optimization pane, and set Default parameter behavior to Inlined.
4 Open the Code Generation pane, and specify ert.tlc as the System Target File.
5 Clear Generate makefile.
6 Select Generate code only.
7 Enable the HTML report generation by opening the Code Generation > Report
pane and selecting Create code generation report and Open report
automatically. Click the horizontal ellipsis and, under Advanced parameters,
select Code-to-model. Enabling the HTML report generation is optional.
8 Click Apply and then OK to exit.

14-4
Prepare a Model for Code Generation

Set Up an Example Model With a Stateflow Chart

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:

• Double-click the Stateflow chart.


• Press Ctrl+R.
4 Select Chart > Add Inputs & Outputs > Data Input from Simulink to add the
inputs to the chart. A Data dialog box opens for each input.
5 Specify the Name (u1, u2, ...) and the Type (Inherit: Same as Simulink)
for each input, unless specified differently in the example. Click OK.

Click Apply and close each dialog box.


6 Select Chart > Add Inputs & Outputs > Data Output from Simulink to add the
outputs to the chart. A Data dialog opens for each output.
7 Specify the Name (y1, y2, ...) and Type (Inherit: Same as Simulink) for
each output, unless specified differently in the example. Click OK.
8 Click Apply and close each dialog box.
9 In the Stateflow Editor, create the Stateflow diagram specific to the example.
10 The inputs and outputs appear on the chart in your model.
11 Connect the Inport and Outport blocks to the Stateflow Chart.
12 Configure the input and output signals; see “Configure Input Ports, Output Ports, and
Arbitrary Signals” on page 14-3.

14-5
14 Patterns for C Code in Embedded Coder

Set Up an Example Model With a MATLAB Function Block

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

Definition, Initialization, and Declaration of Parameter


Data
This example shows how to export the definition, initialization, and declaration of a global
variable that the generated code uses as a parameter.

C Construct
int32 myParam = 3;

extern int32 myParam;

Procedure
1 Create the ex_defn_decl model by using a Gain block.

2 In the model, select View > Property Inspector.


3 In the model, select the Gain block.
4 In the Property Inspector, set the value of the Gain parameter to myParam.
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(3). Click
Create.

A Simulink.Parameter object, myParam, appears in the base workspace. The Gain


block uses the object to set the value of the Gain parameter, in this case, 3.
7 In the Simulink.Parameter property dialog box, set Data type to int32.
8 Set Storage class to ExportToFile.
9 Set HeaderFile to myDecls.h.
10 Set DefinitionFile to myDefns.c. Click OK.
11 Generate code from the model.

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.

/* Declaration for custom storage class: ExportToFile */


extern int32_T myParam;

The generated source file myDefns.c defines and initializes myParam.

/* Definition for custom storage class: ExportToFile */


int32_T myParam = 3;

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

Definition and Declaration of Signal Data


This example shows how to export the definition and declaration of a global variable that
the generated code uses as a signal.

C Construct
float mySig;

extern float mySig;

Procedure
1 Create the ex_defn_decl model by using a Gain block.

2 In the model, select View > Model Data Editor.


3 In the Model Data Editor, view the Inports/Outports tab.
4 From the Change view drop-down list, select Design.
5 In the model, select the Inport block.
6 In the Model Data Editor, for the Inport block, set Signal Name to mySig.
7 Set Data Type to single.
8 From the Change View drop-down list, select Code.
9 For the Inport block, set Storage Class to ExportToFile.
10 Set Header File to myDecls.h.
11 Set Definition File to myDefns.c.
12 Generate code from the model.

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

/* Declaration for custom storage class: ExportToFile */


extern real32_T mySig;

The generated source file myDefns.c defines the variable mySig.

/* Definition for custom storage class: ExportToFile */


real32_T mySig;

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

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

Modeling Pattern for Data Type Conversion — Simulink Block


One method to create a data type conversion is to use a Data Type Conversion block from
the Simulink > Commonly Used Blocks library.

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.

The generated code appears in ex_data_type_SL.c, as follows:

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;
}

The code generator type definition for double is real_T.

Modeling Pattern for Data Type Conversion — Stateflow Chart

Stateflow Chart Type Conversion

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

The generated code appears in ex_data_type_SF.c, as follows:


int32_T u1;
real_T y1;
RT_MODEL_ex_data_type_SF ex_data_type_SF_M_;
RT_MODEL_ex_data_type_SF *const ex_data_type_SF_M = &ex_data_type_SF_M_;
void ex_data_type_SF_step(void)
{
y1 = u1;
}

14-12
See Also

Modeling Pattern for Data Type Conversion — MATLAB


Function Block
Procedure

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

The generated code appears in ex_data_type_ML_func.c, where real32_T is a float


and real_T is a double. Type conversion occurs across assignments.
real32_T u1;
real_T y1;

void ex_data_type_ML_func_step(void)
{
y1 = u1;
}

Other Type Conversions in Modeling


Type conversions can also occur on the output of blocks where the output variable is
specified as a different data type. For example, in the Gain block, you can select the
Inherit via internal rule parameter to control the output signal data type. Another
example of type conversion can occur at the boundary of a Stateflow chart. You can
specify the output variable as a different data type.

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.

2 In the model, select View > Model Data Editor.


3 In the Model Data Editor, on the Parameters tab, set the value of the Gain
parameter to myParam.
4
Next to myParam, click the action button and select Create.
5 In the Create New Data dialog box, set Value to Simulink.Parameter(9.8) and
click Create.

A Simulink.Parameter object, myParam, appears in the base workspace. The Gain


block uses the object to set the value of the Gain parameter, in this case, 9.8.
6 In the Simulink.Parameter property dialog box, set Storage class to
ConstVolatile.

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.

/* Definition for custom storage class: ConstVolatile */


const volatile real_T myParam = 9.8;

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

Relational and Logical Operators


Modeling Patterns for Relational and Logical Operators
• “Modeling Pattern for Relational or Logical Operators — Simulink Blocks” on page 14-
16
• “Modeling Pattern for Relational and Logical Operators – Stateflow Chart” on page 14-
17
• “Modeling Pattern for Relational and Logical Operators — MATLAB Function Block”
on page 14-18

Modeling Pattern for Relational or Logical Operators —


Simulink Blocks

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

Code implementing the logical operator OR is in the ex_logical_SL_step function in


ex_logical_SL.c:
/* Exported block signals */
boolean_T u1; /* '<Root>/u1' */
boolean_T u2; /* '<Root>/u2' */
boolean_T y1; /* '<Root>/Logical Operator'*/

/* Logic: '<Root>/Logical Operator' incorporates:


* Inport: '<Root>/u1'
* Inport: '<Root>/u2'
*/
y1 = (u1 || u2);

Modeling Pattern for Relational and Logical Operators –


Stateflow Chart

ex_logical_SF/Logical Operator Stateflow 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 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

5 Press Ctrl+B to build the model and generate code.

Results

Code implementing the logical operator OR is in the ex_logical_SF_step function in


ex_logical_SF.c:
boolean_T u1; /* '<Root>/u1' */
boolean_T u2; /* '<Root>/u2' */
boolean_T y1; /* '<Root>/Chart' */

void ex_logical_SF_step(void)
{
y1 = (u1 || u2);
}

Modeling Pattern for Relational and Logical Operators —


MATLAB Function Block
This example demonstrates the MATLAB Function block method for incorporating
operators into the generated code using a relational operator.

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

Code implementing the relational operator '>' is in the ex_rel_operator_ML_step


function in ex_rel_operator_ML.c:
real_T u1; /* '<Root>/u1' */
real_T u2; /* '<Root>/u2' */
boolean_T y; /* '<Root>/MATLAB Function' */

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

Simulink Bitwise-Operator Block

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

Code implementing the logical operator OR is in the ex_bit_logic_SL_step function


in ex_bit_logic_SL.c:

14-20
Bitwise Operations

uint8_T u1;
uint8_T y1;

void ex_bit_logic_SL_step(void)
{
y1 = (uint8_T)(u1 & 217);
}

Stateflow Chart

ex_bit_logic_SF/Bit_Logic 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

Code implementing the logical operator OR is in the ex_bit_logic_SF_step function


in ex_bit_logic_SF.c:

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);
}

MATLAB Function Block


In this example, to demonstrate the MATLAB Function block method for implementing
bitwise logic into the generated code, use the bitwise OR, '|'.

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:

function y1 = fcn(u1, u2)

y1 = bitor(u1, u2);
end
4 Press Ctrl+B to build the model and generate code.

Results

Code implementing the bitwise operator OR is in the ex_bit_logic_ML_step function


in ex_bit_logic_ML.c:

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.

classdef ex_myEnumType < Simulink.IntEnumType

enumeration
Choice1(0)
Choice2(1)
end %enumeration

methods (Static)
function retVal = getHeaderFile()
retVal = 'myEnumHdr.h';
end %function

function retVal = getDataScope()


retVal = 'Exported';
end %function
end %methods

end %classdef

Create the model ex_pattern_enum by using an Enumerated Constant block and a


Multiport Switch block.

open_system('ex_pattern_enum')

14-23
14 Patterns for C Code in Embedded Coder

In the model, select View > Model Data Editor.

In the Model Data Editor, select the Parameters tab.

In the model, click the Enumerated Constant block.

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 Create New Data dialog box, set Value to


Simulink.Parameter(ex_myEnumType.Choice1) and click Create. A
Simulink.Parameter object named myChoice appears in the base workspace. The object
stores the enumerated value Choice1 of the type ex_myEnumType.

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 Data Editor, select the Signals tab.

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.

In the model, select View > Property Inspector.

14-24
Enumeration

In the model, select the Multiport Switch block.

In the Property Inspector, set:

• Data port order to Specify indices.


• Data port indices to enumeration('ex_myEnumType'). This expression returns all
of the enumeration members of ex_myEnumType.

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.

Generate code from the model.

rtwbuild('ex_pattern_enum');

### Starting build procedure for model: ex_pattern_enum


### Successful completion of build procedure for model: 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)

ex_myEnumType myChoice = Choice1; /* Variable: myChoice

/* Model step function */

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;
}

/* End of MultiPortSwitch: '<Root>/Multiport Switch' */


}

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

Modeling Pattern for If-Else: Switch block


One method to create an if-else statement is to use a Switch block from the Simulink
> Signal Routing library.

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

/* External outputs (root outports fed by signals with auto storage) */


ExternalOutputs Y;

/* Model step function */


void ex_if_else_SL_step(void)
{
/* Switch: '<Root>/Switch' incorporates:
* Inport: '<Root>/u1'
* Inport: '<Root>/u2'
* Outport: '<Root>/y1'
* RelationalOperator: '<Root>/Relational Operator'
*/
if (U.u1 > U.u2) {
Y.y1 = U.u1;
} else {
Y.y1 = U.u2;
}
}

Modeling Pattern for If-Else: Stateflow Chart

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:

Description If-Else (optional)

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;

/* External outputs (root outports fed by signals with auto storage) */


ExternalOutputs Y;

/* Model step function */


void ex_If_Else_SF_step(void)
{
/* Chart: '<Root>/Chart' incorporates:
* Inport: '<Root>/u1'
* Inport: '<Root>/u2'
*/
/* Gateway: Chart */
/* During: Chart */
/* Entry Internal: Chart */
/* Transition: '<S1>:15' */
/* If-Else */
if (U.u1 > U.u2) {
/* Outport: '<Root>/y1' */
/* Transition: '<S1>:16' */
/* Transition: '<S1>:18' */
Y.y1 = U.u1;

/* Transition: '<S1>:19' */
} else {
/* Outport: '<Root>/y1' */
/* Transition: '<S1>:17' */
Y.y1 = U.u2;
}

/* End of Chart: '<Root>/Chart' */


/* Transition: '<S1>:20' */
}

Modeling Pattern for If-Else: MATLAB Function Block


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.

14-30
If-Else

2 Name your model ex_if_else_ML.


3 In the MATLAB Function Block Editor enter the function, as follows:

function y1 = fcn(u1, u2)


if u1 > u2;
y1 = u1;
else y1 = u2;
end
4 Press Ctrl+B to build the model and generate code.

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;

/* External outputs (root outports fed by signals with auto storage) */


ExternalOutputs Y;

/* Model step function */


void ex_if_else_ML_step(void)
{
/* MATLAB Function Block: '<Root>/MATLAB Function' incorporates:
* Inport: '<Root>/u1'
* Inport: '<Root>/u2'
* Outport: '<Root>/y1'
*/
/* MATLAB Function 'MATLAB Function': '<S1>:1' */
if (U.u1 > U.u2) {
/* '<S1>:1:4' */
/* '<S1>:1:5' */
Y.y1 = U.u1;
} else {
/* '<S1>:1:6' */
Y.y1 = U.u2;
}
}

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

Modeling Pattern for Switch: Switch Case block


One method for creating a switch statement is to use a Switch Case block from the
Simulink > Ports and Subsystems library.

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

9 Enter Ctrl+B to build the model and generate code.

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' */

/* External inputs (root inport signals with auto storage) */


ExternalInputs U;

/* External outputs (root outports fed by signals with auto storage) */


ExternalOutputs Y;

/* Model step function */


void ex_switch_SL_step(void)
{
/* SwitchCase: '<Root>/Switch Case' incorporates:
* ActionPort: '<S1>/Action Port'
* ActionPort: '<S2>/Action Port'
* ActionPort: '<S3>/Action Port'
* Inport: '<Root>/u1'
* SubSystem: '<Root>/Switch Case Action Subsystem'
* SubSystem: '<Root>/Switch Case Action Subsystem1'
* SubSystem: '<Root>/Switch Case Action Subsystem2'
*/
switch (u1) {
case 2:
/* Inport: '<S1>/u2' incorporates:
* Inport: '<Root>/u2'
* Outport: '<Root>/y1'
*/
Y.y1 = U.u2;
break;

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

Modeling Pattern for Switch: MATLAB Function block


Procedure

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:

function y1 = fcn(u1, u2, u3, u4)

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;

/* External outputs (root outports fed by signals with auto storage) */


ExternalOutputs Y;

/* Model step function */


void ex_switch_ML_step(void)
{
/* MATLAB Function Block: '<Root>/MATLAB Function' incorporates:
* Inport: '<Root>/u1'
* Inport: '<Root>/u2'
* Inport: '<Root>/u3'
* Inport: '<Root>/u4'
* Outport: '<Root>/y1'
*/
/* MATLAB Function 'MATLAB Function': '<S1>:1' */
/* '<S1>:1:4' */
switch (U.u1) {
case 2:
/* '<S1>:1:6' */
Y.y1 = U.u2;
break;

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;
}
}

Convert If-Elseif-Else to Switch statement


If a MATLAB Function block or a Stateflow chart uses if-elseif-else decision logic,
you can convert it to a switch statement by using a configuration parameter. In the
Configuration Parameters dialog box, on the Code Generation > Code Style pane,
select the “Convert if-elseif-else patterns to switch-case statements” parameter. For more
information, see “Converting If-Elseif-Else Code to Switch-Case Statements” (Simulink).
For more information on this conversion using a Stateflow chart, see “Enhance
Readability of Code for Flow Charts” on page 39-108.

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

Modeling Pattern for For Loop: For-Iterator Subsystem block


One method for creating a for loop is to use a For Iterator Subsystem block from the
Simulink > Ports and Subsystems library.

Model ex_for_loop_SL

14-37
14 Patterns for C Code in Embedded Coder

For Iterator Subsystem

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

13 Save the subsystem and the model.


14 Enter Ctrl+B to build the model and generate code.

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;

/* External outputs (root outports fed by signals with auto storage) */


ExternalOutputs Y;

/* Model step function */


void ex_for_loop_SL_step(void)
{
int32_T s1_iter;
int32_T rtb_y1;

/* Outputs for iterator SubSystem: '<Root>/For Iterator Subsystem' incorporates:


* ForIterator: '<S1>/For Iterator'
*/
for (s1_iter = 0; s1_iter < 10; s1_iter++) {
/* Sum: '<S1>/Add' incorporates:
* Inport: '<Root>/u1'
* MultiPortSwitch: '<S1>/Index Vector'
* UnitDelay: '<S1>/Unit Delay'
*/
rtb_y1 = U.u1[s1_iter] + DWork.UnitDelay_DSTATE;

/* Update for UnitDelay: '<S1>/Unit Delay' */


DWork.UnitDelay_DSTATE = rtb_y1;
}

/* end of Outputs for SubSystem: '<Root>/For Iterator Subsystem' */

/* Outport: '<Root>/y1' */
Y.y1 = rtb_y1;
}

14-39
14 Patterns for C Code in Embedded Coder

Modeling Pattern for For Loop: Stateflow Chart

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:

Description For Loop (optional)


Initializer expression inx = 0
Loop test expression inx < 10
Counting expression inx++
For loop body y1 = u1[inx] + y1

The Stateflow diagram is shown.

14-40
For Loop

7 Press Ctrl+B to build the model and generate code.

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;

/* External outputs (root outports fed by signals with auto storage) */


ExternalOutputs Y;

/* Model step function */


void ex_for_loop_SF_step(void)
{
int32_T inx;

/* 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' */
}

/* End of Chart: '<Root>/Chart' */


/* Transition: '<S1>:9' */
}

Modeling Pattern for For Loop: MATLAB Function block


Procedure

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' */

/* Model step function */


void ex_for_loop_ML_step(void)
{
int32_T inx;

/* MATLAB Function Block: '<Root>/MATLAB Function' incorporates:


* Inport: '<Root>/u1'
*/
/* MATLAB Function 'MATLAB Function': '<S1>:1' */
/* '<S1>:1:3' */
y1 = 0.0;
for (inx = 0; inx < 10; inx++) {
/* '<S1>:1:5' */
/* '<S1>:1:6' */
y1 = u1[inx] + y1;
}
}

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

Modeling Pattern for While Loop: While Iterator Subsystem


block
One method for creating a while loop is to use a While Iterator Subsystem block from
the Simulink > Ports and Subsystems library.

Model ex_while_loop_SL

14-43
14 Patterns for C Code in Embedded Coder

ex_while_loop_SL/While Iterator Subsystem

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;

/* Constant: '<Root>/Initial Condition SET to TRUE' */


IC = P.InitialConditionSETtoTRUE_Value;

/* Outputs for Iterator SubSystem:


* '<Root>/While Iterator Subsystem' incorporates:
* WhileIterator: '<S1>/While Iterator'
*/
s1_iter = 1;

/* InitializeConditions for Atomic SubSystem: '<S1>/func' */


func_Init();

14-45
14 Patterns for C Code in Embedded Coder

/* End of InitializeConditions for SubSystem: '<S1>/func' */


loopCond = IC;
while (loopCond && (s1_iter <= 100)) {
/* Outputs for Atomic SubSystem: '<S1>/func' */
func();

/* End of Outputs for SubSystem: '<S1>/func' */


loopCond = flag;
s1_iter++;
}

/* End of Outputs for SubSystem: '<Root>/While Iterator Subsystem' */


}

Modeling Pattern for While Loop: Stateflow Chart

Model ex_while_loop_SF

14-46
While Loop

ex_while_loop_SF/Chart Executes the desired 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:

Description While Loop (optional)


While condition (flag) && (num_iter<=100)
Do action func; num_iter++;
8 Place a Subsystem block in your model.
9 Right-click the subsystem and select Block Parameters (Subsystem). The Block
Parameters dialog box opens.
10 Select the Treat as atomic unit parameter to configure the subsystem to generate a
function. This enables parameters on the Code Generation tab.
11 Select the Code Generation tab. From the Function packaging list, select the
option, Nonreusable function.

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:

ex_while_loop_SF/func A function that updates the flag


16 Save and close the subsystem.
17 Connect blocks to the Stateflow chart as shown in the model diagram for
ex_while_loop_SF.
18 Save your model.

Results

The generated code includes the following ex_while_loop_SF_step function in the file
ex_while_loop_SF.c:

/* Exported block signals */


int32_T num_iter; /* '<Root>/Chart' */
boolean_T flag; /* '<S2>/Relational Operator' */

/* Block states (auto storage) */


D_Work DWork;

/* Model step function */


void ex_while_loop_SF_step(void)
{

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();

/* End of Outputs for SubSystem: '<Root>/func' */


num_iter++;

/* Transition: '<S1>:5' */
}

/* End of Chart: '<Root>/Chart' */


/* Transition: '<S1>:1' */
}

Modeling Pattern for While Loop: MATLAB Function Block

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;

while(flag && (num_iter<=100))


func;
flag = func_flag;
num_iter = num_iter + 1;
end
4 Select Edit Data on the Editor tab. The Ports and Data Manager opens.
5 Select Add > Function Call Output. Change the name of the function call output to
func.
6 Click Save and close the MATLAB Function Block Editor.
7 Place a Subsystem block in your model, right-click the subsystem and select Block
Parameters (Subsystem). The Block Parameters dialog box opens.
8 Select the Treat as atomic unit parameter to configure the subsystem to generate a
function. This enables parameters on the Code Generation tab.
9 Select the Code Generation tab. From the Function packaging list, select the
option, Nonreusable function.
10 From the Function name options list, select the option, User specified. The
Function name parameter is displayed.
11 Specify the name as func.
12 Click Apply.
13 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:

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.

/* Model step function */


void ex_while_loop_ML_step(void)
{
boolean_T func_flag_0;
boolean_T flag;
int32_T num_iter;

/* MATLAB Function: '<Root>/MATLAB Function' */


func_flag_0 = func_flag;

/* MATLAB Function 'MATLAB Function': '<S1>:1' */


/* '<S1>:1:3' */
flag = true;

/* '<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();

/* End of Outputs for SubSystem: '<Root>/func' */

/* '<S1>:1:8' */
flag = func_flag_0;

/* '<S1>:1:9' */
num_iter++;
}

/* End of MATLAB Function: '<Root>/MATLAB Function' */


}

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

Modeling Pattern for Do While Loop: While Iterator Subsystem


block
One method for creating a while loop is to use a While Iterator Subsystem block from
the Simulink > Ports and Subsystems library.

ex_do_while_loop_SL

14-53
14 Patterns for C Code in Embedded Coder

ex_do_while_loop_SL/While Iterator Subsystem

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

ex_do_while_loop_SL/While Iterator Subsystem/func


11 Double-click the While Iterator block. This opens the Block Parameters dialog.
12 Set the Maximum number of iterations to 100.
13 Specify the While loop type as do-while.
14 Connect blocks as shown in the model and subsystem diagrams.
15 Enter Ctrl+B to generate code.

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

Modeling Pattern for Do While Loop: Stateflow Chart

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:

Description While Loop (optional)


While condition (flag) && (num_iter<=100)
Do action func; num_iter++;
8 Place a Subsystem block in your model.
9 Right-click the subsystem and select Block Parameters (Subsystem). The Block
Parameters dialog box opens.
10 Select the Treat as atomic unit parameter to configure the subsystem to generate a
function. This enables parameters on the Code Generation tab.
11 Select the Code Generation tab. From the Function packaging list, select the
option, Nonreusable function.
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:

ex_do_while_loop_SF/func Updates the flag


16 Save and close the subsystem.
17 Connect blocks to the Stateflow chart as shown in the model diagram for
ex_do_while_loop_SF.

14-57
14 Patterns for C Code in Embedded Coder

18 Save your model.

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();
}

The function prototype is externed through the subsystem file, add_function.h.


extern void add_function(void);

The function definition is in the subsystem file add_function.c:


void add_function(void)
{
function_call_Y.y1 = u1 + u2;
}

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

Function Call Using Graphical Functions


Procedure

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

ex_func_SF.c contains the generated code:


real_T add_function(real_T in1, real_T in2)
{
return in1 + in2;
}
.
.
.
void ex_func_SF_step(void)
{
y1 = add_function(u1, u2);
}

14-62
Function Prototyping

Control Function Prototype of the model_step Function

ex_control_step_function

Procedure

1 Create the model ex_control_step_function. See “Configure Input Ports, Output


Ports, and Arbitrary Signals” on page 14-3.
2 Open the Configuration Parameters dialog box by pressing Ctrl+E.
3 Open the Configure C/C++ Function Interface dialog box. In the Code Generation >
Interface pane, click Configure Model Functions. The dialog box opens showing a
preview of an execution function prototype with no arguments (void-void). If
arguments have been configured for the model previously, the dialog box displays the
current settings.
4 Configure step function arguments. If an application requires a void-void interface,
clear Configure arguments for function prototype. For this example, select
Configure arguments for function prototype.
5 Display current default settings for the entry-point function arguments by clicking
Get default. An updated diagram appears and a table that lists external I/O ports
with property settings.
6 Configure the step function return argument by setting C return argument to void
or Outport. For this example, select void.
7 Configure the function input and output arguments:

• 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 the outport, set C Identifier Name to argOut.

The function prototype preview is updated as you make these changes.


8 Validate your changes by clicking Validate.
9 Close the Configure C/C++ Function Interface dialog box. Click Apply. Then, click
OK.
10 Generate code and a report. Use the report to verify that the generated step function
in ex_control_step_function.c reflects the argument changes that you made.

For more information about controlling function prototypes, see “Customize Generated C
Function Interfaces” on page 29-2.

Results

ex_control_step_function.c contains the generated code:


void ex_control_step_function_step(real_T argIn1, const real_T *argIn2,...
real_T *argOut)
{
y1 = *argIn2 + argIn1;
}

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

extern double add(double, double);

#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).

• “Use the Legacy Code Tool to Create S-functions” on page 14-65


• “Use a Stateflow Chart to Make Calls to C Functions” on page 14-67
• “Using a MATLAB Function Block to Make Calls to C Functions” on page 14-69

Use the Legacy Code Tool to Create S-functions


This method uses the Legacy Code Tool to create an S-function and generate a TLC file.
The code generation software uses the TLC file to generate code from this S-function. The
advantage of using the Legacy Code Tool is that the generated code is fully inlined and
does not need wrapper functions to access the custom code.

Procedure

1 Create a C header file named add.h that contains the function signature:

extern double add(double, double);

14-65
14 Patterns for C Code in Embedded Coder

2 Create a C source file named add.c that contains the function body:

double add(double u1, double u2)


{
double y1;
y1 = u1 + u2;
return (y1);
}
3 To build an S-function for use in both simulation and code generation, run the
following script or execute each of these commands at the MATLAB command line:

%% Initialize legacy code tool data structure


def = legacy_code('initialize');

%% Specify Source File


def.SourceFiles = {'add.c'};

%% Specify Header File


def.HeaderFiles = {'add.h'};

%% Specify the Name of the generated S-function


def.SFunctionName = 'add_function';

%% Create a c-mex file for S-function


legacy_code('sfcn_cmex_generate', def);

%% Define function signature and target the Output method


def.OutputFcnSpec = ['double y1 = add(double u1, double u2)'];

%% Compile/Mex and generate a block that can be used in simulation


legacy_code('generate_for_sim', def);

%% Create a TLC file for Code Generation


legacy_code('sfcn_tlc_generate', def);

%% Create a Masked S-function Block


legacy_code('slblock_generate', def);

The output of this script produces:

• A new model containing the S-function block


• A TLC file named add_function.tlc.
• A C source file named add_function.c.

14-66
External C Functions

• A mexw32 dll file named add_function.mexw32


4 Add inport blocks and an outport block and make the connections, as shown in the
model.

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

The following code is generated in ex_function_call_lct.c:


real_T u1;
real_T u2;
real_T y1;
void ex_function_call_lct_step(void)
{
y1 = add(u1, u2);
}

The user-specified header file, add.h, is included in ex_function_call_lct.h:

#include "add.h"

Use a Stateflow Chart to Make Calls to C Functions


Procedure

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

ex_exfunction_call_SF.c contains the following code in the step function:


real_T u1;
real_T u2;
real_T y1;

void exfunction_call_SF_step(void)
{
y1 = (real_T)add(u1, u2);
}

ex_exfunction_call_SF.h contains the include statement for add.h:


#include "add.h"

14-68
External C Functions

Using a MATLAB Function Block to Make Calls to C Functions


Procedure

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:

function y1 = add_function(u1, u2)

% Set the class and size of output


y1 = u1;

% Call external C function


y1 = coder.ceval('add',u1,u2);

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

ex_exfunction_call_ML.c contains the following code:

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);
}

ex_exfunction_call_ML.h contains the #include statement for add.h:


#include "add.h"

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)

Macro Definitions (#define)

C Construct
#define myParam 9.8;

Export Generated Macro Definition


Procedure

1 Create the ex_param_macro model by using a Gain block.

2 Create the ex_defn_decl model by using a Gain block.

3 In the model, select View > Model Data Editor.


4 In the Model Data Editor, on the Parameters tab, set the value of the Gain
parameter to myParam.
5
Next to myParam, click the action button and select Create.
6 In the Create New Data dialog box, set Value to Simulink.Parameter(9.8) and
click Create.

A Simulink.Parameter object, myParam, appears in the base workspace. The Gain


block uses the object to set the value of the Gain parameter, in this case, 9.8.
7 In the Simulink.Parameter property dialog box, set Storage class to Define. Click
OK.
8 Generate code from the model.

14-71
14 Patterns for C Code in Embedded Coder

Results

The generated header file ex_param_macro.h defines myParam as a macro.

/* Definition for custom storage class: Define */


#define myParam 9.8

Reuse Macro from Handwritten Code


Procedure

1 Follow the steps in “Export Generated Macro Definition” on page 14-71.


2 In the Model Data Editor, on the Parameters tab, click the Show/refresh
additional information button.
3 Set the Change view drop-down list to Code.
4 Use the Storage Class column to change the storage class of myParam from Define
to ImportedDefine.
5 For myParam, set Header File to external_params.h. With this setting, the
generated code imports the macro definition from a custom header file named
external_params.h.
6 In your current folder, create the C header file external_params.h, which contains
the #define statement.

#ifndef _EXTERNAL_PARAMS
#define _EXTERNAL_PARAMS

#define myParam 9.8

#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.

/* Includes for objects with custom storage classes. */


#include "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

Conditional Inclusions (#if / #endif)


You can generate preprocessor conditional directives in your code by implementing
variant blocks (Model Variants block or Variant Subsystem block) in your model. In the
generated code, preprocessor conditional directives select a section of code to execute at
compile time. To implement variants in your model, see “Create a Simple Variant Model”
(Simulink). To generate code for variants, see “Generate Preprocessor Conditionals for
Variant Systems” on page 15-35.

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.

1 At the command prompt, create a Simulink.AliasType object named float_32


that represents an alias of single.

float_32 = Simulink.AliasType('single')
2 Create the ex_typedef model by using a Gain block.

3 In the model, select View > Model Data Editor.


4 In the Model Data Editor, view the Inports/Outports tab.
5 From the Change View drop-down list, select Design.
6 In the model, select the Inport block.
7 In the Model Data Editor, for the Inport block, set Data Type to float_32.
8 From the Change view drop-down list, select Code.
9 For the Inport block, set Signal Name to mySig.
10 Set Storage Class to ExportedGlobal.

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_

typedef real32_T 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.

typedef float real32_T;

The generated source file ex_typedef.c uses float_32 to define the global variable
mySig.

/* Exported block signals */


float_32 mySig; /* '<Root>/In1' */

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

Open the example model rtwdemo_paraminline.

rtwdemo_paraminline

14-77
14 Patterns for C Code in Embedded Coder

Select View > Model Data Editor.

In the Model Data Editor, select the Parameters tab.

In the model, click the Gain block labeled G1.

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.

In the Simulink.Parameter property dialog box, set Storage class to ExportedGlobal.


With this setting, the structure myStruct appears in the generated code as a global
variable.

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

Generate code from the model.

rtwbuild('rtwdemo_paraminline')

### Starting build procedure for model: rtwdemo_paraminline


### Successful completion of build procedure for model: rtwdemo_paraminline

The generated header file rtwdemo_paraminline_types.h defines a structure type


with a random name.

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

Specify Name of Structure Type

Optionally, specify a name to use for the structure type definition (struct).

At the command prompt, use the function Simulink.Bus.createObject to create a


Simulink.Bus object that represents the structure type.

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.

myStruct.DataType = 'Bus: myStructType';

Generate code from the model.

rtwbuild('rtwdemo_paraminline')

### Starting build procedure for model: rtwdemo_paraminline


### Successful completion of build procedure for model: rtwdemo_paraminline

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

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.

In the model, select Edit > Bus Editor.

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, select View > Model Data Editor.

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.

Generate code from the model.

Results

The generated header file ex_signal_struct_types.h defines the structure type


my_signals_type.

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.

/* Exported block signals */


my_signals_type sig_struct_var; /* '<Root>/Bus Creator' */

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

Nested Structures of Signals


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.

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.

In the model, select Edit > Bus Editor.

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.

Select Output as nonvirtual bus and click OK.

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, select View > Model Data Editor.

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.

Generate code from the model.

Results

The generated header file ex_signal_nested_struct_types.h defines the structure


types. Each structure type corresponds to a Simulink.Bus object.

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;

The generated source file ex_signal_nested_struct.c allocates memory for the


global structure variable sig_struct_var. By default, the name of the A_struct_type
Bus Creator block is Bus Creator2.

/* Exported block signals */


A_struct_type sig_struct_var; /* '<Root>/Bus Creator2' */

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.

2 In the model, select View > Model Data Editor.


3 In the Model Data Editor, on the Parameters tab, use the Value column to set value
of the first Constant block to p1.
4
Next to p1, click the action button and select Create.
5 In the Create New Data dialog box, set Value to Simulink.Parameter(false) and
click Create.

A Simulink.Parameter object named p1 appears in the base workspace. The


object stores a Boolean value, false, and uses the data type boolean.
6 In the Simulink.Parameter property dialog box, click OK.
7 Use the Model Data Editor to configure the other Constant blocks to refer to new
parameter objects named p2 and p3.

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.

/* Type definition for custom storage class: BitField */


typedef struct my_struct_tag {
uint_T p1 : 1;
uint_T p2 : 1;
uint_T p3 : 1;
} my_struct_type;

The generated source file ex_struct_bitfield_CSC.c defines and initializes the


structure variable my_struct.

/* Definition for custom storage class: BitField */


my_struct_type my_struct = {
/* p1 */
0,

/* 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

Arrays for Parameters

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.

A Simulink.Parameter object, myParams, appears in the base workspace. The


Gain block uses the object to set the value of the Gain parameter.
7 In the Simulink.Parameter property dialog box, set Storage class to
ExportedGlobal.

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

/* Exported block parameters */


real32_T myParams[5] = { 1.0F, 2.0F, 3.0F, 4.0F, 5.0F } ;
/* Variable: myParams
* Referenced by: '<Root>/Gain'
*/

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

Arrays for Signals

C Construct
double myIn[5];
double myOut[5];

Procedure
1 Create the ex_signal_array model by using a Gain block.

2 In the model, select View > Model Data Editor.


3 In the Model Data Editor, view the Inports/Outports tab.
4 From the Change View drop-down list, select Design.
5 In the model, select the Inport block.
6 In the Model Data Editor, for the Inport block, set Signal Name to myIn.
7 Set Dimensions to [5 1].
8 For the Outport block, set Signal Name to myOut.
9 From the Change View drop-down list, select Code.
10 For the Inport block and the Outport block, set Storage Class to ExportedGlobal.

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

/* Exported block signals */


real_T myIn[5]; /* '<Root>/In1' */
real_T myOut[5]; /* '<Root>/Out1' */

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.

2 In the model, select View > Model Data Editor.


3 In the Model Data Editor, view the Inports/Outports tab.
4 From the Change view drop-down list, select Code.
5 In the model, select the Inport block.
6 In the Model Data Editor, for the Inport block, set Signal Name to myIn.
7 Set Storage Class to ImportedExternPointer.
8 Generate code from the model.

Results
The generated header file ex_pointer.h declares the pointer.

/* Imported (extern) pointer block signals */


extern real_T *myIn; /* '<Root>/In1' */

In the generated source file ex_pointer.c, in the model step function, the algorithm
dereferences the pointer, myIn.

14-96
See Also

/* Model step function */


void ex_pointer_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/In1'
*/
rtY.Out1 = *myIn;
}

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

Variant Systems in Embedded Coder

• “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

Implement Dimension Variants for Array Sizes in


Generated Code

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.

You use Simulink.Parameter objects to specify dimension information as symbols. For


more information on signal dimensions, see “Signal Dimensions” (Simulink).

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.

Define Symbolic Dimensions

This example uses the model rtwdemo_dimension_variants to show how to


implement symbolic dimensions. This model has four modeling patterns involving vectors
and matrices.

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.

To use a Simulink.Parameter object for dimension specification, it must be defined in the


base workspace and have one of these storage classes:

• Define or ImportedDefine with header file specified


• CompilerFlag
• User-defined custom storage class that defines data as a macro in a specified header
file

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).

Specify Symbolic Dimensions for Blocks and Data Objects

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

dimension specification must have a storage class of either ImportedExtern or


ImportedExternPointer.
4 Open the Block Parameters dialog box of the 1-D Lookup Table1 block. The Table
data field contains the Simulink.Parameter, PT. The Breakpoints 1 field contains
the Simulink.Parameter, PB.
5 In the base workspace, view the information in the Simulink.Parameter dialog boxes
for PB and PT. These parameters contain the character vector '[1,D]' in their
Dimensions field and are arrays consisting of 15 values. The dimension of D are
consistent with the dimension of the PB and PT parameters because D has a value of
15 .
6 Simulate the model. Simulink propagates the dimensions symbolically in the diagram.
During propagation, Simulink establishes modeling constraints among symbols.
Simulink then checks for consistency with these constraints based on current
numerical assignments. One modeling constraint for
rtwdemo_dimension_variants is that C=A+B. The Diagnostic Viewer produces a
warning for any violations of constraints.
7 Change the dimension specification to a different configuration and simulate the
model again.

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]').

Generate Code for a Model with Dimension Variants

Once you have verified dimension specifications through model simulation, generate code
for rtwdemo_dimension_variants.

Create a temporary folder for the build and inspection process.


currentDir = pwd;
[~,cgDir] = rtwdemodir();

Build the model.


model='rtwdemo_dimension_variants';
rtwbuild(model)

15-6
Implement Dimension Variants for Array Sizes in Generated Code

### Starting build procedure for model: rtwdemo_dimension_variants


### Successful completion of build procedure for model: rtwdemo_dimension_variants

View the generated code. In the rtwdemo_dimension_variants.h file, symbolic


dimensions are in data declarations.
hfile = fullfile(cgDir,'rtwdemo_dimension_variants_ert_rtw',...
'rtwdemo_dimension_variants.h');
rtwdemodbtype(hfile,'/* External inputs', '/* Real-time', 1, 0);

/* External inputs (root inport signals with default storage) */


typedef struct {
real_T In2[A]; /* '<Root>/In2' */
real_T In3[B]; /* '<Root>/In3' */
} ExtU;

/* External outputs (root outports fed by signals with default storage) */


typedef struct {
real_T Out1[A + B]; /* '<Root>/Out1' */
real_T Out2[A + B]; /* '<Root>/Out2' */
} ExtY;

The rtwdemo_dimension_variants.h file contains data definitions and preprocessor


conditionals that define constraints established among the symbols during simulation.
One of these constraints is that the value of a symbolic dimension must be greater than 1.
This file also includes the user-provided header file for any Simulink.Parameter
objects with an ImportedDefine custom storage class.
hfile = fullfile(cgDir,'rtwdemo_dimension_variants_ert_rtw',...
'rtwdemo_dimension_variants.h');
rtwdemodbtype(hfile,'#ifndef A', '/* Macros for accessing', 1, 0);

#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

#error The variable for the parameter "D" is not defined


#endif

/*
* 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

/* Constraint 'D > 1' registered by:


* '<Root>/1-D Lookup Table1'
*/
#if D <= 1
# error "The preprocessor definition 'D' must be greater than '1'"
#endif

/* Constraint 'C > 1' registered by:


* '<S2>/Assignment'
*/
#if C <= 1
# error "The preprocessor definition 'C' must be greater than '1'"
#endif

15-8
Implement Dimension Variants for Array Sizes in Generated Code

In the rtwdemo_dimension_variants.c file, symbolic dimensions participate in loop


bound calculations, array size and index offset calculations, and a parameterized utility
function (for example, Lookup Table block) calculation.
cfile = fullfile(cgDir,'rtwdemo_dimension_variants_ert_rtw',...
'rtwdemo_dimension_variants.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);

/* Model step function */


void rtwdemo_dimension_variants_step(void)
{
real_T rtb_VectorConcatenate[A + B];
int32_T s2_iter;
int32_T ForEach_itr;
real_T rtb_VectorConcatenate_m;

/* Gain: '<Root>/Gain' incorporates:


* Inport: '<Root>/In2'
*/
for (ForEach_itr = 0; ForEach_itr <= (int32_T)(A - 1); ForEach_itr++) {
rtb_VectorConcatenate[ForEach_itr] = 2.0 * rtU.In2[ForEach_itr];
}

/* End of Gain: '<Root>/Gain' */

/* Gain: '<Root>/Gain1' incorporates:


* Inport: '<Root>/In3'
*/
for (ForEach_itr = 0; ForEach_itr <= (int32_T)(B - 1); ForEach_itr++) {
rtb_VectorConcatenate[(int32_T)(A + ForEach_itr)] = 3.0 *
rtU.In3[ForEach_itr];
}

/* End of Gain: '<Root>/Gain1' */

/* Outputs for Iterator SubSystem: '<Root>/For Each Subsystem' incorporates:


* ForEach: '<S1>/For Each'
*/
for (ForEach_itr = 0; ForEach_itr <= (int32_T)((int32_T)(A + B) - 1);
ForEach_itr++) {
/* Sum: '<Root>/Add' incorporates:
* Constant: '<Root>/Constant'
* Lookup_n-D: '<Root>/1-D Lookup Table1'
*/
rtb_VectorConcatenate_m = rtb_VectorConcatenate[ForEach_itr] + look1_binlx

15-9
15 Variant Systems in Embedded Coder

(Data[ForEach_itr], PB, PT, (uint32_T)((uint32_T)D - 1U));

/* ForEachSliceAssignment: '<S1>/ImpAsg_InsertedFor_Out1_at_inport_0' incorporates:


* MATLAB Function: '<S1>/MATLAB Function'
*/
/* MATLAB Function 'For Each Subsystem/MATLAB Function': '<S3>:1' */
/* '<S3>:1:4' y = 2*u; */
rtY.Out1[ForEach_itr] = 2.0 * rtb_VectorConcatenate_m;

/* Sum: '<Root>/Add' */
rtb_VectorConcatenate[ForEach_itr] = rtb_VectorConcatenate_m;
}

/* End of Outputs for SubSystem: '<Root>/For Each Subsystem' */

/* Outputs for Iterator SubSystem: '<Root>/For Iterator Subsystem' incorporates:


* ForIterator: '<S2>/For Iterator'
*/
/* Constant: '<Root>/Constant1' */
for (s2_iter = 0; s2_iter < ((int32_T)A); s2_iter++) {
/* Assignment: '<S2>/Assignment' incorporates:
* Constant: '<S2>/Constant'
* Outport: '<Root>/Out2'
* Product: '<S2>/Product'
* Selector: '<S2>/Selector'
*/
if (s2_iter == 0) {
for (ForEach_itr = 0; ForEach_itr <= (int32_T)((int32_T)(A + B) - 1);
ForEach_itr++) {
rtY.Out2[ForEach_itr] = rtb_VectorConcatenate[ForEach_itr];
}
}

rtY.Out2[s2_iter] = rtb_VectorConcatenate[s2_iter] * 2.0;

/* End of Assignment: '<S2>/Assignment' */


}

/* End of Constant: '<Root>/Constant1' */


/* End of Outputs for SubSystem: '<Root>/For Iterator Subsystem' */
}

Close the model and code generation report.

15-10
Implement Dimension Variants for Array Sizes in Generated Code

bdclose(model)
rtwdemoclean;
cd(currentDir)

Set Parameter Value Based on Variant Choice


When you specify the dimensions of a parameter in a model by using a symbol, you must
make sure that the parameter value is consistent with the dimension value. To simulate
different choices for the dimension value, you must manually correct the parameter value.

For example, in the rtwdemo_dimension_variants model , the Simulink.Parameter


object Data stores a vector value, [1 2 3 4 5], and uses a symbolic dimension C with
initial value 5. If you change the value of C, to simulate the model, you must make sure
the number of elements in the vector value matches the new value of C.

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.

1 Open the model.

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.

For general information about using an expression to set the value of a


Simulink.Parameter object, see “Set Variable Value by Using a Mathematical
Expression” (Simulink).

Code Generation Optimization Considerations


When you create a model with symbolic dimensions, be aware of the following
optimization considerations:

• The code generator reuses buffers only if dimension propagation establishes


equivalence among buffers.
• Two loops with symbolic loop bound calculations are fused together only if they share
equivalent symbolic expression.

15-12
Implement Dimension Variants for Array Sizes in Generated Code

• Optimizations do not eliminate a symbolic expression or condition check based on the


current value of a symbolic dimension.

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:

• Only a subset of blocks accepts symbolic dimension specifications. If a block is not


compatible with symbolic dimensions, it causes an update diagram error.
• Simulink.Parameter objects that you use to define symbolic dimensions or have
symbolic dimensions must have one of the storage classes described in this example. If
these specifications are not met, the build procedure for the model fails during code
generation.

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.

In the following cases, supported blocks do not propagate 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.

• Code Replacement for Lookup Tables


• Software-in-the-Loop (SIL) and Processor-in-the-Loop (PIL) simulations
• Accelerator and rapid accelerator simulation modes
• Scope and simulation observation (for example, logging, SDI, and so on)
• Model coverage
• Simulink Design Verifier
• Fixed-Point Designer
• Data Dictionary
• Simulink PLC Coder

15-14
Implement Dimension Variants for Array Sizes in Generated Code

• HDL Coder

The following do not support dimension variants:

• 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].

p=Simulink.Parameter(struct('A',[1 2 3;4 5 6]))


p.DataType='Bus:bo'
bo=Simulink.Bus
bo.Elements(1).Name='A'
bo.Elements(1).Dimensions='[Dim,Dim1]'
Dim=Simulink.Parameter(2)
Dim1=Simulink.Parameter(3)
p.CoderInfo.StorageClass='Custom'
p.CoderInfo.CustomStorageClass='Define'

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.

Description Value of mask Value of block


parameter parameter
(myMaskParam)
myStruct is a structure myStruct.gains myMaskParam
with field gains, which
uses symbolic dimensions.
myStruct is a structure myStruct.subStruct myMaskParam.gains
with field hierarchy
myStruct.subStruct.g
ains. The field gains
uses symbolic dimensions.
myStructs is an array of myStructs(2) myMaskParam.gains
structures. Each structure
has a field gains, which
uses symbolic dimensions.

In these cases, you cannot generate code from the model. As a workaround, choose
one of these techniques:

15-16
See Also

• Use the entire structure (myStruct) or array of structures (myStructs) as the


value of the mask parameter. Under the mask, configure the block parameter to
dereference the target field from the mask parameter by using an expression such
as myMaskParam.subStruct.gains.
• Use literal dimensions instead of symbolic dimensions for the target field (gains).

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 Generation for Variant Blocks


The code generator produces code from a Simulink model containing one or more Variant
Subsystem, Variant Source, and Variant Sink blocks. To learn how to create a model
containing variant blocks, see “Create a Simple Variant Model” (Simulink).

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.

Code generated for Variant Subsystem blocks is surrounded by C preprocessor


conditionals #if, #else, #elif, and #endif. Code generated for Variant Source and
Variant Sink blocks is surrounded by C preprocessor conditionals #if and #endif.
Therefore, the active variant is selected at compile time and the preprocessor
conditionals determine which sections of the code to execute.

To construct model reference variants and generate preprocessor directives in the


generated code, see the example “Use Model Variants to Generate Code That Uses C
Preprocessor Conditionals”.

To construct variant subsystems and generate preprocessor directives in the generated


code, see the example “Use Subsystem Variants To Generate Code That Uses C
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.

Restrictions on Variant Subsystem Code Generation


To generate preprocessor conditionals, the types of blocks that you can place within the
child subsystems of a Variant Subsystem block are limited. Connections are not allowed in
the Variant Subsystem block diagram. However, during the code generation process, one
VariantMerge block is placed at the input of each Outport block within the Variant
Subsystem block diagram. All of the child subsystems connect to each of the
VariantMerge blocks.

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.

Generated Code Components Not Compiled Conditionally


The following components are not conditionally compiled even if only code for variant
subsystems or models that are conditionally compiled reference them.

• rtModel data structure fields


• #include's of utility files
• Global non-constant parameter structure fields; when the configuration parameter
Optimization > Parameter structure is set to NonHierarchical
• Global constant parameter structure fields that are referenced by multiple subsystems
activated by different variants
• Parameters that are configured to use an imported, exported, or custom code
generation storage class, and are referenced by multiple subsystems that are activated
by different variants
• Parameters that are configured to use an imported, exported, or custom code
generation storage class, and are used by variant model blocks

Code Generation for Variant Blocks with One Variant Choice


For modeling patterns in which a Root Inport block connects to a Variant block with one
variant choice, Simulink inserts a hidden block combination of a Ground block, Signal
Conversion block, and a Variant Merge block. If the variant choice evaluates to false, this
block combination produces an output of 0.0.

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

The varianttoground.c file contains this code:

/* Sin: '<Root>/Sine Wave' */


#if SYSCONST_A == 6

varianttoground_B.VM_Conditional_Signal_Subsystem_0_r64 = sin
(varianttoground_M->Timing.t[0]);

#endif /* SYSCONST_A == 6 */

/* End of Sin: '<Root>/Sine Wave' */

/* SignalConversion: '<Root>/VM_SignalConversion_Subsystem_0' */
#if SYSCONST_A != 6

varianttoground_B.VM_Conditional_Signal_Subsystem_0_r64 = 0.0;

#endif /* SYSCONST_A != 6 */

/* End of SignalConversion: '<Root>/VM_SignalConversion_Subsystem_0' */

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

Represent Subsystem and Model Variants in Generated


Code
In this section...
“Step 1: Represent Variant Choices in Simulink” on page 15-23
“Step 2: Specify Conditions That Control Variant Choice Selection” on page 15-27
“Step 3: Configure Model for Generating Preprocessor Conditionals” on page 15-29
“Step 4: Review Generated Code” on page 15-30
“Limitations” on page 15-33

Required products: Simulink, Embedded Coder, Simulink Coder

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.

Step 1: Represent Variant Choices in Simulink


Variant choices are two or more configurations of a component in your model. This
example uses the model rtwdemo_preprocessor_subsys to illustrate how to represent

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).

1 Open the model rtwdemo_preprocessor_subsys.

open_system('rtwdemo_preprocessor_subsys')

The model contains two Variant Subsystem blocks: LeftController and


RightController.

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.

Step 2: Specify Conditions That Control Variant Choice


Selection
You can switch between variant choices by constructing conditional expressions called
variant controls for each variant choice represented in a Variant Subsystem block. Variant
controls determine which variant choice is active, and changing the value of a variant
control causes the active variant choice to switch.

A variant control is a Boolean expression that activates a specific variant choice when it
evaluates to true.

For more information, see “Introduction to Variant Controls” (Simulink) (Simulink).

1 Right-click the LeftController block and select Block Parameters (Subsystem).

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.

You can define VSSMODE as a scalar variable or as a Simulink.Parameter object. In


addition to enabling the specification of parameter value, Simulink.Parameter

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';

Variant control variables defined as Simulink.Parameter objects can have one of


these storage classes.

• Define or ImportedDefine with header file specified


• CompilerFlag
• SystemConstant (AUTOSAR)
• Your own custom storage class that defines data as a macro

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).

Step 3: Configure Model for Generating Preprocessor


Conditionals
Code generated for each variant choice is enclosed within C preprocessor conditionals
#if, #else, #elif, and #endif. Therefore, the active variant is selected at compile time
and the preprocessor conditionals determine which sections of the code to execute.

1 In the Simulink editor, select Simulation > Model Configuration Parameters.


2 Select the Code Generation pane, and set System target file to ert.tlc.
3 In the Report pane, select Create code generation report.
4 In the Configuration Parameters dialog box, clear Ignore custom storage classes
and click Apply.
5 In your model, right-click the LeftController block and select Block Parameters
(Subsystem).
6 Select the option Analyze all choices during update diagram and generate
preprocessor conditionals.

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.

Step 4: Review Generated Code


The code generation report contains a section dedicated to the subsystems that have
variants controlled by preprocessor conditionals.

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

2 Select the Code Variant Report from the left.

15-31
15 Variant Systems in Embedded Coder

In this example, the generated code includes references to the Simulink.Variant


objects LINEAR and NONLINEAR. The code also includes the definitions of macros
corresponding to those variants. The definitions depend on the value of VSSMODE,
which is supplied in an external header file rtwdemo_importedmacros.h. The

15-32
Represent Subsystem and Model Variants in Generated Code

active variant is determined by using preprocessor conditionals (#if) on the macros


(#define) LINEAR and NONLINEAR.
3 Select the rtwdemo_preprocessor_subsys_types.h file from the left.

This file contains the definitions of macros LINEAR and NONLINEAR.

#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.

/* Outputs for Atomic SubSystem: '<Root>/LeftController' */


#if LINEAR
/* Output and update for atomic system: '<S1>/Linear' */
...
#elif NONLINEAR
/* Output and update for atomic system: '<S1>/Nonlinear' */
...
#endif

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

Generate Preprocessor Conditionals for Variant Systems


In this section...
“Define Variant Controls” on page 15-35
“Configure Model for Generating Preprocessor Conditional Directives” on page 15-36
“Special Considerations for Generating Preprocessor Conditionals” on page 15-37
“Generate Variant Control Macros in Same Header File” on page 15-38

Define Variant Controls


For variant systems, conditional expressions called variant controls determine which
variant choice is active. You can specify a variant control as a condition expression, a
Simulink.Variant object specifying a condition expression, a MATLAB variable, or a
Simulink.Parameter object. This example shows how to define variant controls as
Simulink.Parameter objects.
1 Open the Model Explorer. Select the base workspace.
2 In the Model Explorer, select Add > Simulink Parameter. Specify a name for the
new parameter.
3 Use the function Simulink.VariantManager.findVariantControlVars to find
and convert MATLAB variables used in variant control expressions into
Simulink.Parameter objects. For an example, see “Convert Variant Control
Variables into Simulink.Parameter Objects” (Simulink).
4 On the Simulink.Parameter property dialog box, specify the Value and Data type.
5 Select one of these Storage class values.

• 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.

Note The generated code refers to a variant control as a user-defined macro.


The generated code does not contain the value of the macro. The value of the
variant control determines the active variant in the compiled code.

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.

Configure Model for Generating Preprocessor Conditional


Directives
1 Open the Configuration Parameters dialog box.
2 Select the Code Generation pane, and set System target file as ert.tlc.
3 In the Report pane, select Create code generation report.
4 In the Configuration Parameters dialog box, clear the “Ignore custom storage
classes” (Simulink Coder) parameter. In order to generate preprocessor conditionals,
you must use custom storage classes.

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.

Special Considerations for Generating Preprocessor


Conditionals
• The code generation process checks that the inports and outports of a Model Variants
block are identical (same port numbers and names) to the corresponding inports and
outports of its variants. The build process for simulation does not make this check.
Therefore, if your variant block contains mismatched inports or outports, the code
generation process issues an error.
• The port numbers and names for each child variant subsystem must belong to a subset
of the port numbers and names of the parent Variant Subsystem block.
• The code generation process checks that there is at least one active variant by using
the variant control values stored in the base workspace. The variant control that
evaluates to true becomes the active variant. If none of the variant controls evaluates
to true, the default variant, if specified, becomes the active variant. The code
generation process issues an error if an active variant does not exist.
• Implement the condition expressions of the variant objects such that only one
evaluates to true. The generated code includes a test of the variant objects to
determine that there is only one active variant. If this test fails, your code will not
compile.
• If you comment out child subsystems listed in the Variant Choices table in the
Variant Subsystem block parameter dialog box, the code generator does not generate
code for the commented out subsystems.
• If the sample time for a default variant differs from that of the other variant choices,
the #else preprocessor conditional is not generated for the default variant. Instead,
an #if !(<variant conditions>) is generated.
• For Variant Subsystems, the model_private.h file contains conditional parameter
definitions. For example, if the value of a Constant block is a Simulink.Parameter
with an ImportedDefine custom storage class, and the Constant block is in a Variant

15-37
15 Variant Systems in Embedded Coder

Subsystem, the conditional definition of the Simulink.Parameter is in the


model_private.h file.

Generate Variant Control Macros in Same Header File


This example shows how to aggregate multiple variant control macros (#define) into the
same generated header file. This aggregation makes it easier for you to manage the
complexities inherent in a system with multiple interacting variant conditions.

Explore Example Model

Run the script prepare_rtwdemo_preproc_subsys, which opens the model


rtwdemo_preprocessor_subsys and prepares it for this example.

run(fullfile(matlabroot,'examples','ecoder','main','prepare_rtwdemo_preproc_subsys'));

The model contains two Variant Subsystem blocks.

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.

Change Name of Generated Header File Through Model Data Editor

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 model, select View > Model Data Editor.

In the Model Data Editor, select the Parameters tab.

Click the Show/refresh additional information button.

Set the Change view drop-down list to Code.

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.

Reduce Maintenance Effort by Creating Custom Storage Class

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.

Set your current folder to a writable location.

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

Save and close the file.

Set your current folder to the folder that contains the package myPackage.

Open the Custom Storage Class Designer.

cscdesigner('myPackage')

Select the custom storage class Define.

Click Copy. A new custom storage class, Define_1, appears. Select this new custom
storage class.

Set Name to VariantControlVar.

Set Header file to Specify. In the text box, enter variant_controls.h.

Click Apply, Save, and OK.

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

Represent Variant Source and Sink Blocks in Generated


Code
In this section...
“Represent Variant Source and Variant Sink blocks in Simulink” on page 15-42
“Specify Conditions That Control Variant Choice Selection” on page 15-47
“Review the Generated Code” on page 15-47
“Generate Code with Zero Active Variant Controls” on page 15-49
“Global Data Guarding Limitation” on page 15-50
“State Logging Limitation” on page 15-50

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.

You can generate:

• 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.

Represent Variant Source and Variant Sink blocks in Simulink


This example shows how Variant Source blocks make model elements conditional.

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

11 In the MATLAB Command Window, use these commands to define V and W as


Simulink.Parameter objects.

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. .

Variant control variables defined as Simulink.Parameter objects can have one of


these storage classes:

• Define with header file specified


• ImportedDefine with header file specified
• CompilerFlag
• SystemConstant (AUTOSAR)
• User-defined custom storage class that defines data as a macro in a specified
header file

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

Specify Conditions That Control Variant Choice Selection


You can generate code in which each variant choice is enclosed within C preprocessor
conditionals #if and #endif. The compiler chooses the active variant at compile time
and the preprocessor conditionals determine which sections of the code to execute.

1 In the Simulink editor, select Simulation > Model Configuration Parameters.


2 Select the Code Generation pane, and set System target file to ert.tlc.
3 In the Report pane, select Create code generation report.
4 In your model, open the block parameters dialog box for Variant Source.
5 Select the Analyze all choices during update diagram and generate
preprocessor conditionals parameter. During an update diagram or simulation,
when you select this parameter, Simulink analyzes all variant choices. This analysis
provides early validation of the code generation readiness of variant choices. During
code generation, when you select this parameter, the code generator generates
preprocessor conditionals that control the activation of each variant choice.
6 Clear the Override variant conditions and use the following variant parameter.
7 Clear the Allow zero active variant controls parameter.
8 Open the Block Parameters dialog box for Variant Source 1. Repeat steps 5
through 7.
9 Build the model. When code generation is complete, the Code Generation Report is
displayed.

Review the Generated Code


1 In the code generation report, select the inline_variants_example.c file.
2 In the inline_variants_example.c file, calls to the
inline_variants_example_step function and the
inline_variants_example_initialize functions are conditionally compiled as
shown:

/* Model step function */


void inline_variants_example_step(void)
{
real_T rtb_Sine4;
real_T rtb_VariantMerge_For_Variant_So;

/* Sin: '<Root>/Sine1' */

15-47
15 Variant Systems in Embedded Coder

#if V == 1

rtb_Sine4 = sin((real_T)inline_variants_example_DW.counter * 2.0 *


3.1415926535897931 / 10.0);

#endif /* V == 1 */

/* End of Sin: '<Root>/Sine1' */

/* Sin: '<Root>/Sine2' incorporates:


* Sin: '<Root>/Sine3'
* Sum: '<Root>/Add'
*/
#if V == 2

rtb_Sine4 = sin((real_T)inline_variants_example_DW.counter_i * 2.0 *


3.1415926535897931 / 10.0) + sin((real_T)
inline_variants_example_DW.counter_f * 2.0 * 3.1415926535897931 / 10.0);

#endif /* V == 2 */

/* End of Sin: '<Root>/Sine2' */

/* Outport: '<Root>/Out1' incorporates:


* Gain: '<Root>/Gain3'
*/
inline_variants_example_Y.Out1 = 3.0 * rtb_Sine4;

/* Gain: '<Root>/Gain2' */
#if W == 1

rtb_VariantMerge_For_Variant_So = 2.0 * rtb_Sine4;

#endif /* W == 1 */

/* End of Gain: '<Root>/Gain2' */

/* Sin: '<Root>/Sine4' incorporates:


* Sin: '<Root>/Sine5'
* Sum: '<Root>/Add1'
*/
#if W == 2

rtb_VariantMerge_For_Variant_So = sin((real_T)

15-48
Represent Variant Source and Sink Blocks in Generated Code

inline_variants_example_DW.counter_fe * 2.0 * 3.1415926535897931 / 10.0) *


2.0 + sin((real_T)inline_variants_example_DW.counter_e * 2.0 *
3.1415926535897931 / 10.0);

#endif /* W == 2 */

/* End of Sin: '<Root>/Sine4' */

/* Outport: '<Root>/Out2' incorporates:


* Gain: '<Root>/Gain4'
*/
inline_variants_example_Y.Out2 = inline_variants_example_P.Gain4_Gain *
rtb_VariantMerge_For_Variant_So;
...
}

The variables rtb_Sine4 and rtb_VariantMerge_For_Variant_So hold the input


values to the Variant Source blocks. Notice that the code for these variables is
conditional. The variables inline_variants_example_Y.Out1 and
inline_variants_example_Y.Out2 hold the output values of the Variant Source
blocks. Notice that the code for these variables is not conditional.

Generate Code with Zero Active Variant Controls


You can generate code in which blocks connected to the input and the output of a Variant
Source block are conditional.
1 For Variant Source, open the Block Parameters dialog box. Select the parameter
Allow zero active variant controls.
2 For Variant Source 1, open the Block Parameters dialog box. Select the
parameter Allow zero active variant controls.

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.

Generate code for inline_variants_example. Notice in the


inline_variants_example.c file, that the code for the variables
inline_variants_example_Y.Out1 and inline_variants_example_Y.Out2 is
conditional.

15-49
15 Variant Systems in Embedded Coder

/* Model step function */


void inline_variants_example_step(void)
{
...
#if V == 1 || V == 2

inline_variants_example_Y.Out1 = 3.0 * rtb_Sine4;

#endif /* V == 1 || V == 2 */

...
#if (V == 1 && W == 1) || (V == 2 && W == 1) || W == 2

inline_variants_example_Y.Out2 = 4.0 * rtb_VariantMerge_For_Variant_So;

#endif /* (V == 1 && W == 1) || (V == 2 && W == 1) || W == 2 */

...

Global Data Guarding Limitation


For external ports and most DWork vectors, signals, and states, preprocessor conditionals
(#if and #endif) surround global data variable declarations. For models in which you
enable C API code for global block output signals, global block parameters, and discrete
and continuous states, preprocessor conditionals do not surround global data variable
declarations. For information on the C API, see “Exchange Data Between Generated and
External Code Using C API” (Simulink Coder).

State Logging Limitation


There are some rare cases in which preprocessor conditionals do not surround global
data structures that contain state variable declarations. For models that contain Variant
Source blocks or Variant Sink blocks and also contain blocks that maintain state
information, such as Unit Delay blocks, the exclusion of preprocessor conditionals
surrounding state variable declarations can lead to a mismatch between simulation and
code generation results.

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

Configure Dimension Variants for S-Function Blocks


To configure symbolic dimensions for S-function blocks, you can use the following C/C++
functions. You can configure S-functions to support forward propagation, backward
propagation, or forward and backward propagation of symbolic dimensions during
simulation.

Many of these functions return the variable SymbDimsId. A SymbDimsId is a unique


integer value. This value corresponds to each symbolic dimension specification that you
create or is the result of a mathematical operation that you perform with symbolic
dimensions.

Note If you are writing an S-function with symbolic dimensions, you cannot use the
%roll directive. You must write an explicit loop.

C/C++ S-Functions Purpose


ssSetSymbolicDimsSupport Specify whether or not an S-function
supports symbolic dimensions.
mdlSetInputPortSymbolicDimensions Specify the symbolic dimensions of an
input port and how those dimensions
propagate forward.
mdlSetOutputPortSymbolicDimensions Specify the symbolic dimensions of an
output port and how those dimensions
propagate backward.
ssRegisterSymbolicDimsExpr Create a SymbDimsId from an
expression string (aExpr). The
expression string must form a valid
syntax in C.
ssRegisterSymbolicDims Create a SymbDimsId from a vector of
SymbDimsIds.
ssRegisterSymbolicDimsString Create a SymbDimsId from an
identifier string (aString).
ssRegisterSymbolicDimsIntValue Create a SymbDimsId from an integer
value (aIntValue)

15-52
Configure Dimension Variants for S-Function Blocks

C/C++ S-Functions Purpose


ssRegisterSymbolicDimsPlus Create a SymbDimsId by adding two
symbolic dimensions.
ssRegisterSymbolicDimsMinus Create a SymbDimsId by subtracting
two symbolic dimensions.
ssRegisterSymbolicDimsMultiply Create a SymbDimsId by multiplying
two symbolic dimensions.
ssRegisterSymbolicDimsDivide Create a SymbDimsId by dividing two
symbolic dimensions.
ssGetNumSymbolicDims Get the number of dimensions for a
SymbDimsId.
ssGetSymbolicDim Get a SymbDimsId from a vector of
SymbDimsIds.
ssSetInputPortSymbolicDimsId Set the precompiled SymbDimsId of an
input port. You can call this function
from inside the mdlInitializeSizes
function.
ssGetCompInputPortSymbolicDimsId Get the compiled SymbDimsId of an
input port.
ssSetCompInputPortSymbolicDimsId Set the compiled SymbDimsId of an
input port.
ssSetOutputPortSymbolicDimsId Set the precompiled SymbDimsId of an
output port. You can call this function
from inside the mdlInitializeSizes
function.
ssGetCompOutputPortSymbolicDimsId Get the compiled SymbDimsId of an
output port.
ssSetCompOutputPortSymbolicDimsId Set the compiled SymbDimsId of an
output port.
ssSetCompDWorkSymbolicDimsId Set the compiled SymbDimsId of an
index of a block’s data type work
(DWork) vector.

15-53
15 Variant Systems in Embedded Coder

S-Function That Supports Forward Propagation of Symbolic


Dimensions
This S-function subtracts the symbolic dimension B from a symbolic input dimension. It
does not support backward propagation of symbolic dimensions because the compiled
symbolic dimensions of the input port are not set. Symbolic dimensions are set for the
output port, so forward propagation occurs.

static void mdlInitializeSizes(SimStruct *S)


{
// Enable symbolic dimensions for the s-function.
ssSetSymbolicDimsSupport(S, true);
}

#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

S-Function That Supports Forward and Backward Propagation


of Symbolic Dimensions
This S-function transposes two symbolic dimensions. It supports forward and backward
propagation of symbolic dimensions because the compiled symbolic dimension of both the
input and output ports are set.
static void mdlInitializeSizes(SimStruct *S)
{
// Enable symbolic dimensions for the s-function.
ssSetSymbolicDimsSupport(S, true);
}

#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);

ssSetCompInputPortSymbolicDimsId(S, portIndex, symbDimsId);

assert(2U == ssGetNumSymbolicDims(S, symbDimsId));

if (SL_INHERIT ==
ssGetCompOutputPortSymbolicDimsId(S, portIndex)) {

const SymbDimsId idVec[] = {


ssGetSymbolicDim(S, symbDimsId, 1),
ssGetSymbolicDim(S, symbDimsId, 0)};
// Register the transposed dimensions.
// Set the output symbolic dimension to the resulting id.
const SymbDimsId outputDimsId =
ssRegisterSymbolicDims(S, idVec, 2U);

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

int_T portIndex, SymbDimsId symbDimsId)


{
assert(0 == portIndex);
ssSetCompOutputPortSymbolicDimsId(S, portIndex, symbDimsId);

assert(2U == ssGetNumSymbolicDims(S, symbDimsId));

if (SL_INHERIT ==
ssGetCompInputPortSymbolicDimsId(S, portIndex)) {

const SymbDimsId idVec[] = {


ssGetSymbolicDim(S, symbDimsId, 1),
ssGetSymbolicDim(S, symbDimsId, 0)};
const SymbDimsId inputDimsId =
ssRegisterSymbolicDims(S, idVec, 2U);
// Register the transposed dimensions.
// Set the input symbolic dimension to the resulting id.
ssSetCompInputPortSymbolicDimsId(S, portIndex, inputDimsId);
}
}
#endif

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

Generate Code for Variant Subsystem with Child


Subsystems of Different Output Signal Dimensions
In this section...
“Example Model” on page 15-57
“Simulate Model” on page 15-58
“Generate Code” on page 15-59

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.

In the base workspace, A has a Storage class of ImportedDefine(Custom). To use a


Simulink.Parameter object for dimension specification, it must have one of these
storage classes:

• Define or ImportedDefine with header file specified


• CompilerFlag
• User-defined custom storage class that defines data as a macro in a specified header
file

In the base workspace, P1 and P2 have a storage class of ImportedExtern. A


Simulink.Parameter object that uses a Simulink.Parameter for symbolic dimension
specification must have a storage class of either ImportedExtern or
ImportedExternPointer.

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.

/* External outputs (root outports fed by signals with auto storage) */


typedef struct {
int32_T Out1[A]; /* '<Root>/Out1' */
} ExternalOutputs_slexVariantSymb;
4 Open the slexVariantSymbolicDims.c file. If Var equals 1, P1 has five values. If
Var equals 2, P2 has six values. In the Configuration Parameters dialog box, on the
Code Generation > Custom Code pane, the Source file parameter contains this
code.

/* user code (top of source file) */


#if Var == 1

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

Timers in Simulink Coder

• “Absolute and Elapsed Time Computation” on page 16-2


• “Access Timers Programmatically” on page 16-5
• “Generate Code for an Elapsed Time Counter” on page 16-9
• “Absolute Time Limitations” on page 16-12
16 Timers in Simulink Coder

Absolute and Elapsed Time Computation


In this section...
“About Timers” on page 16-2
“Timers for Periodic and Asynchronous Tasks” on page 16-3
“Allocation of Timers” on page 16-3
“Integer Timers in Generated Code” on page 16-3
“Elapsed Time Counters in Triggered Subsystems” on page 16-4

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

• Timers are implemented as unsigned integers in generated code.


• In multirate models, at most one timer is allocated per rate. If no blocks executing at a
given rate require a timer, a timer is not allocated to that rate. This minimizes memory
allocated for timers and significantly reduces overhead involved in maintaining timers.
• Allocation of elapsed time counters for use of blocks within triggered subsystems is
minimized, further reducing memory usage and overhead.
• S-function and TLC APIs let your S-functions access timers, in simulation and code
generation.
• The word size of the timers is determined by a user-specified maximum counter value,
Application lifespan (days) (Simulink). If you specify this value, timers will not
overflow. For more information, see “Control Memory Allocation for Time Counters”
(Simulink Coder).

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

Timers for Periodic and Asynchronous Tasks


Timing services provided for blocks execute within periodic tasks (that is, tasks running
at the model base rate or subrates).

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:

• “Timers in Asynchronous Tasks” on page 18-46


• “Create a Customized Asynchronous Library” on page 18-49

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:

• There are three rates, A, B, and C, in the model.


• No blocks running at rate B require absolute or elapsed time.
• Two blocks running at rate C register a requirement for absolute time.
• One block running at rate A registers a requirement for absolute time.

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.

Integer Timers in Generated Code


In the generated code, timers for absolute and elapsed time are implemented as unsigned
integers. The default size is 64 bits. This is the amount of memory allocated for a timer if
you specify a value of inf for the Application lifespan (days) (Simulink) parameter. For
an application with a sample rate of 1000 MHz, a 64-bit counter will not overflow for
more than 500 years. See “Timers in Asynchronous Tasks” on page 18-46 and “Control
Memory Allocation for Time Counters” on page 56-11 for more information.

16-3
16 Timers in Simulink Coder

Elapsed Time Counters in Triggered Subsystems


Some blocks, such as the Discrete-Time Integrator block, perform computations requiring
the elapsed time (delta T) since the previous block execution. Blocks requiring elapsed
time data must register the requirement (see “Access Timers Programmatically” on page
16-5). A triggered subsystem then allocates and maintains a single elapsed time
counter if required. This timer functions at the subsystem level, not at the individual
block level. The timer is generated if the triggered subsystem (or a unconditionally
executed subsystem within the triggered subsystem) contains one or more blocks
requiring elapsed time data.

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

Access Timers Programmatically


In this section...
“About Timer APIs” on page 16-5
“C API for S-Functions” on page 16-5
“TLC API for Code Generation” on page 16-7

About Timer APIs


This topic describes APIs that let your S-functions take advantage of the efficiencies
offered by absolute and elapsed timers. SimStruct macros are provided for use in
simulation, and TLC functions are provided for inlined code generation. Note that

• 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.

C API for S-Functions


The SimStruct macros described in this topic provide access to absolute and elapsed
timers for S-functions during simulation.

In the functions below, the SimStruct *S argument is a pointer to the simstruct of the
calling S-function.

• void ssSetNeedAbsoluteTime(SimStruct *S, boolean b): if b is TRUE,


registers that the calling S-function requires absolute time data, and allocates an
absolute time counter for the rate at which the S-function executes (if such a counter
has not already been allocated).
• int ssGetNeedAbsoluteTime(SimStruct *S): returns 1 if the S-function has
registered that it requires absolute time.
• double ssGetTaskTime(SimStruct *S, tid): read absolute time for a given
task with task identifier tid. ssGetTaskTime operates transparently, regardless of
whether or not you use the new timer features. ssGetTaskTime is documented in the
SimStruct Functions chapter of the Simulink documentation.

16-5
16 Timers in Simulink Coder

• void ssSetNeedElapseTime(SimStruct *S, boolean b): if b is TRUE,


registers that the calling S-function requires elapsed time data, and allocates an
elapsed time counter for the triggered subsystem in which the S-function executes (if
such a counter has not already been allocated). See also “Elapsed Time Counters in
Triggered Subsystems” on page 16-4.
• int ssGetNeedElapseTime(SimStruct *S): returns 1 if the S-function has
registered that it requires elapsed time.
• void ssGetElapseTime(SimStruct *S, (double *)elapseTime): returns, to
the location pointed to by elapseTime, the value (as a double) of the elapsed time
counter associated with the S-function.
• void ssGetElapseTimeCounterDtype(SimStruct *S, (int *)dtype):
returns the data type of the elapsed time counter associated with the S-function to the
location pointed to by dtype. This function is intended for use with the
ssGetElapseTimeCounter function (see below).
• void ssGetElapseResolution(SimStruct *S, (double *)resolution):
returns the resolution (that is, the sample time) of the elapsed time counter associated
with the S-function to the location pointed to by resolution. This function is
intended for use with the ssGetElapseTimeCounter function (see below).
• void ssGetElapseTimeCounter(SimStruct *S, (void *)elapseTime): This
function is provided for the use of blocks that require the elapsed time values for
fixed-point computations. ssGetElapseTimeCounter returns, to the location pointed
to by elapseTime, the integer value of the elapsed time counter associated with the
S-function. If the counter size is 64 bits, the value is returned as an array of two 32-bit
words, with the low-order word stored at the lower address.

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)

TLC API for Code Generation


The following TLC functions support elapsed time counters in generated code when you
inline S-functions by writing TLC scripts for them.

16-7
16 Timers in Simulink Coder

• LibGetTaskTimeFromTID(block): Generates code to read the absolute time for the


task in which block executes.

LibGetTaskTimeFromTID is documented with other sample time functions in the


TLC Function Library Reference pages of the Target Language Compiler
documentation.

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

Generate Code for an Elapsed Time Counter


This example shows a model that includes a triggered subsystem, Amplifier, consisting
of a Discrete-Time Integrator block that uses an elapsed time counter. The model
ex_elapseTime is in the folder matlab/help/toolbox/rtw/examples.

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;

The elapsed time computation is performed as follows within the ex_elapseTime_step


function:
/* ---
Outputs for Triggered SubSystem:
'<Root>/Amplifier' incorporates:
TriggerPort: '<S1>/Trigger'
--- */
zcEvent = rt_ZCFcn(RISING_ZERO_CROSSING,
&ex_elapseTime_PrevZCX.Amplifier_Trig_ZCE,
((real_T)rtb_PulseGenerator));
if (zcEvent != NO_ZCEVENT) {
elapseT_H = ex_elapseTime_M->Timing.clockTickH0 -
ex_elapseTime_DW.Amplifier_PREV_T[1];
if (ex_elapseTime_DW.Amplifier_PREV_T[0] >
ex_elapseTime_M->Timing.clockTick0) {
elapseT_H--;
}

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

Absolute Time Limitations


Absolute time is the time that has elapsed from the beginning of program execution to the
present time, as distinct from elapsed time, the interval between two events. See
“Absolute and Elapsed Time Computation” on page 16-2 for more information.

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.

The following limitations apply to absolute time:

• 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

Time-Based Scheduling in Simulink


Coder
17 Time-Based Scheduling in Simulink Coder

Time-Based Scheduling and Code Generation


In this section...
“Sample Time Considerations” on page 17-2
“Tasking Modes” on page 17-2
“Model Execution and Rate Transitions” on page 17-4
“Execution During Simulink Model Simulation” on page 17-5
“Model Execution in Real Time” on page 17-5
“Single-Tasking Versus Multitasking Operation” on page 17-6

Sample Time Considerations


Simulink models run at one or more sample times. The Simulink product provides
considerable flexibility in building multirate systems, that is, systems with more than one
sample time. However, this same flexibility also allows you to construct models for which
the code generator cannot generate real-time code for execution in a multitasking
environment. To make multirate models operate as expected in real time (that is, to give
the right answers), you sometimes must modify your model or instruct the Simulink
engine to modify the model for you. In general, the modifications involve placing Rate
Transition blocks between blocks that have unequal sample times. The following sections
discuss issues you must address to use a multirate model in a multitasking environment.
For a comprehensive discussion of sample times, including rate transitions, see “What Is
Sample Time?” (Simulink), “Sample Times in Subsystems” (Simulink), “Sample Times in
Systems” (Simulink), “Resolve Rate Transitions” (Simulink), and associated topics.

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.

Other operating systems, such as POSIX-compliant ones, provide automatic context


switching and task scheduling. This simplifies the operations performed by the ISR. In
this case, the ISR simply enables the model execution task, which is normally blocked.
The next figure illustrates this difference.

17-3
17 Time-Based Scheduling in Simulink Coder

Program execution using a real-time


operating system primitive. See the
Tornado target for an example.

Model Execution and Rate Transitions


To generate code that executes as expected in real time, you (or the Simulink engine)
might need to identify and handle sample rate transitions within the model. In
multitasking mode, by default the Simulink engine flags errors during simulation if the
model contains invalid rate transitions, although you can use the Multitask rate
transition diagnostic to alter this behavior. A similar diagnostic, called Single task rate
transition, exists for single-tasking mode.

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.

Execution During Simulink Model Simulation


Before the Simulink engine simulates a model, it orders the blocks based upon their
topological dependencies. This includes expanding virtual subsystems into the individual
blocks they contain and flattening the entire model into a single list. Once this step is
complete, each block is executed in order.

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).

Model Execution in Real Time


A real-time program differs from a Simulink simulation in that the program must execute
the model code synchronously with real time. Every calculation results in some
computational delay. This means the sample intervals cannot be shortened or lengthened
(as they can be in a Simulink simulation), which leads to less efficient execution.

Consider the following timing figure.

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.

See “Multitasking and Pseudomultitasking Modes” on page 17-12 for a description of


how this works. It is important to understand that section before proceeding here.

Single-Tasking Versus Multitasking Operation


Single-tasking programs require longer sample intervals, because all computations must
be executed within each clock period. This can result in inefficient use of available CPU
time, as shown in the previous figure.

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

Modeling for Single-Tasking Execution


Single-Tasking Mode
You can execute model code in a strictly single-tasking manner. While this mode is less
efficient with regard to execution speed, in certain situations, it can simplify your model.

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.

The next figure illustrates the inefficiency inherent in single-tasking execution.

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.

Build a Program for Single-Tasking Execution


To use single-tasking execution, clear the Treat each discrete rate as a separate task
checkbox on the Solver pane of the Configuration Parameters dialog box. If you select the
checkbox, single-tasking mode is used in the following cases:

• If your model contains one sample time


• If your model contains a continuous and a discrete sample time and the fixed step size
is equal to the discrete sample time

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).

The execution order is determined by data dependencies between blocks. In a real-time


system, the execution order determines the order in which blocks execute within a given
time interval or task. This discussion treats the model's execution order as a given,
because it is concerned with the allocation of block computations to tasks, and the
scheduling of task execution.

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.

In a single-tasking system, if the Configuration Parameters > Optimization >


Advanced parameters > Block reduction option is selected, fast-to-slow Rate
Transition blocks are optimized out of the model. The default case is shown (Block
reduction selected), so block B does not appear in the timing diagrams in this section.
For more information, see “Block reduction” (Simulink).

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

Execution Order and Sample Times (Single-Tasking)

Blocks Sample Time Output Update


(in Execution Order) (in Seconds)
E 0.1 Y Y
F 0.1 Y Y
D 1 Y Y
A 0.1 Y N
C 1 Y Y

Real-Time Single-Tasking Execution

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

Simulated Single-Tasking Execution

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

Modeling for Multitasking Execution

Multitasking and Pseudomultitasking Modes


When periodic tasks execute in a multitasking mode, by default the blocks with the fastest
sample rates are executed by the task with the highest priority, the next fastest blocks are
executed by a task with the next higher priority, and so on. Time available in between the
processing of high-priority tasks is used for processing lower priority tasks. This results in
efficient program execution.

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

Vertical arrows indicate sample time hits.

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

Interrupt 0 Interrupt 1 Interrupt 2 Interrupt 3


Begins Begins
Interrupt 3
Interrupt 1 Ends
t0 t1 Ends t2 t3 t4

Highest Priority

Interrupt 2
Ends

Interrupt 0
Ends

Lowest Priority

Build a Program for Multitasking Execution


To use multitasking execution, select the Treat each discrete rate as a separate task
check box on the Solver pane of the Configuration Parameters dialog box. This menu is
active only if you select Fixed-step as the solver type. Auto mode results in a
multitasking environment if your model has two or more different sample times. A model
with a continuous and a discrete sample time runs in single-tasking mode if the fixed-step
size is equal to the discrete sample time.

Execute Multitasking Models


In cases where the continuous part of a model executes at a rate that is different from the
discrete part, or a model has blocks with different sample rates, the Simulink engine
assigns each block a task identifier (tid) to associate the block with the task that
executes at the block's sample rate.

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).

The execution order is determined by data dependencies between blocks. In a real-time


system, the execution order determines the order in which blocks execute within a given
time interval or task. This discussion treats the model's execution order as a given,
because it is concerned with the allocation of block computations to tasks, and the
scheduling of task execution.

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

Task Allocation of Blocks in Multitasking Execution

Blocks Task Output Update


(in Execution Order)
E 0.1 second task Y Y
F 0.1 second task Y Y
D The Rate Transition block uses port- Y Y
based sample times.
Output runs at the output port sample
time under 0.1 second task.
Update runs at input port sample time
under 1 second task.
For more information on port-based
sample times, see “Inherit Sample Times
for Model Referencing” (Simulink).
A 0.1 second task Y N
B The Rate Transition block uses port- Y N
based sample times.
Output runs at the output port sample
time under 0.1 second task.
For more information on port-based
sample times, see “Inherit Sample Times
for Model Referencing” (Simulink).
C 1 second task Y Y

Real-Time Multitasking Execution

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

Simulated 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

Handle Rate Transitions

Rate Transitions
Two periodic sample rate transitions can exist within a model:

• A faster block driving a slower block


• A slower block driving a faster block

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

Faster Rate Transition Slower


Block Block

Slow-to-fast transitions are illustrated in the next figure.

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

Slower Rate Transition Faster


Block Block

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 Transfer Problems


Rate Transition blocks deal with issues of data integrity and determinism associated with
data transfer between blocks running at different rates.

• 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.

Consider the following scenario:

• A faster block supplies the input to a slower block.


• The slower block reads an input value V1 from the faster block and begins
computations using that value.
• The computations are preempted by another execution of the faster block, which
computes a new output value V2.
• A data integrity problem now arises: when the slower block resumes execution, it
continues its computations, now using the “new” input value V2.

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 Transfer Assumptions


When processing data transfers between tasks, the code generator makes these
assumptions:

• 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).

Rate Transition Block Options


Several parameters of the Rate Transition block are relevant to its use in code generation
for real-time execution, as discussed below. For a complete block description, see Rate
Transition.

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:

• Protected/Deterministic (default): This is the safest mode. The drawback of this


mode is that it introduces deterministic latency into the system for the case of slow-to-
fast periodic rate transitions. For that case, the latency introduced by the Rate
Transition block is one sample period of the slower task. For the case of fast-to-slow
periodic rate transitions, the Rate Transition block introduces no additional latency.
• Protected/NonDeterministic: In this mode, for slow-to-fast periodic rate transitions,
data integrity is protected by double-buffering data transferred between rates. For
fast-to-slow periodic rate transitions, a semaphore flag is used. The blocks
downstream from the Rate Transition block use the latest available data from the
block that drives the Rate Transition block. Maximum latency is less than or equal to
one sample period of the faster task.

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.

Rate Transition Blocks and Continuous Time

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).

Automatic Rate Transition


The Simulink engine can detect mismatched rate transitions in a multitasking model
during an update diagram and automatically insert Rate Transition blocks to handle them.
To enable this, in the Solver pane of model configuration parameters, select
Automatically handle rate transition for data transfer. The default setting for this
option is off. When you select this option:

• 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.

Visualize Inserted Rate Transition Blocks


When you select the Automatically handle rate transition for data transfer option,
Simulink inserts Rate Transition blocks in the paths that have mismatched transition
rates. These blocks are hidden by default. To visualize the inserted blocks, update the
diagram. Badge labels appear in the model and indicate where Simulink inserted Rate
Transition blocks during the compilation phase. For example, in this model, three Rate
Transition blocks were inserted between the two Sine Wave blocks and the Multiplexer
and Integrator when the model compiled. The ZOH and DbBuf badge labels indicate these
blocks.

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.

When you make hidden Rate Transition blocks visible:

• You can see the type of Rate Transition block inserted as well as the location in the
model.

17-28
Handle Rate Transitions

• You can set the Initial Conditions of these blocks.


• You can change block parameters for rate transfer.

Validate the changes to your model by updating your diagram.

Displaying inserted Rate Transition blocks is not compatible with:

• Concurrent execution environment


• Export-function models

To learn more about the types of Rate Transition blocks, see Rate Transition.

Periodic Sample Rate Transitions


These sections describe cases in which Rate Transition blocks are required for periodic
sample rate transitions. The discussion and timing diagrams in these sections are based
on the assumption that the Rate Transition block is used in its default (protected/
deterministic) mode; that is, the Ensure data integrity during data transfer and
Ensure deterministic data transfer (maximum delay) options are both on. These are
the settings used for automatically inserted Rate Transition blocks.

Faster to Slower Transitions in a Simulink Model

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.

Faster to Slower Transitions in Real Time

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.

2 Sec 1 T=2s 1 T=2s


Task
T = 1s T = 2s
Faster Slower 1 Sec
Block Block Task
T=1s 2 T=1s 3 T=1s 2 T=1s 3

Time
1 The faster task (T=1s) completes.

2 Higher priority preemption occurs.


3 The slower task (T=2s) resumes and its inputs
have changed. This leads to unpredictable results.

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.

T=1s Tin = 1Tout = 2 T=2s

Faster Block Rate Transition Slower Block

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

1 Sec T=1s RT T=1s T=1s RT T=1s


Task

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

Slower to Faster Transitions in a Simulink Model

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.

The next figure shows the execution sequence.

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.

Slower to Faster Transitions 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

2 Sec T=2s T=2s


Task

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

1 The faster block executes a second time prior


to the completion of the slower block.
2 The faster block executes before the slower block.

17-32
Handle Rate Transitions

This timing diagram illustrates two problems:

• 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

Slower Rate Transition Faster


Block Block

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.

Protect Data Integrity with volatile Keyword


When you select Ensure data integrity during data transfer, the code generated for a
Rate Transition block defines global buffers and semaphores and uses them to protect the
integrity of the transferred data.

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.

Separate Rate Transition Block Code and Data from Algorithm


Code and Data
By default, Rate Transition block code is set inline with algorithm code and data. If you
have Embedded Coder, you can separate the code and data, so that the generated code
contains separate get and set functions that the model_step functions call and a
dedicated structure for state data. The generated code also contains separate start and

17-35
17 Time-Based Scheduling in Simulink Coder

initialize functions that the model_initialize function calls. To separate Rate


Transition block code and data from algorithm code and data, in the Configuration
Parameters dialog box, set the Rate Transition block code parameter to Function.

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

Configure Time-Based Scheduling


For details about solver options, see “Solver Pane” (Simulink).

Configure Start and Stop Times


The Stop time (Simulink) must be greater than or equal to the Start time (Simulink). If
the stop time is zero, or if the total simulation time (Stop minus Start) is less than zero,
the generated program runs for one step. If the stop time is set to inf, the generated
program runs indefinitely.

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.

Configure the Solver Type


For code generation, you must configure a model to use a fixed-step solver for all targets
except the S-function and RSim targets. You can configure the S-function and RSim
targets with a fixed-step or variable-step solver.

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

Configure the Tasking Mode


The code generator supports both single-tasking and multitasking modes for periodic
sample times. See “Time-Based Scheduling and Code Generation” on page 17-2 for
details.

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

Time-Based Scheduling Example Models

Optimize Memory Usage for Time Counters


This example shows how to optimize the amount of memory that the code generator
allocates for time counters. The example optimizes the memory that stores elapsed time,
the interval of time between two events.

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:

• Lifespan < 0.25 sec: 8 bits


• Lifespan < 1 min: 16 bits
• Lifespan < 49 days: 32 bits
• Lifespan > 50 days: 64 bits

A 64-bit time counter does not overflow for 590 million years.

Open Example Model

Open the example model rtwdemo_abstime.

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

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.

Generate Code and Report

1. Create a temporary folder for the build and inspection process.

2. Configure the model for the code generator to use the GRT system target file and a
lifespan of inf days.

3. Build the model.

### Starting build procedure for model: rtwdemo_abstime


### Successful completion of build procedure for model: rtwdemo_abstime

Review Generated Code

Open the generated source file rtwdemo_abstime.c.

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;
};

/* Block states (default storage) */


extern DW_rtwdemo_abstime_T rtwdemo_abstime_DW;

/* External inputs (root inport signals with default storage) */


extern ExtU_rtwdemo_abstime_T rtwdemo_abstime_U;

/* External outputs (root outports fed by signals with default storage) */


extern ExtY_rtwdemo_abstime_T rtwdemo_abstime_Y;

/* Model entry point functions */


extern void rtwdemo_abstime_initialize(void);
extern void rtwdemo_abstime_step(int_T tid);
extern void rtwdemo_abstime_terminate(void);

/* Real-time Model object */


extern RT_MODEL_rtwdemo_abstime_T *const rtwdemo_abstime_M;

/*-
* 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_ */

Four 32-bit unsigned integers, clockTick1 , clockTickH1 , clockTick2 , and


clockTickH2 are counters for storing the elapsed time of subsystems SS2 and SS3.

Enable Optimization and Regenerate Code

1. Reconfigure the model to set the lifespan to 1 day.

2. Build the model.


### Starting build procedure for model: rtwdemo_abstime
### Successful completion of build procedure for model: rtwdemo_abstime

Review the Regenerated Code

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;
};

/* Block states (default storage) */


extern DW_rtwdemo_abstime_T rtwdemo_abstime_DW;

/* External inputs (root inport signals with default storage) */


extern ExtU_rtwdemo_abstime_T rtwdemo_abstime_U;

/* External outputs (root outports fed by signals with default storage) */


extern ExtY_rtwdemo_abstime_T rtwdemo_abstime_Y;

17-43
17 Time-Based Scheduling in Simulink Coder

/* Model entry point functions */


extern void rtwdemo_abstime_initialize(void);
extern void rtwdemo_abstime_step(int_T tid);
extern void rtwdemo_abstime_terminate(void);

/* Real-time Model object */


extern RT_MODEL_rtwdemo_abstime_T *const rtwdemo_abstime_M;

/*-
* 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

• “Optimization Pane” (Simulink Coder)


• “Timers in Asynchronous Tasks” (Simulink Coder)

17-44
Time-Based Scheduling Example Models

• “Time-Based Scheduling and Code Generation” (Simulink Coder)

Single-Rate Modeling (Bare Board, No OS)


This model shows the code generated for a single-rate discrete-time model configured for
a bare-board target (one with no operating system).

Open Example Model

Open the example model rtwdemo_srbb.

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.

Multirate Modeling in Single-Tasking Mode (Bare Board, no


OS)
This model shows the code generated for a multirate discrete-time model configured for
single-tasking on a bare-board target (one with no operating system).

Open Example Model

Open the example model rtwdemo_mrstbb.

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.

Multirate Modeling in Multitasking Mode (Bare Board, no OS)


This model shows the code generated for a multirate discrete-time model configured for a
multitasking bare-board target (one with no operating system).

Open Example Model

Open the example model rtwdemo_mrmtbb.

open_system('rtwdemo_mrmtbb')

17-49
17 Time-Based Scheduling in Simulink Coder

17-50
Time-Based Scheduling Example Models

Explore Example Model

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.

Data Transfer Assumptions

Basis of operation for data transfers between tasks:

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)

Trade Determinism and Data Integrity to Improve System


Performance
This model shows the differences in the operation modes of the Rate Transition block
when used in a multirate, multitasking model. The flexible options for the Rate Transition
block allow you to select the mode that is best suited for your application. You can trade
levels of determinism and data integrity to improve system performance.

17-51
17 Time-Based Scheduling in Simulink Coder

Rate Transition Block Modes of Operation

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 Transfer Assumptions

Basis of operation for data transfers between tasks:

• 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

Model rtwdemo_ratetrans shows the differences in the operation modes of the


following Rate Transition blocks.

Rate Transition block DetAndIntegF2S

Determinism and data integrity (fast to slow transition):

• The block output is used as a persistent data buffer.


• Data is written to output at slower rate but done during the faster rate context
• Data as seen by the slower rate is always the value when both the faster and slower
rate last executed. Any subsequent steps by the faster rate (and associated data
updates) while the slower rate is running are not seen by the slower rate.

Rate Transition block DetAndIntegS2F

Determinism and data integrity (slow to fast transition):

• 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.

Rate Transition block IntegOnlyF2S

Data integrity only (fast to slow transition):

• The block output is used as a persistent data buffer.


• Data is written to buffer during the faster rate context if a flag indicates it not in the
process of being read.
• The flag is set and data is copied from the buffer to output at the slow rate, the flag is
then cleared. This is an additional copy as compared to the deterministic case.
• Data as seen by the slower rate can be from a more recent step of the faster rate than
from when the slower rate and faster rate both executed.

Rate Transition block IntegOnlyS2F

Data integrity only (slow to fast transition):

17-54
See Also

• Uses two persistent data buffers, both are internal buffers.


• One of the 2 buffers is always copied to the output at faster rate.
• One of the 2 buffers is written at the slower rate and during the slower rate context,
then the active buffer is switched.
• The data as seen by the faster rate can be more recent than for the deterministic case.
Specifically, when both the slower and faster rate have their hits, the faster rate will
see a previous value from the slower rate. But, subsequent steps for the faster rate
may see an updated value (when the slower rate updates the non-active buffer and
switches the active buffer flag.

Rate Transition block NoneF2S

No code is generated for the Rate Transition block when determinism and data integrity
is waived.

Rate Transition block NoneS2F

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

Event-Based Scheduling in Simulink


Coder

• “Asynchronous Events” on page 18-2


• “Generate Interrupt Service Routines” on page 18-6
• “Spawn and Synchronize Execution of RTOS Task” on page 18-15
• “Pass Asynchronous Events in RTOS as Input To a Referenced Model” on page 18-32
• “Rate Transitions and Asynchronous Blocks” on page 18-40
• “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
• “Asynchronous Support Limitations” on page 18-63
18 Event-Based Scheduling in Simulink Coder

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

Block Library for Calls to an Example Real-Time Operating


System
The next figure shows the blocks in the vxlib1 block library.

4. VxWorks is a registered trademark of Wind River Systems, Inc.

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 vxlib1 library includes blocks you can use to

• Generate interrupt-level code — Async Interrupt block


• Spawn an RTOS task that calls a function call subsystem — Task Sync block
• Enable data integrity when transferring data between blocks running as different
tasks — Protected RT block
• Use an unprotected/nondeterministic mode when transferring data between blocks
running as different tasks — Unprotected RT block

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

Access the Block Library for RTOS Integration


To access the example RTOS (VxWorks) block library, enter the MATLAB command
vxlib1.

Generate Code Using Library Blocks for RTOS Integration


To generate an example RTOS compatible application from a model containing vxlib1
library blocks, use the following configuration parameter values for your model.

• 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).

Examples and Additional Information


Additional information relevant to the topics in this chapter can be found in

• 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

Generate Interrupt Service Routines


To generate an interrupt service routine (ISR) associated with a specific VME interrupt
level for the example RTOS (VxWorks), use the Async Interrupt block. The Async Interrupt
block enables the specified interrupt level and installs an ISR that calls a connected
function call subsystem.

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.

Connecting the Async Interrupt Block


To generate an ISR, connect an output of the Async Interrupt block to the control input of

• A function call subsystem


• The input of a Task Sync block
• The input to a Stateflow chart configured for a function call input event

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

Requirements and Restrictions


Note the following requirements and restrictions:

• The Async Interrupt block supports VME interrupts 1 through 7.


• The Async Interrupt block uses the following system calls to the example RTOS
(VxWorks):

• 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.

Using the Async Interrupt Block in Simulation and Code


Generation
This section describes a dual-model approach to the development and implementation of
real-time systems that include ISRs. In this approach, you develop one model that
includes a plant and a controller for simulation, and another model that only includes the
controller for code generation. Using a Simulink library, you can implement changes to
both models simultaneously. The next figure shows how changes made to the plant or
controller, both of which are in a library, are propagated to the models.

Model
Plant (for simulation)
Plant Controller

Library: Changes made here Interrupt


affect both models. Block
(Simulation
input enabled)
Controller
Interrupt
Block Model
Simulink Coder library (for code generation)
Interrupt
Block
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

Dual-Model Approach: Simulation


The following block diagram shows a simple model that illustrates the dual-model
approach to modeling. During simulation, the Pulse Generator blocks provide simulated
interrupt signals.

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.)

Dual-Model Approach: Code Generation


In the generated code for the sample model,

18-9
18 Event-Based Scheduling in Simulink Coder

• Ground blocks provide input signals to the Environment Controller block


• The Async Interrupt block does not use its simulation input

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.

Installing an ISR requires two RTOS (VxWorks) calls, int_connect and


sysInt_Enable. The Async Interrupt block inserts these calls in the
model_initialize function, as shown in the following code excerpt.
/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */
/* Connect and enable ISR function: isr_num1_vec192 */
if( intConnect(INUM_TO_IVEC(192), isr_num1_vec192, 0) != OK) {
printf("intConnect failed for ISR 1.\n");
}
sysIntEnable(1);

18-11
18 Event-Based Scheduling in Simulink Coder

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


/* Connect and enable ISR function: isr_num2_vec193 */
if( intConnect(INUM_TO_IVEC(193), isr_num2_vec193, 0) != OK)
{
printf("intConnect failed for ISR 2.\n");
}
sysIntEnable(2);

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.

Generated ISR Code

The actual ISR generated for IRQ1 in the RTOS (VxWorks) is listed below.

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */

void isr_num1_vec192(void)
{
int_T lock;
FP_CONTEXT context;

/* Use tickGet() as a portable tick counter example.


A much higher resolution can be achieved with a
hardware counter */
Async_Code_M->Timing.clockTick2 = tickGet();

/* disable interrupts (system is configured as non-ive) */


lock = intLock();

/* save floating point context */


fppSave(&context);

/* Call the system: <Root>/Subsystem A */


Count(0, 0);

/* restore floating point context */


fppRestore(&context);

/* re-enable interrupts */

18-12
See Also

intUnlock(lock);
}

There are several features of the ISR that should be noted:

• 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.

See “Timers in Asynchronous Tasks” on page 18-46 for details.

Model Termination Code

The model's termination function disables the interrupts in the RTOS (VxWorks):

/* Model terminate function */


void Async_Code_terminate(void)
{
/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */
/* Disable interrupt for ISR system: isr_num1_vec192 */
sysIntDisable(1);

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


/* Disable interrupt for ISR system: isr_num2_vec193 */
sysIntDisable(2);
}

See Also

More About
• “Spawn and Synchronize Execution of RTOS Task” (Simulink Coder)

18-13
18 Event-Based Scheduling in Simulink Coder

• “Pass Asynchronous Events in RTOS as Input To a Referenced Model” (Simulink


Coder)
• “Import Asynchronous Event Data for Simulation” (Simulink Coder)
• “Rate Transitions and Asynchronous Blocks” (Simulink Coder)

18-14
Spawn and Synchronize Execution of RTOS Task

Spawn and Synchronize Execution of RTOS Task


This example shows how to simulate and generate code for asynchronous events on a
multitasking real-time operating system (VxWorks®). The model shows different
techniques for handling asynchronous events depending on the size of the triggered
subsystems.

About the Example Model

Open the example model rtwdemo_async.

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

• Function call subsystem


• Task Sync block
• A Stateflow® chart configured for a function call input event
• A referenced model with an Inport block that connects to one of the preceding model
elements

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:

• Function call subsystem


• Task Sync block
• A Stateflow® chart configured for a function call input event

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:

• Between an Async Interrupt block and a function-call subsystem or Stateflow® chart.


• At the output port of a Stateflow® chart that has an event, Output to Simulink,
that you configure as a function call.

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 Transfer Assumptions

• 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

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 Report

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.

1. Create a temporary folder for the build and inspection process.

18-18
Spawn and Synchronize Execution of RTOS Task

2. Build the model.

### Starting build procedure for model: rtwdemo_async


Warning: Simulink Coder: The tornado.tlc target will be removed in a future
release.

### Wrapping unrecognized make command (angle brackets added)


### <make>
### in default batch file
### Successful completion of code generation for model: rtwdemo_async

Review Initialization Code

Open the generated source file rtwdemo_async.c. The initialization code:

1. Creates and initializes the synchronization semaphore Task0_semaphore.

*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID = semBCreate(SEM_Q_PRIORITY,


SEM_EMPTY);
if (rtwdemo_async_DW.SFunction_PWORK.SemID == NULL) {
printf("semBCreate call failed for block Task0.\n");
}

2. Spawns task task0 and assigns the task priority 50.

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");
}

/* End of Start for S-Function (vxtask1): '<S5>/S-Function' */

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


/* Connect and enable ISR function: isr_num1_vec192 */
if (intConnect(INUM_TO_IVEC(192), isr_num1_vec192, 0) != OK) {
printf("intConnect failed for ISR 1.\n");
}

18-19
18 Event-Based Scheduling in Simulink Coder

sysIntEnable(1);

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


/* Connect and enable ISR function: isr_num2_vec193 */
if (intConnect(INUM_TO_IVEC(193), isr_num2_vec193, 0) != OK) {
printf("intConnect failed for ISR 2.\n");
}

sysIntEnable(2);

3. Connects and enables ISR isr_num1_vec192 for interrupt 1 and ISR


isr_num2_vec193 for interrupt 2.

{
int32_T i;

/* InitializeConditions for RateTransition: '<Root>/Protected RT1' */


for (i = 0; i < 60; i++) {
rtwdemo_async_DW.ProtectedRT1_Buffer[i] = 0.0;
}

/* End of InitializeConditions for RateTransition: '<Root>/Protected RT1' */

/* InitializeConditions for RateTransition: '<Root>/Protected RT2' */


for (i = 0; i < 60; i++) {
rtwdemo_async_DW.ProtectedRT2_Buffer[i] = 0.0;
}

/* End of InitializeConditions for RateTransition: '<Root>/Protected RT2' */

/* SystemInitialize for S-Function (vxinterrupt1): '<Root>/Async Interrupt' incorpo


* SubSystem: '<Root>/Count'
*/
/* System initialize for function-call system: '<Root>/Count' */
rtwdemo_async_DW.Count_PREV_T = rtwdemo_async_M->Timing.clockTick2;

/* InitializeConditions for DiscreteIntegrator: '<S2>/Integrator' */


rtwdemo_async_DW.Integrator_DSTATE_l = 0.0;

/* SystemInitialize for Outport: '<Root>/Out1' incorporates:


* Outport: '<S2>/Out'
*/
rtwdemo_async_Y.Out1 = 0.0;

18-20
Spawn and Synchronize Execution of RTOS Task

/* SystemInitialize for S-Function (vxinterrupt1): '<Root>/Async Interrupt' incorpo


* SubSystem: '<S4>/Subsystem'
*/

/* System initialize for function-call system: '<S4>/Subsystem' */

/* SystemInitialize for S-Function (vxtask1): '<S5>/S-Function' incorporates:


* SubSystem: '<Root>/Algorithm'
*/

/* System initialize for function-call system: '<Root>/Algorithm' */


rtwdemo_async_M->Timing.clockTick4 = rtwdemo_async_M->Timing.clockTick3;
rtwdemo_async_DW.Algorithm_PREV_T = rtwdemo_async_M->Timing.clockTick4;

/* InitializeConditions for DiscreteIntegrator: '<S1>/Integrator' */


rtwdemo_async_DW.Integrator_DSTATE = 0.0;

/* SystemInitialize for Outport: '<S1>/Out1' */


memset(&rtwdemo_async_B.Sum[0], 0, 60U * sizeof(real_T));

/* SystemInitialize for Outport: '<Root>/Out3' incorporates:


* Outport: '<S1>/Out2'
*/
rtwdemo_async_Y.Out3 = 0.0;

/* End of SystemInitialize for S-Function (vxtask1): '<S5>/S-Function' */

/* End of SystemInitialize for S-Function (vxinterrupt1): '<Root>/Async Interrupt'


}
}

/* Model terminate function */


static void rtwdemo_async_terminate(void)
{
/* Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


/* Disable interrupt for ISR system: isr_num1_vec192 */
sysIntDisable(1);

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


/* Disable interrupt for ISR system: isr_num2_vec193 */
sysIntDisable(2);

18-21
18 Event-Based Scheduling in Simulink Coder

/* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */

/* Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' incorporates:


* SubSystem: '<S4>/Subsystem'
*/

/* Termination for function-call system: '<S4>/Subsystem' */

/* Terminate for S-Function (vxtask1): '<S5>/S-Function' */

/* VxWorks Task Block: '<S5>/S-Function' (vxtask1) */


/* Destroy task: Task0 */
taskDelete(rtwdemo_async_DW.SFunction_IWORK.TaskID);

/* End of Terminate for S-Function (vxtask1): '<S5>/S-Function' */

/* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */


}

/*========================================================================*
* Start of Classic call interface *
*========================================================================*/
void MdlOutputs(int_T tid)
{
rtwdemo_async_output(tid);
}

void MdlUpdate(int_T tid)


{
rtwdemo_async_update(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));

/* initialize real-time model */


(void) memset((void *)rtwdemo_async_M, 0,
sizeof(RT_MODEL_rtwdemo_async_T));

/* Initialize timing info */


{
int_T *mdlTsMap = rtwdemo_async_M->Timing.sampleTimeTaskIDArray;
mdlTsMap[0] = 0;
mdlTsMap[1] = 1;
rtwdemo_async_M->Timing.sampleTimeTaskIDPtr = (&mdlTsMap[0]);
rtwdemo_async_M->Timing.sampleTimes =
(&rtwdemo_async_M->Timing.sampleTimesArray[0]);
rtwdemo_async_M->Timing.offsetTimes =
(&rtwdemo_async_M->Timing.offsetTimesArray[0]);

/* 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.

Review Task and Task Synchronization Code

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

logMsg("Aborting real-time simulation.\n",0,0,0,0,0,0);


semGive(stopSem);
return(ERROR);

#endif

18-25
18 Event-Based Scheduling in Simulink Coder

} else {
semTake(*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID, WAIT_FOREVER);
}

/* Use the upstream clock tick counter for this Task. */


rtwdemo_async_M->Timing.clockTick4 = rtwdemo_async_M->Timing.clockTick3;

/* Call the system: '<Root>/Algorithm' */


{
{
int32_T tmp;
int32_T i;

/* RateTransition: '<Root>/Protected RT1' */


tmp = rtwdemo_async_DW.ProtectedRT1_ActiveBufIdx * 60;
for (i = 0; i < 60; i++) {
rtwdemo_async_B.ProtectedRT1[i] =
rtwdemo_async_DW.ProtectedRT1_Buffer[i + tmp];
}

/* End of RateTransition: '<Root>/Protected RT1' */

/* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */

/* S-Function (vxtask1): '<S5>/S-Function' */

/* Output and update for function-call system: '<Root>/Algorithm' */


{
real_T tmp;
int32_T i;
uint32_T Algorithm_ELAPS_T_tmp;
rtwdemo_async_M->Timing.clockTick4 =
rtwdemo_async_M->Timing.clockTick3;
Algorithm_ELAPS_T_tmp = rtwdemo_async_M->Timing.clockTick4;
rtwdemo_async_DW.Algorithm_ELAPS_T = Algorithm_ELAPS_T_tmp -
rtwdemo_async_DW.Algorithm_PREV_T;
rtwdemo_async_DW.Algorithm_PREV_T = Algorithm_ELAPS_T_tmp;

/* Outport: '<Root>/Out3' incorporates:


* DiscreteIntegrator: '<S1>/Integrator'
*/
rtwdemo_async_Y.Out3 = rtwdemo_async_DW.Integrator_DSTATE;

/* Sum: '<S1>/Sum' incorporates:

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;
}

/* End of Sum: '<S1>/Sum' */

/* Sum: '<S1>/Sum1' */
tmp = -0.0;
for (i = 0; i < 60; i++) {
tmp += rtwdemo_async_B.Sum[i];
}

/* Update for DiscreteIntegrator: '<S1>/Integrator' incorporates:


* Sum: '<S1>/Sum1'
*/
rtwdemo_async_DW.Integrator_DSTATE += 0.016666666666666666 * (real_T)
rtwdemo_async_DW.Algorithm_ELAPS_T * tmp;
}

/* End of Outputs for S-Function (vxtask1): '<S5>/S-Function' */

/* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */


}

{
int32_T i;

/* Update for RateTransition: '<Root>/Protected RT2' */


for (i = 0; i < 60; i++) {
rtwdemo_async_DW.ProtectedRT2_Buffer[i +
(rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx == 0) * 60] =
rtwdemo_async_B.Sum[i];
}

rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx = (int8_T)
(rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx == 0);

/* End of Update for RateTransition: '<Root>/Protected RT2' */


}
}
}

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;

/* Use tickGet() as a portable tick


counter example. A much higher resolution can
be achieved with a hardware counter */
rtwdemo_async_M->Timing.clockTick2 = tickGet();

/* disable interrupts (system is configured as non-preemptive) */


lock = intLock();

/* save floating point context */


fppSave(&context);

/* Call the system: '<Root>/Count' */


{
/* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */

/* Output and update for function-call system: '<Root>/Count' */


{
uint32_T Count_ELAPS_T_tmp;
Count_ELAPS_T_tmp = rtwdemo_async_M->Timing.clockTick2;
rtwdemo_async_DW.Count_ELAPS_T = Count_ELAPS_T_tmp -
rtwdemo_async_DW.Count_PREV_T;
rtwdemo_async_DW.Count_PREV_T = Count_ELAPS_T_tmp;

/* Outport: '<Root>/Out1' incorporates:

18-28
Spawn and Synchronize Execution of RTOS Task

* DiscreteIntegrator: '<S2>/Integrator'
*/
rtwdemo_async_Y.Out1 = rtwdemo_async_DW.Integrator_DSTATE_l;

/* Update for DiscreteIntegrator: '<S2>/Integrator' */


rtwdemo_async_DW.Integrator_DSTATE_l += 0.016666666666666666 * (real_T)
rtwdemo_async_DW.Count_ELAPS_T;
}

/* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */


}

/* restore floating point context */


fppRestore(&context);

/* re-enable interrupts */
intUnlock(lock);
}

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */

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();

/* Call the system: '<S4>/Subsystem' */


{
/* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */

/* Output and update for function-call system: '<S4>/Subsystem' */

/* S-Function (vxtask1): '<S5>/S-Function' */

/* VxWorks Task Block: '<S5>/S-Function' (vxtask1) */


/* Release semaphore for system task: Task0 */
semGive(*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID);

18-29
18 Event-Based Scheduling in Simulink Coder

/* End of Outputs for S-Function (vxtask1): '<S5>/S-Function' */

/* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */


}
}

/* VxWorks Task Block: '<S5>/S-Function' (vxtask1) */

Review Task Termination Code

The Task Sync block generates the following termination code.

static void rtwdemo_async_terminate(void)


{
/* Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


/* Disable interrupt for ISR system: isr_num1_vec192 */
sysIntDisable(1);

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


/* Disable interrupt for ISR system: isr_num2_vec193 */
sysIntDisable(2);

/* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */

/* Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' incorporates:


* SubSystem: '<S4>/Subsystem'
*/

/* Termination for function-call system: '<S4>/Subsystem' */

/* Terminate for S-Function (vxtask1): '<S5>/S-Function' */

/* VxWorks Task Block: '<S5>/S-Function' (vxtask1) */


/* Destroy task: Task0 */
taskDelete(rtwdemo_async_DW.SFunction_IWORK.TaskID);

/* End of Terminate for S-Function (vxtask1): '<S5>/S-Function' */

/* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */


}

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

Pass Asynchronous Events in RTOS as Input To a


Referenced Model
This example shows how to simulate and generate code for a model that triggers
asynchronous events in an example RTOS (VxWorks®) that get passed as input to a
referenced model.

Open Example Model

Open the example model rtwdemo_async_mdlreftop.

Warning: Undefined function 'LibraryBrowserCustomizer' for


input arguments of type 'DAStudio.CustomizationManager'.

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:

• Function call subsystem


• Task Sync block
• A Stateflow® chart configured for a function call input event
• A referenced model with a Inport block that connects to one of the preceding model
elements

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.

Open the referenced model.

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 Transfer Assumptions

• 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

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 Report

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.

1. Create a temporary folder for the build and inspection process.

2. Build the model.

Warning: Simulink Coder: The tornado.tlc target will be removed in a future release.

### Wrapping unrecognized make command (angle brackets added)


### <make>
### in default batch file
### Successfully updated the model reference RTW target for model: rtwdemo_async_mdlref
### Starting build procedure for model: rtwdemo_async_mdlreftop
Warning: Simulink Coder: The tornado.tlc target will be removed in a future release.

18-35
18 Event-Based Scheduling in Simulink Coder

### Wrapping unrecognized make command (angle brackets added)


### <make>
### in default batch file
### Successful completion of code generation for model: rtwdemo_async_mdlreftop

Review Initialization Code

Open the generated source file rtwdemo_async_mdlreftop.c. The initialization code


connects and enables ISR isr_num1_vec192 for interrupt 1 and ISR isr_num2_vec193
for interrupt 2.

static void rtwdemo_async_mdlreftop_initialize(void)


{
/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */
/* Connect and enable ISR function: isr_num1_vec192 */
if (intConnect(INUM_TO_IVEC(192), isr_num1_vec192, 0) != OK) {
printf("intConnect failed for ISR 1.\n");
}

sysIntEnable(1);

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


/* Connect and enable ISR function: isr_num2_vec193 */
if (intConnect(INUM_TO_IVEC(193), isr_num2_vec193, 0) != OK) {
printf("intConnect failed for ISR 2.\n");
}

sysIntEnable(2);

/* SystemInitialize for ModelReference: '<Root>/Model' */


rtwdemo_async_mdlrefbot_Init(&rtwdemo_async_mdlreftop_Y.Out1);

/* Enable for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */

/* Enable for ModelReference: '<Root>/Model' incorporates:


* Enable for Inport: '<Root>/In1_60hz'
* Enable for Inport: '<Root>/In2_60_hz'
* Enable for Inport: '<Root>/In3_60hz'
*/
rtwdemo_async_mdlrefbot_Interrupt1_Enable();
rtwdemo_async_mdlrefbot_Interrupt2_Enable();

/* End of Enable for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */


}

18-36
Pass Asynchronous Events in RTOS as Input To a Referenced Model

Review ISR Code

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;

/* disable interrupts (system is configured as non-preemptive) */


lock = intLock();

/* save floating point context */


fppSave(&context);

/* Call the system: '<Root>/Model' */


{
/* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */

/* ModelReference: '<Root>/Model' incorporates:


* Inport: '<Root>/In1_60hz'
* Inport: '<Root>/In2_60_hz'
* Inport: '<Root>/In3_60hz'
*/
rtwdemo_async_mdlrefbot_Interrupt1(&rtwdemo_async_mdlreftop_Y.Out1);

/* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */


}

/* restore floating point context */


fppRestore(&context);

/* re-enable interrupts */
intUnlock(lock);

18-37
18 Event-Based Scheduling in Simulink Coder

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


void isr_num2_vec193(void)
{
FP_CONTEXT context;

/* save floating point context */


fppSave(&context);

/* Call the system: '<Root>/Model' */


{
/* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */

/* ModelReference: '<Root>/Model' incorporates:


* Inport: '<Root>/In1_60hz'
* Inport: '<Root>/In2_60_hz'
* Inport: '<Root>/In3_60hz'
*/
rtwdemo_async_mdlrefbot_Interrupt2();

/* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */


}

/* restore floating point context */


fppRestore(&context);
}

Review Task Termination Code

The Task Sync block generates the following termination code.

static void rtwdemo_async_mdlreftop_terminate(void)


{
/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */
/* Disable interrupt for ISR system: isr_num1_vec192 */
sysIntDisable(1);

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


/* Disable interrupt for ISR system: isr_num2_vec193 */
sysIntDisable(2);
}

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

Rate Transitions and Asynchronous Blocks


Because an asynchronous function call subsystem can preempt or be preempted by other
model code, an inconsistency arises when more than one signal element is connected to
an asynchronous block. The issue is that signals passed to and from the function call
subsystem can be in the process of being written to or read from when the preemption
occurs. Thus, some old and some new data is used. This situation can also occur with
scalar signals in some cases. For example, if a signal is a double (8 bytes), the read or
write operation might require two machine instructions. The following sections describe
these issues.
In this section...
“About Rate Transitions and Asynchronous Blocks” on page 18-40
“Handle Rate Transitions for Asynchronous Tasks” on page 18-42
“Handle Multiple Asynchronous Interrupts” on page 18-42
“Protect Data Integrity with volatile Keyword” on page 18-44

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.

About Rate Transitions and Asynchronous Blocks


The Simulink Rate Transition block is designed to deal with preemption problems that
occur in data transfer between blocks running at different rates. These issues are
discussed in “Time-Based Scheduling and Code Generation” (Simulink Coder).

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

Handle Rate Transitions for Asynchronous Tasks


For rate transitions that involve asynchronous tasks, you can maintain data integrity.
However, you cannot achieve determinism. You have the option of using the Rate
Transition block or target-specific rate transition blocks.

Consider the following model, which includes a Rate Transition block.

You can use the Rate Transition block in either of the following modes:

• Maintain data integrity, no determinism


• Unprotected

Alternatively, you can use target-specific rate transition blocks. The following blocks are
available for the example RTOS (VxWorks):

• Protected Rate Transition block (reader)


• Protected Rate Transition block (writer)
• Unprotected Rate Transition block

Handle Multiple Asynchronous Interrupts


Consider the following model, in which two functions trigger the same subsystem.

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:

The function call subsystem <name> has multiple asynchronous


triggers that do not specify priority. Data integrity will
not be maintained if these triggers can preempt one another.

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:

• A function call subsystem is triggered by two asynchronous triggers (TriggerA and


TriggerB) having identical priority settings.
• Each trigger sets the source of time and timer attributes by calling the functions
ssSetTimeSource and ssSetAsyncTimerAttributes.
• The triggered subsystem contains a block that needs elapsed or absolute time (for
example, a Discrete Time Integrator).

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:

• If the time source is set to SS_TIMESOURCE_BASERATE, the code generator produces


timer code in the function call subsystem, updating the clock tick variable from the
base rate clock tick. Data integrity is maintained if the same priority is assigned to
TriggerA and TriggerB.
• If the time source is SS_TIMESOURCE_SELF, generated code for both TriggerA and
TriggerB updates the same clock tick variable from the hardware clock.

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.

Protect Data Integrity with volatile Keyword


When you select Ensure data integrity during data transfer, the code generated for a
Rate Transition block defines volatile global buffers and semaphores and uses them to
protect the integrity of the transferred data. If necessary, for additional protection, or for
protection without a Rate Transition block, you can explicitly apply volatile to the

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

Timers in Asynchronous Tasks


An ISR can set a source for absolute time. This is done with the function
ssSetTimeSource. The function ssSetTimeSource cannot be called before
ssSetOutputPortWidth is called. If this occurs, the program will come to a halt and
generate an error message. ssSetTimeSource has the following three options:

• 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.

By default, the counter is implemented as a 32-bit unsigned integer member of the


Timing substructure of the real-time model structure. For a target that supports the
rtModel data structure, when the time data type is not set by using
ssSetAsyncTimeDataType, the counter word size is determined by the Application
lifespan (days) (Simulink) model parameter. As an example (from ERT target code),

/* Real-time Model Data Structure */


struct _RT_MODEL_elapseTime_exp_Tag {
const char *errorStatus;

/*
* 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.

/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */


void isr_num2_vec193(void)
{

/* Use tickGet() as a portable tick counter example. A much


higher resolution can be achieved with a hardware counter */
rtM->Timing.clockTick2 = 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

Create a Customized Asynchronous Library


This topic describes how to implement asynchronous blocks for use with your target
RTOS, using the Async Interrupt and Task Sync blocks as a starting point. Rate Transition
blocks are target-independent, so you do not need to develop customized rate transition
blocks. The following sections provide implementation details.

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.

About Implementing Asynchronous Blocks


You can customize the asynchronous library blocks by modifying the block
implementation. These files are

• The block's underlying S-function MEX-file


• The TLC files that control code generation of the block

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.

Custom block implementation is an advanced topic, requiring familiarity with the


Simulink MEX S-function format and API, and with the Target Language Compiler (TLC).
These topics are covered in the following documents:

• Simulink topics “What Is an S-Function?” (Simulink), “Use S-Functions in Models”


(Simulink), “How S-Functions Work” (Simulink), and “Implementing S-Functions”
(Simulink) describe MEX S-functions and the S-function API in general.

18-49
18 Event-Based Scheduling in Simulink Coder

• The “Inlining S-Functions” (Simulink Coder), “Inline C MEX S-Functions” (Simulink


Coder), and “S-Functions and Code Generation” (Simulink Coder) describe how to
create a TLC block implementation for use in code generation.

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).

Async Interrupt Block Implementation


The source files for the Async Interrupt block are located in matlabroot/rtw/c/
tornado/devices (open):

• vxinterrupt1.c: C MEX-file source code, for use in configuration and simulation


• vxinterrupt1.tlc: TLC implementation, for use in code generation
• asynclib.tlc: library of TLC support functions, called by the TLC implementation of
the block. The library calls are summarized in “asynclib.tlc Support Library” on page
18-56.

C MEX Block Implementation

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).

The mdlInitializeSizes function uses special SimStruct macros and SS_OPTIONS


settings that are required for asynchronous blocks, as described below.

Note that the following macros cannot be called before ssSetOutputPortWidth is


called:

• 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.

The function prototype is


ssSetAsyncTimerAttributes(SimStruct *S, double res)

where

• S is a Simstruct pointer.
• res is the Timer resolution (seconds) parameter value.

The following code excerpt shows the call to ssSetAsyncTimerAttributes.


/* Setup Async Timer attributes */
ssSetAsyncTimerAttributes(S,mxGetPr(TICK_RES)[0]);

ssSetAsyncTaskPriorities

ssSetAsyncTaskPriorities sets the Simulink task priority for blocks executing at


each interrupt level, as specified in the block's Simulink task priority field.

The function prototype is


ssSetAsyncTaskPriorities(SimStruct *S, int numISRs,
int *priorityArray)

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

• priorityarray is an integer array containing the interrupt numbers specified in the


VME interrupt number(s) parameter.

The following code excerpt shows the call to ssSetAsyncTaskPriorities:

/* Setup Async Task Priorities */


priorityArray = malloc(numISRs*sizeof(int_T));
for (i=0; i<numISRs; i++) {
priorityArray[i] = (int_T)(mxGetPr(ISR_PRIORITIES)[i]);
}
ssSetAsyncTaskPriorities(S, numISRs, priorityArray);
free(priorityArray);
priorityArray = NULL;
}

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 |

If an S-function specifies the SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME option


and inherits a sample time of Inf, the code generator determines how to produce code
for the block based on whether the block is invariant. A block is invariant if its port
signals are invariant. A signal is invariant if it has a constant value during the entire
simulation. A Constant block sample time does not guarantee that the port signals are
invariant. For more information, see “Inline Invariant Signals” (Simulink Coder). If the
block is not invariant, the code generator produces code only in the initialize entry-point
function. If the block is invariant, the code generator does not produce code for the block.

TLC Implementation

This section discusses each function of vxinterrupt1.tlc, with an emphasis on target-


specific features that you will need to change to generate code for your target RTOS.
Generate #include Directives

vxinterrupt1.tlc begins with the statement

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.

In a custom implementation, this naming convention is optional.

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:

• Generates a call to the downstream block (cached in a temporary buffer).


• Determines whether the ISR should be locked or not (as specified in the Preemption
Flag(s) block parameter).
• Determines whether the block connected to the Async Interrupt block is a Task Sync
block. (This information is obtained by using the asynclib calls
LibGetFcnCallBlock and LibGetBlockAttribute.) If so,

• 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.

Task Sync Block Implementation


The source files for the Task Sync block are located in matlabroot/rtw/c/tornado/
devices (open). They are

• vxtask1.cpp: MEX-file source code, for use in configuration and simulation.


• vxtask1.tlc: TLC implementation, for use in code generation.
• asynclib.tlc: library of TLC support functions, called by the TLC implementation of
the block. The library calls are summarized in “asynclib.tlc Support Library” on page
18-56.

C MEX Block Implementation

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);

priority = (int_T) (*(mxGetPr(PRIORITY)));


ssSetAsyncTaskPriorities(S,1,&priority);

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

vxtask1.tlc begins with the statement

%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.

asynclib.tlc Support Library


asynclib.tlc is a library of TLC functions that support the implementation of
asynchronous blocks. Some functions are specifically designed for use in asynchronous
blocks. For example, LibSetAsyncCounter generates a call to update a timer for an
asynchronous block. Other functions are utilities that return information required by
asynchronous blocks (for example, information about connected function call
subsystems).

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

Summary of asynclib.tlc Library Functions

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

• “Import Asynchronous Event Data for Simulation” (Simulink Coder)


• “Rate Transitions and Asynchronous Blocks” (Simulink Coder)
• “Asynchronous Support Limitations” (Simulink Coder)

18-58
Import Asynchronous Event Data for Simulation

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 time points at which each asynchronous event occurs


• The number of asynchronous events at each time point

Input Data Format


You can enter your asynchronous data at the MATLAB command line or on the Data
Import/Export pane of the Configuration Parameters dialog box. In either case, a
number of restrictions apply to the data format.

• 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

1 To input data via the Configuration Parameters dialog box,

a Select Simulation > Configuration Parameters > Data Import/Export.


b Select the Input parameter.
c For this example, enter the following command in the MATLAB window:

>> t = [1 1 5 9 9 9]', u = [[0:10]' [0:10]']

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

Here the first column contains the simulation times.

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

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

Asynchronous Task Priority


The Simulink product does not simulate asynchronous task behavior. Although you can
specify a task priority for an asynchronous task represented in a model with the Task
Sync block, the priority setting is for code generation purposes only and is not honored
during simulation.

Convert an Asynchronous Subsystem into a Model Reference


You can use the Asynchronous Task Specification block to specify an asynchronous
function-call input to a model reference. However, you must convert the Async Interrupt
and Function-Call blocks into a subsystem and then convert the subsystem into a model
reference.

Following is an example with step-by-step instructions for conversion.

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

• “Use Discrete and Continuous Time” on page 19-2


• “Optimize Multirate Multitasking Execution for RTOS Run-Time Environments”
on page 19-4
19 Scheduling Considerations in Embedded Coder

Use Discrete and Continuous Time

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

Support for Discrete and Continuous Time Blocks


The ERT target supports code generation for discrete and continuous time blocks. If the
Support: continuous time option is selected on the Code Generation > Interface
pane, you can use these blocks in your models, without restriction.

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

Support for Continuous Solvers


The ERT target supports continuous solvers. In the Solver options dialog, you can select
an available solver in the Solver menu. (Note that the solver Type must be fixed-step
for use with the ERT target.)

Note Custom targets must be modified to support continuous time. The required
modifications are described in “Customize System Target Files” (Simulink Coder).

Support for Stop Time


The ERT target supports the stop time for a model. When generating host-based
executables, the stop time value is honored if one of the following is true:

19-2
See Also

• External mode is selected on the Code Generation > Interface pane


• MAT-file logging is selected
• Classic call interface is selected

Otherwise, the executable runs indefinitely.

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

Optimize Multirate Multitasking Execution for RTOS


Run-Time Environments
Using the rtmStepTask macro, run-time environments that employ task management
mechanisms of an real-time operating system (RTOS)—for example, VxWorks—can
improve performance of generated code by eliminating redundant scheduling calls during
the execution of tasks in a multirate, multitasking model, The following sections describe
implementation details.

Use rtmStepTask
The rtmStepTask macro is defined in model.h and its syntax is as follows:
boolean task_ready = rtmStepTask(rtm, idx);

The arguments are:

• rtm: pointer to the real-time model structure (rtM)


• idx: task identifier (tid) of the task whose scheduling counter is to be tested

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.

Schedule Code for Real-time Model without an RTOS


To understand the optimization that is available for an RTOS target, consider how the
ERT target schedules tasks for bareboard targets (where RTOS is not present). The ERT
target maintains scheduling counters and event flags for each subrate task. The
scheduling counters are implemented within the real-time model (rtM) data structure as
arrays, indexed on task identifier (tid).

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.

Schedule Code for Multirate Multitasking on an RTOS


The following task scheduling code, from ertmainlib.tlc, is designed for multirate
multitasking operation on an example RTOS (VxWorks) target. The example uses the TLC
function RTMTaskRunsThisBaseStep to generate calls to the rtmStepTask macro. A
loop iterates over each subrate task, and rtmStepTask is called for each task. If
rtmStepTask returns TRUE, the RTOS semGive function is called, and the RTOS
schedules the task to run.
%assign ifarg = RTMTaskRunsThisBaseStep("i")
for (i = 1; i < %<FcnNumST>; i++) {
if (%<ifarg>) {
semGive(taskSemList[i]);
if (semTake(taskSemList[i],NO_WAIT) != ERROR) {
logMsg("Rate for SubRate task %d is too fast.\n",i,0,0,0,0,0);
semGive(taskSemList[i]);
}
}
}

Suppress Redundant Scheduling Calls


Redundant scheduling calls are still generated by default for backward compatibility. To
change this setting and suppress them, add the following TLC variable definition to your
system target file before the %include "codegenentry.tlc" statement:
%assign SuppressSetEventsForThisBaseRateFcn = 1

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

Define Storage Classes, Memory Sections, and Function


Templates for Software Architecture
In a team or large organization, to enable multiple users to generate code that conforms
to a standard architecture, you can create and share code generation definitions, such as
storage classes, with those users. When configuring code generation settings for different
models, the users can apply the definitions to data and function elements in the models,
generating standardized code.

Create Code Definitions for Use as Default Code Generation


Settings
To control the default appearance of model elements in the generated code, you apply
settings to categories of elements, such as data and functions, by using the Code Mapping
Editor. For more information, see “Configure Default Code Generation for Categories of
Model Data and Functions” on page 21-7.

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

Create Code Definitions to Override Default Settings


To override the default settings that you specify in the Code Mapping Editor, you apply
code generation settings to individual model elements by using other tools such as the
Model Data Editor and the Property Inspector. For general information, see “Environment
for Configuring Model Data and Functions for Code Generation” on page 21-2.

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.

Avoid Maintaining Duplicate Definitions in Packages and


Dictionaries
If you want to use the same code generation definition as a default setting and for direct
application to individual model elements, you do not need to store one copy of the
definition in an Embedded Coder Dictionary and another copy in a package. Instead, store
the definition in a package (by using the Custom Storage Class Designer). Then, configure
one or more Embedded Coder Dictionaries to refer to the definition in the package. With
this technique, when you want to make changes to the definition, you make the changes
in only one place, the package.

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”.

Deploy Code Generation Definitions to Users


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

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.

Maintain Code Generation Definitions


In a model, you apply a code definition to a model element by selecting the name of the
definition in a drop-down list, for example, in the Model Data Editor or in the Code
Mapping Editor. Also, you can associate a memory section with a storage class or function
template by using a drop-down list in the Custom Storage Class Designer or in an
Embedded Coder Dictionary.

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

Embedded Coder Dictionary Definitions

If you created the code definition in an Embedded Coder Dictionary:

• 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.

Interact with Code Generation Definitions Programmatically


You cannot create code generation definitions programmatically. However, for Embedded
Coder Dictionary definitions, you can delete, copy, and move code definitions between
models and data dictionaries by using these functions:

• 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

Deploy Code Generation Definitions


As described in “Define Storage Classes, Memory Sections, and Function Templates for
Software Architecture” on page 20-2, you can create code generation definitions that you
and other users can apply to model elements such as data and functions. The code
definitions control the appearance of those elements in the generated code.

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.

Share Code Generation Definitions Between Multiple Models


and Users
When you create custom code generation definitions, to share the definitions between
models and other users:

• 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.

Share Embedded Coder Dictionary Definition Between Models


This example shows how to create a storage class that yields separate global variables in
the generated code and share the storage class between two models, rtwdemo_roll and
rtwdemo_advsc. Then, you configure each model to use the storage class as the default
code generation setting for internal data, which includes block states.

It is a best practice to store shared code generation definitions in a standalone data


dictionary, which means that no models are linked directly to the dictionary. Then, you
can link the target models to one or more additional, intermediate dictionaries, which you
configure to refer to the standalone dictionary. With this modular dictionary hierarchy,
each model can store other data, such as design data, separately from the code
generation definitions.

20-6
Deploy Code Generation Definitions

The figure shows an example dictionary hierarchy. In the figure:

• modelOne.slx and modelTwo.slx are different model files.


• dataForModelOne.sldd and dataForModelTwo.sldd are data dictionaries. Each
dictionary stores design data, such as numeric MATLAB variables, for one of the
models.
• coderDefs.sldd is a shared data dictionary that stores code generation definitions
for both models. The other dictionaries reference coderDefs.sldd.

Create Code Generation Definition in Standalone Data Dictionary

Create a data dictionary. Then, create the storage class in the dictionary.

1 At the command prompt, open the Model Explorer.

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 Models to Data Dictionaries

Link each model to a separate data dictionary. Then, configure each dictionary to refer to
the standalone dictionary (coderDefs.sldd).

1 Open the models.

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.

rtwdemo_advsc uses a variable in the base workspace, so Simulink migrates the


variable into the dictionary.

20-8
Deploy Code Generation Definitions

Apply Code Generation Definition in Models

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.

/* Storage class 'internalsInFile' */


real32_T rtwdemo__FixPtUnitDelay1_DSTATE;
real32_T rtwdemo_roll_Integrator_DSTATE;
int8_T rtwde_Integrator_PrevResetState;
6 Optionally, generate code from rtwdemo_advsc and confirm that the code appears
as expected.

Migrate Definitions from Model File to Shared Data Dictionary


If you create code generation definitions in the Embedded Coder Dictionary of a model,
the definitions are stored in the model file. If you want to share the definitions between
models:

1 Create a shared data dictionary as shown in “Share Embedded Coder Dictionary


Definition Between Models” on page 20-6. Before you proceed to the next step, make
sure all of the target models have access to the shared dictionary.
2 Use the coder.dictionary.move function to migrate the definitions from the
source model file to the shared data dictionary.
3 Optionally, copy Code Mapping Editor settings from the source model to other models
by using the programmatic interface of the Code Mapping Editor (see “Configure
Default Data and Function Code Generation Programmatically” on page 21-22).

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).

Create and Apply Storage Class

1 Open the example model rtwdemo_roll.

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

Coder Dictionary button .


4 In the Embedded Coder Dictionary dialog box, on the Storage Classes tab, click
Add.
5 For the new storage class, set these property values:

• 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.

Create Referenced Model

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.

Move Storage Class to 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.

To link the models to separate dictionaries:

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')

Now, both models have access to the storage class internalsInFile.

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.

Definitions in Shared Dictionary Do Not Appear in Code


Mapping Editor
If a model file contains Embedded Coder Dictionary definitions, and the model is linked to
a data dictionary that also contains Embedded Coder Dictionary definitions, the Code
Mapping Editor uses the definitions in the model file. To resolve this issue so that you can
use the definitions in the data dictionary, remove the definitions from the model file. Use
one or more of these functions:

• coder.dictionary.remove, which deletes all of the code generation definitions in a


model file or data dictionary.
• coder.dictionary.move, which moves all of the code generation definitions from a
model or data dictionary to a different model or data dictionary.

Make Shared Definitions in a Data Dictionary Available to New


Models
A model that you create from the Simulink Start Page or by using the new_system
function is not linked to a Simulink data dictionary. The new model cannot access code
generation definitions that you store in a data dictionary.

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).

Use Data Dictionary to Store Code Definitions but Not Design


Data
A Simulink data dictionary can store design data such as MATLAB variables and
Simulink.AliasType objects (see “Global and Shared Data: Data Dictionary”
(Simulink)). However, migrating the design data of a large model or of multiple models
from the base workspace to a data dictionary can take time and careful planning.

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).

Opening Code Perspective Generates Error


In a hierarchy of referenced data dictionaries (see “Dictionary Referencing” (Simulink)),
only one dictionary can store code generation definitions in an Embedded Coder
Dictionary. When you open the Code Perspective in a model that has access to multiple
Embedded Coder Dictionaries through referenced data dictionaries, Simulink generates
an error. To resolve the error, use coder.dictionary.move and
coder.dictionary.remove to transfer and delete Embedded Coder Dictionaries until
only one exists in the dictionary hierarchy. If necessary, store the Embedded Coder
Dictionary in a standalone, shared data dictionary as described in “Share Embedded
Coder Dictionary Definition Between Models” on page 20-6.

Limitations for Definitions in a Simulink Data Dictionary


When you store code generation definitions in a data dictionary, these limitations apply:

20-13
20 Representing a Software Architecture by Creating Code Generation Definitions

• In a hierarchy of referenced data dictionaries (see “Dictionary Referencing”


(Simulink)), only one dictionary can store code generation definitions in an Embedded
Coder Dictionary. You cannot partition the definitions by storing them in multiple
referenced dictionaries.

• 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

Conform to Software Architecture by Sharing and


Copying Default Code Generation Settings Between
Models
You and other users can configure default code generation settings for categories of
model data and functions by using the Code Mapping Editor (see “Configure Default Code
Generation for Categories of Model Data and Functions” on page 21-7). You can also
configure other model-wide code generation settings through configuration parameters.
With these broad, general settings, you can make models generate code that conforms to
a general software architecture by default.

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

Tools to Copy and Share Settings


Tool Description and Reference
Considerations
Template models You can create a template “Create a Template from a
model with preconfigured Model” (Simulink)
settings such as
configuration parameter
settings and Code Mapping
Editor settings.

However, when you create a


model by instantiating a
template, the new model is
not linked to a data
dictionary. If the
preconfigured settings in
the template model depend
on shared data that you
store in a data dictionary,
you must configure
dictionary linking and
referencing for each new
model.
Template projects You can create a template “What Are Simulink
Simulink project that Projects?” (Simulink)
contains models, data
dictionaries, and other
artifacts. You can also write
project shortcuts that
execute custom code to
create models, copy
settings, and share settings.

20-16
Conform to Software Architecture by Sharing and Copying Default Code Generation Settings Between Models

Tool Description and Reference


Considerations
Programmatic interfaces To copy settings between “Techniques to Copy
models, you can write Settings” on page 20-18
scripts, callbacks, and
shortcuts. Each kind of
setting has a programmatic
interface.
Configuration set objects To share configuration “About Configuration
parameter settings between References” (Simulink)
models, you can create a
configuration set object that
each model can refer to.
Data dictionaries A Simulink data dictionary For general information
stores variables, objects, about data dictionaries,
and other data for one or including how to access
more models. You can create them programmatically, see
hierarchies of referenced “What Is a Data
dictionaries to share Dictionary?” (Simulink). For
configuration parameter an example that shows how
settings and to partition and to store shared data for a
organize the settings. model reference hierarchy
in a standalone dictionary,
It is a best practice to store see “Partition Data for
shared settings in a Model Reference Hierarchy
standalone dictionary, which Using Data Dictionaries”
means that no models are (Simulink).
linked to the dictionary.
Then, you can link models to
one or more additional,
intermediate dictionaries,
which you configure to refer
to the standalone dictionary.
With this modular dictionary
hierarchy, each model can
store other data, such as
design data, separately from
the shared settings.

20-17
20 Representing a Software Architecture by Creating Code Generation Definitions

Techniques to Copy Settings


To copy settings, use one or more of the techniques described in the table.

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).

• A Simulink Project shortcut. The


shortcut can create a model and copy
settings into the model. For information
about project shortcuts, see “What Can
You Do With Project Shortcuts?”
(Simulink).

To copy settings programmatically, use the


appropriate programmatic interface.

• For configuration parameter settings,


use the set_param and get_param
functions.
• For Code Mapping Editor settings, see
“Configure Default Data and Function
Code Generation Programmatically” on
page 21-22.

Techniques to Share Settings


• To share configuration parameter settings, create a configuration set object. Create a
template model that refers to the object through a configuration reference.

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

Migrate Memory Section and Shared Utility Settings


from Configuration Parameters to Code Mapping Editor
Starting in R2018a, for new models:

• 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.

Also, if you use the coder.mapping.create function on such a model, Simulink


migrates memory section and shared utility settings in this manner.

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

• Translating the configuration parameter settings into Code Mapping Editor


settings.
• If the model is not linked to a data dictionary, configuring the Embedded Coder
Dictionary in the model file to refer to the memory section package and to contain
a function customization template.
• If the model is linked to a data dictionary, the migration process makes changes to the
dictionary, which you must save. The changes include:

• 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.

If the data dictionary references other dictionaries, the migration process


configures the dictionary at the bottom of the reference hierarchy so other models
and dictionaries in the hierarchy can use the memory section and function template
definitions.
• If the model refers to a Simulink.ConfigSet object, configuring the Embedded
Coder Dictionary of the data dictionary that stores the object.

Considerations Before Migrating


• Typically, when you open the Code Perspective, it executes the migration process
without prompting you. Do not open the Code Perspective unless you are ready to
migrate memory section and shared utility naming settings.

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.

If you do not accept, you cannot use the Code Perspective.


• If you use Simulink data dictionaries, before you or other users open the Code
Perspective in any models, consider creating and configuring the dictionaries first.

In a hierarchy of referenced data dictionaries (for example, a dictionary hierarchy that


parallels a model hierarchy), only one dictionary can contain an Embedded Coder
Dictionary. Setting up data dictionaries before migrating associated models enables

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.

For information about sharing an Embedded Coder Dictionary between models by


using referenced dictionaries, see “Share Embedded Coder Dictionary Definition
Between Models” on page 20-6.
• The migration process makes changes based on the active configuration set of the
model (see “Manage a Configuration Set” (Simulink)) at the time that you open the
Code Perspective. Before you open the Code Perspective, activate the configuration set
whose settings you want the migration process to use.

The process ignores settings in inactive configuration sets. If different configuration


sets of the model specify different settings, you must choose one set to migrate.

Considerations After Migrating


• In a branching hierarchy of referenced models and referenced data dictionaries, after
you or other users migrate referenced models in different branches, opening the Code
Perspective in a parent model can generate an error due to the presence of multiple
Embedded Coder Dictionaries in the data dictionary hierarchy. To resolve these errors,
use coder.dictionary.move and coder.dictionary.remove to transfer and
delete Embedded Coder Dictionaries until only one dictionary remains. Place the
remaining Embedded Coder Dictionary in a data dictionary at the bottom of the
hierarchy so that all of the models can access the memory section and function
template definitions.

For information about sharing an Embedded Coder Dictionary between models by


using referenced dictionaries, see “Share Embedded Coder Dictionary Definition
Between Models” on page 20-6.
• After you migrate a model, Embedded Coder ignores memory section and shared
utility settings in the configuration parameters. If you use set_param or get_param
to access these configuration parameter settings programmatically, the functions
generate warnings. To change or set these settings, use the Code Mapping Editor or
the equivalent programmatic interface as described in “Configure Default Code
Generation for Categories of Model Data and Functions” on page 21-7.

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

Configuring Data and Functions in


the Generated Code

• “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

Environment for Configuring Model Data and Functions


for Code Generation
When you generate code from a model, the code includes:

• Entry-point functions such as model_step, which your application code calls to


execute the model algorithm.
• Data such as signals, states, and parameters, which your application code can read
and write to.

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

standardization by customizing the Simulink development environment that engineers


use.

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.

Software Engineer: Configure Default Settings


For each category of data and functions in a model, such as root-level inputs, parameters,
and execution functions, you can specify default code generation settings. For example,
you can configure the generated code to conform to these objectives by default:

• 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.

To configure default settings, use the Code Mapping Editor.

Software Engineer: Override Default Settings


After using the Code Mapping Editor to configure model-wide default settings, you can
override the defaults for individual data elements and functions.

21-4
See Also

Override Defaults For Action


Data Use the Model Data Editor Code view. Apply a
setting in the Storage Class column. See
“Configure Data Properties by Using the Model
Data Editor” (Simulink).
Model entry-point functions Use the Model Interface dialog box. Open it from
model_step and modelinitialize the Code Generation > Interface pane in the
Model Configuration Parameters dialog box. See
“Customize Generated C Function Interfaces” on
page 29-2.

System Architect: Create Code Generation Definitions


Using the Code Mapping Editor and the Model Data Editor, application developers apply
code generation definitions, such as the built-in storage class ExportedGlobal, to model
data elements and functions. To standardize the code that you and your users generate
from multiple models, you can create and share custom definitions with meaningful
names. Creating custom definitions also enables you to achieve code generation
objectives that the built-in definitions cannot satisfy.

• 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

Configure Default Code Generation for Categories of


Model Data and Functions
Reduce the effort of preparing a model for code generation by specifying default
configurations for categories of data elements and functions across a model. Applying
default configurations can save time and reduce the risk of introducing errors in code,
especially for larger models and models from which you generate multi-instance code.

You can set a default code generation configuration for:

• 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.

Configure Default Data and Function Configurations in Model


Editing Environment
To specify default code generation configurations for model data and functions
interactively in Simulink model editing environment, use the Code Mapping Editor and
Property Inspector. When a model is in Code Perspective mode, the editor and inspector
are accessible. After preparing the model for code generation, the Embedded Coder
Quick Start tool places a model in Code Perspective mode. Alternatively, you can enable
Code Perspective mode from the Simulink Editor by doing one of the following:

• 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.

Configure Default Code Generation for Data


You configure default code generation for categories of data elements in a model by
associating the categories with storage classes and memory sections. Data elements are
grouped into these categories.

Model Element Category Description


Inports Root-level input ports of a model.
Outports Root-level output ports of a model.
Global parameters Parameters that are defined in the base workspace or in a
data dictionary. Multiple models in an application can use
these parameters.
Local parameters Parameters that are defined within a model, such as
parameters in the model workspace. Excludes model
arguments.
Global data stores Data stores that are defined by a signal object in the base
workspace or in a data dictionary. Multiple models in an
application can use these data stores.

21-8
Configure Default Code Generation for Categories of Model Data and Functions

Model Element Category Description


Shared local data stores Data Store Memory blocks with the block parameter
Share across model instances set. These data stores
are accessible only in the model where they are defined.
The data store value is shared across instances of the
model.
Internal data Local data, such as data stores, discrete block states,
block output signals, and zero-crossing signals.
Constants Constant-value block output and constant parameters in a
model.

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.

Before configuring default code generation settings for data, consider:

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.

In this example, the code generation requirements for data:

• Use project type definition DBL_FLOAT defined in header file exDblFloat.h.


• Get data element ex_input1 from header file exInDataMem.h. The data is used for
computing a value stored in memory, and then used in an if-else condition of a Switch
block.
• Get data elements ex_input2, ex_input3, and ex_input4 from header file
exInDataLut.h. The data is used in lookup tables Table1 and Table2.
• Data imported into the model from header files exInDataMem.h and exInDataLut.h
is of type DBL_FLOAT, a project standard.

21-10
Configure Default Code Generation for Categories of Model Data and Functions

• Parameter K1 must be tunable to enable calibration.


• Data store mode defines data that is shared within the model. The Logical Operator
block writes to the data store and a Rate Transition block reads from the data store.
• Data element X represents the delay for the Unit Delay block.
• Store data that is internal to the model, such as delay X, in a section of memory
labeled internalDataMem.
• Export output data declarations to header file exSysOut.h and definitions to
exSysOut.c.

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.

Set Up Example Environment

1 Copy these external source and header files from matlabroot/toolbox/rtw/


rtwdemos to a writable working folder. These files define and declare the external
data type and data that the generated code uses.

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

2 Open your copy of example model rtwdemo_configdefaults.

3 To gain access to the Code Mapping Editor, open the Code Perspective. Click Code >
C/C++ Code > Configure Model in Code Perspective.

Configure Default Settings for Inport Data

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 Default Settings for Inport In1

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

1 Open the Model Data Editor.


2 In the Source column, select In1.
3 Set the storage class for In1 to ImportFromFile.
4 Set Header File to inDataMem.h.
5 Return to the Code Mappings Editor by clicking the Code Mappings - C tab.

Configure Default Settings for Local Parameters

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 Optimizations From Eliminating Parameter From Generated Code

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 Memory Section for Internal Data

Define a memory section for storing the unit delay X, data that is internal to the model.

1 Return to the Code Mappings Editor.


2
Open the Embedded Coder Dictionary by clicking .
3 Click the Memory Sections tab.
4 Click Add.
5 In the new row at the bottom of the table, name the new memory section
internalDataMem. Also set:

• Pre Statement to #pragma start INTERNALDATA


• Post Statement to #pragma end INTERNALDATA
• Statements Surround to Group of variables
6 Close the dictionary.

21-13
21 Configuring Data and Functions in the Generated Code

Configure Default Memory Section for Internal Data

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.

Configure Default Settings for Outport Data

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.

Generate and Verify Code

• Use the code generation report to verify the following


code:rtwdemo_configdefaults_private.h includes header files that declare
external input data:
#include "exInDataMem.h"
#include "exInDataLut.h"
• rtwdemo_configdefaults.c initializes the gain variable K1 and uses the variable in
the model step function exFast_step1.
DBL_FLOAT K1 = 2.0;
.
.
.
void exFast_step1(void)
{
DBL_FLOAT rtb_Gain;

rtb_Gain = K1 * look1_binlc(ex_input2, rtCP_Table1_bp01Data,


rtCP_Table1_tableData, 10U);
.
.
.
}

• rtwdemo_configdefaults.c includes pragma control lines that define memory


sections for the local data store, unit delay, and constants.
#pragma start INTERNALDATA
BlockIO_rtwdemo_configdefaults B;
#pragma end INTERNALDATA

21-14
Configure Default Code Generation for Categories of Model Data and Functions

#pragma start INTERNALDATA


D_Work_rtwdemo_configdefaults DWork;
#pragma end INTERNALDATA

#pragma start INTERNALDATA


RT_MODEL_rtwdemo_configdefaults M_;
#pragma end INTERNALDATA

#pragma start INTERNALDATA


RT_MODEL_rtwdemo_configdefaults *const M = &M_;
#pragma end INTERNALDATA

• exSysOut.c includes an exported data definition for Out1.


#include "rtwtypes.h"
#include "rtwdemo_dataconfig_types.h"

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;

Configure Default Code Generation for Functions


Configure default code generation for a category of functions by using the Code
Mapping Editor to associate the category with a function customization template.

Model Function Description


Category
Initialize/Terminate Initialization and termination function code, such as
model_initialize and model_terminate.
Execution Execution code for a model, such as model_step and
model_reset.
Shared utility Code for shared utility functions.

A function customization template defines how the code generator produces code for a
category of functions. For a function category, you can define:

• A rule for naming functions


• A location in memory for function definitions (memory section)

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.

In this example, code generation requirments for entry-point functions:

• Store generated initialize and terminate functions in memory section


functionSlowMem and execution functions in memory section functionFastMem.
• Use the naming rule exSlow_$N to name initialize and terminate entry-point
functions. Use the naming rule exFast_$N to name execution functions.

To configure default code generation settings for the functions, use the Embedded
Coder Dictionary and Code Mapping Editor.

Open Model

Open the copy of example model rtwdemo_configdefaults that you previously


created.

Define Memory Sections

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:

• Pre Statement to #pragma start FASTMEM

21-17
21 Configuring Data and Functions in the Generated Code

• Post Statement to #pragma end FASTMEM


5 Click Add again. Name the memory section functionSlowMem. Then, set:

• Pre Statement to #pragma start SLOWMEM


• Post Statement to #pragma end SLOWMEM

Define Function Customization Templates

To configure categories of functions, define function customization templates. Unless you


define templates in the Embedded Coder Dictionary that are associated with a model, the
only available template is Default. Based on the requirements, in the dictionary, define
two function customization templates: one to specify the naming rule and memory section
for initialize and terminate functions and one to specify the naming rule and memory
section for execution functions.

1 In the Embedded Coder Dictionary, click the Function Customization Templates


tab.
2 Click Add.
3 In the new row of the table, name the new template exFastFunction. Then, set:

• 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:

• Function Name to exSlow_$N.


• Memory Section to functionSlowMem.

Configure Default Settings for Functions

1 To access the Code Mapping Editor, open the Code Perspective.


2 In the Code Mapping Editor, click the Function Defaults tab.
3 Configure the initialize and terminate entry-point functions. For category Initialize/
Terminate, from the template menu, exSlowFunction.
4 Configure the execution entry-point functions. For category Execution, select
template exFastFunction.

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.

Generate and Verify Code

Use the code generation report to verify the following code:

• 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 exFast_step2(void) /* Sample time: [1.5s, 0.0s] */


{
DWork.RateTransition1_Buffer0 = ((ex_input1 > 10.0) || (ex_input1 < -10.0));
}

#pragma end FASTMEM

#pragma start SLOWMEM

void exSlow_initialize(void)
{
/* (no initialization code required) */
}

#pragma end SLOWMEM


.
.
.

• To gain access to the entry-point function declarations in


rtwdemo_configdefaults.h, use the header file links in the report. Verify that the
correct pragma control statements surround the declarations. For example:
.
.
.

21-19
21 Configuring Data and Functions in the Generated Code

#pragma start SLOWMEM


extern void exSlow_initialize(void);
#pragma end SLOWMEM

#pragma start FASTMEM


extern void exFast_step0(void);
#pragma end SLOWMEM
.
.
.

Configure Default Data and Function Code Generation with


Definitions Stored in Shared Data Dictionary
You have the option of configuring default data and function code generation with
definitions that are set up in a Simulink data dictionary. A data dictionary enables sharing
of code definitions between models. Using definitions in a data dictionary, configure
default mappings:

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.

This example shows how to link model model rtwdemo_configdefaults to data


dictionary exSharedCodeDefs.sldd. That data dictionary includes Embedded Coder
Dictionary definitions for:

• Memory section internalDataMem with Pre Statement set to #pragma start


INTERNALDATA and Post Statement set to #pragma end INTERNALDATA.
• Memory section functionFastMem with Pre Statement set to #pragma start
FASTMEM and Post Statement set to #pragma end FASTMEM.
• Memory section functionSlowMem with Pre Statement set to #pragma start
SLOWMEM and Post Statement set to #pragma end SLOWMEM.
• Function customization template exFastFunction with function naming rule
exFast_$N and memory section functionFastMem
• Function customization template exSlowFunction with function naming rule
exSlow_$N and memory section functionSlowMem

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.

Link Model to Data Dictionary

1 Open model rtwdemo_configdefaults.


2 In the model window, select File > Model Properties > Link to Data Dictionary.
3 In the Model Properties dialog box, select Data Dictionary and click Browse.
4 Open the dictionary exSharedCodeDefs.sldd through the Open Data Dictionary
dialog box.
5 In the Model Properties dialog box, click OK. The Link Model to Data Dictionary
dialog box appears. Leave the option Migrate reference variables from base
workspace to dictionary 'sharedCodeDefs.sldd' selected. Click OK. Simulink links
the model to the dictionary and migrates design data from the base workspace to the
dictionary.
6 In the lower-left corner of the model, click the data dictionary badge. The dictionary
opens in Model Explorer.
7 In the Model Hierarchy pane, under exSharedCodeDefs, select Embedded Coder
Dictionary.
8 In the Dialog pane, click Open Embedded Coder Dictionary.
9 Verify that the dictionary includes the required code definitions.

Configure Default Categories for Code Generation

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.

Configure Default Data and Function Code Generation


Programmatically
This example shows how to configure default data and function code generation for
example model rtwdemo_configdefaults.The example uses the default mapping
programming interface to specify code generation requirements for model data and
functions. Use that interface to automate the configuration, or if you prefer to configure
models programmatically. For information about configuring the default data and funciton
code generation by using the Code Mapping Editor, see “Configure Default Code
Generation for Categories of Model Data and Functions” on page 21-7.

Open the Model

The model rtwdemo_configdefaults uses multiple execution rates and is configured


for single-instance usage.

open_system('rtwdemo_configdefaults')

21-22
Configure Default Code Generation for Categories of Model Data and Functions

Code Generation Requirements

For this example, the code generation requirements:

• 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:

• Memory sections internalDataMem, functionFastMem, and functionSlowMem.


• Function customization templates exFastFunction and exSlowFunction.

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');

Identify Category, Property, and Value Combinations To Set As Data Defaults

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()

ans = 1x8 cell array


Columns 1 through 4

{'Inports'} {'Outports'} {'GlobalParameters'} {'LocalParameters'}

Columns 5 through 7

{'SharedLocalDat...'} {'GlobalDataStores'} {'InternalData'}

Column 8

{'Constants'}

For data categories Inports, Outports, LocalParameters, and InternalData


identify the properties that you can set with calls to
coder.mapping.defaults.allowedProperties.
coder.mapping.defaults.allowedProperties('rtwdemo_configdefaults', 'Inports')

ans = 2x1 cell array


{'StorageClass'}
{'HeaderFile' }

coder.mapping.defaults.allowedProperties('rtwdemo_configdefaults', 'Outports')

ans = 4x1 cell array


{'StorageClass' }

21-24
Configure Default Code Generation for Categories of Model Data and Functions

{'HeaderFile' }
{'DefinitionFile'}
{'Owner' }

coder.mapping.defaults.allowedProperties('rtwdemo_configdefaults', 'LocalParameters')

ans = 1x1 cell array


{'StorageClass'}

coder.mapping.defaults.allowedProperties('rtwdemo_configdefaults', 'InternalData')

ans = 2x1 cell array


{'StorageClass' }
{'MemorySection'}

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:

• StorageClass with categories Inports, Outports, LocalParameters, and


InternalData
• MemorySection with InternalData

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

ans = 9x1 cell array


{'Default' }
{'ExportedGlobal' }
{'ImportedExtern' }
{'ImportedExternPointer'}
{'Volatile' }
{'ExportToFile' }
{'ImportFromFile' }
{'AutoScope' }
{'GetSet' }

coder.mapping.defaults.allowedValues('rtwdemo_configdefaults', 'Outports', 'StorageClas

21-25
21 Configuring Data and Functions in the Generated Code

ans = 9x1 cell array


{'Default' }
{'ExportedGlobal' }
{'ImportedExtern' }
{'ImportedExternPointer'}
{'Volatile' }
{'ExportToFile' }
{'ImportFromFile' }
{'AutoScope' }
{'GetSet' }

coder.mapping.defaults.allowedValues('rtwdemo_configdefaults', 'LocalParameters', 'Stor

ans = 14x1 cell array


{'Default' }
{'ExportedGlobal' }
{'ImportedExtern' }
{'ImportedExternPointer'}
{'Const' }
{'Volatile' }
{'ConstVolatile' }
{'Define' }
{'ImportedDefine' }
{'ExportToFile' }
{'ImportFromFile' }
{'FileScope' }
{'GetSet' }
{'CompilerFlag' }

coder.mapping.defaults.allowedValues('rtwdemo_configdefaults', 'InternalData', 'Storage

ans = 10x1 cell array


{'Default' }
{'ExportedGlobal' }
{'ImportedExtern' }
{'ImportedExternPointer'}
{'Volatile' }
{'ExportToFile' }
{'ImportFromFile' }
{'FileScope' }
{'AutoScope' }
{'GetSet' }

21-26
Configure Default Code Generation for Categories of Model Data and Functions

coder.mapping.defaults.allowedValues('rtwdemo_configdefaults', 'InternalData', 'MemoryS

ans = 5x1 cell array


{'None' }
{'MemVolatile' }
{'functionFastMem'}
{'functionSlowMem'}
{'internalDataMem'}

Identify Category, Property, and Value Combinations To Set As Function Defaults

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()

ans = 1x3 cell array


{'InitializeTermi...'} {'Execution'} {'SharedUtility'}

The categories that apply are InitializeTerminate and Execution.

For function categories InitializeTerminate and Execution, identify the properties


that you can set with calls to coder.mapping.defaults.allowedProperties.
coder.mapping.defaults.allowedProperties('rtwdemo_configdefaults', 'InitializeTerminate

ans = 1x1 cell array


{'FunctionCustomizationTemplate'}

You get the same output for category Execution.

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

ans = 3x1 cell array


{'Default' }
{'exSlowFunction'}
{'exFastFunction'}

The list of templates is the same for InitializeTerminate and Execution.

Set Relevant Category, Property, and Value Combinations

Set relevant category, property, and value combinations with calls to


coder.mapping.defaults.set.

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');

Verify Default Mappings

Verify default mappings with calls to coder.mapping.defaults.get.

coder.mapping.defaults.get('rtwdemo_configdefaults', 'Inports', 'StorageClass')

ans =
'ImportFromFile'

coder.mapping.defaults.get('rtwdemo_configdefaults', 'Inports', 'HeaderFile')

21-28
Configure Default Code Generation for Categories of Model Data and Functions

ans =
'exInDataLut.h'

coder.mapping.defaults.get('rtwdemo_configdefaults', 'Outports', 'StorageClass')

ans =
'ExportToFile'

coder.mapping.defaults.get('rtwdemo_configdefaults', 'Outports', 'HeaderFile')

ans =
'exSysOut.h'

coder.mapping.defaults.get('rtwdemo_configdefaults', 'Outports', 'DefinitionFile')

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 Header File Setting

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.

Create a handle to the output port of block In1.


portHandles = get_param('rtwdemo_configdefaults/In1', 'PortHandles');
outH = portHandles.Outport;

In the base workspace, create a temporary signal object.


temp_Obj = Simulink.Signal

temp_Obj =
Signal with properties:

CoderInfo: [1x1 Simulink.CoderInfo]


Description: ''
DataType: 'auto'
Min: []
Max: []
Unit: ''
Dimensions: -1
DimensionsMode: 'auto'
Complexity: 'auto'
SampleTime: -1
InitialValue: ''

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';

Define the instance-specific header file, exDataInMem.h, in the nested


Simulink.CoderInfo object by using the CustomAttributes property.

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

Unresolved Storage Classes, Function Customization


Templates, and Memory Sections
If someone removes the definition for a storage class, function customization template, or
memory section from the Embedded Coder Dictionary associated with a model, the Code
Mapping Editor identifies the definition as Unresolved. For example, this figure shows
that the function customization template for execution entry-point functions was removed
from the dictionary associated with the model.

To fix the unresolved code definition, do one of the following:

• 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.

Elimination of Parameters and Other Internal Data by


Optimizations
Code generation optimizations can eliminate data from the code, which means your
application code cannot interact with the data. For general information about data
elimination by optimizations, see “How Generated Code Stores Internal Signal, State, and
Parameter Data” on page 22-50.

The optimizations can eliminate data in these categories:

• Global parameters
• Local parameters
• Internal data

The optimizations cannot eliminate:

• Data in other categories.


• Data that the code needs for numeric accuracy, including most block states, which are
in the Internal data category.

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.

To prevent optimizations from eliminating individual data elements, explicitly apply a


storage class to the element by using the Model Data Editor. The storage class controls
the appearance of the data in the generated code. To force a data element to use the
default storage class that you specify in the Code Mapping Editor, explicitly apply the
storage class Model default. See “Choose a Storage Class for Controlling Data
Representation in the Generated Code” on page 22-69.

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:

• Structure-based built-in storage classes, Struct and BitField


• Package storage classes of type FlatStructure or Other (requires you to write
TLC code) , which you create with the Custom Storage Class Designer

.
• 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

Data Representation in Simulink


Coder

• “Configure Data Accessibility for Rapid Prototyping” on page 22-3


• “Access Signal, State, and Parameter Data During Execution” on page 22-7
• “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
• “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
• “Choose a Storage Class for Controlling Data Representation in the Generated Code”
on page 22-69
• “Use Storage Classes in Reentrant, Multi-Instance Models and Components”
on page 22-79
• “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements”
on page 22-81
• “Use Enumerated Data in Generated Code” on page 22-90
• “Data Stores in Generated Code” on page 22-100
• “Specify Single-Precision Data Type for Embedded Application” on page 22-111
• “Tune Phase Parameter of Sine Wave Block During Code Execution” on page 22-115
• “Switch Between Output Waveforms During Code Execution for Waveform Generator
Block” on page 22-117
• “Create Tunable Calibration Parameter in the Generated Code” on page 22-121
• “Limitations for Block Parameter Tunability in the Generated Code” on page 22-135
• “Code Generation of Parameter Objects With Expression Values” on page 22-139
• “Specify Instance-Specific Parameter Values for Reusable Referenced Model”
on page 22-142
• “Parameter Data Types in the Generated Code” on page 22-156
22 Data Representation in Simulink Coder

• “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
• “Organize Data into Structures in Generated Code” on page 22-177
• “Switch Between Sets of Parameter Values During Simulation and Code Execution”
on page 22-196
• “Design Data Interface by Configuring Inport and Outport Blocks” on page 22-206
• “Generate Efficient Code for Bus Signals” on page 22-212
• “Control Signal and State Initialization in the Generated Code” on page 22-216
• “Initialization of Signal, State, and Parameter Data in the Generated Code”
on page 22-228
• “Optimize Speed and Size of Signal Processing Algorithm by Using Fixed-Point Data”
on page 22-239
• “Optimize Generated Code Using Fixed-Point Data with Simulink®, Stateflow®, and
MATLAB®” on page 22-241
• “Declare Workspace Variables as Tunable Parameters Using the Model Parameter
Configuration Dialog Box” on page 22-243
• “Share Data Between Code Generated from Simulink, Stateflow, and MATLAB”
on page 22-247

22-2
Configure Data Accessibility for Rapid Prototyping

Configure Data Accessibility for Rapid Prototyping


As you iteratively develop a model, you capture the values of signals and states that
model execution generates. You also tune parameter values during execution to observe
the effect on the signals and states. You can then base your design decisions upon
analysis of these outputs. To access signal, state, and parameter data in a rapid
prototyping environment, you can configure the generated code to store the data in
addressable memory.

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.

Access Signal, State, and Parameter Data During Execution


For an example that shows how to configure data accessibility for rapid prototyping, see
“Access Signal, State, and Parameter Data During Execution” on page 22-7.

22-3
22 Data Representation in Simulink Coder

Configure Data Accessibility


Goal Considerations and More Information
Configure signals as Clear the model configuration parameter Signal storage reuse and
accessible and parameters set the configuration parameter Default parameter behavior to
as tunable by default Tunable. These settings prevent the elimination of storage for signals
and prevent parameter inlining. Each block parameter and signal line
appears in the generated code as a field of a structure. For more
information about these data 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.

For more information about Default parameter behavior, see


“Default parameter behavior” (Simulink Coder). For more information
about optimizations that eliminate storage for signals, see “How
Generated Code Stores Internal Signal, State, and Parameter Data” on
page 22-50 and “Minimize Computations and Storage for
Intermediate Results at Block Outputs” (Simulink Coder).
Preserve accessibility and You can generate more efficient code by selecting optimizations such
tunability of a data item as Signal storage reuse, but the code generator eliminates storage
after you select for as many data items as possible. To exclude individual data items
optimizations from the optimizations:

• Configure a signal as a test point (see “Configure Signals as Test


Points” (Simulink)) or apply a storage class such as
ExportedGlobal to the signal (see “Apply Storage Classes to
Individual Signal, State, and Parameter Data Elements” on page 22-
81). If you use test points, when you later configure the model for
efficient production code, you can subject all of the test-point
signals to optimizations by selecting the model configuration
parameter Ignore test point signals. Apply a storage class only
when you need to control the representation of the signal in the
code.
• Apply a storage class, such as ExportedGlobal, to states and
parameters. See “Apply Storage Classes to Individual Signal, State,
and Parameter Data Elements” on page 22-81.

22-4
Configure Data Accessibility for Rapid Prototyping

Goal Considerations and More Information


Represent a data item as a When you disable optimizations, signal lines, block states, and
separate global variable in parameters appear in the generated code as fields of structures. You
the generated code cannot control the names of the structures without Embedded Coder.
To instead store a data item in a separate global variable whose name,
file placement, and other characteristics you can control, apply a
storage class to a signal, state, or Simulink.Parameter object. See
“Apply Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 22-81.
Generate a standardized You can configure the generated code to contain extra code and files so
C-code interface for that you can access model data through standardized interfaces. For
accessing data more information, see “Exchange Data Between Generated and
External Code Using C API” on page 46-2.
Tune parameters and When you generate code and an external executable from a model, you
monitor signals during can simulate the model in external mode to communicate with the
external mode simulation running executable. You can tune parameters and monitor signals
during the simulation. However, in this simulation mode, parameter
tunability limitations that apply to code generation also apply to the
simulation. For information about the code generation limitations, see
“Limitations for Block Parameter Tunability in the Generated Code” on
page 22-135.

For information about external mode, see “Host-Target Communication


with External Mode Simulation” on page 44-2.
Tune parameters and If you have Simulink Real-Time, you can tune parameters and monitor
monitor signals with signals during execution of your real-time application. Make signals
Simulink Real-Time accessible and parameters tunable by clearing optimizations and
applying test points and storage classes. See “Parameter Tuning with
Simulink Real-Time Explorer” (Simulink Real-Time).

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

Access Signal, State, and Parameter Data During


Execution
As you iteratively develop a model, you capture output signal and state data that model
execution generates. You also tune parameter values during execution to observe the
effect on the outputs. You can then base your design decisions upon analysis of these
outputs. To access this signal, state, and parameter data in a rapid prototyping
environment, you can configure the generated code to store the data in addressable
memory.

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.

Explore Example Model

Run a script that prepares the model rtwdemo_basicsc for this example.

run(fullfile(matlabroot,'examples','simulinkcoder','main','prepare_rtwdemo_basicsc'));

Open the example model, 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')

Generate code from the model.

22-8
Access Signal, State, and Parameter Data During Execution

rtwbuild('rtwdemo_basicsc')

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: 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)

/* Block signals (default storage) */


typedef struct {
real32_T Table1; /* '<Root>/Table1' */
real32_T Gain; /* '<Root>/Gain' */
real32_T Delay; /* '<Root>/Delay' */
real32_T Table2; /* '<Root>/Table2' */
boolean_T RelOp1; /* '<Root>/RelOp1' */
boolean_T RelOp2; /* '<Root>/RelOp2' */
boolean_T LogOp; /* '<Root>/LogOp' */
} B_rtwdemo_basicsc_T;

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)

/* Parameters (default storage) */


struct P_rtwdemo_basicsc_T_ {
real_T K2; /* Variable: K2
* Referenced by: '<Root>/Stateflow Chart'
*/
real32_T LOWER; /* Variable: LOWER
* Referenced by: '<Root>/Constant2'
*/
real32_T T1Break[11]; /* Variable: T1Break
* Referenced by: '<Root>/Table1'

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)

/* Block signals (default storage) */


B_rtwdemo_basicsc_T rtwdemo_basicsc_B;

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

Exclude Data Items from Optimizations

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.

Select the optimizations that you previously cleared.

set_param('rtwdemo_basicsc','OptimizeBlockIOStorage','on')
set_param('rtwdemo_basicsc','LocalBlockOutputs','on')
set_param('rtwdemo_basicsc','DefaultParameterBehavior','Inlined')

In the model, select View > Model Data Editor.

In the Model Data Editor, inspect the Signals tab.

Set the Change view drop-down list to Instrumentation.

In the model, select the output signal of the Gain block.

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')

Inspect the Parameters tab.

In the model, select the Gain block.

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';

Generate code from the model.


rtwbuild('rtwdemo_basicsc')

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: rtwdemo_basicsc

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)

/* Block signals (default storage) */


typedef struct {
real32_T Gain; /* '<Root>/Gain' */
} B_rtwdemo_basicsc_T;

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)

/* Parameters (default storage) */


struct P_rtwdemo_basicsc_T_ {
real32_T K1; /* Variable: K1
* Referenced by: '<Root>/Gain'
*/
};

Access Data Through Generated Interfaces

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"

#define paramIdx 0 /* Index of the target parameter,


determined by inspecting the array of structures generated by the C API. */
#define sigIdx 0 /* Index of the target signal,
determined by inspecting the array of structures generated by the C API. */

void tuneFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr)


{
/* Take action with the parameter value only at
the beginning of simulation and at the 5-second mark. */
if (*tPtr == 0 || *tPtr == 5) {

/* Local variables to store information extracted from


the model mapping information (mmi). */
void** dataAddrMap;
const rtwCAPI_DataTypeMap *dataTypeMap;
const rtwCAPI_ModelParameters *params;
int_T addrIdx;
uint16_T dTypeIdx;
uint8_T slDataType;

/* Use built-in C API macros to extract information. */


dataAddrMap = rtwCAPI_GetDataAddressMap(mmi);
dataTypeMap = rtwCAPI_GetDataTypeMap(mmi);
params = rtwCAPI_GetModelParameters(mmi);
addrIdx = rtwCAPI_GetModelParameterAddrIdx(params,paramIdx);
dTypeIdx = rtwCAPI_GetModelParameterDataTypeIdx(params,paramIdx);
slDataType = rtwCAPI_GetDataTypeSLId(dataTypeMap, dTypeIdx);

/* Handle data types 'double' and 'int8'. */


switch (slDataType) {

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;
}
}
}
}

void logFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr)


{
/* Take action with the signal value only when
the simulation time is an integer value. */
if (*tPtr-(int_T)*tPtr == 0) {

/* Local variables to store information extracted from


the model mapping information (mmi). */
void** dataAddrMap;
const rtwCAPI_DataTypeMap *dataTypeMap;
const rtwCAPI_Signals *sigs;
int_T addrIdx;
uint16_T dTypeIdx;
uint8_T slDataType;

/* Use built-in C API macros to extract information. */


dataAddrMap = rtwCAPI_GetDataAddressMap(mmi);
dataTypeMap = rtwCAPI_GetDataTypeMap(mmi);
sigs = rtwCAPI_GetSignals(mmi);
addrIdx = rtwCAPI_GetSignalAddrIdx(sigs,sigIdx);
dTypeIdx = rtwCAPI_GetSignalDataTypeIdx(sigs,sigIdx);
slDataType = rtwCAPI_GetDataTypeSLId(dataTypeMap, dTypeIdx);

/* Handle data types 'double' and 'single'. */


switch (slDataType) {

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')

Load the Custom Code block library.

custcode

Add a System Outputs block to the model.

add_block('custcode/System Outputs','rtwdemo_basicsc/System Outputs')

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)

Generate code from the model.

rtwbuild('rtwdemo_basicsc')

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: 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)

/* Block output signal information */


static const rtwCAPI_Signals rtBlockSignals[] = {
/* addrMapIndex, sysNum, blockPath,
* signalName, portNumber, dataTypeIndex, dimIndex, fxpIndex, sTimeIndex
*/
{ 0, 0, TARGET_STRING("rtwdemo_basicsc/Gain"),
TARGET_STRING(""), 0, 0, 0, 0, 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)

/* user code (Output function Body) */

/* System '<Root>' */
{
rtwdemo_basicsc_U.input2++;
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
tuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
}

/* DataStoreWrite: '<Root>/DSWrite' incorporates:


* Constant: '<Root>/Constant1'
* Constant: '<Root>/Constant2'
* Inport: '<Root>/In1'
* Logic: '<Root>/LogOp'
* RelationalOperator: '<Root>/RelOp1'
* RelationalOperator: '<Root>/RelOp2'
*/
rtwdemo_basicsc_DW.mode = ((rtwdemo_basicsc_U.input1 > 10.0F) ||
(rtwdemo_basicsc_U.input1 < -10.0F));

/* Gain: '<Root>/Gain' incorporates:


* Inport: '<Root>/In2'
* Lookup_n-D: '<Root>/Table1'
*/
rtwdemo_basicsc_B.Gain = rtwdemo_basicsc_P.K1 * look1_iflf_binlx
(rtwdemo_basicsc_U.input2, rtCP_Table1_bp01Data, rtCP_Table1_tableData, 10U);

22-18
Access Signal, State, and Parameter Data During Execution

/* Chart: '<Root>/Stateflow Chart' */


/* Gateway: Stateflow Chart */
/* During: Stateflow Chart */
/* Entry Internal: Stateflow Chart */
/* Transition: '<S1>:5' */
if (rtwdemo_basicsc_DW.mode) {
/* Transition: '<S1>:6' */
/* Transition: '<S1>:2' */
rtwdemo_basicsc_DW.X = rtwdemo_basicsc_B.Gain;
} else {
/* Transition: '<S1>:4' */
}

/* Outport: '<Root>/Out1' incorporates:


* Chart: '<Root>/Stateflow Chart'
*/
/* Transition: '<S1>:3' */
rtwdemo_basicsc_Y.Out1 = (real32_T)(rtwdemo_basicsc_DW.X * 3.0);

/* Lookup_n-D: '<Root>/Table2' incorporates:


* Inport: '<Root>/In3'
* Inport: '<Root>/In4'
*/
rtwdemo_basicsc_DW.X = look2_iflf_binlx(rtwdemo_basicsc_U.input3,
rtwdemo_basicsc_U.input4, rtCP_Table2_bp01Data, rtCP_Table2_bp02Data,
rtCP_Table2_tableData, rtCP_Table2_maxIndex, 3U);

/* user code (Output function Trailer) */

/* 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));

/* signal main to stop simulation */


{ /* Sample time: [1.0s, 0.0s] */
if ((rtmGetTFinal(rtwdemo_basicsc_M)!=-1) &&
!((rtmGetTFinal(rtwdemo_basicsc_M)-rtwdemo_basicsc_M->Timing.taskTime0) >
rtwdemo_basicsc_M->Timing.taskTime0 * (DBL_EPSILON))) {

22-19
22 Data Representation in Simulink Coder

rtmSetErrorStatus(rtwdemo_basicsc_M, "Simulation finished");


}
}

/* Update absolute time for base rate */


/* The "clockTick0" counts the number of times the code of this task has
* been executed. The absolute time is the multiplication of "clockTick0"
* and "Timing.stepSize0". Size of "clockTick0" ensures timer will not
* overflow during the application lifespan selected.
* Timer of this task consists of two 32 bit unsigned integers.
* The two integers represent the low bits Timing.clockTick0 and the high bits
* Timing.clockTickH0. When the low bit overflows to 0, the high bits increment.
*/
if (!(++rtwdemo_basicsc_M->Timing.clockTick0)) {
++rtwdemo_basicsc_M->Timing.clockTickH0;
}

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;
}

/* Model initialize function */


void rtwdemo_basicsc_initialize(void)
{
/* Registration code */

/* initialize non-finites */
rt_InitInfAndNaN(sizeof(real_T));

/* initialize real-time model */


(void) memset((void *)rtwdemo_basicsc_M, 0,
sizeof(RT_MODEL_rtwdemo_basicsc_T));
rtmSetTFinal(rtwdemo_basicsc_M, 10.0);
rtwdemo_basicsc_M->Timing.stepSize0 = 1.0;

/* Setup for data logging */


{
static RTWLogInfo rt_DataLoggingInfo;
rt_DataLoggingInfo.loggingInterval = NULL;
rtwdemo_basicsc_M->rtwLogInfo = &rt_DataLoggingInfo;
}

/* Setup for data logging */

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
};

static int_T rt_LoggedOutputNumDimensions[] = {


1
};

static int_T rt_LoggedOutputDimensions[] = {


1
};

static boolean_T rt_LoggedOutputIsVarDims[] = {


0
};

static void* rt_LoggedCurrentSignalDimensions[] = {


(NULL)
};

22-21
22 Data Representation in Simulink Coder

static int_T rt_LoggedCurrentSignalDimensionsSize[] = {


4
};

static BuiltInDTypeId rt_LoggedOutputDataTypeIds[] = {


SS_SINGLE
};

static int_T rt_LoggedOutputComplexSignals[] = {


0
};

static RTWPreprocessingFcnPtr rt_LoggingPreprocessingFcnPtrs[] = {


(NULL)
};

static const char_T *rt_LoggedOutputLabels[] = {


"output" };

static const char_T *rt_LoggedOutputBlockNames[] = {


"rtwdemo_basicsc/Out1" };

static RTWLogDataTypeConvert rt_RTWLogDataTypeConvert[] = {


{ 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 }
};

static RTWLogSignalInfo rt_LoggedOutputSignalInfo[] = {


{
1,
rt_LoggedOutputWidths,
rt_LoggedOutputNumDimensions,
rt_LoggedOutputDimensions,
rt_LoggedOutputIsVarDims,
rt_LoggedCurrentSignalDimensions,
rt_LoggedCurrentSignalDimensionsSize,
rt_LoggedOutputDataTypeIds,
rt_LoggedOutputComplexSignals,
(NULL),
rt_LoggingPreprocessingFcnPtrs,

{ 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);

/* set currSigDims field */


rt_LoggedCurrentSignalDimensions[0] = &rt_LoggedOutputWidths[0];
}

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;

/* Initialize DataMapInfo substructure containing ModelMap for C API */


rtwdemo_basicsc_InitializeDataMapInfo();

/* Matfile logging */
rt_StartDataLoggingWithStartTime(rtwdemo_basicsc_M->rtwLogInfo, 0.0,
rtmGetTFinal(rtwdemo_basicsc_M), rtwdemo_basicsc_M->Timing.stepSize0,
(&rtmGetErrorStatus(rtwdemo_basicsc_M)));

/* Start for DataStoreMemory: '<Root>/Data Store Memory' */


rtwdemo_basicsc_DW.mode = false;

22-23
22 Data Representation in Simulink Coder

/* InitializeConditions for UnitDelay: '<Root>/Delay' */


rtwdemo_basicsc_DW.X = 0.0F;
}

/* Model terminate function */


void rtwdemo_basicsc_terminate(void)
{
/* (no terminate code required) */
}

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)

/* user code (Output function Trailer) */

/* 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

At the command prompt, run the generated executable rtwdemo_bascisc.exe.

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

Standard Data Structures in the Generated Code


By default, signal lines, block parameters, states, and other model data appear in the
generated code as fields of standard structures. For general information, see “How
Generated Code Stores Internal Signal, State, and Parameter Data” (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.

Data Structures Generated for a Model

Short Name of Structure Type Data Represented in the Structure


ExtU Data from root Inport blocks
ExtY Data from root Outport blocks
B Block output signals
ConstB Block outputs that have constant values
P Block parameters
ConstP Constant parameters
DW Discrete block states
XDis Status of enabled subsystems

For additional structures, see “System-generated identifiers” (Simulink Coder).

You can exclude data from appearing in these structures by using:

• 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

Control Characteristics of Data Structures (Embedded Coder)


To control the characteristics of the standard data structures, use the information in the
table.

Name How to Change Name


Structure types Specify a naming rule to use for all of the
types. Set a value for Configuration
Parameters > Global types.
Global structure variables Specify a naming rule with Configuration
Parameters > Global variables.
Names of structure fields By default, the name of each structure field
derives from the name of the data item in
the model (for example, the name of a block
state, which you specify by using the State
name block parameter). Specify a naming
rule with Configuration Parameters >
Field name of global types.
Data types of structure fields Use Simulink.AliasType objects and
data type replacement to rename primitive
types for the corresponding data items in
the model. See “Control Data Type Names
in Generated Code” on page 24-2.

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

Use the Real-Time Model Data Structure


The code generator uses the real-time model (RT_MODEL) data structure. This structure
is also referred to as the rtModel data structure. You can access rtModel data by using
a set of macros analogous to the ssSetxxx and ssGetxxx macros that S-functions use to
access SimStruct data, including noninlined S-functions compiled by the code
generator.

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

Macros for Accessing the Real-Time Model Data Structure

rtm Macro Syntax Description


rtmGetdX(rtm) Get the derivatives of block continuous states
rtmGetOffsetTimePtr(RT_MDL rtM) Return the pointer to vector that stores sample
time offsets of the model associated with rtM
rtmGetNumSampleTimes(RT_MDL rtM) Get the number of sample times that a block has
rtmGetPerTaskSampleHitsPtr(RT_MDL) Return a pointer to NumSampleTime ×
NumSampleTime matrix
rtmGetRTWExtModeInfo(RT_MDL rtM) Return an external mode information data
structure of the model (used internally for
external mode)
rtmGetRTWLogInfo(RT_MDL) Return a data structure used by code generator
logging (internal use only)
rtmGetRTWRTModelMethodsInfo(RT_MDL) Return a data structure of real-time model
methods information (internal use only)
rtmGetRTWSolverInfo(RT_MDL) Return data structure containing solver
information of the model (internal use only)
rtmGetSampleHitPtr(RT_MDL) Return a pointer to Sample Hit flag vector
rtmGetSampleTime(RT_MDL rtM, int TID) Get task sample time
rtmGetSampleTimePtr(RT_MDL rtM) Get pointer to a task sample time
rtmGetSampleTimeTaskIDPtr(RT_MDL rtM) Get pointer to a task ID
rtmGetSimTimeStep(RT_MDL) Return simulation step type ID
(MINOR_TIME_STEP, MAJOR_TIME_STEP)
rtmGetStepSize(RT_MDL) Return the fundamental step size of the model
rtmGetT(RT_MDL,t) Get the current simulation time
rtmSetT(RT_MDL,t) Set the time of the next sample hit
rtmGetTaskTime(RT_MDL,tid) Get the current time for the current task
rtmGetTFinal(RT_MDL) Get the simulation stop time
rtmSetTFinal(RT_MDL,finalT) Set the simulation stop time
rtmGetTimingData(RT_MDL) Return a data structure used by timing engine of
the model (internal use only)

22-30
Use the Real-Time Model Data Structure

rtm Macro Syntax Description


rtmGetTPtr(RT_MDL) Return a pointer to the current time
rtmGetTStart(RT_MDL) Get the simulation start time
rtmIsContinuousTask(rtm) Determine whether a task is continuous
rtmIsMajorTimeStep(rtm) Determine whether the simulation is in a major
step
rtmIsSampleHit(RT_MDL,tid) Determine whether the sample time is hit
rtmGetErrorStatus(rtm) Get the current error status
rtmSetErrorStatus(rtm,val) Set the current error status
rtmGetErrorStatusPointer(rtm) Return a pointer to the current error status
rtmGetStopRequested(rtm) Return whether a stop is requested
rtmGetBlockIO(rtm) Get the block I/O data structure
rtmSetBlockIO(rtm,val) Set the block I/O data structure
rtmGetContStates(rtm) Get the continuous states data structure
rtmSetContStates(rtm,val) Set the continuous states data structure
rtmGetDefaultParam(rtm) Get the default parameters data structure
rtmSetDefaultParam(rtm,val) Set the default parameters data structure
rtmGetPrevZCSigState(rtm) Get the previous zero-crossing signal state data
structure
rtmSetPrevZCSigState(rtm,val) Set the previous zero-crossing signal state data
structure
rtmGetRootDWork(rtm) Get the DWork data structure
rtmSetRootDWork(rtm,val) Set the DWork data structure
rtmGetU(rtm) Get the root inputs data structure (when root
inputs are passed as part of the model data
structure)
rtmSetU(rtm,val) Set the root inputs data structure (when root
inputs are passed as part of the model data
structure)

22-31
22 Data Representation in Simulink Coder

rtm Macro Syntax Description


rtmGetY(rtm) Get the root outputs data structure (when root
outputs are passed as part of the model data
structure)
rtmSetY(rtm,val) Set the root outputs data structure (when root
outputs are passed as part of the model data
structure)

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

How Generated Code Exchanges Data with an


Environment
To use the code that you generate from a model, you call the generated entry-point
functions such as step and initialize. The environment in which you call these
functions must provide input signal data and, depending on your application, scheduling
information. The generated algorithm then calculates output data that the calling
environment can use. The environment and the algorithm can exchange this data through
global variables or through formal parameters (arguments).

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:

• Write code that calls the generated code.


• Generate reusable (reentrant) code that you can call multiple times in a single
application.
• Integrate the generated code with other, external code in your application.

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.

Data Interfaces in the Generated Code


This example shows how the generated code exchanges data with an environment.

Explore Example Model

Open the example model rtwdemo_roll.

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')

Generate Nonreusable Code

Generate code from the model.

rtwbuild('rtwdemo_roll')

### Starting build procedure for model: rtwdemo_roll


### Successful completion of build procedure for model: 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)

/* External inputs (root inport signals with default storage) */


typedef struct {
real32_T Phi; /* '<Root>/Phi' */
real32_T Psi; /* '<Root>/Psi' */
real32_T Rate_FB; /* '<Root>/Rate_FB' */
real32_T TAS; /* '<Root>/TAS' */
boolean_T AP_Eng; /* '<Root>/AP_Eng' */
boolean_T HDG_Mode; /* '<Root>/HDG_Mode' */
real32_T HDG_Ref; /* '<Root>/HDG_Ref' */
real32_T Turn_Knob; /* '<Root>/Turn_Knob' */
} ExtU_rtwdemo_roll_T;

/* External outputs (root outports fed by signals with default storage) */


typedef struct {
real32_T Ail_Cmd; /* '<Root>/Ail_Cmd' */
} ExtY_rtwdemo_roll_T;

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)

/* Real-time Model Data Structure */


struct tag_RTM_rtwdemo_roll_T {
const char_T *errorStatus;
};

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)

/* Forward declaration for rtModel */


typedef struct tag_RTM_rtwdemo_roll_T RT_MODEL_rtwdemo_roll_T;

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)

/* External inputs (root inport signals with default storage) */


ExtU_rtwdemo_roll_T rtwdemo_roll_U;

/* External outputs (root outports fed by signals with default storage) */


ExtY_rtwdemo_roll_T rtwdemo_roll_Y;

/* 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

/* Model step function */


void rtwdemo_roll_step(void)

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).

rtwdemodbtype(file,'if (rtwdemo_roll_U.AP_Eng) {',' }',1,1)

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.

The model initialization function, rtwdemo_roll_initialize, initializes all of the input


and output data to zero. The function also initializes the error status. The function directly
accesses the global variables, which means the function is not reentrant.

rtwdemodbtype(file,'/* Model initialize function */',...


'rtmSetErrorStatus(rtwdemo_roll_M, (NULL));',1,1)

/* Model initialize function */


void rtwdemo_roll_initialize(void)

22-37
22 Data Representation in Simulink Coder

{
/* Registration code */

/* initialize error status */


rtmSetErrorStatus(rtwdemo_roll_M, (NULL));

rtwdemodbtype(file,' /* external inputs */',...


'/* SystemInitialize for Atomic SubSystem:',1,0)

/* external inputs */
(void)memset((void *)&rtwdemo_roll_U, 0, sizeof(ExtU_rtwdemo_roll_T));

/* external outputs */
rtwdemo_roll_Y.Ail_Cmd = 0.0F;

Generate Reusable Code

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')

Generate code from the model.


rtwbuild('rtwdemo_roll')

### Starting build procedure for model: rtwdemo_roll


### Successful completion of build procedure for model: rtwdemo_roll

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

/* Real-time Model Data Structure */


struct tag_RTM_rtwdemo_roll_T {
const char_T *errorStatus;
ExtU_rtwdemo_roll_T *inputs;
ExtY_rtwdemo_roll_T *outputs;
DW_rtwdemo_roll_T *dwork;
};

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)

/* Model data allocation function */


RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)

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)

/* Model step function */


void rtwdemo_roll_step(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

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)

DW_rtwdemo_roll_T *rtwdemo_roll_DW = ((DW_rtwdemo_roll_T *)


rtwdemo_roll_M->dwork);
ExtU_rtwdemo_roll_T *rtwdemo_roll_U = (ExtU_rtwdemo_roll_T *)

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.

rtwdemodbtype(file,' if (rtwdemo_roll_U->AP_Eng) {',...


' /* End of Switch: ''<Root>/EngSwitch'' */',1,1)

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;
}
}

/* End of Saturate: '<S1>/CmdLimit' */


/* End of Outputs for SubSystem: '<Root>/BasicRollMode' */
} else {
/* Sum: '<S1>/Sum2' incorporates:
* Constant: '<Root>/Zero'
* Outport: '<Root>/Ail_Cmd'
*/
rtwdemo_roll_Y->Ail_Cmd = 0.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

/* Model initialize function */


void rtwdemo_roll_initialize(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

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.

Configure Data Interface


To control the characteristics of the data interface in the generated code, see “Control
Data and Function Interface in Generated Code” on page 22-42.

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

Control Data and Function Interface in Generated Code


To use the code that you generate from a model, you call the generated entry-point
functions such as step and initialize. The calling environment and the generated
functions can exchange input and output data through global variables or through formal
parameters (arguments). This data and the exchange mechanisms constitute the
interfaces of the entry-point functions. For information about the default interfaces for
reentrant and nonreentrant models in the generated code, see “How Generated Code
Exchanges Data with an Environment” on page 22-33.

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).

Control Type Names, Field Names, and Variable Names of


Standard I/O Structures (Embedded Coder)
By default, for nonreentrant code, Inport blocks at the root level of the model appear in
the generated code as fields of a global structure variable. Similarly, Outport blocks
appear in a different structure. For reentrant code, depending on your setting for
Configuration Parameters > Code Generation > Interface > Pass root-level I/O as,
the code can also package input and output data into standard structures.

With Embedded Coder, you can control these names. See “Control Characteristics of Data
Structures (Embedded Coder)” (Simulink Coder).

Control Names of Generated Entry-Point Functions (Embedded


Coder)
To use the generated code, you write code that calls generated entry-point functions. For
example, entry-point functions include model_step, model_initialize, and top-level
functions generated from an export-function model. To control the names of the model
entry-point functions, choose one or both of these techniques, which require Embedded
Coder:

22-42
Control Data and Function Interface in Generated Code

• Specify a default naming rule for categories of entry-point functions by applying


function customization templates in the Code Mapping Tool. With this technique, the
naming rule applies to all of the functions in each category. For more information, see
“Configure Default Code Generation for Functions” on page 21-15.
• Apply function prototype control to individual functions. With this technique:

• 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.

Control Data Interface for Nonreentrant Code


When you set Configuration Parameters > Code Generation > Interface > Code
interface packaging to Nonreusable function (the default), the generated entry-
point functions are not reentrant. Typically, the functions exchange data with the calling
environment through direct access to global variables.

Configure Inport or Outport Block as Separate Global Variable

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.

For this technique, you must have Embedded Coder.


• To override the default for an individual block, apply a different storage class by using
other tools such as the Model Data Editor or the Property Inspector. See “Apply
Storage Classes to Individual Signal, State, and Parameter Data Elements” (Simulink
Coder).

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).

Configure Generated Code to Read or Write to Global Variables Defined by


External Code

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.

Package Multiple Inputs or Outputs into Custom Structure

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.

Configure Inport or Outport Block as Function Call (Embedded Coder)

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.

Pass Inputs and Outputs Through Function Arguments (Embedded Coder)

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.

Configure Referenced Model Inputs and Outputs as Global Variables (void-void)

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

Control Data Interface for Reentrant Code


When you set Configuration Parameters > Code Generation > Interface > Code
interface packaging to Reusable function, the generated entry-point functions are
reentrant. The functions exchange data with the calling environment through formal
parameters (arguments). By default, each root-level Inport and Outport block appears in
the generated code as a separate argument instead of a field of the standard I/O
structures.

• To reduce the number of arguments, see “Reduce Number of Arguments by Using


Structures” (Simulink Coder).
• To control the data types of the arguments, see “Control Data Types of Arguments”
(Simulink Coder).

Prevent Unintended Changes to the Interface


Some changes that you make to a model change the signatures of the entry-point
functions in the generated code. For example, if you change the name of the model, the
names of the functions can change. If you configure the model code to exchange data
through arguments, when you add or remove Inport or Outport blocks or change the
names of the blocks, the corresponding arguments can change.

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

Reduce Number of Arguments by Using Structures


Reducing the number of arguments of a function can improve the readability of the code
and reduce consumption of stack memory. To create a structure argument that can pass
multiple pieces of data at one time, use any of these techniques:

• 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).

Control Data Types of Arguments


You can configure the generated entry-point functions to exchange data through
arguments. For a scalar or array argument, to control the name of the primitive data type,
use a Simulink.AliasType object to either set the data type of the corresponding block
or to configure data type replacements for the entire model. These techniques require
Embedded Coder. For more information, see “Control Data Type Names in Generated
Code” on page 24-2.

Promote Data Item to the Interface


By default, the code generator assumes that Inport and Outport blocks at the root level of
the model constitute the data interface of the model. You can promote an arbitrary signal,
block parameter, or block state to the interface so that other systems and components can
access it. See “Promote Internal Data to the Interface” on page 22-63.

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

How Generated Code Stores Internal Signal, State, and


Parameter Data
To calculate outputs from inputs, the generated code stores some internal data in global
memory. A signal that does not connect to a root-level input or output (Inport or Outport
block) is internal data.

Internal data can also include:

• 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

Internal Data in the Generated Code


This example shows how the generated code stores internal data such as block states.

Explore Example Model

Open the example model rtwdemo_roll.

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')

Generate Nonreusable Code

Set these configuration parameters:

• Set Default parameter behavior to Tunable.


• Clear Signal storage reuse.

set_param('rtwdemo_roll','DefaultParameterBehavior','Tunable',...
'OptimizeBlockIOStorage','off')

Generate code from the model.

rtwbuild('rtwdemo_roll')

### Starting build procedure for model: rtwdemo_roll


### Successful completion of build procedure for model: 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)

/* Block signals (default storage) */


typedef struct {
real32_T phiCmd; /* '<Root>/ModeSwitch' */
real32_T Abs; /* '<S3>/Abs' */
real32_T FixPtUnitDelay1; /* '<S7>/FixPt Unit Delay1' */
real32_T Xnew; /* '<S7>/Enable' */
real32_T TKSwitch; /* '<S3>/TKSwitch' */
real32_T RefSwitch; /* '<S3>/RefSwitch' */

22-52
How Generated Code Stores Internal Signal, State, and Parameter Data

real32_T Integrator; /* '<S1>/Integrator' */


real32_T DispLimit; /* '<S1>/DispLimit' */
real32_T Sum; /* '<S1>/Sum' */
real32_T DispGain; /* '<S1>/DispGain' */
real32_T RateLimit; /* '<S1>/RateLimit' */
real32_T Sum1; /* '<S1>/Sum1' */
real32_T RateGain; /* '<S1>/RateGain' */
real32_T Sum2; /* '<S1>/Sum2' */
real32_T CmdLimit; /* '<S1>/CmdLimit' */
real32_T IntGain; /* '<S1>/IntGain' */
real32_T hdgError; /* '<S2>/Sum' */
real32_T DispGain_a; /* '<S2>/DispGain' */
real32_T Product; /* '<S2>/Product' */
boolean_T NotEngaged; /* '<S3>/NotEngaged' */
boolean_T TKThreshold; /* '<S3>/TKThreshold' */
boolean_T RefThreshold2; /* '<S3>/RefThreshold2' */
boolean_T RefThreshold1; /* '<S3>/RefThreshold1' */
boolean_T Or; /* '<S3>/Or' */
boolean_T NotEngaged_e; /* '<S1>/NotEngaged' */
} B_rtwdemo_roll_T;

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)

/* 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;

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

rtwdemodbtype(file,'/* Real-time Model Data Structure */',...


'/* Block parameters (default storage) */',1,0)

/* Real-time Model Data Structure */


struct tag_RTM_rtwdemo_roll_T {
const char_T *errorStatus;
};

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)

/* Forward declaration for rtModel */


typedef struct tag_RTM_rtwdemo_roll_T RT_MODEL_rtwdemo_roll_T;

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)

/* Block signals (default storage) */


B_rtwdemo_roll_T rtwdemo_roll_B;

/* Block states (default storage) */


DW_rtwdemo_roll_T rtwdemo_roll_DW;

/* External inputs (root inport signals with default storage) */


ExtU_rtwdemo_roll_T rtwdemo_roll_U;

/* External outputs (root outports fed by signals with default storage) */


ExtY_rtwdemo_roll_T rtwdemo_roll_Y;

/* 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)

/* Model step function */


void rtwdemo_roll_step(void)

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;
}

if (rtwdemo_roll_DW.Integrator_DSTATE >= rtwdemo_roll_P.intLim) {


rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.intLim;
} else {
if (rtwdemo_roll_DW.Integrator_DSTATE <= rtwdemo_roll_P.Integrator_LowerSat)
{
rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.Integrator_LowerSat;
}
}

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

The model initialization function rtwdemo_roll_initialize initializes all of the


internal data to zero. The function also initializes the error status by calling a specialized
macro function. The initialization function directly accesses the global variables, which
means that the function is not reentrant.
rtwdemodbtype(file,'/* Model initialize function */',...
'sizeof(DW_rtwdemo_roll_T));',1,1)

/* Model initialize function */


void rtwdemo_roll_initialize(void)
{
/* Registration code */

/* initialize error status */


rtmSetErrorStatus(rtwdemo_roll_M, (NULL));

/* 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)

/* SystemInitialize for Atomic SubSystem: '<Root>/RollAngleReference' */


/* InitializeConditions for UnitDelay: '<S7>/FixPt Unit Delay1' */
rtwdemo_roll_DW.FixPtUnitDelay1_DSTATE = rtwdemo_roll_P.LatchPhi_vinit;

/* End of SystemInitialize for SubSystem: '<Root>/RollAngleReference' */

/* SystemInitialize for Atomic SubSystem: '<Root>/BasicRollMode' */


/* InitializeConditions for DiscreteIntegrator: '<S1>/Integrator' */
rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.Integrator_IC;
rtwdemo_roll_DW.Integrator_PrevResetState = 0;

22-56
How Generated Code Stores Internal Signal, State, and Parameter Data

/* End of SystemInitialize for SubSystem: '<Root>/BasicRollMode' */


}

Generate Reusable Code

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')

Generate code from the model.


rtwbuild('rtwdemo_roll')

### Starting build procedure for model: rtwdemo_roll


### Successful completion of build procedure for model: rtwdemo_roll

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)

/* Real-time Model Data Structure */


struct tag_RTM_rtwdemo_roll_T {
const char_T *errorStatus;
B_rtwdemo_roll_T *blockIO;
P_rtwdemo_roll_T *defaultParam;
ExtU_rtwdemo_roll_T *inputs;
ExtY_rtwdemo_roll_T *outputs;
boolean_T paramIsMalloced;
DW_rtwdemo_roll_T *dwork;
};

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)

/* Model data allocation function */


RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)

The model step function accepts an argument that represents the real-time model data
structure.

rtwdemodbtype(file,'/* Model step function */','void rtwdemo_roll_step',1,1)

/* Model step function */


void rtwdemo_roll_step(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

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)

P_rtwdemo_roll_T *rtwdemo_roll_P_e = ((P_rtwdemo_roll_T *)


rtwdemo_roll_M->defaultParam);
B_rtwdemo_roll_T *rtwdemo_roll_B = ((B_rtwdemo_roll_T *)
rtwdemo_roll_M->blockIO);
DW_rtwdemo_roll_T *rtwdemo_roll_DW = ((DW_rtwdemo_roll_T *)
rtwdemo_roll_M->dwork);
ExtU_rtwdemo_roll_T *rtwdemo_roll_U = (ExtU_rtwdemo_roll_T *)
rtwdemo_roll_M->inputs;
ExtY_rtwdemo_roll_T *rtwdemo_roll_Y = (ExtY_rtwdemo_roll_T *)
rtwdemo_roll_M->outputs;

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

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_e->Integrator_IC;
}

if (rtwdemo_roll_DW->Integrator_DSTATE >= rtwdemo_roll_P_e->intLim) {


rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P_e->intLim;
} else {
if (rtwdemo_roll_DW->Integrator_DSTATE <=
rtwdemo_roll_P_e->Integrator_LowerSat) {
rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P_e->Integrator_LowerSat;
}
}

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)

/* Model initialize function */


void rtwdemo_roll_initialize(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

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.

Eliminate Internal Data with Code Generation Optimizations

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')

Generate code from the model.

rtwbuild('rtwdemo_roll')

### Starting build procedure for model: rtwdemo_roll


### Successful completion of build procedure for model: 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)

/* 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;

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)

/* Update for DiscreteIntegrator: '<S1>/Integrator' incorporates:


* Gain: '<S1>/IntGain'
*/
rtwdemo_roll_DW.Integrator_DSTATE += 0.5F * rtb_TKSwitch * 0.025F;
if (rtwdemo_roll_DW.Integrator_DSTATE >= 5.0F) {
rtwdemo_roll_DW.Integrator_DSTATE = 5.0F;

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.

Local Variables in the Generated Code


When you select the optimization Configuration Parameters > Enable local block
outputs, the code generator attempts to yield more efficient code by representing
internal signals as local variables instead of fields of a global structure. If the memory
consumed by local variables risks exceeding the stack space available on your target
hardware, consider indicating the maximum stack size by setting Configuration
Parameters > Maximum stack size (bytes). For more information, see “Maximum
stack size (bytes)” (Simulink Coder).

Appearance of Test Points in the Generated Code


A test point is a signal that is stored in a unique memory location. For information about
including test points in your model, see “Test Points” (Simulink).

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.

If you have Embedded Coder:

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.

Appearance of Workspace Variables in the Generated Code


Workspace variables are variables that you use to specify block parameter values in a
model. Workspace variables include numeric MATLAB variables and
Simulink.Parameter objects that you store in a workspace, such as the base
workspace, or in a data dictionary.

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

Promote Internal Data to the Interface


By default, the code generator assumes that other systems and components in your
application do not need to access internal data. For example, internal data are subject to
optimizations that can eliminate them from the generated code. For prototyping and
testing purposes, you can access internal data by clearing the optimizations or by
configuring test points and applying storage classes (see “Configure Data Accessibility for
Rapid Prototyping” on page 22-3). For optimized production code, configure individual
data items to appear in the generated code as part of the model interface.

Data That You Can Promote

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:

• A global symbol, such as a global variable or a call to a specialized function


• A formal parameter (argument) of the generated entry-point functions

The table shows the mechanisms that each category of data can use to participate in the
interface.

Category of Data Appear as Global Symbol Appear as Argument of


Entry-Point Function
Root-level Inport or Outport Only for a nonreentrant Yes.
block model.
Signal connecting two Only for a nonreentrant Only for a reentrant model
blocks model. and only as a field of a
structure.

Alternatively, connect the


signal to a root-level
Outport block.
Block state Only for a nonreentrant Only for a reentrant model
model. and only as a field of a
structure.

22-63
22 Data Representation in Simulink Coder

Category of Data Appear as Global Symbol Appear as Argument of


Entry-Point Function
Data store such as a Data Yes. Only for a reentrant model
Store Memory block and only as a field of a
structure.
Block parameter or Yes. Only as a field of a
parameter object such as structure.
Simulink.Parameter

Single-Instance Algorithm

For a single-instance algorithm (you set Code interface packaging to Nonreusable


function), apply storage classes directly to individual data items by using the Model
Data Editor or the Property Inspector. With a directly applied storage class, a data item
appears in the code as a global symbol such as a global variable. The storage class also
prevents optimizations from eliminating storage for the data item.

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).

Control Default Representation of Internal Data (Embedded


Coder)
By default, the code generator aggregates internal data that optimizations cannot
eliminate, such as most state data, into standard structures such as the DWork structure.
With Embedded Coder, you can control how the generated code stores this data.

Control Placement of Data in Memory by Inserting Pragmas

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.

Organize Data into Structures According to Subcomponents

• 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

• Set Configuration Parameters > Model Referencing > Total number of


instances allowed per top model to One. For more information, see “Code
Generation of Referenced Models” on page 4-2.
• Set Total number of instances allowed per top model to Multiple and create
a structured storage class by using an Embedded Coder Dictionary. Then, apply the
storage class to categories of data by using the Code Mapping Editor. To create a
storage class, see “Define Storage Classes, Memory Sections, and Function
Templates for Software Architecture” on page 20-2. To apply the storage class to
categories of data, see “Configure Default Code Generation for Data” on page 21-8.

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.

Create Separate Global Variables Instead of Structure Fields

To make a category of internal data appear in the generated code as separate,


unstructured global variables instead of fields of a standard data structure, apply an
unstructured storage class to the data category by using the Code Mapping Editor. For
example, apply the storage class ExportedGlobal. However, if you generate multi-
instance, reentrant code by setting the configuration parameter Code interface
packaging to a value other than Nonreusable function, you cannot use this
technique for some categories of data (see “Use Storage Classes in Reentrant, Multi-
Instance Models and Components” (Simulink Coder)).

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

Choose a Storage Class for Controlling Data


Representation in the Generated Code
A storage class is a code generation setting that you apply to model data, such as signals,
block parameters, and states. Use storage classes to control the appearance of data
elements 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

Storage Class Name Description


Auto Auto is the default storage class setting for
each data element in a model. The data
element is subject to code generation
optimizations, which can eliminate the
element from the code or change the
representation of the element. For
information about these optimizations, such
as those on the Configuration
Parameters > Code Generation >
Optimization pane, see “How Generated
Code Stores Internal Signal, State, and
Parameter Data” (Simulink Coder).

Optimizations cannot eliminate some data,


such as most block states, from the code.
This remaining data acquire the
appropriate default storage class that you
specify with the Code Mapping Editor (see
“Configure Default Code Generation for
Data” on page 21-8—requires Embedded
Coder). If you leave the storage class
setting in the Code Mapping Editor at the
default value, Default, the data element
appears as a field of the appropriate
standard data structure (see “How
Generated Code Stores Internal Signal,
State, and Parameter Data” on page 22-50).

If optimizations cannot eliminate the data


element, the name of the element in the
code is based on naming rules that you
specify with model configuration
parameters (see “Identifier Format Control”
on page 39-22—requires Embedded
Coder).

Use this storage class to enable


optimizations to operate on the data

22-70
Choose a Storage Class for Controlling Data Representation in the Generated Code

Storage Class Name Description


element, potentially generating more
efficient code.
Model default The data element acquires the
corresponding default storage class that
you specify with the Code Mapping Editor.
The name of the data element in the code is
the same as the name in the model.

Use this storage class to prevent


optimizations from eliminating storage for a
data element (see “How Generated Code
Stores Internal Signal, State, and
Parameter Data” (Simulink Coder)).
ExportedGlobal Generate a global variable definition and
declaration. The name of the variable is the
name of the data element. The code
declares the variable in the generated file
model.h, which you can include
(#include) in your external code.
ImportedExtern Generate code that reads from and writes
to a global variable defined by your external
code. The generated code declares the
variable in the generated file
model_private.h so that the model
entry-point functions can read and write to
the variable.

Use this storage class to make a data


element in a model represent a global
variable that your external code defines.
The generated algorithmic code uses the
variable without defining it.

22-71
22 Data Representation in Simulink Coder

Storage Class Name Description


ImportedExternPointer Generate code that reads from and writes
to a global pointer variable defined by your
external code. The generated code declares
the variable in the generated file
model_private.h and reads and writes to
the data by dereferencing the pointer.

Use this storage class when your external


code defines a data element and provides a
pointer for accessing that data.

If you have Embedded Coder, you can choose additional built-in storage classes, shown in
the next table.

Storage Class Description Use for Signal or Use for


Name State Data Parameter Data
BitField Generate a structure that stores Yes Yes
Boolean data in named bit fields. For
an example, see “Bitfields” on page 14-
89.

You cannot use this storage class in the


Code Mapping Editor.

22-72
Choose a Storage Class for Controlling Data Representation in the Generated Code

Storage Class Description Use for Signal or Use for


Name State Data Parameter Data
CompilerFlag Supports preprocessor conditionals No Yes
defined via compiler flag or option. See
“Generate Preprocessor Conditionals
for Variant Systems” on page 15-35.

If you build the generated code by


using Embedded Coder (you clear
Configuration Parameters >
Generate code only), to specify the
compiler option, you can 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).
Const Generate a global variable definition No Yes
and declaration with the const type
qualifier.
ConstVolatile Generate a global variable definition No Yes
and declaration with the const and
volatile type qualifiers. For an
example, see “Type Qualifiers” on page
14-14.
Define Generate a macro (#define directive) No Yes
such as #define myParam 5. For an
example, see “Macro Definitions
(#define)” on page 14-71.
ExportToFile Generate a global variable definition Yes Yes
and declaration. You can specify the
names of the files that define and
declare the variable.

22-73
22 Data Representation in Simulink Coder

Storage Class Description Use for Signal or Use for


Name State Data Parameter Data
FileScope Generate a global variable definition Yes Yes
and declaration with the static type
qualifier. In the generated code, the
scope of the variable is limited to the
current file, which is typically
model.c.

In a model reference hierarchy, if a


referenced model uses a parameter
object (such as
Simulink.Parameter) that you
create in the base workspace or a data
dictionary, you cannot apply
FileScope to the object. As a
workaround, move the parameter
object into the model workspace of the
referenced model. Then, you can use
FileScope.
GetSet Generate code that interacts with data Yes Yes
by calling your custom accessor
functions. Your external code defines
the data and provides the function
definitions. For examples, see “Access
Data Through Functions with Custom
Storage Class GetSet” on page 26-42.
ImportedDefine Generate code that uses a macro No Yes
(#define directive) defined in a
header file in your external code. For
an example, see “Macro Definitions
(#define)” on page 14-71.
ImportFromFile Generate code that reads from and Yes Yes
writes to a global variable defined by
your external code. Similar to
ExportToFile, but the generated
code does not define the variable.

22-74
Choose a Storage Class for Controlling Data Representation in the Generated Code

Storage Class Description Use for Signal or Use for


Name State Data Parameter Data
Reusable Generate more efficient code that Yes No
stores intermediate calculations of a
data path (a series of connected
blocks) in a single, reused global
variable. For an example, see “Specify
Buffer Reuse by Using Simulink.Signal
Objects” on page 58-19.

You can apply this storage class only to


a Simulink.Signal object that
represents multiple signal lines in a
model.
Struct Generate a global structure whose Yes Yes
name you can specify. For examples,
see “Organize Parameter Data into a
Structure by Using the Struct Custom
Storage Class” on page 26-23 and
“Structures of Signals” on page 14-81.

You cannot use this storage class in the


Code Mapping Editor.
Volatile Generate a global variable definition Yes Yes
and declaration with the volatile
type qualifier.
ParamStruct Generate global structures that No Yes
contain parameter data. In a hierarchy
of components (referenced models or
atomic subsystems), you can use this
storage class to create a
corresponding hierarchy of parameter
structures. This storage class appears
only in the Code Mapping Editor for
the data category called Local
parameters.

22-75
22 Data Representation in Simulink Coder

Storage Class Description Use for Signal or Use for


Name State Data Parameter Data
SignalStruct Generate global structures that Yes No
contain signal or state data. In a
hierarchy of components (referenced
models or atomic subsystems), you can
use this storage class to create a
corresponding hierarchy of signal and
state structures. This storage class
appears only in the Code Mapping
Editor.
Localizable For signals, if possible, generate Yes (signals not No
variables that are local to functions states)
rather than in global storage.
Generating local variables prevents
the code generator from implementing
optimizations that remove the
variables from the generated code. For
an example, see “Generate Local
Variables with Localizable Custom
Storage Class” on page 26-94.

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).

Specify File Names and Other Data Attributes With Storage


Class (Embedded Coder)
After you apply some storage classes, such as ExportToFile, you can specify additional
settings such as declaration (header) and definition file names. In the Code Mapping
Editor, to access these additional settings, you use the Property Inspector.

With other storage classes, you cannot specify additional settings.

• 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.

Specify Default #include Syntax for Header Files That Declare


Data (Embedded Coder)
To control the file placement of a data item, such as a signal line or block state, in the
generated code, you can apply a storage class to the data item (see “Apply Custom
Storage Classes to Individual Signal, State, and Parameter Data Elements” on page 26-
19). You then use the Header file custom attribute to specify the generated or external
header file that contains the declaration of the data.

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>.

Storage Class Limitations


• When you use storage classes in the Code Mapping Editor (Embedded Coder), some
limitations apply. See “Limitations” on page 21-33.
• Data objects cannot use an Embedded Coder storage class and a multiword data type.
• The Fcn block does not support parameters with an Embedded Coder storage class in
code generation.
• For Embedded Coder storage classes in models that use referenced models:

• 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

• If a parameter object exists in the base workspace or a data dictionary, and a


referenced model uses the object, you cannot apply the storage class FileScope.
As a workaround, move the object into the model workspace of the referenced
model. Then, you can use FileScope.
• You cannot apply the storage class FileScope to data items used by a data exchange
interface (C API, external mode, or ASAP2) or MAT-file logging. File-scoped data is not
externally accessible.

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

Use Storage Classes in Reentrant, Multi-Instance Models


and Components
The code that you generate from a model or component (referenced model or subsystem)
is multi-instance code if it allows your application to maintain multiple independent
instances of the component during execution. For example, you can generate reentrant,
multi-instance code from an entire model by setting the model configuration parameter
Code interface packaging to Reusable function. For general information about
multi-instance models and components, see “Code Reuse” (Simulink Coder).

Under some circumstances, applying storage classes can:

• Prevent you from generating multi-instance code.


• Cause some data elements to appear in the generated code as singletons, which
means that each instance of the model or component directly accesses the same
shared, global data, creating dependencies between the instances.

To avoid errors and unexpected generation of single-instance code and singleton data,
observe the guidelines and limitations below.

Directly Applied Storage Classes


When you apply a storage class directly to a data element (see “Apply Storage Classes to
Individual Signal, State, and Parameter Data Elements” (Simulink Coder)):

• 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.

Storage Classes Applied by Default


When you apply a default storage class by using the Code Mapping Editor (see “Configure
Default Code Generation for Data” on page 21-8—requires Embedded Coder):

• For these data categories, you can generate only singleton data:

• Local parameters
• Global parameters

22-79
22 Data Representation in Simulink Coder

• Global data stores


• Shared local data stores
• For these data categories, you can generate only instance-specific data, which means
each instance of the model or component operates on a separate copy of the data:

• 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

Apply Storage Classes to Individual Signal, State, and


Parameter Data Elements
A storage class is a code generation setting that you apply to a data item (signal, block
parameter, or state) in a model. When you directly apply it to a data item, a storage class:

• 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).

Directly apply storage classes to individual data items to:

• Tune parameters and monitor signals and states during execution.


• Configure data placement in memory through memory sections.
• Generate code that exchanges data (for example, global variables) with your external
code.

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.

Apply Storage Classes to Data Items


This example shows how to apply storage classes to a signal, a block state, and a block
parameter in a model.

Explore Example Model

Open the example model rtwdemo_roll.

open_system('rtwdemo_roll')

22-81
22 Data Representation in Simulink Coder

Navigate into the BasicRollMode subsystem.


open_system('rtwdemo_roll/BasicRollMode')

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

The subsystem contains a Constant block labeled UpThr.

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.

Apply Storage Classes

Navigate to the root level of the model.

Select View > Model Data Editor.

To see the data items in the subsystems, activate the Change scope button.

Select the Signals tab.

Set the Change view drop-down list to Code.

In the Filter contents box, enter integrator.

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

Select the States tab.

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.

Set the Change view drop-down list to Design.

In the Filter contents box, enter UpThr.

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';

Generate and Inspect Code

Generate code from the model.

set_param('rtwdemo_roll','SystemTargetFile','grt.tlc')
rtwbuild('rtwdemo_roll')

### Starting build procedure for model: rtwdemo_roll


### Successful completion of build procedure for model: 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)

/* Exported block signals */


real32_T mySignal; /* '<S1>/Integrator' */

/* Exported block parameters */


real32_T UpThr = 6.0F; /* Variable: UpThr
* Referenced by: '<S3>/UpThr'
*/

/* Exported block states */


real32_T myState; /* '<S1>/Integrator' */

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.

Built-In Storage Classes You Can Choose


The default storage class setting for a data item is Auto, which means the code generator
determines how the item appears in the code. For a list of built-in storage classes that you
can choose, see “Choose a Storage Class for Controlling Data Representation in the
Generated Code” (Simulink Coder).

22-85
22 Data Representation in Simulink Coder

Decide Where to Store Storage Class Specification


For each individual signal or state data item (including Data Store Memory blocks) to
which you directly apply a storage class, Simulinkstores your storage class specification
either in the model file or in the properties of a signal data object (Simulink.Signal),
which you create in the base workspace, a model workspace, or a data dictionary. To
apply a storage class to a block parameter, you must create a parameter data object (such
as Simulink.Parameter) and specify the storage class in the object.

• 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

Techniques to Apply Storage Classes Interactively


To apply storage classes to multiple data items in a list that you can search, sort, and
filter, use the Model Data Editor (View > Model Data Editor) as shown in “Apply
Storage Classes to Data Items” on page 22-81.

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.

Techniques to Apply Storage Classes Programmatically


• For a block parameter, use set_param to set the value of the parameter. Use other
commands to create and configure the properties of the required parameter object.
For an example, see “Create Tunable Calibration Parameter in the Generated Code” on
page 22-121.
• For a signal, use get_param or find_system to return a handle to the block port
that generates the signal. Use the parameters of the handle to name the signal, then
apply the storage class directly (see “Apply Storage Class Directly to Signal Line”
(Simulink Coder)) or configure the signal to acquire settings, including the storage
class, from a signal object (see “Use Data Objects in Simulink Models” (Simulink)).
• For an Inport block, configure the signal line that exits the block. For an Outport
block, configure the block or the signal line that enters the block. For an example, see
“Design Data Interface by Configuring Inport and Outport Blocks” on page 22-206.
• For a block state, use set_param to interact with the block. Name the state, then
apply the storage class directly (see “Apply Storage Class Directly to Block State”
(Simulink Coder)) or configure the state to acquire the storage class from a signal
object (see “Use Data Objects in Simulink Models” (Simulink)).

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).

Apply Storage Class Directly to Signal Line

This example shows how to programmatically apply a storage class directly to a signal
line.

1 Open the example model rtwdemo_secondOrderSystem.

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.

Apply Storage Class Directly to Block State

This example shows how to programmatically apply a storage class to a block state.

1 Open the example model rtwdemo_basicsc.

rtwdemo_basicsc
2 Name the state of the Delay block as myState.

set_param('rtwdemo_basicsc/Delay','StateName','myState')

22-88
See Also

3 Set the storage class of the state to ExportedGlobal.

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.

Parameter Object Configuration Quick Reference Diagram


This diagram shows the code generation and storage class options that control the
representation of parameter objects in the generated code.

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

Use Enumerated Data in Generated Code


In this section...
“Enumerated Data Types” on page 22-90
“Specify Integer Data Type for Enumeration” on page 22-90
“Customize Enumerated Data Type” on page 22-92
“Control Enumerated Type Implementation in Generated Code” on page 22-96
“Type Casting for Enumerations” on page 22-98
“Enumerated Type Limitations” on page 22-99

Enumerated Data Types


Enumerated data is data that is restricted to a finite set of values. An enumerated data
type is a MATLAB class that defines a set of enumerated values. Each enumerated value
consists of an enumerated name and an underlying integer which the software uses
internally and in generated code. The following is a MATLAB class definition for an
enumerated data type named BasicColors, which is used in the examples in this
section.
classdef BasicColors < Simulink.IntEnumType
enumeration
Red(0)
Yellow(1)
Blue(2)
end
end

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).

Specify Integer Data Type for Enumeration


When you specify a data type for your enumeration, you can:

• Control the size of enumerated data types in the generated code by specifying a
superclass.

22-90
Use Enumerated Data in Generated Code

• Reduce RAM/ROM usage.


• Improve code portability.
• Improve integration with legacy code.

You can specify any of these integer data types:

• int8
• uint8
• int16
• uint16
• int32
• Simulink.IntEnumType. Specify values in the range of the signed integer for your
hardware platform.

Use a Class Definition in a MATLAB File

To specify an integer data type size, derive your enumeration class from the integer data
type.

classdef Colors < int8


enumeration
Red(0)
Green(1)
Blue(2)
end
end

The code generator generates this code:


typedef int8_T Colors;

#define Red ((Colors)0)


#define Green ((Colors)1)
#define Blue ((Colors)2)

Use the Function Simulink.defineIntEnumType

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 code generator generates this code:

typedef int8_T Colors;

#define Red ((Colors)0)


#define Green ((Colors)1)
#define Blue ((Colors)2)

Customize Enumerated Data Type


When you generate code from a model that uses enumerated data, you can implement
these static methods to customize the behavior of the type during simulation and in
generated code:

• getDefaultValue — Specifies the default value of the enumerated data type.


• getDescription — Specifies a description of the enumerated data type.
• getHeaderFile — Specifies a header file where the type is defined for generated
code.
• getDataScope — Specifies whether generated code exports or imports the
enumerated data type definition to or from a separate header file.
• addClassNameToEnumNames — Specifies whether the class name becomes a prefix in
generated code.

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

Static Method Purpose Default Value Custom Return Value


Without
Implementing
Method
getDefaultValue Specifies the default First member specified A character vector
enumeration member in the enumeration containing the name of
for the class. definition an enumeration
member in the class
(see “Instantiate
Enumerations”
(Simulink)).
getDescription Specifies a description '' A character vector
of the enumeration containing the
class. description of the type.
getHeaderFile Specifies the name of a '' A character vector
header file. The method containing the name of
getDataScope the header file that
determines the defines the enumerated
significance of the file. type.

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

Static Method Purpose Default Value Custom Return Value


Without
Implementing
Method
getDataScope Specifies whether 'Auto' One of: 'Auto',
generated code exports 'Exported', or
or imports the 'Imported'.
definition of the
enumerated data type.
Use the method
getHeaderFile to
specify the generated
or included header file
that defines the type.
addClassNameToEnum Specifies whether to false true or false.
Names prefix the class name in
generated code.

Specify a Description

To specify a description for an enumerated data type, include this method in the
methods(Static) section of the enumeration class:

function retVal = getDescription()


% GETDESCRIPTION Optional description of the data type.
retVal = 'description';
end

Substitute a MATLAB character vector for description. The generated code that
defines the enumerated type includes the specified description.

Import Type Definition in Generated Code

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

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 = 'Imported';
end

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 create a Simulink enumeration that corresponds to your existing C-code enumeration,


use the Simulink.importExternalCTypes function.

Export Type Definition in Generated Code

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

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 = 'exported_enum_type.h';
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

Add Prefixes To Class Names

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.

Control Enumerated Type Implementation in Generated Code


Suppose that you define an enumerated type BasicColors. You can specify that the
generated code implement the type definition using:

• 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

Implement Enumerated Type Using enum Block

To implement the type definition using an enum block:

• 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

Implement Enumerated Type Using a Specific Integer Type

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_

typedef int8_T BasicColors;

#define Red ((BasicColors)0) /* Default value */


#define Yellow ((BasicColors)1)
#define Blue ((BasicColors)2)

22-97
22 Data Representation in Simulink Coder

#endif

By default, the generated file model_types.h contains enumerated type definitions.

Type Casting for Enumerations


Safe Casting

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.

Enable and Disable Safe Casting

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.

Safe Cast Function in Generated Code

This example shows how the safe cast function int32_T


ET08_safe_cast_to_BasicColors for the enumeration BasicColors appears in
generated code when generated for 32-bit hardware.

static int32_T ET08_safe_cast_to_BasicColors(int32_T input)


{
int32_T output;
/* Initialize output value to default value for BasicColors (Red) */

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.

Enumerated Type Limitations


• Generated code does not support logging enumerated data.

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

Data Stores in Generated Code


In this section...
“About Data Stores” on page 22-100
“Generate Code for Data Store Memory Blocks” on page 22-100
“Storage Classes for Data Store Memory Blocks” on page 22-101
“Data Store Buffering in Generated Code” on page 22-103
“Data Stores Shared by Instances of a Reusable Model” on page 22-106
“Structures in Generated Code Using Data Stores” on page 22-107

About Data Stores


A data store contains data that is accessible in a model hierarchy at or below the level in
which the data store is defined. Data stores can allow subsystems and referenced models
to share data without having to use I/O ports to pass the data from level to level. See
“Data Stores with Data Store Memory Blocks” (Simulink) for information about data
stores in Simulink. This section provides additional information about data store code
generation.

Generate Code for Data Store Memory Blocks


To control the code generated for a Data Store Memory block, apply a storage class to the
data store. You can associate a Data Store Memory block with a signal object that you
store in a workspace or data dictionary, and control code generation for the block by
applying the storage class to the object:

1 In the model, select View > Model Data Editor.


2 In the Model Data Editor, select the Data Stores tab.
3 Begin editing the name of the target Data Store Memory block by clicking the
corresponding row in the Name column.
4
Next to the name, click the button and select Create and Resolve.
5 In the Create New Data dialog box, set Value to Simulink.Signal. Optionally, use
the Location drop-down list to choose a workspace for storing the resulting
Simulink.Signal object.

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.

The property dialog box for the object opens.


7 Use the Storage class drop-down list to apply the target storage class.

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.

Storage Classes for Data Store Memory Blocks


You can control how Data Store Memory blocks in your model are stored and represented
in the generated code by assigning storage classes and type qualifiers. You do this in
almost exactly the same way you assign storage classes and type qualifiers for block
states.

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.

Storage Class Declaration Code


Auto or Model default In model.h model_DWork.myData =
rtb_SineWave;
(when Code Mapping Editor typedef struct
specifies Default storage D_Work_tag
class) {
real_T myData;
}
D_Work;

In model.c or model.cpp
/* Block states (auto storage) */
D_Work model_DWork;

ExportedGlobal In model.c or model.cpp myData = rtb_SineWave;

/* Exported block states */


real_T myData;

In model.h
extern real_T myData;

ImportedExtern In model_private.h myData = rtb_SineWave;

extern real_T myData;

ImportedExternPointer In model_private.h (*myData) = rtb_SineWave;

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.

Data Store Buffering in Generated Code


A Data Store Read block is a nonvirtual block that copies the value of the data store to its
output buffer when it executes. Since the value is buffered, downstream blocks connected
to the output of the data store read utilize the same value, even if a Data Store Write
block updates the data store in between execution of two of the downstream blocks.

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:

The following execution order applies:

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.

The next figure shows another example:

In this example, the following execution order applies:

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.

Data Stores Shared by Instances of a Reusable Model


You can use a data store to share a piece of data between the instances of a reusable
referenced model (see “Specify Reusability of Referenced Models” (Simulink)) or a model
that you configure to generate reentrant code (by setting the configuration parameter

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.

Structures in Generated Code Using Data Stores


If you use more than one data store to provide global access to multiple signals in
generated code, you can combine the signals into a single structure variable by using one
data store. This combination of signal data can help you integrate the code generated
from a model with other existing code that requires the data in a structure format.

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.

Explore Example Model

1 Open the example model ex_bus_struct_in_code.

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 Data Store

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.

1 Open the Bus Editor tool.

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.

Write to Data Store Elements

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.

1 Open the Biomass Calc subsystem.


2 Delete the Data Store Memory block BioBTURate.
3 In the block dialog box for the Data Store Write block, set Data store name to
Raw_BTU_Data.

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.

5 Modify the Gas Calc and Coal Calc subsystems similarly.

• Delete the Data Store Memory block in each subsystem.


• In each Data Store Write block dialog box, set Data store name to
Raw_BTU_Data.
• In the Gas Calc subsystem, use the Data Store Write block to write to the data
store element GasBTU. In the Coal Calc subsystem, write to the element
CoalBTU.

22-109
22 Data Representation in Simulink Coder

Generate Code with Data Store Structure

1 Generate code for the example model.


2 In the code generation report, view the file ex_bus_struct_in_code_types.h.
The code defines a structure that corresponds to the bus type Raw_BTU_Rate.

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

Specify Single-Precision Data Type for Embedded


Application
When you want code that uses only single precision, such as when you are targeting a
single-precision processor, you can use model configuration parameters and block
parameters to prevent the introduction of double in the model.

To design and validate a single-precision model, see “Validate a Floating-Point Embedded


Model” (Simulink). If you have Fixed-Point Designer, you can use the Single Precision
Converter app (see “Single-Precision Design for Simulink” (Fixed-Point Designer)).

Use single Data Type as Default for Underspecified Types


This example shows how to avoid introducing a double-precision data type in code
generated for a single-precision hardware target.

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.

Explore Example Model

Open the example model rtwdemo_underspecified_datatype and configure it to show the


generated names of blocks.

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.

Generate Code with double as Default Data Type

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')

Generate code from the model.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_underspecified_datatype


### Successful completion of build procedure for model: rtwdemo_underspecified_datatype

22-112
Specify Single-Precision Data Type for Embedded Application

In the code generation report, view the file rtwdemo_underspecified_datatype.h.


The code uses the double data type to define the variables In2, In3, and In4 because
the Inport data types are underspecified in the model.
cfile = fullfile('rtwdemo_underspecified_datatype_grt_rtw',...
'rtwdemo_underspecified_datatype.h');
rtwdemodbtype(cfile,...
'/* External inputs (root inport signals with default storage) */',...
'/* External outputs (root outports fed by signals with default storage) */',...
1, 0);

/* External inputs (root inport signals with default storage) */


typedef struct {
int8_T In1; /* '<Root>/In1' */
real_T In2; /* '<Root>/In2' */
real_T In3; /* '<Root>/In3' */
real_T In4; /* '<Root>/In4' */
} ExtU_rtwdemo_underspecified_d_T;

Generate Code with single as Default Data Type

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.

Alternatively, enable the optimization at the command prompt.


set_param(model, 'DefaultUnderspecifiedDataType', 'single');

Generate code from the model.


rtwbuild(model)

### Starting build procedure for model: rtwdemo_underspecified_datatype


### Successful completion of build procedure for model: rtwdemo_underspecified_datatype

In the code generation report, view the file rtwdemo_underspecified_datatype.h.


The code uses the single data type to define the variables In2, In3, and In4.
rtwdemodbtype(cfile,...
'/* External inputs (root inport signals with default storage) */',...
'/* External outputs (root outports fed by signals with default storage) */',...
1, 0);

/* External inputs (root inport signals with default storage) */

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

Tune Phase Parameter of Sine Wave Block During Code


Execution
Under certain conditions, you cannot configure the Phase parameter of a Sine Wave
block to appear in the generated code as a tunable global variable (for more information,
see the block reference page). This example shows how to generate code so that you can
tune the phase during execution.

Create the model ex_phase_tunable by using a Digital Clock block.

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')

Generate code from the model.

rtwbuild('ex_phase_tunable')

### Starting build procedure for model: ex_phase_tunable


### Successful completion of code generation for model: 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)

/* Outport: '<Root>/Out1' incorporates:


* DigitalClock: '<Root>/Digital Clock'
* Sin: '<Root>/Sine Wave'
*/

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

Switch Between Output Waveforms During Code


Execution for Waveform Generator Block
This example shows how to generate code that enables you to switch between stimulus
waveforms during code execution.

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.

Create the model ex_switch_waveform.

open_system('ex_switch_waveform')

In the Waveform Generator block, configure this waveform:

square(amp,10,0,dutyCycle)

In the base workspace, create the variables amp and 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)

Set the model configuration parameter Default parameter behavior to Tunable.


set_param('ex_switch_waveform','DefaultParameterBehavior','Tunable')

Generate code from the model.


rtwbuild('ex_switch_waveform')

### Starting build procedure for model: ex_switch_waveform


### Successful completion of code generation for model: ex_switch_waveform

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)

/* Parameters (default storage) */


struct P_ex_switch_waveform_T_ {
real_T WaveformGeneratorStimulus_Selec;/* Mask Parameter: WaveformGeneratorStimulus_S
* Referenced by: '<S1>/Switch'
*/
real_T GainControlSystem_Gain; /* Expression: 3.5
* Referenced by: '<Root>/Gain (Control System)'
*/
};

The file ex_switch_waveform_data.c defines a global structure variable and initializes


the field value to 1. This value represents the baseline waveform.
file = fullfile('ex_switch_waveform_grt_rtw','ex_switch_waveform_data.c');
rtwdemodbtype(file,'/* Block parameters (default storage) */','};',1,1)

/* Block parameters (default storage) */

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;
}

/* End of MultiPortSwitch: '<S1>/MultiportSwitch' */

/* Outport: '<Root>/Out1' incorporates:


* Gain: '<Root>/Gain (Control System)'

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

Create Tunable Calibration Parameter in the Generated


Code
A calibration parameter is a value stored in global memory that an algorithm reads for
use in calculations but does not write to. Calibration parameters are tunable because you
can change the stored value during algorithm execution. You create calibration
parameters so that you can:

• 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.

In Simulink, create a Simulink.Parameter object to represent a calibration parameter.


You use the parameter object to set block parameter values, such as the Gain parameter
of a Gain block. To control the representation of the parameter object in the generated
code, you apply a storage class to the object.

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.

Represent Block Parameter as Tunable Global Variable


This example shows how to create tunable parameter data by representing block
parameters as global variables in the generated code.

Configure Block Parameter by Using Parameter Object

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, select View > Model Data Editor.

In the Model Data Editor, inspect the Parameters tab.

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.

Alternatively, use these commands at the command prompt:


set_param('rtwdemo_paraminline/G2','Gain','myOtherGain')
myOtherGain = Simulink.Parameter(-2);
myOtherGain.CoderInfo.StorageClass = 'ExportedGlobal';

Generate and Inspect Code

Generate code from the model.


rtwbuild('rtwdemo_paraminline')

### Starting build procedure for model: rtwdemo_paraminline


### Successful completion of build procedure for model: rtwdemo_paraminline

The generated file rtwdemo_paraminline.h contains extern declarations of the global


variables myGainParam and myOtherGain. You can include (#include) this header file
so that your code can read and write the value of the variable during execution.
file = fullfile('rtwdemo_paraminline_grt_rtw','rtwdemo_paraminline.h');
rtwdemodbtype(file,...
'extern real_T myGainParam;','Referenced by: ''<Root>/G2''',1,1)

extern real_T myGainParam; /* Variable: myGainParam


* Referenced by: '<Root>/G1'
*/
extern real_T myOtherGain; /* Variable: myOtherGain
* Referenced by: '<Root>/G2'

The file rtwdemo_paraminline.c allocates memory for and initializes myGainParam


and myOtherGain.
file = fullfile('rtwdemo_paraminline_grt_rtw','rtwdemo_paraminline.c');
rtwdemodbtype(file,...
'/* Exported block parameters */','Referenced by: ''<Root>/G2''',1,1)

/* Exported block parameters */

22-123
22 Data Representation in Simulink Coder

real_T myGainParam = 2.0; /* Variable: myGainParam


* Referenced by: '<Root>/G1'
*/
real_T myOtherGain = -2.0; /* Variable: myOtherGain
* Referenced by: '<Root>/G2'

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)

/* Model step function */


void rtwdemo_paraminline_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Gain: '<Root>/G1'
* Gain: '<Root>/G2'
* Inport: '<Root>/In1'
* Sum: '<Root>/Sum'
*/
rtwdemo_paraminline_Y.Out1 = myGainParam * rtwdemo_paraminline_U.In1 +
myOtherGain * -75.0;
}

Apply Storage Class When Block Parameter Refers to Numeric


MATLAB Variable
If you use a numeric variable to set the value of a block parameter, you cannot apply a
storage class to the variable. As a workaround, you can convert the variable to a
parameter object, and then apply a storage class to the object. To convert the variable to
a parameter object, choose one of these techniques:

• 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.

You can also use this technique in the Model Explorer.


• Use the Data Object Wizard (see “Create Data Objects for a Model Using Data Object
Wizard” (Simulink)). In the Wizard, select the Parameters check box. The Wizard

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.

Create Storage Class That Represents Calibration Parameters


(Embedded Coder)
This example shows how to create a storage class that yields a calibration parameter in
the generated code. The storage class causes each parameter object
(Simulink.Parameter) to appear as a global variable with special decorations such as
keywords and pragmas.

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)

const volatile float param1 = 3.0F;


const volatile float param2 = 5.0F;
const volatile float param3 = 7.0F;

#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.

1 Set your current MATLAB folder to a writable location.


2 Copy the +SimulinkDemos package folder into your current folder. Name the copy
+myPackage.

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.

Create Storage Class and Memory Section

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.

Set Default Parameter Object to myPackage.Parameter

To make applying the storage class easier, use the Model Explorer to change the default
parameter object from Simulink.Parameter to myPackage.Parameter.

1 At the command prompt, open the Model Explorer.

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.

Apply Storage Class

In the example model rtwdemo_roll, the BasicRollMode subsystem represents a PID


controller. Configure the P, I, and D parameters as calibration parameters.

22-127
22 Data Representation in Simulink Coder

1 Open the model.

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.

The Model Data Editor converts the workspace variables to myPackage.Parameter


objects. Now, you can apply a storage class to the objects.
10 In the Storage Class column for any of the rows, select CalParam.

Configure Generation of ASAP2 Interface

Configure the model to generate a2l files. Select Configuration Parameters > Code
Generation > Interface > ASAP2 interface.

Generate and Inspect Code

1 Generate code from the model.


2 In the code generation report, inspect the calPrms.c file. The file defines the
calibration parameters.

/* Exported data definition */


#pragma SEC(CALPRM)

/* Definition for custom storage class: CalParam */


const volatile real32_T dispGain = 0.75F;
const volatile real32_T intGain = 0.5F;
const volatile real32_T rateGain = 2.0F;

22-128
Create Tunable Calibration Parameter in the Generated Code

#pragma SEC()

The file calPrms.h declares the parameters.


3 Inspect the interface file rtwdemo_roll.a2l. The file contains information about
each parameter, for example, for dispGain.

/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

Initialize Parameter Value From System Constant or Other


Macro (Embedded Coder)
You can generate code that initializes a tunable parameter with a value calculated from
some system constants (macros). For example, you can generate this code, which
initializes a tunable parameter totalVol with a value calculated from macros
numVessels and vesInitVol:

#define numVessels 16
#define vesInitVol 18.2

double totalVol = numVessels * vesInitVol;

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:

1 Create parameter objects that represent the system constants.

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.

totalVol.Value = slexpr('numVessels * vesInitVol');


5 Use totalVol to set block parameter values in your model. The code that you
generate from the model initializes the tunable parameter with a value based on the
system constants.

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).

Code Generation Impact of Storage Location for Parameter


Objects
You can create a parameter object in the base workspace, a model workspace, or a data
dictionary. However, when you end your MATLAB session, variables in the base
workspace are deleted. To determine where to store parameter objects and other
variables that a model uses, see “Determine Where to Store Variables and Objects for
Simulink Models” (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.

If you store an AUTOSAR.Parameter object in a model workspace, the code generator


ignores the storage class that you specify for the object.

Configure Accessibility of Signal Data


When you tune the value of a parameter during algorithm execution, you monitor or
capture output signal values to analyze the effect of the tuning. To represent signals in
the generated code as accessible data, you can use techniques such as test points and
storage classes. See “Configure Data Accessibility for Rapid Prototyping” on page 22-3.

Programmatic Interfaces for Tuning Parameters


You can configure the generated code to include:

22-131
22 Data Representation in Simulink Coder

• A C application programming interface (API) for tuning parameters independent of


external mode. The generated code includes extra code so that you can write your own
code to access parameter values. See “Exchange Data Between Generated and
External Code Using C API” on page 46-2.
• A Target Language Compiler API for tuning parameters independently of external
mode. See “Parameter Functions” (Simulink Coder).

Set Tunable Parameter Minimum and Maximum Values


It is a best practice to specify minimum and maximum values for tunable parameters.

You can specify these minimum and maximum values:

• 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).

Considerations for Other Modeling Goals

Goal Considerations and More Information


Apply storage type qualifiers If you have Embedded Coder, to generate the storage type
const and volatile qualifiers, see “Protect Global Data with const and volatile
Keywords” on page 30-17.
Prevent name clashes between If you have Embedded Coder, use the storage class FileScope or
parameters in different a similar storage class that you create. See “Choose a Storage
components by applying the Class for Controlling Data Representation in the Generated Code”
keyword static on page 22-69.
Generate ASAP2 (a2l) You can generate an a2l file that uses the ASAP2 standard to
description describe your calibration parameters. For more information, see
“Define ASAP2 Information for Parameters and Signals” on page
47-4.

22-132
See Also

Goal Considerations and More Information


Generate AUTOSAR (arxml) If you have Embedded Coder, you can generate an arxml file that
description describes calibration parameters used by models that you
configure for the AUTOSAR standard. See “Model AUTOSAR
Calibration Parameters and Lookup Tables”.
Store lookup table data for To store lookup table data for calibration according to the ASAP2
calibration or AUTOSAR standards (for example, STD_AXIS, COM_AXIS, or
CURVE), you can use Simulink.LookupTable and
Simulink.Breakpoint objects in lookup table blocks. However,
some limitations apply. See Simulink.LookupTable.

To work around the limitations of Simulink.LookupTable and


Simulink.Breakpoint objects, use Simulink.Parameter and
AUTOSAR.Parameter objects instead. See “Define ASAP2
Information for Parameters and Signals” on page 47-4 and
“Configure STD_AXIS and COM_AXIS Lookup Tables for AUTOSAR
Measurement and Calibration”.
Use pragmas to store If you have an Embedded Coder license, to generate code that
parameter data in specific includes custom pragmas, use custom storage classes and memory
memory locations sections. See “Control Data and Function Placement in Memory by
Inserting Pragmas” on page 30-2.

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

Limitations for Block Parameter Tunability in the


Generated Code
A block parameter, MATLAB variable, or Simulink.Parameter object is tunable if it
appears in the generated code as data stored in memory, such as a global variable. For
example, when you apply the storage class ExportedGlobal to a parameter object, the
parameter object appears tunable in the generated code. When you set Default
parameter behavior to Tunable, MATLAB variables and parameter objects appear
tunable in the generated code. By definition, model arguments also appear tunable.

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.

Tunable Expression Limitations


You can specify block parameter values as expressions that use Simulink.Parameter
objects or workspace variables. For example, you can use the expression 5 *
gainParam. For general information about using expressions to set block parameter
values, see “Use Mathematical Expressions, MATLAB Functions, and Custom Functions”
(Simulink). For limitations with respect to expressions that you use to set the values of
Simulink.Parameter objects, see “Code Generation of Parameter Objects With
Expression Values” (Simulink Coder).

A tunable workspace variable is a Simulink.Parameter object or workspace variable


that appears tunable in the generated code. For example, an object or variable is tunable
if you apply a storage class other than Auto or if you set Default parameter behavior to
Tunable.

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.

Category Operators or Functions


1 + - .* ./ < > <= >= == ~= & |
2 * /
3 abs, acos, asin, atan, atan2, boolean, ceil, cos, cosh, exp,
floor, log, log10, sign, sin, sinh, sqrt, tan, tanh, single,
int8, int16, int32, uint8, uint16, uint32
4 : .^ ^ [] {} . \ .\ ' .' , ;

• Use operators from category 1 without loss of tunability.


• Use operators from category 2 in expressions as long as at least one operand is a
scalar. For example, scalar/scalar and scalar/matrix operand combinations are
supported, but matrix/matrix combinations are not supported.
• You can use tunable workspace variables as arguments for the functions in
category 3. If you use other functions, the code generator removes the tunability of
the arguments.
• The operators in category 4 are not supported.
• The Fcn and If blocks do not support tunable expressions for code generation or in
referenced models.
• You can write mask initialization code that creates and modifies variables. If you use
those variables in an expression, the expression is not tunable.
• You can specify any data type for the Simulink.Parameter objects or workspace
variables that makeup expressions. As long as the data type of these variables and
objects and the data type of the corresponding block parameters are the same or
double, the code generator can preserve tunability.

22-136
Limitations for Block Parameter Tunability in the Generated Code

Linear Block Parameter Tunability


These blocks have a Realization parameter that affects the tunability of their numeric
parameters:

• Transfer Fcn
• State-Space
• Discrete State-Space

To set the Realization parameter, you must use the command prompt:

set_param(gcb,'Realization','auto')

For the Realization parameter, you can choose these options:

• 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

Code Generation of Parameter Objects With Expression


Values
As described in “Set Variable Value by Using a Mathematical Expression” (Simulink), you
can set the value of a Simulink.Parameter object to an expression involving other
MATLAB variables or parameter objects. When you generate code from a model that uses
such a parameter object, to achieve your goal, use the information in the table.

Goal Technique and More Information


Generate code without Embedded Coder. For the parameter object that uses the
expression, apply any available storage
class (see “Apply Storage Classes to
Individual Signal, State, and Parameter
Data Elements” (Simulink Coder)).

For the parameter objects used in the


expression, apply only the storage class
Auto.
Generate code that defines a global See “Initialize Parameter Value From
variable and initializes it by using an System Constant or Other Macro
expression involving system constants and (Embedded Coder)” on page 22-129.
other macros (requires Embedded Coder).
Generate code that defines a macro whose For the parameter object that uses the
value is an expression involving other expression, apply a storage class that yields
macros (requires Embedded Coder). a macro in the generated code, such as
Define (see “Macro Definitions (#define)”
on page 14-71).

For the parameter objects used in the


expression, apply storage classes that yield
imported macros. For example, use the
storage class ImportedDefine. Your
external code must define these macros.

Considerations and Limitations


• To avoid errors that prevent code generation, if you apply a storage class other than
Auto to the dependent parameter object (which uses the expression as its value), the

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:

• If possible, for a parameter object used in an expression, leave the DataType


property at the default value, auto.

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

Specify Instance-Specific Parameter Values for Reusable


Referenced Model
When you use model referencing to break a large system into components, each
component is a separate model. You can reuse a component by referring to it with
multiple Model blocks. Each Model block is an instance of the component. You can then
configure a block parameter (such as the Gain parameter of a Gain block) to use either
the same value or a different value for each instance of the component. To use different
values, create and use a model argument to set the value of the block parameter.

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.

Pass Parameter Data to Referenced Model Entry-Point


Functions as Arguments
Configure a referenced model to accept parameter data through formal parameters of the
generated model entry-point function. This technique enables you to specify a different
parameter value for each instance (Model block) of the referenced model.

Configure Referenced Model to Use Model Arguments

Create the model ex_arg_code_ref. This model represents a reusable algorithm.

open_system('ex_arg_code_ref')

22-142
Specify Instance-Specific Parameter Values for Reusable Referenced Model

In the model, select View > Model Data Editor.

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.

Select the Parameters tab.

In the model, select the Gain block.

In the Model Data Editor, use the Value column to set the value of the Gain parameter to
gainArg.

Next to gainArg, click the action button and select Create.

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

Save the ex_arg_code_ref model.

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')

Specify Instance-Specific Parameter Values in Model Blocks

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'))

Generate code from the top model.

rtwbuild('ex_arg_code')

22-145
22 Data Representation in Simulink Coder

The file ex_arg_code_ref.c defines the referenced model entry-point function,


ex_arg_code_ref. The function has two formal parameters, rtp_coeffArg and
rtp_gainArg, that correspond to the model arguments, coeffArg and gainArg. The
formal parameters use the data type real32_T, which corresponds to the data type
single in Simulink.

/* Output and update for referenced model:


'ex_arg_code_ref' */
void ex_arg_code_ref(const real32_T *rtu_In1,
real32_T *rty_Out1,
DW_ex_arg_code_ref_f_T *localDW,
real32_T rtp_coeffArg,
real32_T rtp_gainArg)

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);

/* ModelReference: '<Root>/Model1' incorporates:


* Inport: '<Root>/In1'
* Outport: '<Root>/Out2'
*/
ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out2,
&(ex_arg_code_DW.Model1_InstanceData.rtdw), 1.11F, 3.34F);

The formal parameters use the data type real32_T (single).

• The block parameters in ex_arg_code_ref determine their data types through


internal rules. For example, in the Gain block dialog box, on the Parameter
Attributes tab, Parameter data type is set to Inherit: Inherit via internal
rule (the default). In this case, the internal rule chooses the same data type as the
input and output signals, single.
• The model arguments in the model workspace use context-sensitive data typing
because the value of the DataType property is set to auto (the default). With this
setting, the model arguments use the same data type as the block parameters,
single.
• The formal parameters in the generated code use the same data type as the model
arguments, single.

22-146
Specify Instance-Specific Parameter Values for Reusable Referenced Model

Generate Tunable Argument Values

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'))

View the contents of the ex_arg_code_ref model workspace in Model Explorer by


selecting View > Model Explorer > Model Explorer.

Copy gainArg and coeffArg from the ex_arg_code_ref model workspace to the base
workspace.

Rename gainArg as gainForInst1. Rename coeffArg as coeffForInst1.

gainForInst1 = getVariable(modelWorkspace,'gainArg');
gainForInst1 = copy(gainForInst1);
coeffForInst1 = getVariable(modelWorkspace,'coeffArg');
coeffForInst1 = copy(coeffForInst1);

Copy gainForInst1 and coeffForInst1 as gainForInst2 and coeffForInst2.

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.

Set the Change view drop-down list to Code.

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';

Generate code from the top model.

rtwbuild('ex_arg_code')

The file ex_arg_code.c defines the global variables that correspond to the parameter
objects in the base workspace.

/* Exported block parameters */


real32_T coeffForInst1 = 0.98F; /* Variable: coeffForInst1
* Referenced by: '<Root>/Model'
*/
real32_T coeffForInst2 = 1.11F; /* Variable: coeffForInst2
* Referenced by: '<Root>/Model1'
*/
real32_T gainForInst1 = 2.98F; /* Variable: gainForInst1
* Referenced by: '<Root>/Model'
*/
real32_T gainForInst2 = 3.34F; /* Variable: gainForInst2
* Referenced by: '<Root>/Model1'
*/

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);

/* ModelReference: '<Root>/Model1' incorporates:


* Inport: '<Root>/In1'
* Outport: '<Root>/Out2'
*/
ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out2,
&(ex_arg_code_DW.Model1_InstanceData.rtdw), coeffForInst2,
gainForInst2);

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.

Group Multiple Model Arguments into Single Structure

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

In the Contents pane, configure structArg as the only model argument.

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'))

Click the Show/refresh additional information button.

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';

At the command prompt, use the function Simulink.Bus.createObject to create a


Simulink.Bus object. The hierarchy of elements in the object matches the hierarchy of
the structure fields. The default name of the object is slBus1.

Simulink.Bus.createObject(structForInst1.Value);

Rename the bus object as myParamStructType by copying it.

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.

structForInst1.DataType = 'Bus: myParamStructType';


structForInst2.DataType = '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 the ex_arg_code_ref model.

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';

Generate code from the top model ex_arg_code.

rtwbuild('ex_arg_code')

The file ex_arg_code_types.h defines the structure type myParamStructType, which


corresponds to the Simulink.Bus object.

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.

/* Output and update for referenced model:


'ex_arg_code_ref' */
void ex_arg_code_ref(const real32_T *rtu_In1,

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.

/* Exported block parameters */


myParamStructType structForInst1 = {
2.98F,
0.98F
} ; /* Variable: structForInst1
* Referenced by: '<Root>/Model'
*/

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);

/* ModelReference: '<Root>/Model1' incorporates:


* Inport: '<Root>/In1'
* Outport: '<Root>/Out2'
*/
ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out2,
&(ex_arg_code_DW.Model1_InstanceData.rtdw), &structForInst2);

Control Data Types of Model Arguments and Argument Values


When you use model arguments, you can apply a data type to:

• 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

• The argument values that you specify in Model blocks.

To generate efficient code by eliminating unnecessary typecasts and C shifts, consider


using inherited and context-sensitive data typing to match the data types.

• 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.

• A literal number such as 15.23. Do not use a typed expression such as


single(15.23).
• A MATLAB variable whose data type is double.
• A Simulink.Parameter object whose DataType property is set to auto.

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.

Use Model Argument in Different Data Type Contexts

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

Parameter Data Types in the Generated Code


The data type of a block parameter (such as the Gain parameter of a Gain block), numeric
MATLAB variable, or Simulink.Parameter object determines the data type that the
corresponding entity in the generated code uses (for example, a global variable or an
argument of a function). To generate more efficient code, you can match parameter data
types with signal data types or store parameters in smaller data types.

For basic information about setting block parameter data types in a model, see “Control
Block Parameter Data Types” (Simulink).

Significance of Parameter Data Types


The data type that a block parameter, MATLAB variable, or parameter object uses
determines the data type that the generated code uses to store the parameter value in
memory. For example:

• 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

Typecasts Due to Parameter Data Type Mismatches


When the data types of block parameters, workspace variables, and signals differ, blocks
can use typecasts to reconcile the data type mismatches. These typecasts can cause the
generated code algorithm, including the model step function, to include explicit casts to
reconcile mismatches in storage data type and C bit shifts to reconcile mismatches in
fixed-point scaling.

Parameter data type mismatches can occur when:

• 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.

Detect Downcast and Loss of Precision due to Data Type Mismatches

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).

Considerations for Other Modeling Patterns


When you use specific modeling patterns and constructs such as fixed-point data types,
parameter structures, and lookup table objects, use different techniques to control
parameter data types.

• “Tunable Parameters and Best-Precision Fixed-Point Scaling” on page 22-158


• “Control Data Types of Structure Fields” on page 22-159
• “Control Data Types of Lookup Table Objects” on page 22-159
• “Data Typing for Expressions in Parameter Objects” on page 22-160

Tunable Parameters and Best-Precision Fixed-Point Scaling

To apply best-precision fixed-point scaling to a tunable block parameter or parameter


object, you can use the Fixed-Point Tool to autoscale an entire system or use the Data
Type Assistant to configure individual parameters or objects. See “Calculate Best-
Precision Fixed-Point Scaling for Tunable Block Parameters” (Simulink).

If a tunable parameter uses best-precision fixed-point scaling, Simulink chooses a data


type based on the minimum and maximum values that you specify for the parameter (see
“Specify Minimum and Maximum Values for Block Parameters” (Simulink)). You can
specify these values in the block dialog box that uses the parameter or in the properties
of a Simulink.Parameter object.

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.

Control Data Types of Structure Fields

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).

Control Data Types of Lookup Table Objects

When you use Simulink.LookupTable and Simulink.Breakpoint objects to store


table and breakpoint data for a lookup table block, to control the data types of the table
and breakpoint data, use one of these techniques:

• Set the Value property of the embedded Simulink.lookuptable.Table and


Simulink.lookuptable.Breakpoint objects by using untyped expressions such as
[1 2 3], which returns a double vector. To control the data type, set the DataType
property to a value other than auto.

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:

• Customize the name of the data type in the generated code.


• Match the data type of the table or breakpoint data with the data type of a signal in
the model.
• Set the Value property of the embedded objects by using typed expressions such as
single([1 2 3]). To use a fixed-point data type, set the Value property with an fi
object.

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.

When blocks in a subsystem use Simulink.LookupTable or Simulink.Breakpoint


objects, you cannot set data type override (see “Control Fixed-Point Instrumentation and
Data Type Override” (Simulink)) only on the subsystem. Instead, set data type override on
the entire model.

Data Typing for Expressions in Parameter Objects

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

• “Control Signal Data Types” (Simulink)


• “How Generated Code Stores Internal Signal, State, and Parameter Data” on page
22-50

22-161
22 Data Representation in Simulink Coder

Generate Efficient Code by Specifying Data Types for


Block Parameters
To generate more efficient code, match the data types of block parameters (such as the
Gain parameter of a Gain block) with signal data types. Alternatively, you can store
parameters in smaller data types.

Eliminate Unnecessary Typecasts and Shifts by Matching Data


Types
These examples show how to generate efficient code by configuring a block parameter to
use the same data type as a signal that the block operates on.

Store Data Type Information in Model

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 View > Model Data Editor.

In the Model Data Editor, select the Parameters tab.

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 Model Data Editor, set Change view to Design.

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';

Generate code from the model.


rtwbuild('rtwdemo_basicsc')

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: rtwdemo_basicsc

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)

/* Exported block parameters */


real32_T K1 = 2.0F; /* Variable: K1

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.

Store Data Type Information in Parameter Object

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.

At the command prompt, create a Simulink.NumericType object that represents the


data type single.

myType = Simulink.NumericType;
myType.DataTypeMode = 'Single';

Use the Model Data Editor Data Type column to set these data types to myType:

• The parameter object. Use the Parameters tab.


• The Inport block named In2. Use the Inports/Outports tab. Due to data type
propagation, the input signal of the Gain block also uses 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''')

Generate code from the model.

rtwbuild('rtwdemo_basicsc')

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: rtwdemo_basicsc

22-165
22 Data Representation in Simulink Coder

The global variable K1 continues to use the data type real32_T.

file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* Exported block parameters */','real32_T K1 = 2.0F;',1,1)

/* Exported block parameters */


real32_T K1 = 2.0F; /* Variable: K1

Reduce Memory Consumption by Storing Parameter Value in


Small Data Type
When you use a parameter object (for example, Simulink.Parameter) to set block
parameter values, you can configure the object to appear in the generated code as a
tunable global variable. By default, the parameter object and the corresponding global
variable typically uses the same data type as the signal or signals on which the block
operates. For example, if the input signal of a Gain block uses the data type int16, the
parameter object typically use the same data type. To reduce the amount of memory that
this variable consumes, specify that the variable use a smaller integer data type such as
int8.

Store Parameter Value in Integer Data Type

Run the script prepare_rtwdemo_basicsc_2, which prepares the model


rtwdemo_basicsc for this example.

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.

In the model, select View > Model Data Editor.

In the Model Data Editor, inspect the Parameters tab.

Click the Show/refresh additional information button.

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''')

Generate code from the model.


rtwbuild('rtwdemo_basicsc')

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: rtwdemo_basicsc

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)

/* Exported block parameters */


int8_T K1 = 2; /* Variable: K1

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)

rtwdemo_basicsc_DW.X = (real32_T)K1 * look1_iflf_binlx


(rtwdemo_basicsc_U.input2, rtCP_Table1_bp01Data, rtCP_Table1_tableData,
10U);

22-168
Generate Efficient Code by Specifying Data Types for Block Parameters

Store Fixed-Point Parameter Value in Smaller Integer Data Type

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.

Open the example model fxpdemo_direct_form2 and configure it to show the


generated names of blocks.

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.

Set Gain to myGainParam and click Apply.

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.

Set Parameter data type to fixdt(0,8) and click Apply.

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')

Generate code from the model.

evalc('rtwbuild(''fxpdemo_direct_form2'')');

The generated file fxpdemo_direct_form2.c defines the global variable myGainParam


by using the data type uint8_T, which corresponds to the specified word length, 8. The
code initializes the variable by using an integer value that, given the fraction length of 5,
represents the real-world parameter value 1.85.

file = fullfile('fxpdemo_direct_form2_grt_rtw','fxpdemo_direct_form2.c');
rtwdemodbtype(file,'/* Exported block parameters */','uint8_T myGainParam = 59U;',1,1)

/* Exported block parameters */


uint8_T myGainParam = 59U; /* Variable: myGainParam

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.

rtwdemodbtype(file,'/* Gain: ''<Root>/Gain5'' */',...


'/* Gain: ''<Root>/Gain'' incorporates:',1,0)

/* 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

• “Parameter Data Types in the Generated Code” on page 22-156


• “Reuse Parameter Data in Different Data Type Contexts” on page 22-173

22-172
Reuse Parameter Data in Different Data Type Contexts

Reuse Parameter Data in Different Data Type Contexts


When you use a Simulink.Parameter object or a numeric MATLAB variable to set two
or more block parameter values, if the block parameters have different data types, you
must explicitly specify the data type of the object or variable. For example, you cannot
leave the data type of the parameter object at the default value, auto.

Create and Configure Example Model

Create the model ex_paramdt_contexts.

ex_paramdt_contexts

In the model, select View > Model Data Editor.

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.

For the Gain parameters, set Value to myGainParam.

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.

Match Parameter Object Data Type with Signal Data Type

Optionally, use a Simulink.NumericType or Simulink.AliasType object to set the


parameter object data type and one of the signal data types. This technique eliminates
unnecessary typecasts and shifts in the generated code due to a mismatch between the
parameter object data type and the signal data type.

At the command prompt, create a Simulink.NumericType object to represent the data


type int8.
sharedType_int8 = fixdt('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.

Generate and Inspect Code

Generate code from the model.

rtwbuild('ex_paramdt_contexts')

### Starting build procedure for model: ex_paramdt_contexts


### Successful completion of build procedure for model: ex_paramdt_contexts

The generated file ex_paramdt_contexts.c defines the global variable myGainParam


by using the data type int8_T, which corresponds to the data type int8 in Simulink.

file = fullfile('ex_paramdt_contexts_grt_rtw','ex_paramdt_contexts.c');
rtwdemodbtype(file,'/* Exported block parameters */','int8_T myGainParam = 3;',1,1)

/* Exported block parameters */


int8_T myGainParam = 3; /* Variable: myGainParam

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.

rtwdemodbtype(file,'/* Model step function */',...


'/* Model initialize function */',1,0)

22-175
22 Data Representation in Simulink Coder

/* Model step function */


void ex_paramdt_contexts_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Gain: '<Root>/Gain - single'
* Inport: '<Root>/In1'
*/
ex_paramdt_contexts_Y.Out1 = (real32_T)myGainParam * ex_paramdt_contexts_U.In1;

/* Outport: '<Root>/Out2' incorporates:


* Gain: '<Root>/Gain - int8'
* Inport: '<Root>/In2'
*/
ex_paramdt_contexts_Y.Out2 = (int8_T)(myGainParam * ex_paramdt_contexts_U.In2);
}

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

Organize Data into Structures in Generated Code


In C code, you use structures (struct) to store data in contiguous locations in memory.
You can organize data, such as signals and states, by using meaningful names. Each
structure acts as a namespace, so you can reuse a name to designate multiple data items.
Like arrays, with structures, you can write code that efficiently transfers and operates on
large amounts of data by using pointers.

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.

• For an example that shows how to


organize parameter data, see
“Structures of Parameters” on page 22-
184.
• For an example that shows how to
organize signal data, see “Structures of
Signals” on page 22-187.

To create an array of structures, see


“Arrays of Structures” on page 22-194.
Exchange structured data between Create a Simulink.Bus object that
generated code and your external code, for represents the structure type that you
example, when the external code already want. If your external code already defines
defines a custom structure type and a the type, use the
corresponding global variable. Simulink.importExternalCTypes
function to generate the bus object. Use the
bus object to set the data types of
nonvirtual bus signals and parameter
structures in your model. For an example,
see “Exchange Structured and Enumerated
Data Between Generated and External
Code” on page 24-34.

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:

• Configure root-level Inport and


Outport blocks to appear in the code
as structure fields. Replace multiple
such blocks with a single block that
you configure as a nonvirtual bus
signal. With this technique, you have
the greatest control over the
structure characteristics. As you add
blocks to the model, you must
manually modify the bus definitions.
See “Nonvirtual Buses and
Parameter Structures” on page 22-
183.
• Organize model arguments into a
custom structure (see “Specify
Instance-Specific Parameter Values
for Reusable Referenced Model” on
page 22-142).
• To reduce the number of arguments for
the entry-point functions of a masked,
reentrant subsystem, aggregate mask
parameters into a custom structure.
Organize lookup table data into a structure. Use Simulink.LookupTable and
Simulink.Breakpoint objects. See
Simulink.LookupTable.

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.

Techniques to Create Structures


To create structures in the generated code, you can use any of these techniques:

• 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.

To decide which techniques to use, use the information in the table.

Capability Default Application Direct Application Nonvirtual Buses


of Structured of Structured and Parameter
Storage Class Storage Class Structures
Aggregate new data Yes No No
items into a
structure by default
Prevent elimination No Yes Only if you directly
of the target data by apply a storage class
optimizations such as
(specify that the data ExportedGlobal to
appear in the the bus or structure
generated code)
Aggregate data into Yes Yes No
a structure without
changing the
appearance of the
block diagram

22-181
22 Data Representation in Simulink Coder

Capability Default Application Direct Application Nonvirtual Buses


of Structured of Structured and Parameter
Storage Class Storage Class Structures
Place signal, state, No Yes No
and parameter data
in the same structure
Include state data in Yes Yes No
a structure
Organize structures No No Yes
into nested
structures
Organize structures No No Yes
into an array of
structures
Control name of Yes Yes, but the type Yes
structure type name derives from
the variable name,
which you specify
Create a structure to Yes, but you must No Yes
reduce the number create your own
of arguments in a storage class by
generated function using an Embedded
Coder Dictionary
Requires Embedded Yes Yes No
Coder

Default Application of Structured Storage Class


You can apply a default storage class to a category of model data. As you add blocks and
signals to the model, the associated data acquire the default storage class that you
specify. To aggregate new data into structures by default, you can apply structured
storage classes. You must use the built-in storage classes ParamStruct and
SignalStruct or create your own storage class by using an Embedded Coder Dictionary.

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.

Direct Application of Structured Storage Class


You can apply a structured storage class to individual data items. The direct application
prevents code generation optimizations, such as Default parameter behavior and
Signal storage reuse, from eliminating each data item from the generated code. The
direct application also overrides the default storage classes that you specify with Code
Mappings > Data Defaults.

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.

Nonvirtual Buses and Parameter Structures


• To create a nonvirtual bus signal, use a Bus Creator block to organize multiple signal
lines into a single bus, or configure an Inport block or Outport block as a nonvirtual
bus. You must create a Simulink.Bus object that represents the structure type. For
an example, see “Structures of Signals” on page 22-187. For general information
about nonvirtual buses, see “Getting Started with Buses” (Simulink).
• To create a parameter structure, use MATLAB commands or the Variable Editor to
organize the values of multiple block parameters into a MATLAB structure. Optionally,
create a Simulink.Bus object so that you can control the name of the structure type
and other characteristics such as the data type and dimensions of each field. For an
example, see “Structures of Parameters” on page 22-184. For general information
about parameter structures, see “Organize Related Block Parameter Definitions in
Structures” (Simulink).

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

Open the example model rtwdemo_paraminline.

rtwdemo_paraminline

22-184
Organize Data into Structures in Generated Code

Select View > Model Data Editor.

In the Model Data Editor, select the Parameters tab.

In the model, click the Gain block labeled G1.

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.

In the Simulink.Parameter property dialog box, set Storage class to ExportedGlobal.


With this setting, the structure myStruct appears in the generated code as a global
variable.

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

Generate code from the model.

rtwbuild('rtwdemo_paraminline')

### Starting build procedure for model: rtwdemo_paraminline


### Successful completion of build procedure for model: rtwdemo_paraminline

The generated header file rtwdemo_paraminline_types.h defines a structure type


with a random name.

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

Specify Name of Structure Type

Optionally, specify a name to use for the structure type definition (struct).

At the command prompt, use the function Simulink.Bus.createObject to create a


Simulink.Bus object that represents the structure type.

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';

Generate code from the model.


rtwbuild('rtwdemo_paraminline')

### Starting build procedure for model: rtwdemo_paraminline


### Successful completion of build procedure for model: rtwdemo_paraminline

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.

In the model, select Edit > Bus Editor.

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, select View > Model Data Editor.

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.

Generate code from the model.

Results

The generated header file ex_signal_struct_types.h defines the structure type


my_signals_type.

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.

/* Exported block signals */


my_signals_type sig_struct_var; /* '<Root>/Bus Creator' */

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.

Nested Structures of Signals

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.

In the model, select Edit > Bus Editor.

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.

Select Output as nonvirtual bus and click OK.

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, select View > Model Data Editor.

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.

Generate code from the model.

Results

The generated header file ex_signal_nested_struct_types.h defines the structure


types. Each structure type corresponds to a Simulink.Bus object.

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;

The generated source file ex_signal_nested_struct.c allocates memory for the


global structure variable sig_struct_var. By default, the name of the A_struct_type
Bus Creator block is Bus Creator2.

/* Exported block signals */


A_struct_type sig_struct_var; /* '<Root>/Bus Creator2' */

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.

Combine Techniques to Work Around Limitations


To work around some of the limitations of each technique, you can combine structured
custom storage classes with nonvirtual buses and parameter structures. For example, you
can:

• 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

Switch Between Sets of Parameter Values During


Simulation and Code Execution
To store multiple independent sets of values for the same block parameters, you can use
an array of structures. To switch between the parameter sets, create a variable that acts
as an index into the array, and change the value of the variable. You can change the value
of the variable during simulation and, if the variable is tunable, during execution of the
generated code.

Explore Example Model

Open this example model:

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.

Navigate to the switchable_compensation nested subsystem.

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 the low_mode subsystem.

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.

Store Parameter Values in Array of Structures

Store the existing set of numerator coefficients in a Simulink.Parameter object whose


value is a structure. Each field of the structure stores the coefficients for one of the
Discrete Filter blocks.

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.

Create Variable to Switch Between Parameter Sets

Create a Simulink.Parameter object named Ctrl.

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

Use Bus Object as Data Type of Array of Structures

Optionally, create a Simulink.Bus object to use as the data type of the array of
structures. You can:

• Control the shape of the structures.


• For each field, control characteristics such as data type and physical units.
• Control the name of the struct type in the generated code.

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.

params.DataType = 'Bus: paramsType';

Use Enumerated Type for Switching Variable

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.

Create an enumerated type named FilterCoeffs. Create an enumeration member for


each of the structures in params. Set the underlying integer value of each enumeration
member to the corresponding index in params.

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

Add New Objects to Data Dictionary

Add the objects that you created to the data dictionary


sldemo_fuelsys_dd_controller.sldd.
dictObj = Simulink.data.dictionary.open('sldemo_fuelsys_dd_controller.sldd');
sectObj = getSection(dictObj,'Design Data');
addEntry(sectObj,'Ctrl',Ctrl)
addEntry(sectObj,'params',params)
addEntry(sectObj,'paramsType',paramsType)

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).

Switch Between Parameter Sets During Simulation

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.

In the Model Explorer, view the contents of the data dictionary


sldemo_fuelsys_dd_controller.sldd. Set the value of Ctrl to
FilterCoeffs.Weak.

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.

Stop the simulation.

Generate and Inspect Code

If you have Simulink Coder software, you can generate code that enables you to switch
between the parameter sets during code execution.

In the Model Explorer, view the contents of the data dictionary


sldemo_fuelsys_dd_controller.sldd. In the Contents pane, set Column View to
Storage Class.

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.

Alternatively, to configure the objects, use these commands:

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);

Generate code from the controller model.

22-202
Switch Between Sets of Parameter Values During Simulation and Code Execution

rtwbuild('sldemo_fuelsys_dd_controller')

### Starting build procedure for model: sldemo_fuelsys_dd_controller


### Successful completion of code generation for model: sldemo_fuelsys_dd_controller

In the code generation report, view the header file


sldemo_fuelsys_dd_controller_types.h. The code defines the enumerated data
type FilterCoeffs.
file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',...
'sldemo_fuelsys_dd_controller_types.h');
rtwdemodbtype(file,'#ifndef DEFINED_TYPEDEF_FOR_FilterCoeffs_',...
'/* Forward declaration for rtModel */',1,0)

#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

View the source file sldemo_fuelsys_dd_controller.c. The code uses the


enumerated type to define the switching variable Ctrl.

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)

FilterCoeffs Ctrl = Aggressive; /* Variable: Ctrl


* Referenced by:
* '<S12>/Discrete Filter'
* '<S13>/Discrete Filter'
*/

The code also defines the array of structures params.

rtwdemodbtype(file,'/* Exported block parameters */',...


'/* Variable: params',1,1)

/* Exported block parameters */


paramsType params[2] = { {
{ 8.7696F, -8.5104F },

{ 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

Design Data Interface by Configuring Inport and Outport


Blocks
The data interface of a model is the means by which the model exchanges data (for
example, signal values) with other, external models or systems. Customize the data
interface of a model to:

• Enable integration of the generated code with your own code.


• Improve traceability and readability of the code.

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.

Design Data Interface

Open the example model rtwdemo_basicsc.

open_system('rtwdemo_basicsc')

22-206
Design Data Interface by Configuring Inport and Outport Blocks

Configure the model to show the generated names of blocks.

set_param('rtwdemo_basicsc','HideAutomaticNames','off')

In the model, select View > Model Data Editor.

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

Set the Change View drop-down list to Code.

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')

Generate code from the model.


rtwbuild('rtwdemo_basicsc');

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: rtwdemo_basicsc

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)

/* Exported block signals */


real32_T input1; /* '<Root>/In1' */

22-208
Design Data Interface by Configuring Inport and Outport Blocks

real32_T input2; /* '<Root>/In2' */


real32_T input3; /* '<Root>/In3' */
real32_T input4; /* '<Root>/In4' */
real32_T output_sig; /* '<Root>/Out1' */

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).

Reduce Manual Data Entry by Configuring Default Storage Class (Embedded


Coder)

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')

Route Signal Data to Multiple Outputs

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:

1 Branch the target signal line to each Outport block.


2 For more efficient code, set the storage class of the target signal line to Auto (the
default). Optimizations can then eliminate the signal line from the generated code.
3 Use the Model Data Editor to apply the custom storage class GetSet to one Outport
block and ExportToFile to the other Outport block. Apply a signal name to each
block.

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

Generate Efficient Code for Bus Signals


In this section...
“Code Efficiency for Bus Signals” on page 22-212
“Set Bus Diagnostics” on page 22-213
“Optimize Virtual and Nonvirtual Buses” on page 22-213

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.

Code Efficiency for Bus Signals


When you use buses in a model for which you intend to generate code:

• 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:

• Simplify the layout of the model.


• Increase the efficiency of generated code.

22-212
Generate Efficient Code for Bus Signals

• Define data structures for function (subsystem) interfaces.


• Define data structures that match existing data structures in external C code.

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.

Set Bus Diagnostics


Simulink provides diagnostics that you can use to optimize bus usage. Set the following
values on the Configuration Parameters > Diagnostics > Connectivity pane.

Optimize Virtual and Nonvirtual Buses


Virtual buses are graphical conveniences that do not affect generated code. As a result,
the code generation engine is able to fully optimize the signals in the bus. Use virtual
buses rather than nonvirtual buses wherever possible. You can convert between virtual
and nonvirtual buses by using Signal Conversion blocks. In some cases, Simulink
automatically converts a virtual bus to a nonvirtual bus when required. For example, a
Stateflow chart converts an input virtual bus to a nonvirtual bus.

To bundle function-call signals, you must use a virtual bus.

You must use nonvirtual buses for:

• Nonauto storage classes

22-213
22 Data Representation in Simulink Coder

• Generating a specific structure from the bus


• Root-level Inport or Outport blocks when the bus has mixed data types

Avoid Nonlocal Nested Buses in Nonvirtual Buses

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

Control Signal and State Initialization in the Generated


Code
To initialize signals and discrete states with custom values for simulation and code
generation, you can use signal objects and block parameters. Data initialization increases
application reliability and is a requirement of safety critical applications. Initializing
signals for both simulation and code generation can expedite transitions between phases
of Model-Based Design.

For basic information about specifying initial values for signals and discrete states in a
model, see “Initialize Signals and Discrete States” (Simulink).

Signal and State Initialization in the Generated Code


The initialization behavior for code generation is the same as that for model simulation
with the following exceptions:

• 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.

For example, consider the model rtwdemo_sigobj_iv.

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

/* Start for enable system: '<Root>/Enabled Subsystem (state X1 inside)' */

/* virtual outports code */

/* (Virtual) Outport Block: '<S2>/Out1' */

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 */

static void rtwdemo_sigobj_iv_output(void)


{
.
.
.
/* Disable for enable system: '<Root>/Enabled Subsystem (state X1 inside)' */

/* (Virtual) Outport Block: '<S2>/Out1' */

S2 = aa2;

Generate Tunable Initial Conditions


You can represent initial conditions for signals and states by creating tunable global
variables in the generated code. These variables allow you to restart an application by
using initial conditions that are stored in memory.

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.

Explore Example Model

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

In the base workspace, double-click the Simulink.Signal object X1 to view its


properties. The Initial value property is set to aa1.

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.

Generate and Inspect Code

Generate code with the example model.

### Starting build procedure for model: rtwdemo_sigobj_iv


### Successful completion of build procedure for model: rtwdemo_sigobj_iv

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.

/* Exported block states */


real_T X1; /* '<S2>/Unit Delay' */

/* Exported block signals */


real_T S1; /* '<Root>/In1' */
real_T S3; /* '<Root>/Signal Conversion' */
real_T S2; /* '<S2>/Unit Delay' */

The code uses global variables to represent the tunable parameters aa1 and aa2.

/* Exported block parameters */


real_T aa1 = -2.5; /* Variable: aa1

real_T aa2 = -2.0; /* Variable: 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.

/* SystemInitialize for Enabled SubSystem: '<Root>/Enabled Subsystem (state X1 inside


/* InitializeConditions for UnitDelay: '<S2>/Unit Delay' */
X1 = aa1;

/* SystemInitialize for Outport: '<S2>/Out1' */

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;
}
}

Generate Tunable Initial Condition Structure for Bus Signal


When you use a MATLAB® structure to specify initialization values for the signal
elements in a bus, you can create a tunable global structure in the generated code.

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).

Generate Tunable Initial Condition Structure

This example shows how to use a tunable structure parameter to initialize a virtual bus
signal.

Open the example model rtwdemo_tunable_init_struct and configure it to show the


generated names of blocks.

In the model, select View > Model Data Editor.

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

In the Model Data Editor, inspect the States tab.

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)')

Generate code from the example model.

### Starting build procedure for model: rtwdemo_tunable_init_struct


### Successful completion of build procedure for model: rtwdemo_tunable_init_struct

In the code generation report, view the file rtwdemo_tunable_init_struct_types.h.


The code defines a structure type whose fields use the data types that you specified in the
struct expression.

#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;

View the file rtwdemo_tunable_init_struct.h. The struct type definition of the


global parameters structure contains a substructure, UnitDelay_InitialCondition,
which represents the Initial condition parameter of the Unit Delay block.

struct P_rtwdemo_tunable_init_struct_T_ {
struct_mqGi1jsItE0G7cf1bNqMu UnitDelay_InitialCondition;/* Mask Parameter: UnitDelay_

View the file rtwdemo_tunable_init_struct_data.c. This source file allocates


memory for the global parameters structure. The substructure
UnitDelay_InitialCondition appears.

/* Block parameters (default storage) */

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
},

View the file rtwdemo_tunable_init_struct.c. The model initialization function uses


the fields of the substructure to initialize the block states.

/* InitializeConditions for UnitDelay: '<Root>/Unit Delay' */


rtwdemo_tunable_init_struct_DW.UnitDelay_1_DSTATE =
rtwdemo_tunable_init_struct_P.UnitDelay_InitialCondition.thermocpl;
rtwdemo_tunable_init_struct_DW.UnitDelay_2_DSTATE =
rtwdemo_tunable_init_struct_P.UnitDelay_InitialCondition.magFlow;
rtwdemo_tunable_init_struct_DW.UnitDelay_3_DSTATE =
rtwdemo_tunable_init_struct_P.UnitDelay_InitialCondition.posSwitch;

Use Bus Object to Specify Data Types

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).

Open the example model rtwdemo_init_struct_busobj and configure it to show the


generated names of blocks.

22-224
Control Signal and State Initialization in the Generated Code

In the base workspace, double-click the Simulink.Bus object ComponentData. The


object defines three signal elements: thermocpl, magFlow, and posSwitch. The
elements each use a different data type.

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 Data Editor, inspect the Parameters tab.

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

Click the Show/refresh additional information button. The parameter object,


initStruct, appears in the data table as a row.

Use the Data Type column to set the data type of initStruct to Bus:
ComponentData.

initStruct.DataType = 'Bus: ComponentData';

Set the Change View drop-down list to Code.

Use the Storage Class column to apply the storage class ExportedGlobal to
initStruct.

initStruct.StorageClass = 'ExportedGlobal';

Generate code from the example model.

### Starting build procedure for model: rtwdemo_init_struct_busobj


### Successful completion of build procedure for model: rtwdemo_init_struct_busobj

In the code generation report, view the file rtwdemo_init_struct_busobj_types.h.


The code creates a structure type ComponentData whose fields use the data types in the
bus object.

#ifndef DEFINED_TYPEDEF_FOR_ComponentData_
#define DEFINED_TYPEDEF_FOR_ComponentData_

typedef struct {
real_T thermocpl;
uint32_T magFlow;
boolean_T posSwitch;
} ComponentData;

View the file rtwdemo_init_struct_busobj.c. The code creates a global variable to


represent the tunable parameter object initStruct.

/* Exported block parameters */


ComponentData initStruct = {
15.23,
79U,
0
} ; /* Variable: initStruct

22-226
See Also

The model initialization function uses the structure fields to initialize the block states.

/* InitializeConditions for UnitDelay: '<Root>/Unit Delay' */


rtwdemo_init_struct_busobj_DW.UnitDelay_1_DSTATE = initStruct.thermocpl;
rtwdemo_init_struct_busobj_DW.UnitDelay_2_DSTATE = initStruct.magFlow;
rtwdemo_init_struct_busobj_DW.UnitDelay_3_DSTATE = initStruct.posSwitch;

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

Initialization of Signal, State, and Parameter Data in the


Generated Code
Signal lines, block parameters, and block states in a model can appear in the generated
code as data, for example, as global variables. By default, the code initializes this data
before execution of the primary algorithm. To match the numerics of simulation in
Simulink, the code generator chooses the initial values based on specifications that you
make in the model.

By understanding how the generated code initializes data, you can:

• 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 and Dynamic Initialization


To initialize a data item such as a global variable, an application can use either static or
dynamic initialization.

• 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

Real-World Ground Initialization Requiring Nonzero Bit


Pattern
Each data item has a real-world ground value. This value can depend on the data type of
the item. For example, for a signal whose data type is double or int8, the real-world
ground value is zero. For an enumeration, the ground value is the default enumeration
member.

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.

Initialization of Signal and State Data


In a model, you can control signal and state initial values through block parameters. For
example, to set the initial value of a Unit Delay block, you use the Initial condition
parameter. In some cases, you can also use the InitialValue property of a
Simulink.Signal object. For most of these block parameters, the default value is 0.

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

• The generated code defines (allocates memory for) the data.


• The data use a storage class other than Auto (the default storage class) or Model
default (when the Code Mapping Editor specifies the Default storage class,
the default setting).

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.

memset for Bulk Initialization

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).

Tunable Initial Values

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.

Initialization of Parameter Data


The generated code statically initializes parameter data to the values that you specify in
Simulink.

To express the initial value of a tunable parameter (a global variable) as a mathematical


expression involving system constants or other macros, which requires Embedded Coder,
see “Initialization by Mathematical Expression (Embedded Coder)” (Simulink Coder).

Kinds of Parameter Data

These model elements appear in the generated code as parameter data:

• 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.

Initialization by Mathematical Expression (Embedded Coder)

You can set the value of a parameter object (such as Simulink.Parameter) to a


mathematical expression involving numbers, MATLAB variables, and other parameter
objects. See “Set Variable Value by Using a Mathematical Expression” (Simulink).

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).

Data Initialization in the Generated Code


This example shows how the generated code initializes signal, state, and parameter data.

Explore Example Model

Open the example model, rtwdemo_rtwintro.

open_system('rtwdemo_rtwintro')

In the model, select View > Model Data Editor.

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 Initial Value to a nonzero number, for example, 5.

set_param('rtwdemo_rtwintro/X','InitialCondition','5')

Set the Change view drop-down list to Code.

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, open the Amplifier subsystem, which is a triggered subsystem.

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, inspect the configuration parameter Configuration Parameters >


Optimization > Default parameter behavior. The configuration parameter is set to
Inlined, which means block parameters, including initial values, appear in the
generated code as inlined literals or as const data.

Navigate to the root level of the model.

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.

For INC, set the value in the Value column to Simulink.Parameter(uint8(1)).


MATLAB converts INC to a Simulink.Parameter object.

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';

Generate and Inspect Code

Generate code from the model.

rtwbuild('rtwdemo_rtwintro');

### Starting build procedure for model: rtwdemo_rtwintro


### Successful completion of build procedure for model: 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)

/* Exported block parameters */


uint8_T INC = 1U; /* Variable: INC

In the same file, inspect the definition of the rtwdemo_rtwintro_initialize function.


First, the function uses memset to initialize all of the internal signals in the model to a
stored value of 0.

rtwdemodbtype(file,'/* block I/O */','sizeof(B_rtwdemo_rtwintro_T));',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.

rtwdemodbtype(file,'/* exported global states */','X = 0U;',1,1)

/* exported global states */


X = 0U;

The function also initializes other data, including the root-level inputs and outputs (Inport
and Outport blocks), to the appropriate ground values.

rtwdemodbtype(file,'/* external inputs */','Amplifier_Trig_ZCE = POS_ZCSIG;',1,1)

/* 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.

rtwdemodbtype(file,'/* InitializeConditions for UnitDelay: ''<Root>/X'' */',...


'X = 5U;',1,1)

/* InitializeConditions for UnitDelay: '<Root>/X' */


X = 5U;

Finally, the function initializes the output of the Amplifier subsystem.

rtwdemodbtype(file,'SystemInitialize for Triggered SubSystem',...


'End of SystemInitialize for SubSystem',1,1)

/* SystemInitialize for Triggered SubSystem: '<Root>/Amplifier' */


/* SystemInitialize for Outport: '<Root>/Output' incorporates:
* Outport: '<S1>/Out'
*/
rtwdemo_rtwintro_Y.Output = 0;

22-235
22 Data Representation in Simulink Coder

Inspect Difference Between Stored Value and Real-World Value

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 Data Editor, inspect the Signals tab.

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')

To prevent compilation errors on different platforms, select the model configuration


parameter Generate code only. This setting causes the model to generate only code.
set_param('rtwdemo_rtwintro','GenCodeOnly','on')

Generate code from the model.


rtwbuild('rtwdemo_rtwintro')

### Starting build procedure for model: rtwdemo_rtwintro


### Successful completion of code generation for model: rtwdemo_rtwintro

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)

/* exported global states */


X = -3;

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.

rtwdemodbtype(file,'/* InitializeConditions for UnitDelay: ''<Root>/X'' */',...


'X = 2;',1,1)

/* InitializeConditions for UnitDelay: '<Root>/X' */


X = 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.

For more information, see “Generate Code That Responds to


Initialize, Reset, and Terminate Events” on page 9-2.
Prevent generation If your application environment already initializes global variables to
of code that zero, for more efficient code, you can prevent the generation of
explicitly initializes statements that explicitly initialize global variables to zero. This
data to zero optimization applies only to signals and states whose initial values
are stored in memory as zero. For example, the code generator does
not apply the optimization to:

• 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.

The optimization requires Embedded Coder. For more information,


see “Remove Initialization Code” on page 59-4.

22-237
22 Data Representation in Simulink Coder

Goal More Information


Generate code that You can generate code that reuses (imports) data that your external
imports data from code defines. For example, you can apply the storage class
your external code ImportedExtern to a signal line, block state, or parameter object.
For imported data:

• 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.

For more information, including how to prevent the generated code


from initializing imported data, see “Exchange Data Between
External Calling Code and Generated Code” (Simulink Coder).

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

Optimize Speed and Size of Signal Processing Algorithm


by Using Fixed-Point Data
This model shows a fixed-point version of an acoustic noise canceller.

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®

Optimize Generated Code Using Fixed-Point Data with


Simulink®, Stateflow®, and MATLAB®
This model shows fixed-point code generation in 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

Declare Workspace Variables as Tunable Parameters


Using the Model Parameter Configuration Dialog Box
You can use the Model Parameter Configuration dialog box to declare numeric MATLAB
variables in the base workspace as tunable parameters. You can select code generation
options, such as storage class, for each tunable parameter.

However, it is a best practice to instead use parameter objects to declare tunable


parameters. Do not use the Model Parameter Configuration dialog box to select
parameter objects in the base workspace. To use parameter objects, instead of the Model
Parameter Configuration dialog box, to declare tunable parameters, see “Apply Storage
Classes to Individual Signal, State, and Parameter Data Elements” on page 22-81.

Note You cannot use the Model Parameter Configuration dialog box to declare tunable
parameters for a referenced model. Use Simulink.Parameter objects instead.

Declare Existing Workspace Variables as Tunable Parameters


Use the Model Parameter Configuration dialog box to declare existing workspace
variables as tunable parameters for a model.
1 In the Configuration Parameters dialog box, on the Optimization pane, click
Configure.
2 In the Model Parameter Configuration dialog box, under Source list, select a method
to populate the list of available workspace variables.

• 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.

Declare New Tunable Parameters


Use the Model Parameter Configuration dialog box to declare new tunable parameters.
You can use this technique to declare the names of tunable parameters, and to adjust
their code generation settings, before you create the corresponding workspace variables.

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.

Set Tunable Parameter Code Generation Options


To set the properties of tunable parameters listed under Global (tunable) parameters
in the Model Parameter Configuration dialog box, select a parameter and specify a
storage class and, optionally, a storage type qualifier.

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

For more information about tunable parameter storage


classes, see “Apply Storage Classes to Individual
Signal, State, and Parameter Data Elements” on page
22-81.
Storage type qualifier For variables with a storage class other than Auto, you
can add a qualifier (such as const or volatile) to the
generated storage declaration. To do so, you can select
a predefined qualifier from the list, or add qualifiers not
in the list by typing them in. The code generator does
not check the storage type qualifier for validity, and
includes the qualifier text in the generated code
without checking syntax .

Programmatically Declare Workspace Variables as Tunable


Parameters
Tune Parameters from the Command Line

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')

The following commands declare tunable parameters or set corresponding properties:

• set_param(gcs,'TunableVars',str)

The argument str (character vector) is a comma-separated list of variable names.


• set_param(gcs,'TunableVarsStorageClass',str)

The argument str (character vector) is a comma-separated list of storage class


settings.

The valid storage class settings are

• Auto
• ExportedGlobal
• ImportedExtern
• ImportedExternPointer
• set_param(gcs,'TunableVarsTypeQualifier',str)

The argument str (character vector) is a comma-separated list of storage type


qualifiers.

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

Share Data Between Code Generated from Simulink,


Stateflow, and MATLAB
Stateflow and MATLAB Coder can fully define their data definitions, or they can inherit
them from Simulink. Data definition capabilities include:

• Inheriting input/output data types and sizes from Simulink.


• Parameterized data types and sizes. That is, data type and size may be specified as a
function of another data's type and size, e.g., type(y)=type(u) and
size(y)=size(u).
• Inferred output size and type from Simulink via signal attribute back propagation.
• Parameter scoped data, which allows referencing Simulink parameters in Stateflow
and MATLAB.

Open Example Model

Open the example model rtwdemo_dynamicio.

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

Data Definition and Declaration


Management in Embedded Coder

• “Control Placement of Global Data Definitions and Declarations in Generated Files”


on page 23-2
• “Establish Data Ownership in a System of Components” on page 23-15
23 Data Definition and Declaration Management in Embedded Coder

Control Placement of Global Data Definitions and


Declarations in Generated Files
The generated code can create standard, global structure variables whose fields
represent the signal, state, and parameter data in a model. With storage classes, you can
configure data to appear in the code as separate global variables or custom global
structures. For information about the standard data structures, see “How Generated Code
Stores Internal Signal, State, and Parameter Data” on page 22-50 and “How Generated
Code Exchanges Data with an Environment” on page 22-33. For information about
storage classes, see “Choose a Storage Class for Controlling Data Representation in the
Generated Code” on page 22-69.

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

Goal Details and Techniques


Generate a variable that external code can Apply a storage class with exported data
use scope, such as ExportToFile. The
generated code declares the variable in a
file that your code can include (#include).

To generate an extern declaration in


model.h, consider using the storage class
ExportedGlobal.

Alternatively, to place the declaration in a


file whose name you can specify, choose one
of these techniques:

• To aggregate multiple variable


declarations into one or more specific
header files by default, apply a storage
class such as ExportToFile to a
category of data by using the Code
Mapping Editor. As you add blocks and
signals to the model, new data items are
declared in the files that you specify.
• To explicitly specify the placement for
an individual data item, directly apply a
storage class such as ExportToFile
and specify a header file name by using
the Header file custom attribute. To
configure multiple data items in a list
that you can search, sort, and filter, use
the Model Data Editor (see “Configure
Data Properties by Using the Model
Data Editor” (Simulink)).

See “Exchange Data Between External


Calling Code and Generated Code” on page
42-102.

23-3
23 Data Definition and Declaration Management in Embedded Coder

Goal Details and Techniques


Generate code that uses a variable defined Apply a storage class with imported data
by external code scope, such as ImportFromFile, to a data
element in a model that represents the
variable. Then, the generated code does not
define the variable, but instead includes
(#include) an external header file whose
name you can specify. The generated
algorithm (for example, the model step
function) reads and writes to the variable.

Alternatively, if you do not have an external


declaration header file or do not want the
generated code to include a header file,
apply the storage class ImportedExtern.
Then, the generated code declares the
variable in model_private.h.

See “Exchange Data Between External


Calling Code and Generated Code” on page
42-102.

23-4
Control Placement of Global Data Definitions and Declarations in Generated Files

Goal Details and Techniques


• Reduce the size of a generated file by Depending on the setting of Configuration
creating multiple smaller files Parameters > File packaging format,
• Organize data into different files to generated files such as model.c and
make generated code easier to model_data.c can contain many
understand definitions of global variables.
Corresponding header files can contain
many declarations.

• To make model.c smaller, consider


setting File packaging format to
Modular or Compact (with
separate data file). Then, the
generated code defines the standard
structures that represent tunable and
constant parameter data in
model_data.c instead of model.c.
• To place different categories of data (for
example, global parameters, block
states, and internal signals) in specific
files by default, use the Code Mapping
Editor. For each category of data, use a
storage class such as ExportToFile
and specify the custom attribute
Header file. See “Configure Default
Code Generation for Data” on page 21-8.
• For precise control over the file
placement of data, apply storage classes
such as ExportToFile to individual
data items. Use the custom attributes of
the storage class, such as Definition
file and Header file, to specify file
placement for each data item. To
configure multiple data elements at
once, you can use the Model Data
Editor. For an example, see “Definition
and Declaration of Signal Data” on page
14-9.

23-5
23 Data Definition and Declaration Management in Embedded Coder

Goal Details and Techniques


Combine multiple files into a single file • Consider setting the model
configuration parameter File
packaging format to Compact. Then,
the code generator does not create the
model_data.c file. Instead, the
definitions of the standard structures
that store tunable and constant
parameter data appear in model.c.
• When you apply a custom storage class
such as ExportToFile to data
elements, leave the custom attributes
Definition file and Header file blank,
the default value. Also, set the model
configuration parameter Data
definition to Data defined in
source file. Then, the data
definitions appear in model.c with the
definitions of other global data.

23-6
Control Placement of Global Data Definitions and Declarations in Generated Files

Goal Details and Techniques


Separate data definitions from function By default, the generated file that defines
definitions the entry-point functions for a model or
subsystem also defines the data for that
model or subsystem. When you frequently
make changes to data, especially initial
values for tunable parameters, the
changing source code files can impede
verification and make change management
more difficult. To separate the data from
the functions:

• Consider setting the model


configuration parameter File
packaging format to a value that
results in the generation of the separate
data file model_data.c. Then, the
definitions of the standard structures
that store tunable and constant
parameter data appear in this file
instead of in model.c.
• Apply storage classes such as
ExportToFile to data elements by
using the Code Mapping Editor and the
Model Data Editor. Use the custom
attributes of the custom storage class,
such as Definition file and Header file,
to specify file placement. For more
information, see “Configure Default
Code Generation for Data” on page 21-8
and “Apply Custom Storage Classes to
Individual Signal, State, and Parameter
Data Elements” on page 26-19.
Isolate data definitions in separate files for See “Organize Data to Support Component-
component-based, team-oriented model Based, Team-Oriented Model Development”
development on page 23-9.

23-7
23 Data Definition and Declaration Management in Embedded Coder

Goal Details and Techniques


Aggregate definitions of variant control As described in “Generate Preprocessor
parameters (#define macros) into a single Conditionals for Variant Systems” on page
header file 15-35, a variant control parameter is a
parameter object such as
Simulink.Parameter. You apply a
storage class that makes the object appear
in the generated code as a macro. To
control the file placement, choose one of
these techniques:

• For each variant control parameter that


uses the storage class Define, set the
Header file property to the same value.
To configure these objects in a list that
you can search, sort, and filter, you can
use the Model Data Editor Parameters
tab. For an example, see “Generate
Variant Control Macros in Same Header
File” on page 15-38.
• Create one or more storage classes that
represent variant control parameters. In
the Custom Storage Class Designer, you
can set Header file to a value that
applies to all of the variant control
parameters that use the storage class.
With this technique, you do not need to
manually specify a header file for each
variant control parameter. For more
information, see “Create Custom
Storage Classes by Using the Custom
Storage Class Designer” on page 26-
26.

23-8
Control Placement of Global Data Definitions and Declarations in Generated Files

Organize Data to Support Component-Based, Team-Oriented


Model Development
Depending on your model configuration, data definitions can appear aggregated in large
generated files. In a system of components (subsystems or referenced models), you can
separate and organize the data definitions into manageable, meaningful files based on the
component hierarchy.

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).

Instead, you can place global data


definitions with other components in the
hierarchy. For an example involving
referenced models, see “Establish Data
Ownership in a System of Components” on
page 23-15.

• To place a data definition with the code


generated for a referenced model, use a
built-in storage class such as
ExportToFile, or a storage class that
you create in a package, and set the
Owner property to the name of the
referenced model.

To use Owner in a model, you must


select the model configuration
parameter Use owner from data
object for data definition placement.
The default setting for this parameter,
cleared, means the code generator
ignores the setting that you specify for
Owner.

If only one referenced model uses a


parameter object, consider storing the
object in the model workspace of that
model. Then, the code generated for

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.

To generate separate data structures for a


subsystem, select the Function with
separate data parameter in the subsystem
block. Then, the subsystem data appear in
separate structure variables that the
subsystem code defines. See “Generate
Modular Function Code” on page 29-65.

Specify Default Placement


When you create data in a model by adding blocks and signal lines, by default, the data
definitions appear in model.c. To specify a different default placement, use these tools
and parameters:

• 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

ExportToFile to a data category and, in the Property Inspector, use the


DefinitionFile,HeaderFile, and Owner custom attributes to control file placement.
• The model configuration parameters Data definition and Data declaration. These
configuration parameters specify the default file placement for data items to which
you apply storage classes.

• 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.

For more information, see “Data definition” and “Data declaration”.


• The subsystem block parameter Function with separate data. When you select this
parameter, the standard structures that store the subsystem data, such as the DWork
structure, appear as separate structure variables. By default, the variable definitions
appear in the source file that defines the subsystem execution function. See “Generate
Modular Function Code” on page 29-65.

Override Default Placement for Individual Data Items


For an individual data item, to override the default file placement, use the Model Data
Editor to apply a storage class directly. For example, to make a data item appear in the
generated code as a global variable, apply the custom storage class ExportToFile.
Then, use the Definition file, Header file custom attributes to control file placement. To
apply storage classes directly, see “Apply Custom Storage Classes to Individual Signal,
State, and Parameter Data Elements” on page 26-19.

Prevent Name Clashes by Configuring Data Item as static


To apply the C keyword static to a global variable, which can help you avoid name
clashes by limiting the scope of the variable name to the file that defines the variable,
choose one of these techniques:

• 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.

Code Generation Impact of Storage Location for Parameter


Objects
You can create a parameter object (such as Simulink.Parameter) in the base
workspace, a model workspace, or a data dictionary. However, when you apply a storage
class or custom storage class to the object, the location of the object can impact the file
placement of the corresponding data definition in the generated code. See “Code
Generation Impact of Storage Location for Parameter Objects” on page 22-130.

Specify Default #include Syntax for Data Header Files


To control the file placement of a data item, such as a signal line or block state, in the
generated code, you can apply a storage class to the data item (see “Apply Custom
Storage Classes to Individual Signal, State, and Parameter Data Elements” on page 26-
19). You then use the Header file custom attribute to specify the generated or external
header file that contains the declaration of the data.

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

Establish Data Ownership in a System of Components


This example shows how to establish ownership of global data in the code generated from
a system of components (referenced models).

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.

Explore Example Model

Copy the script file prepare_sldemo_fuelsys_dd_ctrl.m to your current folder.

[~, ~] = 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 the airflow_calc model.

open_system('airflow_calc')

23-16
Establish Data Ownership in a System of Components

In this model, select View > Model Data Editor.

In the Model Data Editor, set the Change view drop-down list to Code.

In the model, select the upper Outport block.

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.

In the Filter contents box, enter numerator. The Simulink.Parameter object


numerator_param, which is in the base workspace, sets the value of the Numerator
parameter in the Discrete Filter block labeled Throttle Transient. The object uses
the storage class ExportToFile.

23-17
23 Data Definition and Declaration Management in Embedded Coder

Select the Signals tab.

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 the fuel_calc 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.

Generate and Inspect Code

Generate code from the controller model, sldemo_fuelsys_dd_controller.

rtwbuild('sldemo_fuelsys_dd_controller')

23-18
Establish Data Ownership in a System of Components

### Starting build procedure for model: airflow_calc


### Successful completion of build procedure for model: airflow_calc
### Starting build procedure for model: fuel_calc
### Successful completion of build procedure for model: fuel_calc
### Starting build procedure for model: sldemo_fuelsys_dd_controller
### Successful completion of build procedure for model: sldemo_fuelsys_dd_controller

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)

/* Definition for custom storage class: ExportToFile */


real32_T e0;

In the code generation report, return to the code generated for


sldemo_fuelsys_dd_controller.

The file sldemo_fuelsys_dd_controller.c defines the other global variables.

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);

/* Definition for custom storage class: ExportToFile */


real32_T est_airflow;
real32_T fb_correction;
real32_T fuel_rate;
real32_T numerator_param[2] = { 0.01F, -0.01F } ;

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.

Configure Data Ownership

In this example, you configure code generation settings so that:

• 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 airflow_calc model, select View > Property Inspector.

In the Model Data Editor, select the Inports/Outports tab.

Find the row that corresponds to the Outport block est_airflow.

In the row, click the icon in the left column. The Property Inspector shows the properties
of the Outport block.

In the Property Inspector, under Code, set CoderInfo.CustomAttributes.Owner to


airflow_calc. The code generator places the definition of the global variable with the
code generated for airflow_calc.

For fb_correction, use the Model Data Editor and the Property Inspector to set Owner
to airflow_calc.

Select the Parameters tab.

Find the row that corresponds to the parameter object, numerator_param.

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.

In the fuel_calc model, select View > Property Inspector.

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))

clear temp portHandles outportHandle numerator_param

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')

Save the component models.


save_system('fuel_calc')
save_system('airflow_calc')

Generate Improved Code

Generate code from the controller model, sldemo_fuelsys_dd_controller.


rtwbuild('sldemo_fuelsys_dd_controller')

### Starting build procedure for model: airflow_calc


### Successful completion of build procedure for model: airflow_calc
### Starting build procedure for model: fuel_calc
### Successful completion of build procedure for model: fuel_calc
### Starting build procedure for model: sldemo_fuelsys_dd_controller
### Successful completion of build procedure for model: sldemo_fuelsys_dd_controller

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)

/* Definition for custom storage class: ExportToFile */

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)

/* Definition for custom storage class: ExportToFile */


real32_T fuel_rate;

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.

In the est_airflow property dialog box, set Storage class to ExportToFile.

23-23
23 Data Definition and Declaration Management in Embedded Coder

Set Owner to airflow_calc.

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')

clear portHandles outportHandle

Save the component models and generate code from


sldemo_fuelsys_dd_controller. The code is the same as it was before you created
the Simulink.Signal objects. Now, you can make changes to the signal objects instead
of the corresponding blocks and lines in the models.

save_system('airflow_calc')
save_system('fuel_calc')
rtwbuild('sldemo_fuelsys_dd_controller')

23-24
See Also

### Starting build procedure for model: airflow_calc


### Successful completion of build procedure for model: airflow_calc
### Starting build procedure for model: fuel_calc
### Successful completion of build procedure for model: fuel_calc
### Starting build procedure for model: sldemo_fuelsys_dd_controller
### Successful completion of build procedure for model: sldemo_fuelsys_dd_controller

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

Data Types in Embedded Coder

• “Control Data Type Names in Generated Code” on page 24-2


• “Control File Placement of Custom Data Types” on page 24-23
• “Replace and Rename Data Types to Conform to Coding Standards” on page 24-27
• “Exchange Structured and Enumerated Data Between Generated and External Code”
on page 24-34
• “Specify Boolean and Data Type Limit Identifiers” on page 24-42
24 Data Types in Embedded Coder

Control Data Type Names in Generated Code


By default, the generated code uses Simulink Coder data type aliases to define scalar and
array variables. For example, the Simulink Coder type real32_T corresponds to the
Simulink type single. The code defines these types through typedef statements that
build on C primitive types such as float and short. You can configure the code to use
custom type names instead.

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.

Control these type names to help you to:

• 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.

Control Names of Primitive Data Types


To rename a Simulink Coder primitive data type such as int8_T, first create a
Simulink.AliasType object whose name matches the type name that you want the
generated code to use. For example, to create a type named myType, at the command
prompt, enter:

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.

Simulink Coder Type Name Corresponding Simulink Type Name


real_T double
real32_T single
int32_T int32
int16_T int16
int8_T int8
uint32_T uint32
uint16_T uint16
uint8_T uint8
boolean_T boolean

For configuring data type replacement


throughout an entire model (Configuration
Parameters > Code Generation > Data
Type Replacement), you can alternatively
use one of these types:

• uint8
• int8
• intn*
int_T intn*
uint_T uintn*
char_T intn*

* Replace n with the number of bits displayed in Configuration Parameters >


Hardware Implementation for either Number of bits: int or Number of bits: char.
Use the appropriate number of bits for the data type that you want to rename.

Note The boolean_T BaseType must promote to a signed int.

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.

For an example that shows how to use a Simulink.AliasType object directly in a


model, see “Create Data Type Alias in the Generated Code” on page 24-12.

24-4
Control Data Type Names in Generated Code

Control Names of Primitive Types Technique


Change the name of a primitive type that Configure a data type replacement for an
the generated code uses to define variables entire model.
by default (for example, int8_T).
To replace a default Simulink Coder data
type name with the corresponding Simulink
type name, for example, to replace int8_T
with int8, you do not need to create a
Simulink.AliasType object. See “Use
Simulink Data Type Names Instead of
Simulink Coder Data Type Names” on page
24-6.

To share data type replacements


throughout a model reference hierarchy,
use referenced configuration sets (see
“Share a Configuration Across Referenced
Models” (Simulink)).
Configure the generated code to define a In the model, locate the data item that
particular data item, such as a variable, by corresponds to the variable. For example,
using a specific, meaningful type name. trace from the code generation report to
the model. Use the name of the
Simulink.AliasType object to set the
data type of the item.

If necessary, to prevent other data items in


upstream and downstream blocks from
using the same type name, configure those
items to use a data type setting that is not
inherited. By default, most signals use the
inherited type Inherit: Inherit via
internal rule.

24-5
24 Data Types in Embedded Coder

Control Names of Primitive Types Technique


Use the same type name for multiple In the model, use the name of a
signals and other data items in a data path, Simulink.AliasType object to set the
which is a series of connected blocks. data type of one of the signals in the path,
for example, a root-level Inport block or a
Constant block. For example, if the path
begins with an Inport block at the root level
of the model, you can specify the type in
that block. By default, due to data type
propagation, the data items in the other
blocks typically inherit the same type.

In most cases, no matter where on the data


path you specify the type, downstream data
items inherit the type. You can configure
upstream data items to inherit the type, too.
Consider specifying the type in a block that
you do not expect to remove or change
frequently.
Configure the generated code to replace an Use the name of the
implementation-dependent type, such as Simulink.AliasType object to configure
char_T or boolean_T, and another type of multiple data type replacements
equivalent bit length with a single type simultaneously. See “Replace
name that you specify. Implementation-Dependent Types with the
Same Type Name” on page 24-8.

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

To replace boolean_T, int_T, or uint_T, use the information in the table.

Simulink Coder Type Name Replacement Names to Use


boolean_T One of these names:

• boolean
• uint8
• int8
• intn*
int_T intn*
uint_T uintn*
char_T intn*

* Replace n with the number of bits displayed in Configuration Parameters >


Hardware Implementation for either Number of bits: int or Number of bits: char.
Use the appropriate number of bits for the data type that you want to replace.

24-7
24 Data Types in Embedded Coder

You cannot use this technique to replace real_T with double or real32_T with
single.

Replace Implementation-Dependent Types with the Same Type Name

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.

1 Configure your target hardware settings in Configuration Parameters > Hardware


Implementation.
2 Create a Simulink.AliasType object named myInt. In this case, because int_T
and int32_T represent a 32-bit signed integer, set BaseType to int32.

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.

Define Abstract Numeric Types and Rename Types

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.

Explore Example Model

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

Key Features of User-Defined Types

• Displayed and propagated on signal lines


• Used to parameterize a model by type (e.g., In1 specifies its Output data type as
ENG_SPEED)
• Types with a common ancestor can be mixed, whereby the common ancestor is
propagated (e.g., output of Sum1)
• Intrinsically supported by the Simulink Model Explorer
• Include an optional header file attribute that is ideal for importing legacy types
(ignored for GRT targets)
• Types used in the generated code (ignored for GRT targets)

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

• User-defined types are a feature of Simulink that facilitate parameterization of the


data types in a model. Embedded Coder preserves alias data type names (e.g.,
ENG_SPEED) in the generated code, whereas Simulink Coder implements user-define
types as their base type (e.g., real32_T).
• Embedded Coder also enables you to replace the built-in data types with user-defined
data types in the generated code.

Control Names of Structure Types


To control the names of the standard structures that Simulink Coder creates by default to
store data (model_P for parameter data, for example), use Configuration Parameters >
Code Generation > Symbols > Global types to specify a naming rule. For more
information, see “Customize Generated Identifiers” on page 78-21.

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.

Generate Code That Reuses Data Types From External Code


To generate code that reuses a data type definition from your external C code, specify the
data scope of the corresponding data type object or enumeration in Simulink as
Imported. With this setting, the generated code includes (#include) the definition from
your code. For more information about controlling the file placement of a custom data
type, see “Control File Placement of Custom Data Types” on page 24-23.

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

Create Data Type Alias in the Generated Code


This example shows how to configure the generated code to use a data type name
(typedef) that you specify.

Export Type Definition

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.

Create a Simulink.AliasType object named mySingleAlias that acts as an alias for


the built-in data type single.

mySingleAlias = Simulink.AliasType('single')

mySingleAlias =

AliasType with properties:

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 the model rtwdemo_basicsc.

open_system('rtwdemo_basicsc')

24-12
Control Data Type Names in Generated Code

Configure the model to show the generated names of blocks.


set_param('rtwdemo_basicsc','HideAutomaticNames','off')

In the model, select View > Model Data Editor.

In the model, select the Inport block labeled In1.

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')

Generate code from the model.


rtwbuild('rtwdemo_basicsc')

24-13
24 Data Types in Embedded Coder

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: rtwdemo_basicsc

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"

typedef real32_T mySingleAlias;


typedef creal32_T cmySingleAlias;

#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

/* External inputs (root inport signals with default storage) */


typedef struct {
mySingleAlias input1; /* '<Root>/In1' */
real32_T input2; /* '<Root>/In2' */
real32_T input3; /* '<Root>/In3' */
real32_T input4; /* '<Root>/In4' */
} ExtU_rtwdemo_basicsc_T;

Import Type Definition

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_

typedef float myTypeAlias;

#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.

At the command prompt, create a Simulink.AliasType object named myTypeAlias


that creates an alias for the built-in type single. The Simulink data type single
corresponds to the C data type float.

myTypeAlias = Simulink.AliasType('single')

myTypeAlias =

AliasType with properties:

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';

Open the model rtwdemo_basicsc.


open_system('rtwdemo_basicsc')

In the model, select View > Model Data Editor.

In the model, select the Inport block labeled In1.

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')

Generate code from the model.


rtwbuild('rtwdemo_basicsc')

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: rtwdemo_basicsc

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)

/* External inputs (root inport signals with default storage) */


typedef struct {
myTypeAlias input1; /* '<Root>/In1' */
real32_T input2; /* '<Root>/In2' */
real32_T input3; /* '<Root>/In3' */
real32_T input4; /* '<Root>/In4' */
} ExtU_rtwdemo_basicsc_T;

Display Base Data Types and Aliases on Model Diagram

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).

Create a Named Fixed-Point Data Type in the Generated Code


This example shows how to create and name a fixed-point data type in generated code.
You can use the name of the type to specify parameter and signal data types throughout a
model and in generated code.

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 the model rtwdemo_fixpt1.

open_system('rtwdemo_fixpt1')

24-17
24 Data Types in Embedded Coder

Configure the model to show the generated names of the blocks.

set_param('rtwdemo_fixpt1','HideAutomaticNames','off')

In the model, select View > Model Data Editor.

In the Model Data Editor, select the Parameters tab.

In the model, select the Gain block.

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 Simulink.Parameter property dialog box, set Storage class to


ExportedGlobal. Click OK. With this setting, myParam appears in the generated code
as a separate global variable.

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')

Select the configuration parameter Generate code only.


set_param('rtwdemo_fixpt1','GenCodeOnly','on')

Generate code from the model.


rtwbuild('rtwdemo_fixpt1')

24-19
24 Data Types in Embedded Coder

### Starting build procedure for model: rtwdemo_fixpt1


### Successful completion of code generation for model: rtwdemo_fixpt1

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_

typedef int16_T myFixType;


typedef cint16_T cmyFixType;

#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)

myFixType myParam = 128; /* Variable: myParam

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

rtwdemo_fixpt1_Y.Out1 = (myFixType)((myParam * rtb_Conversion) >> 4);

Rename Data Type Object


To rename a data type object such as Simulink.AliasType or Simulink.Bus after you
create it (for example, to rename an alias when coding standards change or when you
encounter a naming conflict), you can allow Simulink to rename the object and correct all
of the references to the object that appear in a model or models. In the Model Explorer,
right-click the variable and select Rename All. For more information, see “Rename
Variables” (Simulink).

Display Signal Data Types on Block Diagram


For readability, you can display signal data types directly on a block diagram. When you
use custom names for primitive data types, you can choose to display the custom name
(the alias), the underlying primitive, or both. See “Port Data Types” (Simulink).

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.

Data Type Replacement Limitations

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

Control File Placement of Custom Data Types


By default, when you use data type objects, such as Simulink.AliasType and
Simulink.Bus, and custom enumerations to specify data types for signals and block
parameters, the code generated from the model defines the types (for example, with
typedef statements). To ease integration of the generated code with other existing code
and to modularize the generated code, you can control the file placement of the type
definitions by adjusting the properties of the objects and the enumerations.

Data Scope and Header File


To control the file placement of a custom type definition in generated code, set the
DataScope and HeaderFile properties of the data type object according to the table.
Similarly, for an enumeration that you define in a MATLAB file, set the return arguments
of the getDataScope and getHeaderFile methods.

• typename is the name of the custom data type.


• filename is the name of a header file.
• model is the name of the model.

Goal Specify DataScope as Specify HeaderFile as


Export type definition to Auto Empty
model_types.h
Import type definition from Auto or Imported filename (if necessary,
a header file that you include a .h extension)
create, filename
Export type definition to a Exported filename or filename.h
generated header file,
filename.h
Export type definition to a Exported Empty
generated header file,
typename.h

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

Considerations for Data Type Replacement

• 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.

Import Definition of Numerically Complex Data Type

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"

typedef int32_T IAT_int32;


typedef cint32_T cIAT_int32;

#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.

Suppose you use several Simulink.AliasType objects: mySingleAlias,


myDoubleAlias, and myIntAlias with these properties:

• DataScope set to Exported


• HeaderFile set to myTypes.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"

typedef real_T myDoubleAlias;


typedef real32_T mySingleAlias;
typedef int16_T myIntAlias;

#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:

• DataScope set to Auto


• HeaderFile not specified

When you generate code, the file model_types.h contains the guarded typedef
statement:

#ifndef _DEFINED_TYPEDEF_FOR_mySingleAlias_
#define _DEFINED_TYPEDEF_FOR_mySingleAlias_

typedef real32_T 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

Replace and Rename Data Types to Conform to Coding


Standards
By default, the generated code uses data type aliases such as real_T and int32_T. The
code uses these aliases to define global and local variables. If your coding standards
require that you use other data type aliases, including aliases that your existing code
defines, you can:

• Configure data type replacement for the entire model.


• Configure individual data items (such as signals, parameters, and states) to use
specific data type aliases.

For information about controlling data types in a model, see “Control Signal Data Types”
(Simulink).

Inspect External C Code


Save this C code into a file named my_types.h in your current folder. This file represents
a header file in your existing code that defines custom data type aliases by using typedef
statements.

#include <stdbool.h>

typedef double my_dblPrecision;


typedef short my_int16;
typedef bool my_bool;

Explore Example Model and Default Generated Code


1 Open the example model ex_data_type_replacement.

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

5 Set the Change view drop-down list to Design.


6 Update the block diagram.

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.

typedef double real_T;


10 Inspect the file ex_data_type_replacement.c. The code uses the default data
type aliases to declare and define variables. For example, the code uses the data
types real_T, int16_T, and boolean_T to define the global variables flowIn,
temp, and intlk.

real_T flowIn; /* '<Root>/In3' */


int16_T temp; /* '<Root>/Add2' */
boolean_T intlk; /* '<S1>/Compare' */

The model step function defines local variables by using the same data type aliases.

real_T rtb_Add;
real_T rtb_FilterCoefficient;

Reuse External Data Type Definitions


Configure the generated code to define variables by using the custom data types defined
in my_types.h instead of the default type names.
1 At the command prompt, create a Simulink.AliasType object for each data type
alias that your external code defines.

Simulink.importExternalCTypes('my_types.h');

In the base workspace, the Simulink.importExternalCTypes function creates


the objects my_dblPrecision, my_int16, and my_bool.

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.

Simulink Name Replacement Name


double my_dblPrecision
int16 my_int16
boolean my_bool
4 Generate code from the model.
5 In the code generation report, inspect the file rtwtypes.h. Now, the code uses an
#include directive to import the contents of the external header file my_types.h,
which contains the custom data type aliases.
#include "my_types.h" /* User defined replacement datatype for int16_T real_T boolean_T */

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.

my_dblPrecision flowIn; /* '<Root>/In3' */


my_int16 temp; /* '<Root>/Add2' */
my_bool intlk; /* '<S1>/Compare' */

The model step function defines local variables by using the custom data type
aliases.

my_dblPrecision rtb_Add;
my_dblPrecision rtb_FilterCoefficient;

Create Meaningful Data Type Aliases for Individual Data Items


Suppose your coding standards require that important data items use a data type whose
name indicates the real-world significance. You can create more Simulink.AliasType
objects to represent these custom data type aliases. Use the objects to set the data types
of data items in the model.

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.

Block Output Data Type


Flow Setpoint flow_T
Add2 (which feeds the Compare block) diffTemp_T
2 Use the Model Data Editor Inports/Outports tab to set the data type of the third
Inport block to flow_T.
3 In the model, select View > Property Inspector.
4 Select the block labeled Flow Controller. In the Property Inspector, click Open to
open the block dialog box.
5 On the Data Types tab, set Sum output to ctrl_T. Click OK.

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

typedef my_dblPrecision flow_T;


typedef my_int16 diffTemp_T;
typedef my_dblPrecision ctrl_T;
10 In the file ex_data_type_replacement.c, the code defines global variables by
using the new type names.

flow_T flowIn; /* '<Root>/In3' */


flow_T flowSetPt; /* '<Root>/Flow Setpoint' */
ctrl_T flowCtrl; /* '<Root>/Interlock' */
diffTemp_T temp; /* '<Root>/Add2' */
11 For blocks that do not use the new data types, the corresponding generated code
continues to use the replacement types that you specified earlier. For example, in the
file ex_data_type_replacement.h, the outputs of the blocks In1 and In2 appear
as structure fields that use the replacement type my_int16.

/* External inputs (root inport signals with auto storage) */


typedef struct {
my_int16 In1; /* '<Root>/In1' */
my_int16 In2; /* '<Root>/In2' */
} ExtU_ex_data_type_replacement_T;

Create Single Point of Definition for Primitive Types


The custom data type aliases flow_T and ctrl_T map to the primitive data type double.
If you want to change this underlying data type from double to single (float), you
must remember to modify the BaseType property of both Simulink.AliasType
objects.

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.

1 At the command prompt, create a Simulink.NumericType object to represent the


primitive data type single.

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.

By default, the Simulink.NumericType object does not cause another typedef


statement to appear in the generated code.

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).

Permanently Store Data Type Objects


The Simulink.NumericType and Simulink.AliasType objects in the base workspace
do not persist if you end your current MATLAB session. To permanently store these
objects, consider migrating your model to a data dictionary. See “Migrate Models to Use
Simulink Data Dictionary” (Simulink).

Create and Maintain Objects Corresponding to Multiple C


typedef Statements
To create Simulink.AliasType objects for a large number of typedef statements in
your external C code, consider using the Simulink.importExternalCTypes function.

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

Exchange Structured and Enumerated Data Between


Generated and External Code
This example shows how to generate code that exchanges data with external, existing
code. Construct and configure a model to match data types with the external code and to
avoid duplicating type definitions and memory allocation (definition of global variables).
Then, compile the generated code together with the external code into a single
application.

Inspect External Code


Create the file ex_cc_algorithm.c in your current folder.

#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.

Create the file ex_cc_algorithm.h in your current folder.

#ifndef ex_cc_algorithm_h
#define ex_cc_algorithm_h

typedef float float_32;

typedef enum {

24-34
Exchange Structured and Enumerated Data Between Generated and External Code

TMP_HI = 0,
TMP_LO,
NORM,
} err_T;

typedef struct inSigs_tag {


err_T err;
float_32 sig1;
float_32 sig2;
} inSigs_T;

typedef struct calPrms_tag {


float_32 cal1;
float_32 cal2;
float_32 cal3;
} calPrms_T;

extern calPrms_T calPrms;


extern inSigs_T inSigs;

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:

• Defines and initializes calPrms.


• Calculates values for the fields of inSigs.
• Reuses the type definitions (such as err_T and float_32) that the external code
defines.

24-35
24 Data Types in Embedded Coder

Create Simulink Model


1 So that you can create enumerated and structured data in the Simulink model, first
create Simulink representations of the data types that the external code defines.
Store the Simulink types in a new data dictionary named ex_cc_integ.sldd.

Simulink.importExternalCTypes('ex_cc_algorithm.h',...
'DataDictionary','ex_cc_integ.sldd');

The data dictionary appears in your current folder.


2 To inspect the dictionary contents in the Model Explorer, in your current folder,
double-click the file, ex_cc_integ.sldd.

The Simulink.importExternalCTypes function creates Simulink.Bus,


Simulink.AliasType, and Simulink.data.dictionary.EnumTypeDefinition
objects that correspond to the custom C data types from ex_cc_algorithm.h.
3 Create a new model and save it in your current folder as ex_struct_enum_integ.
4 Link the model to the data dictionary. In the model, select File > Model Properties
> Link to Data Dictionary.
5 Add algorithmic blocks that calculate the fields of inSigs.

24-36
Exchange Structured and Enumerated Data Between Generated and External Code

Now that you have the algorithm model, you must:

• Organize the output signals into a structure variable named inSigs.


• Create the structure variable calPrms.
• Include ex_cc_algorithm.c in the build process that compiles the code after code
generation.

24-37
24 Data Types in Embedded Coder

Configure Generated Code to Write Output Data to Existing


Structure Variable
1 Add a Bus Creator block near the existing Outport blocks. The output of a Bus
Creator block is a bus signal, which you can configure to appear in the generated
code as a structure.
2 In the Bus Creator block, set these parameters:

• 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.

Configure Generated Code to Define Parameter Data


Configure the generated code to define the global structure variable, calPrms, that the
external code needs.

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

5 On the Bus Editor toolbar, click the Create/Edit a Simulink.Parameter Object


from a Bus Object button.
6 In the MATLAB Editor, copy the generated MATLAB code and run the code at the
command prompt. The code creates a Simulink.Parameter object in the base
workspace.
7 In the Model Explorer Model Hierarchy pane, select Base Workspace.
8 Use the Model Explorer to move the parameter object, calPrms_T_Param, from the
base workspace to the Design Data section of the data dictionary.
9 With the data dictionary selected, in the Contents pane, rename the parameter
object as calPrms.
10 In the Model Data Editor, select the Parameters tab.
11 Set the Change view drop-down list to Design.
12 For the Gain block, replace the value 13.8900013 with calPrms.cal1.
13 In the other Gain block, use calPrms.cal2.
14 While editing the value of the other Gain block, next to calPrms.cal2, click the

action button and select calPrms > Open.


15
In the calPrms property dialog box, next to the Value box, click the action button
and select Open Variable Editor.
16 Use the Variable Editor to set the field values in the parameter object.

• 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.

When you finish, close the Variable Editor.


17 In the property dialog box, set Storage class to ExportedGlobal. Click OK.
18 Use the Model Explorer to save the changes that you made to the dictionary.

Generate, Compile, and Inspect Code


1 Configure the model to include ex_cc_algorithm.c in the build process. Set
Configuration Parameters > Code Generation > Custom Code > Additional
build information > Source files to ex_cc_algorithm.c.
2 Generate code from the model.

24-40
See Also

3 Inspect the generated file ex_struct_enum_integ.c. The file defines and


initializes calPrms.

/* Exported block parameters */


calPrms_T calPrms = {
13.8900013F,
0.998300076F,
15.23F
} ; /* Variable: calPrms

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);

Replace Data Type Names Throughout Model


To generate code that uses float_32 instead of the default, real32_T, instead of
manually specifying the data types of block output signals and bus elements, you can use
data type replacement (Configuration Parameters > Code Generation > Data Type
Replacement). For more information, see “Replace and Rename Data Types to Conform
to Coding Standards” on page 24-27.

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

Specify Boolean and Data Type Limit Identifiers


You can use command-line parameters to replace the default Boolean and data type limit
identifiers. If you want to associate the data type limit identifiers with the data type
names, consider replacing the default identifiers. You can also use command-line
parameters to import a header file with the Boolean and data type limit identifier
definitions.

Data Type Limit Identifiers


You can control the data type limit identifiers in the generated code by using the
command-line parameters in this table.

Data Type Limit Default Identifier Command-Line Parameter


8-bit integer maximum MAX_int8_T MaxIdInt8
16-bit integer maximum MAX_int16_T MaxIdInt16
32-bit integer maximum MAX_int32_T MaxIdInt32
8-bit unsigned integer MAX_uint8_T MaxIdUint8
maximum
16-bit unsigned integer MAX_uint16_T MaxIdUint16
maximum
32-bit unsigned integer MAX_uint32_T MaxIdUint32
maximum
8-bit integer minimum MIN_int8_T MinIdInt8
16-bit integer minimum MIN_int16_T MinIdInt16
32-bit integer minimum MIN_int32_T MinIdInt32

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

#define s4g_S4MAX ((int8_T)(127))


#define s4g_S4MIN ((int8_T)(-128))

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.

Boolean Default Identifier Command-Line Parameter


True true BooleanTrueId
False false BooleanFalseId

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:

#define bFalse (0U)


#define bTrue (1U)

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.

Boolean and Data Type Limit Identifier Header Files


You can import a header file that defines Boolean and data type limit identifiers using the
command-line parameter TypeLimitIdReplacementHeaderFile. The header file is
included in rtwtypes.h. You must use the command-line parameters to specify the
Boolean and data type limit identifiers that are included in the imported header file.

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');

The generated file rtwtypes.h includes myfile.h.

/* Import type limit identifier replacement definitions. */


#include "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

Module Packaging Tool (MPT) Data


Objects in Embedded Coder
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder

MPT Data Object Properties


In this section...
“Specify Persistence Level for Signals and Parameters” on page 25-16
“Register mpt User Object Types” on page 25-19

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

Parameter and Signal Property Values

Class: Property Available Property Description


Parameter, Values
Signal, or (* Indicates
Both Default)
Both User object type *auto Prenamed and predefined property sets
that are registered in the
sl_customization.m file. (See
“Register mpt User Object Types” on
page 25-19.) This field is active when a
user object type is registered.

Select auto if this field is available but


you do not want to apply the properties of
a user object type to a selected data
object. The fields on the Model Explorer
are populated with default values.
Listed user object Select a user object type name to apply
type name the properties and values that you
associated with this name in the
sl_customization.m file. The fields on
the Model Explorer are automatically
populated with those values.
Parameter Value *0 The data type and numeric value of the
data object. For example, int8(5). The
numeric value is used as an initial
parameter value in the generated code.
Both Data type Used to specify the data type for an
mpt.Signal data object, but not for an
mpt.Parameter data object. The data
type for an mpt.Parameter data object
is specified in the Value field above. See
“About Data Types in Simulink”
(Simulink).
Both Unit *null Units of measurement of the signal or
parameter. (Enter text in this field.)

25-4
MPT Data Object Properties

Class: Property Available Property Description


Parameter, Values
Signal, or (* Indicates
Both Default)
Both Dimensions *-1 The dimension of the signal or parameter.
For a parameter, the dimension is derived
from its value.
Both Complexity *auto Complexity specifies whether the signal
or parameter is a real or complex number.
real Select auto for the code generator to
decide. For a parameter, the complexity is
complex derived from its value.
Signal Sample time *-1 Model or block execution rate.
Signal Sample mode *auto Determines how the signal propagates
through the model. Select auto for the
code generator to decide.
Sample based The signal propagates through the model
one sample at a time.
Frame based The signal propagates through the model
in batches of samples.
Both Minimum *0.0 The minimum value to which the
parameter or signal is expected to be
bound.
Number within the
minimum range of the
parameter or signal.
(Based on the data
type and resolution of
the parameter or
signal.)
Both Maximum *0.0 Maximum value to which the parameter
or signal is expected to be bound. (Enter
information using a dialog box.)
Code generation
options

25-5
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder

Class: Property Available Property Description


Parameter, Values
Signal, or (* Indicates
Both Default)
Storage class Note that an auto selection for a storage
class tells the build process to decide how
to declare and store the selected
parameter or signal.
Both Global (Custom) Global (Custom) is Specifies that a code generator not place
the default storage a qualifier in the data object's declaration.
class for mpt data
objects.
Both Memory section *Default Memory section allows you to specify
storage directives for the data object.
Default specifies that the code
generator not place a type qualifier and
pragma statement with the data object's
declaration.
Parameter MemConst Places the const type qualifier in the
declaration.
Both MemVolatile Places the volatile type qualifier in the
declaration.
Parameter MemConstVolatile Places the const volatile type
qualifier in the declaration.

25-6
MPT Data Object Properties

Class: Property Available Property Description


Parameter, Values
Signal, or (* Indicates
Both Default)
Both Header file Name of the file used to import or export
the data object. This file contains the
declaration (extern) to the data object.

Also, you can specify this header filename


between the double-quotation or angle-
bracket delimiter. You can specify the
delimiter with or without the .h
extension. For example, specify
"object.h" or "object". For the
selected data object, this overrides the
general delimiter selection in the
#include file delimiter field on the
Configuration Parameters dialog box.
Both Owner *Blank The name of the module that owns this
signal or parameter. This is used to help
determine the ownership of a definition.
For details, see “Control Placement of
Global Data Definitions and Declarations
in Generated Files” on page 23-2.
Both Definition file *Blank Name of the file that defines the data
object.
Valid character vector

25-7
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder

Class: Property Available Property Description


Parameter, Values
Signal, or (* Indicates
Both Default)
Both Persistence level The number you specify is relative to
Signal display level or Parameter tune
level on the Code Placement pane of the
Configuration Parameters dialog box. For
a signal, allows you to specify whether or
not the code generator declares the data
object as global data. For a parameter,
allows you to specify whether or not the
code generator declares the data object
as tunable global data. See Signal
display level and Parameter tune level
in “Model Configuration Parameters:
Code Generation Code Placement”.
Both Bitfield (Custom) Embeds Boolean data in a named bit field.
Struct name Name of the struct into which the
object's data will be packed.
Parameter Const (Custom) Places the const type qualifier in the
declaration.
Parameter Header file See above.
Parameter Owner See above.
Parameter Definition file See above.
Parameter Persistence See above.
level
Both Volatile (Custom) Places the volatile type qualifier in the
declaration.
Both Header file See above.
Both Owner See above.
Both Definition file See above.
Both Persistence See above.
level

25-8
MPT Data Object Properties

Class: Property Available Property Description


Parameter, Values
Signal, or (* Indicates
Both Default)
Parameter ConstVolatile Places the const volatile type
(Custom) qualifier in declaration.
Parameter Header file See above.
Parameter Owner See above.
Parameter Definition file See above.
Parameter Persistence See above.
level
Parameter Define (Custom) Represents parameters with a #define
macro.
Parameter Header file See above.
Both ExportToFile Generates global variable definition, and
(Custom) generates a user-specified header (.h) file
that contains the declaration (extern) to
that variable.
Both Memory section See above.
Both Header file See above.
Both Definition file See above.
Both ImportFromFile Includes predefined header files
(Custom) containing global variable declarations,
and places the #include in a
corresponding file. Assumes external code
defines (allocates memory) for the global
variable.
Both Data access *Direct Allows you to specify whether the
identifier that corresponds to the selected
data object stores data of a data type
(Direct) or stores the address of the
data (a pointer).

25-9
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder

Class: Property Available Property Description


Parameter, Values
Signal, or (* Indicates
Both Default)
Both Pointer If you select Pointer, the code generator
places * before the identifier in the
generated code.
Header file See above.
Both Struct (Custom) Embeds data in a named struct to
encapsulate sets of data.
Both Struct name See above.
Signal GetSet (Custom) Reads (gets) and writes (sets) data using
functions.
Signal Header file See above.
Signal Get function Specify the Get function.
Signal Set function Specify the Set function.
Both Alias *null As explained in detail in “Override Data
Object Naming Rules” on page 39-18,
for a Simulink or mpt data object
(identifier), specifying a name in the Alias
field overrides the global naming rule
selection you make on the Configuration
Parameters dialog box.
Valid ANSIa C/C++
variable name
Both Description *null Text description of the parameter or
signal. Appears as a comment beside the
signal or parameter's identifier in the
generated code.
Character vector

25-10
MPT Data Object Properties

Class: Property Available Property Description


Parameter, Values
Signal, or (* Indicates
Both Default)
Signal Reusable Allows the code generator to reuse a pair
(Custom) of root I/O signals when you specify the
same name and the same custom storage
class for both. The custom storage class is
either Reusable (Custom) or derived
from Reusable (Custom).
Signal Data Scope *Auto You can specify the scope of symbols code
generation generates for a data object of
this class by selecting a value for
DataScope. When you take the default of
Auto, code generation determines the
symbol scope internally. If possible,
symbols have File scope. Otherwise,
they have Exported scope.
File Code generation defines the scope of each
symbol as the file that defines it. File
scope requires each symbol to be used in
a single file. If the same symbol is
referenced in multiple files, code
generation reports an error.
Exported Code generation exports symbols to
external code in the header file specified
by the HeaderFile field. If a HeaderFile
is not specified, symbols are exported to
external code in model.h.
Imported Code generation imports symbols from
external code in the header file specified
by the HeaderFile field. If you do not
specify a header file, code generation
generates an extern directive in
model_private.h.
Signal Header file See above.
Signal Owner See above.

25-11
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder

Class: Property Available Property Description


Parameter, Values
Signal, or (* Indicates
Both Default)
Signal Definition file See above.
a. ANSI is a registered trademark of the American National Standards Institute, Inc.

25-12
MPT Data Object Properties

mpt Package Custom Storage Classes

CSC Name Purpose Signals? Parameters?


BitField Generate a struct declaration Y Y
that embeds Boolean data in
named bit fields.
CompilerFlag Supports preprocessor N Y
conditionals defined via compiler
flag. See “Generate Preprocessor
Conditionals for Variant Systems”
on page 15-35.
Const Generate a constant declaration N Y
with the const type qualifier.
ConstVolatile Generate declaration of volatile N Y
constant with the const
volatile type qualifier.
Define Generate #define directive. Y Y
ExportToFile Generate header (.h) file, with Y Y
user-specified name, containing
global variable declarations.
FileScope Generate a static qualifier suffix Y Y
for a variable declaration so that
the scope of the variable is limited
to the current file.
GetSet Supports specialized function calls Y Y
to read and write the memory
associated with a Data Store
Memory block. See “Access Data
Through Functions with Custom
Storage Class GetSet” on page 26-
42.
Global The default custom storage class Y Y
for the mpt package. Generate the
declaration and definition of a data
object in specified files, and use
the specified memory section.

25-13
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder

CSC Name Purpose Signals? Parameters?


ImportedDefin Supports preprocessor N Y
e conditionals defined via legacy
header file. See “Generate
Preprocessor Conditionals for
Variant Systems” on page 15-35.
ImportFromFil Generate directives to include Y Y
e predefined header files containing
global variable declarations.
Reusable Allows the code generator to reuse Y N
a pair of root I/O signals when you
specify the same name and the
same custom storage class for
both. The custom storage class is
either Reusable (Custom) or
derived from Reusable
(Custom).
Struct Generate a struct declaration Y Y
encapsulating parameter or signal
object data.
StructConst Generate a struct declaration, N Y
with a const type qualifier,
encapsulating parameter object
data.
StructVolatil Generate a struct declaration, Y Y
e with a volatile type qualifier,
encapsulating parameter or signal
object data.
Volatile Use volatile type qualifier in Y Y
declaration.

25-14
MPT Data Object Properties

Examples of Property Value Changes on Generated Code

What I noticed when Change I made to property What I noticed after


inspecting the .c/.cpp file value settings regenerating and
reinspecting the file
Example 1: In the Model Explorer, I clicked the I notice two differences. One
Parameter data objects can be data object GAIN. I noticed that is that now GAIN is declared
declared or defined as the property value for its Memory as a variable with the
constants. I know that the data section property is set at statement real_T GAIN =
object GAIN is a parameter. I MemConst. I changed this to 5.0;. The second difference
want this to be declared or Default. is that the declaration now is
defined in the .c file as a located in the MemConst
variable. But I notice that GAIN memory section in the .c
is declared as a constant by the or .cpp file.
statement const real_T
GAIN = 5.0;. Also, this
statement is in the constant
section of the file.
Example 2: I changed the Storage class GAIN is not declared in the .c
I notice again the declaration of selection to Define (Custom). file as a MemConst
GAIN in the .c file mentioned parameter. Rather, it is
in Example 1. It appears as defined as a #define macro
real_T GAIN = 5.0;. But I by the code #define GAIN
have changed my mind. I want 5.0, and this is located near
data object GAIN to be the top of the .c file with the
#define. other preprocessor directives.
Example 3: On the Model Explorer, I notice #define GAIN 5.0 is not
I changed my mind again after that the property value for the present in this .c file.
doing Example 2. I do want Header file property is blank. I Instead, the #include
GAIN defined using the changed this to filename.h. (I filename.h code appears as
#define preprocessor chose the ANSI C/C++ double a preprocessor directive at
directive. But I do not want to quote mechanism for the the top of the file.
include the #define in this file. #include, but could have chosen
I know it exists in another file the angle bracket mechanism.)
and I want to reference that Also, I must make the user-defined
file. filename.h available to the
compiler, placing it either in the
system path or local directory.

25-15
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder

What I noticed when Change I made to property What I noticed after


inspecting the .c/.cpp file value settings regenerating and
reinspecting the file
Example 4: In the Model Explorer, I selected The identifier
I have one more change I want the data object data_in. I noticed data_in_alias now
to make. Let us say that we that the Alias field is blank. I appears in the .c file
have declared the data object changed this to data_in_alias, everywhere data_in
data_in, and that its which I know is a valid ANSI C/C+ appeared.
declaration statement in the .c + variable name.
file reads
real_T data_in = 0.0;. I
want to replace this statement
with an alias in the .c file.

Specify Persistence Level for Signals and Parameters


With this procedure, you can control the persistence level of signal and parameter objects
associated with a model. Persistence level allows you to make intermediate variables or
parameters global during initial development. At the later stages of development, you can
use this procedure to remove these signals and parameters for efficiency. Use the
Persistence Level property of mpt.Signal and mpt.Parameter data objects. For
descriptions of the properties on the Model Explorer, see “MPT Data Object Properties”
on page 25-2.

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

Register mpt User Object Types


• “Introduction” on page 25-19
• “Register mpt User Object Types Using sl_customization.m” on page 25-19
• “mpt User Object Type Customization Using sl_customization.m” on page 25-20

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).

Register mpt User Object Types Using sl_customization.m

To register mpt user object type customizations, you create an instance of


sl_customization.m and include it on the MATLAB path of the Simulink installation
that you want to customize. The sl_customization function accepts one argument: a
handle to a customization manager object. For example,
function sl_customization(cm)

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:

• addMPTObjectType(hObj, objectTypeName, classtype, propName1,


propValue1, propName2, propValue2, ...)

25-19
25 Module Packaging Tool (MPT) Data Objects in Embedded Coder

addMPTObjectType(hObj, objectTypeName, classtype, {propName1,


propName2, ...}, {propValue1, propValue2, ...})

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.

• objectTypeName — Name of the user object type


• classType — Class to which the user object type applies: 'Signal',
'Parameter', or 'Both'
• propName — Name of a property of an mpt or mpt-derived data object to be
populated with a corresponding propValue when the registered user object type
is selected
• propValue — Specifies the value for a corresponding propName
• moveMPTObjectTypeToTop(hObj, objectTypeName)

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.

mpt User Object Type Customization Using sl_customization.m

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.

Example 25.1. sl_customization.m for mpt Object Type Customizations


function sl_customization(cm)
% Register user customizations

25-20
MPT Data Object Properties

% Get default (factory) customizations


hObj = cm.slDataObjectCustomizer;

% Add commonly used signal types


hObj.addMPTObjectType(...
'EngineType','Signal',...
'DataType', 'uint8',...
'Min', 0,...
'Max', 255,...
'Unit','m/s');

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:

1 Start a MATLAB session.


2 Open Model Explorer, for example, by entering the MATLAB command daexplr.
3 Select Base Workspace.
4 Add an mpt signal, for example, by selecting Add > Add Custom.
5 In the right-hand pane display for the added mpt signal, examine the User object
type drop-down list, noting the impact of the changes specified in “mpt User Object
Type Customization Using sl_customization.m” on page 25-20.
6 From the User object type drop-down list, select one of the registered user signal
types, for example, FuelType, and verify that the displayed settings are consistent
with the arguments specified to the addMPTObjectType method in
sl_customization.m.

25-21
26

Custom Storage Classes in


Embedded Coder

• “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

Reuse Parameter Data from External Code in the


Generated Code
This example shows how to generate code that imports a parameter value from your
external code.

Create External Code Files

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
};

Save the declaration in your current folder in a file called ex_vector_import_decs.h.

#include "ex_vector_import_cust_types.h"

extern my_int8 myGains[3];

Save the data type definition my_int8 in your current folder in a file called
ex_vector_import_cust_types.h.

typedef signed char my_int8;

Import Parameter Value for Simulation

In your current folder, right-click the file ex_vector_import_src.c and select Import
Data.

In the Import dialog box, set Output Type to Numeric Matrix.

Set the name of the generated MATLAB variable to tempVar.

Select only the parameter values (2, 4, and 6) to import.

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.

Alternatively, use the command prompt to manually create tempVar.


tempVar = [2;4;6];

At the command prompt, create a Simulink.Parameter object that represents


myGains.
myGains = Simulink.Parameter(tempVar);

Create and Configure Model

Create the model ex_vector_import.


open_system('ex_vector_import')

In the model, select View > Model Data Editor.

In the Model Data Editor, inspect the Parameters tab.

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.

Set the Change view drop-down list to Code.

Set these properties for myGains:

• Storage Class to ImportFromFile


• Header File to ex_vector_import_decs.h

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';

At the command prompt, create a Simulink.AliasType object to represent your


custom data type my_int8. Set the DataScope and HeaderFile properties to import
the type definition from your external code.
my_int8 = Simulink.AliasType('int8');
my_int8.DataScope = 'Imported';
my_int8.HeaderFile = 'ex_vector_import_cust_types.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')

Generate and Inspect Code

Generate code from the model.


rtwbuild('ex_vector_import')

26-4
Reuse Parameter Data from External Code in the Generated Code

### Starting build procedure for model: ex_vector_import


### Successful completion of build procedure for model: ex_vector_import

The generated file ex_vector_import.h includes the external header files


ex_vector_import_decs.h and ex_vector_import_cust_types.h, which contain
the parameter variable declaration (myGains) and custom type definition (my_int8).

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"

/* Includes for objects with custom storage classes. */


#include "ex_vector_import_decs.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)

/* Model step function */


void ex_vector_import_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Gain: '<Root>/Gain'
* Inport: '<Root>/In1'
*/
rtY.Out1[0] = (real_T)myGains[0] * rtU.In1;
rtY.Out1[1] = (real_T)myGains[1] * rtU.In1;
rtY.Out1[2] = (real_T)myGains[2] * rtU.In1;
}

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

Import Parameter Data with Conditionally Compiled


Dimension Length
Suppose your external code conditionally allocates memory for and initializes lookup table
and breakpoint set data based on a dimension length that you specify as a #define
macro. This example shows how to generate code that imports this external global data.

Create External Code Files

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

extern double T1Break[bpLen];


extern double T1Data[bpLen];

Explore and Configure Example Model

Open the example model rtwdemo_basicsc.

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.

At the command prompt, convert the variables to Simulink.Parameter objects.


T1Data = Simulink.Parameter(T1Data);
T1Break = Simulink.Parameter(T1Break);

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';

At the command prompt, create a Simulink.Parameter object to represent the custom


macro bpLen.

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.

T1Data.Dimensions = '[1 bpLen]';


T1Break.Dimensions = '[1 bpLen]';
set_param('rtwdemo_basicsc','AllowSymbolicDim','on')

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')

Generate and Inspect Code

Generate code from the model.

rtwbuild('rtwdemo_basicsc')

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: 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

Access Structured Data Through a Pointer That External


Code Defines
This example shows how to generate code that uses global data that some handwritten
code defines. In the handwritten code, a pointer variable points to one of two structure
variables that contain parameter data. A handwritten function switches the pointer
between the two structures. The generated code accesses the parameter data by
dereferencing the pointer variable.

Explore External Code

Open the example source file rtwdemo_importstruct_user.c. The code defines a


structure variable ReferenceStruct as constant (const) data and statically initializes
each field.

/* Constant default data struct: ReferenceStruct */


const DataStruct_type ReferenceStruct =
{
11, /* OFFSET */
2 /* GAIN */
};

The code defines another structure variable, WorkingStruct, as volatile (volatile)


data.

/* Volatile data struct: WorkingStruct */


volatile DataStruct_type WorkingStruct;

The code defines a function that copies the field values from ReferenceStruct to
WorkingStruct.

/* Function to initialize WorkingStruct with data from ReferenceStruct */


void Init_WorkingStruct(void)
{
memcpy((void*)&WorkingStruct, &ReferenceStruct, sizeof(ReferenceStruct));
}

The code defines StructPointer, which is a const volatile pointer to a structure.


The code initializes the pointer to the address of ReferenceStruct.

26-12
Access Structured Data Through a Pointer That External Code Defines

/* Create pointer to the default data struct, e.g. ReferenceStruct */


const volatile DataStruct_type *StructPointer = &ReferenceStruct;

Finally, the code defines a function that can dynamically set StructPointer to point to
either ReferenceStruct or WorkingStruct.

/* Function to switch between structures */


void SwitchStructPointer(Dataset_T Dataset)
{
switch (Dataset)
{
case Working:
StructPointer = &WorkingStruct;
break;
default:
StructPointer = &ReferenceStruct;
}
}

The example header file rtwdemo_importstruct_user.h defines the enumeration


Dataset_T and the structure type Datastruct_type. The file includes (#include) the
built-in Simulink® Coder™ header file rtwtypes.h, which defines (typedef) Simulink
Coder data types such as int16_T.

#include "rtwtypes.h"

typedef enum {
Reference=0,
Working
} Dataset_T;

typedef struct DataStruct_tag {


int16_T OFFSET; /* OFFSET */
int16_T GAIN; /* GAIN */
} DataStruct_type;

The file also declares the global variables and the functions.

Purpose of External Code

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

dereferencing (->) StructPointer. A software engineer can write code that


dynamically switches StructPointer between the address of WorkingStruct and
ReferenceStruct by passing the corresponding enumeration member as the input
argument in calls to the SwitchStructPointer function.

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.

Explore Example Model

Open the example model, rtwdemo_importstruct.

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.

In the model, select View > Model Data Editor.

26-15
26 Custom Storage Classes in Embedded Coder

In the Model Data Editor, inspect the Parameters tab.

Set the Change view drop-down list to Code.

Click the Show/refresh additional information button.

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')

This example package defines multiple custom storage classes, including


StructPointer. You cannot edit the definitions. However, you can create your own
packages and custom storage classes later. For an example that shows how to create a
package and a custom storage class, see “Create and Apply a Custom Storage Class” on
page 26-26.

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

structure variable in the generated code. In this example, StructPointer is the


name of the variable that the external code defines.
• Type name is set to DataStruct_type, which is the name of the structure type that
the example 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.

Generate and Inspect Code

Generate code from the model.

In the generated file rtwdemo_importstruct.c, the model initialization function calls


Init_WorkingStruct.

/* Model initialize function */


void rtwdemo_importstruct_initialize(void)
{
/* user code (Initialize function Body) */

/* Initialize the volatile memory data set before switching to it */


Init_WorkingStruct();
}

/*

The algorithm in the model execution (step) function dereferences the pointer variable
StructPointer.

/* Model step function */


void rtwdemo_importstruct_step(void)

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

Apply Custom Storage Classes to Individual Signal,


State, and Parameter Data Elements
In “Apply Storage Classes to Individual Signal, State, and Parameter Data Elements” on
page 22-81, you control the declaration and definition of global variables in the generated
code by applying storage classes directly to individual data elements. With Embedded
Coder and an ERT-based system target file, you can use custom storage classes for more
precise control over the way that data appear in the generated code.

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.

Built-In Custom Storage Classes


For a list of built-in custom storage classes that you can choose, see “Choose a Storage
Class for Controlling Data Representation in the Generated Code” on page 22-69.

Create Your Own Custom Storage Class


If the custom storage classes from the Simulink package do not satisfy your
requirements, you can define your own custom storage classes. For information about
defining your own custom storage class, see “Create Code Definitions to Override Default
Settings” on page 20-3.

Techniques to Apply Custom Storage Classes Interactively


To directly apply a custom storage class from the built-in package Simulink interactively,
use the same techniques that you use to directly apply standard storage classes,
described in “Apply Storage Classes to Individual Signal, State, and Parameter Data
Elements” on page 22-81.

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.

Target Class Does Not Appear in List of Signal Object Classes

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:

1 From the list, select Customize class lists.


2 In the dialog box, under Signal classes, select the check box next to the class that
you want. For example, to use custom storage classes from the built-in package mpt,
select the check box next to mpt.Signal. Click OK.

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

1 In the Model Explorer Model Hierarchy pane, select Base Workspace.


2
In the toolbar, click the arrow next to the Add Signal button.
3 In the drop-down list, select Customize class lists.
4 In the Customize class lists dialog box, select a signal class from the target
package. Click OK.
5 In the Model Explorer toolbar, click the arrow next to the Add Signal button.
6 In the drop-down list, select the target signal class.

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).

Techniques to Apply Custom Storage Classes


Programmatically
To apply a custom storage class to an individual data item programmatically:

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).

Apply Custom Storage Class Directly to Signal Line Programmatically

This example shows how to apply a custom storage class directly to a signal line in a
model, without an external data object.

1 Open the example model rtwdemo_secondOrderSystem.

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;

3 Set the name of the corresponding signal to ForceSignal.

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

Modify Custom Storage Class Applied Directly to Signal Line

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

Organize Parameter Data into a Structure by Using the Struct


Custom Storage Class
This example shows how to use the Struct custom storage class to organize block
parameter values into a structure in the generated code. You apply the storage class
directly to individual data items in a model.

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

2 In the model, select View > Model Data Editor.


3 In the Model Data Editor, select the Parameters tab.
4 In the model, select the upper Constant block.
5 In the Model Data Editor, use the Value column to set the constant value to p1.
6
Next to p1, click the action button and select Create.
7 In the Create New Data dialog box, set Value to Simulink.Parameter(1.0) and
click Create.

A Simulink.Parameter object named p1 appears in the base workspace.


8 In the property dialog box for p1, click OK.
9 Use the Model Data Editor to set the other constant values by using parameter
objects named p2 (value 2.0) and p3 (value 3.0).
10 In the Model Data Editor, set the Change view drop-down list to Code.
11 Click the Show/refresh additional information button.

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.

The file ex_struct_param.h defines a structure type, my_struct_type.


/* Type definition for custom storage class: Struct */
typedef struct my_struct_tag {
real_T p1;
real_T p2;

26-24
See Also

real_T p3;
} my_struct_type;

The file ex_struct_param.c defines the global variable my_struct.


/* Definition for custom storage class: Struct */
my_struct_type my_struct = {
/* p1 */
1.0,

/* p2 */
2.0,

/* p3 */
3.0
};

Custom Storage Class Limitations


For information about limitations, see “Storage Class Limitations” on page 22-77.

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

Create Custom Storage Classes by Using the Custom


Storage Class Designer
You can use built-in custom storage classes such as ExportToFile to control the
appearance of data in the generated code (see “Apply Custom Storage Classes to
Individual Signal, State, and Parameter Data Elements” on page 26-19). If the built-in
custom storage classes do not satisfy your requirements, you can create your own custom
storage classes. As described in “Define Storage Classes, Memory Sections, and Function
Templates for Software Architecture” on page 20-2, to create a custom storage class that
you can apply to individual data elements (for example, in the Model Data Editor), you
must create the storage class in a package by using the Custom Storage Class Designer.

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.

Create and Apply a Custom Storage Class


This example shows how to control code generated from a model by creating and
applying your own custom storage class.

Explore Example Model

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.

Create Data Class Package

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.

% Remember the current folder path


currentPath = pwd;

% Navigate to the example package folder


demoPath = '\toolbox\simulink\simdemos\dataclasses';
cd([matlabroot,demoPath])
2 Copy the +SimulinkDemos folder to your clipboard.
3 Return to your working 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

The function useLocalCustomStorageClasses allows you to apply the custom


storage classes that myPackage defines to data objects that you create from
myPackage.
7 Save and close the file.
8 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'.
9 Save and close the file.

26-27
26 Custom Storage Classes in Embedded Coder

Create Custom Storage Class

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.

Apply Custom Storage Class

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

1 Generate code for the example model.

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.

/* Declaration for custom storage class: ExportToGlobal */


extern boolean_T O2alarm;
extern real_T O2limit;
extern boolean_T pressurealarm;
extern real_T pressurelimit;
extern boolean_T rpmalarm;
extern real_T rpmlimit;
extern boolean_T tempalarm;
extern real_T templimit;
3 View the generated file global.c. The file contains the definitions of the model
signals and parameters that use the custom storage class ExportToGlobal.

/* Definition for custom storage class: ExportToGlobal */


boolean_T O2alarm;
real_T O2limit = 0.96;
boolean_T pressurealarm;
real_T pressurelimit = 45.2;
boolean_T rpmalarm;
real_T rpmlimit = 7400.0;
boolean_T tempalarm;
real_T templimit = 202.0;

Modify a Built-In Custom Storage Class


You cannot directly modify a built-in custom storage class, such as ExportToFile from
the Simulink package, but you can create a copy, and then modify the copy. When you
create a new package with no csc_registration.m file, and then open the Custom
Storage Class Designer for the first time in that package, Simulink copies the definitions
of the built-in custom storage classes into the package. Then, in the Custom Storage Class
Designer, you can modify the copied definitions. Alternatively, to keep the built-in custom
storage classes available in your package, copy one of them by clicking Copy, then modify
the resulting copy.

26-30
Create Custom Storage Classes by Using the Custom Storage Class Designer

Control Data Representation by Configuring Custom Storage


Class Properties
The Custom Storage Class Designer is a tool for creating and managing custom storage
classes and memory sections. To open the Custom Storage Class Designer for a specific
package, for example, +mypkg, at the command prompt, use the cscdesigner function:

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.

Kind of Data in Generated Code Technique


Structure Set Type to FlatStructure. See
“Generate Structured Data” on page 26-
33.
Macro Set Data initialization to Macro and clear
For signals. See “Generate a Macro” on
page 26-32.
Pointer Set Data access to Pointer and Data
scope to Auto, Imported, or Instance
specific. Your external code must define
the pointer variable.
static data (file-scoped data) Set Data scope to File.
const or volatile data Set Memory section to a memory section
that specifies const, volatile, or both.
For example, use one of the built-in memory
sections MemConst, MemVolatile, and
MemConstVolatile. To create your own
memory section, see “Control Data and
Function Placement in Memory by Inserting
Pragmas” on page 30-2.

26-31
26 Custom Storage Classes in Embedded Coder

Kind of Data in Generated Code Technique


Calls to external functions to read and write See “Call Custom Accessor Functions or
to data Macros Instead of Reading and Writing to
Variables” on page 26-34.

Allow Users of Custom Storage Class to Specify Property Value

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).

Generate Structured Data

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.

Control Assignment of Initial Value in Generated Code

• To use the default Simulink Coder initialization strategy, set Data initialization to the
default value, Auto.

• The generated code statically initializes parameter data with an assignment


statement at the top of a .c or .cpp source file, outside of any function.
• The generated code dynamically initializes signal and state data as part of the
initialization function of the model (named model_initialize by default).
• To statically initialize the data, set Data initialization to Static.
• To dynamically initialize the data, set Data initialization to Dynamic.
• To prevent the generated code from initializing the data, set Data initialization to
None. When your external code initializes the data, use this setting to prevent the
generated code from overwriting your initialization.

26-33
26 Custom Storage Classes in Embedded Coder

Call Custom Accessor Functions or Macros Instead of Reading and Writing to


Variables

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 create a similar custom storage class, set Type to AccessFunction.

• Specify the names of the external functions.

• 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).

Generate Code That Uses Data From External Code

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

Generate Code Comments with Data Definitions and Declarations

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.

Avoid Errors During Code Generation by Validating Custom


Storage Class Configuration
As you configure a custom storage class in the Custom Storage Class Designer, to check
for possible errors in the configuration, click Validate.

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.

Make Custom Storage Classes Available Outside the Current


Folder
To use a custom storage class that you create, you must make the defining package
available. Either set your current folder to the folder that contains the package or add the
folder containing the package folder to the MATLAB path (see “What Is the MATLAB
Search Path?” (MATLAB)). Adding the package to the MATLAB path enables you to use
the custom storage classes no matter where you set your current folder.

Share Custom Storage Class Between Packages


When you create a package, you can refer to a custom storage class defined in another
package such as the built-in package Simulink or a different package that you created.

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.

Control Appearance of Storage Class Drop-Down List


When you apply a custom storage class to a data item, you select the custom storage class
from a drop-down list.

• 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.

Protect Custom Storage Class Definitions


When you click Save in the Custom Storage Class Designer, the Designer saves memory
section and custom storage class definitions into the csc_registration.m file in the
package folder. To determine the location of this file, in the Custom Storage Class
Designer, inspect the value of Filename.

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.

A best practice is to keep both csc_registration.m and csc_registration.p in


your package folder. That way, if you need to modify the custom storage classes by using
the Designer, you can delete csc_registration.p and later regenerate it after you
finish the modifications. Because the P-coded version of the file takes precedence, when
both files exist in the package, the custom storage classes are protected and cannot be
modified in the Custom Storage Class Designer.

Further Customize Generated Code by Writing TLC Code


If creating your own custom storage class by manipulating the properties in the Custom
Storage Class Designer does not satisfy your requirements, you can finely control the
generated code by writing TLC code for your custom storage class. Use an advanced
mode of the Custom Storage Class Designer and, for the custom storage class, set Type to
Other. See “Finely Control Data Representation by Writing TLC Code for a Custom
Storage Class” on page 26-39.

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

Finely Control Data Representation by Writing TLC Code


for a Custom Storage Class
If creating your own custom storage class by using the properties in an Embedded Coder
Dictionary or the Custom Storage Class Designer does not meet your requirements for
controlling data representation in the generated code, you can write TLC code that
explicitly controls the effect that a custom storage class has on the code. For example, to
create a custom storage class that yields arbitrarily nested structures, you must write
TLC code. In the Custom Storage Class Designer, these advanced custom storage classes
have Type set to Other. You cannot create such a storage class in an Embedded Coder
Dictionary, so you cannot use the storage class as a default code generation setting in the
Code Mapping Editor.

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).

Create Custom Attributes Class for Custom Storage Class


As described in “Allow Users of Custom Storage Class to Specify Property Value” on page
26-32, instance-specific properties enable users of a custom storage class to control the
effect that the storage class has on each data item. For example, the built-in custom
storage class ExportToFile has several instance-specific properties such as Header file
and Definition file.

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).

Write TLC Code for Custom Storage Class


To control the effect of your custom storage class, write TLC code that specifies the code
to generate for each data item.

26-39
26 Custom Storage Classes in Embedded Coder

1 In your package folder (for example, +myPackage), create a tlc folder.


2 Copy a TLC template such as TEMPLATE_v1.tlc from the folder matlabroot/
toolbox/rtw/targets/ecoder/csc_templates (open) into your tlc folder.
3 Write your TLC code, following the comments in the template file. The comments
describe how to specify, for example, how the generated code declares, defines, and
accesses (by value or by reference) each data item.

Create Custom Storage Class by Using Custom Storage Class


Designer
To create your custom storage class in your package, you open the Custom Storage Class
Designer in an advanced mode.

1 At the command prompt, enter:

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

Access Data Through Functions with Custom Storage


Class GetSet
To integrate the generated code with legacy code that uses specialized functions to read
from and write to data, you can use the custom storage class GetSet. Signals, block
parameters, and states that use GetSet appear in the generated code as calls to accessor
functions. You provide the function definitions.

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”.

Access Legacy Data Using Get and Set Functions


This example shows how to generate code that interfaces with legacy code by using
specialized get and set functions to access data.

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)

/* Scalar get() and set() functions */

double get_inSig(void)
{
return ex_getset_data.scalars.inSig;
}

void set_inSig(double value)


{
ex_getset_data.scalars.inSig = value;
}

double get_scalarParam(void)
{
return ex_getset_data.scalars.scalarParam;

26-43
26 Custom Storage Classes in Embedded Coder

void set_scalarParam(double value)


{
ex_getset_data.scalars.scalarParam = value;
}

double get_outSig(void)
{
return ex_getset_data.scalars.outSig;
}

void set_outSig(double value)


{
ex_getset_data.scalars.outSig = value;
}

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.

Generate code with the example model.

rtwbuild('rtwdemo_getset_scalar');

### Starting build procedure for model: rtwdemo_getset_scalar


### Successful completion of build procedure for model: 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)

/* Model step function */


void rtwdemo_getset_scalar_step(void)
{
/* Gain: '<Root>/Gain' incorporates:
* Inport: '<Root>/In1'
*/
set_outSig(get_scalarParam() * get_inSig());
}

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.

Use GetSet with Vector Data


This example shows how to apply the custom storage class GetSet to signals and
parameters that are vectors.

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 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.

rtwdemodbtype('ComponentDataHdr.h','/* VectorData */','} VectorData;',1,1)

/* 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.

rtwdemodbtype('getsetSrc.c','/* Field "vectors" */','/* End of "vectors" */',1,1)

26-46
Access Data Through Functions with Custom Storage Class GetSet

/* Field "vectors" */
{
{5.7, 6.8, 1.2, 3.5, 10.1},

{12.3, 18.7, 21.2, 28, 32.9},

{0.0, 0.0, 0.0, 0.0, 0.0}


},
/* End of "vectors" */

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)

/* Vector get() and set() functions */

double get_inVector(int index)


{
return ex_getset_data.vectors.inVector[index];
}

void set_inVector(int index, double value)


{
ex_getset_data.vectors.inVector[index] = value;
}

double get_vectorParam(int index)


{
return ex_getset_data.vectors.vectorParam[index];
}

void set_vectorParam(int index, double value)


{
ex_getset_data.vectors.vectorParam[index] = value;
}

double get_outVector(int index)


{

26-47
26 Custom Storage Classes in Embedded Coder

return ex_getset_data.vectors.outVector[index];
}

void set_outVector(int index, double value)


{
ex_getset_data.vectors.outVector[index] = value;
}

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.

Generate code with the example model.

rtwbuild('rtwdemo_getset_vector');

### Starting build procedure for model: rtwdemo_getset_vector


### Successful completion of build procedure for model: 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)

/* Model step function */


void rtwdemo_getset_vector_step(void)
{
int32_T i;

/* Gain: '<Root>/Gain' incorporates:


* Inport: '<Root>/In1'
*/
for (i = 0; i < 5; i++) {
set_outVector(i, get_vectorParam(i) * get_inVector(i));
}

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.

Use GetSet with Structured Data


This example shows how to apply the custom storage class GetSet to nonvirtual bus
signals and structure parameters in a model.

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.

rtwdemodbtype('ComponentDataHdr.h','/* StructData */','} StructData;',1,1)

/* 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.

rtwdemodbtype('ComponentDataHdr.h','/* SigBus */','} ParamBus',1,1)

/* 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},

{12.3, 9.6, 1.76},

{0.0, 0.0, 0.0}


},
/* End of "structs" */

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)

/* Structure get() and set() functions */

SigBus get_inStruct(void)
{
return ex_getset_data.structs.inStruct;
}

void set_inStruct(SigBus value)


{
ex_getset_data.structs.inStruct = value;
}

ParamBus get_structParam(void)
{
return ex_getset_data.structs.structParam;
}

void set_structParam(ParamBus value)


{
ex_getset_data.structs.structParam = value;
}

SigBus get_outStruct(void)

26-51
26 Custom Storage Classes in Embedded Coder

{
return ex_getset_data.structs.outStruct;
}

void set_outStruct(SigBus value)


{
ex_getset_data.structs.outStruct = value;
}

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.

Generate code with the example model.

rtwbuild('rtwdemo_getset_struct');

### Starting build procedure for model: rtwdemo_getset_struct


### Successful completion of build procedure for model: 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)

/* Model step function */


void rtwdemo_getset_struct_step(void)
{
/* Bias: '<Root>/Bias' incorporates:
* Inport: '<Root>/In1'
*/
rtDW.BusCreator.cmd = (get_inStruct()).cmd + (get_structParam()).offset;

/* Gain: '<Root>/Gain' incorporates:


* Inport: '<Root>/In1'
*/
rtDW.BusCreator.sensor1 = (get_structParam()).gain1 * (get_inStruct()).sensor1;

/* Gain: '<Root>/Gain1' incorporates:


* Inport: '<Root>/In1'
*/
rtDW.BusCreator.sensor2 = (get_structParam()).gain2 * (get_inStruct()).sensor2;

26-53
26 Custom Storage Classes in Embedded Coder

/* SignalConversion: '<Root>/Signal Conversion' */


set_outStruct(rtDW.BusCreator);
}

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.

Use GetSet with Matrix Data


This example shows how to apply the custom storage class GetSet to signals and
parameters that are matrices.

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},

{8.3, 12.0, 11.5, 2.0, 5.7,


7.5, 12.8, 11.1, 8.4, 9.9,
10.9, 4.6, 2.7, 16.3, 3.8},

{0.0, 0.0, 0.0,


0.0, 0.0, 0.0,
0.0, 0.0, 0.0}
}
/* End of "matrices" */

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

#define MATRIXOUTPUT_NROWS MATRIXPARAM_NROWS


#define MATRIXOUTPUT_NCOLS MATRIXINPUT_NCOLS

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)

/* Matrix get() and set() functions */

double get_matrixInput(int colIndex)


{
int rowIndexGetInput = MATRIXINPUT_NCOLS * (colIndex % MATRIXINPUT_NROWS) + colInde
return ex_getset_data.matrices.matrixInput[rowIndexGetInput];
}

void set_matrixInput(int colIndex, double value)


{
int rowIndexSetInput = MATRIXINPUT_NCOLS * (colIndex % MATRIXINPUT_NROWS) + colInde
ex_getset_data.matrices.matrixInput[rowIndexSetInput] = value;
}

double get_matrixParam(int colIndex)


{
int rowIndexGetParam = MATRIXPARAM_NCOLS * (colIndex % MATRIXPARAM_NROWS) + colInde
return ex_getset_data.matrices.matrixParam[rowIndexGetParam];
}

void set_matrixParam(int colIndex, double value)


{
int rowIndexSetParam = MATRIXPARAM_NCOLS * (colIndex % MATRIXPARAM_NROWS) + colInde
ex_getset_data.matrices.matrixParam[rowIndexSetParam] = value;
}

double get_matrixOutput(int colIndex)


{

26-56
Access Data Through Functions with Custom Storage Class GetSet

int rowIndexGetOut = MATRIXOUTPUT_NCOLS * (colIndex % MATRIXOUTPUT_NROWS) + colInde


return ex_getset_data.matrices.matrixOutput[rowIndexGetOut];
}

void set_matrixOutput(int colIndex, double value)


{
int rowIndexSetOut = MATRIXOUTPUT_NCOLS * (colIndex % MATRIXOUTPUT_NROWS) + colInde
ex_getset_data.matrices.matrixOutput[rowIndexSetOut] = value;
}

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.

Generate code with the example model.

rtwbuild('rtwdemo_getset_matrix');

### Starting build procedure for model: rtwdemo_getset_matrix


### Successful completion of build procedure for model: 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)

/* Model step function */


void rtwdemo_getset_matrix_step(void)
{
int32_T i;
int32_T i_0;
int32_T i_1;

26-58
Access Data Through Functions with Custom Storage Class GetSet

int32_T matrixOutput_tmp;

/* Product: '<Root>/Product' incorporates:


* Constant: '<Root>/Constant'
* Inport: '<Root>/In1'
*/
for (i_0 = 0; i_0 < 3; i_0++) {
for (i = 0; i < 3; i++) {
matrixOutput_tmp = i + 3 * i_0;
set_matrixOutput(matrixOutput_tmp, 0.0);
for (i_1 = 0; i_1 < 5; i_1++) {
set_matrixOutput(matrixOutput_tmp, get_matrixParam(3 * i_1 + i) *
get_matrixInput(5 * i_0 + i_1) + get_matrixOutput(3 *
i_0 + i));
}

Specify Header File or Function Naming Scheme for All Data


Items
By default, you specify a header file name, get function name, and set function name for
each data item, such as a signal or parameter, that uses the custom storage class GetSet.

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.

Access Scalar and Array Data Through Macro Instead of


Function Call
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.

• 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

GetSet Custom Storage Class Restrictions


• GetSet does not support complex signals.
• Multiple data in the same model cannot use the same GetFunction or SetFunction.
• Some blocks do not directly support GetSet.
• Custom S-functions do not directly support GetSet.

To use GetSet with an unsupported block or a custom S-function:

1 Insert a Signal Conversion block at the output of the block or function.


2 In the Signal Conversion block dialog box, select Exclude this block from 'Block
reduction' optimization.
3 Assign the custom storage class GetSet to the output of the Signal Conversion block.

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

Integrate External Application Code with Code


Generated from PID Controller
This example shows how to generate C code from a control algorithm model and integrate
that code with existing, external application code. In the complete application, which
consists of three modules, the algorithm module must exchange data with other modules
through global variables. In the example, you configure the generated code to interact
with existing external variables, resemble the external code in appearance and
organization, and conform to specific coding requirements.

Inspect External Code

Set your current folder to a writable location.

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');

In your current folder, open ext_code_main.c. This application code represents an


embedded system with a trivial scheduling algorithm (a while loop) and three modules
whose algorithms run in every execution cycle: ex_ext_inputs_proc,
ex_ext_ctrl_alg, and ex_ext_outputs_proc.

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'))

In the io_drivers folder, inspect ex_sensor_accessors.c. This file defines functions,


get_fromSensor_flow and get_fromSensor_temp, that return raw data recorded by
a flow sensor and a temperature sensor. For this example, the functions return trivial
sinusoidal stimuli for the control algorithm.

type(fullfile('io_drivers','ex_sensor_accessors.c'))

26-62
Integrate External Application Code with Code Generated from PID Controller

In the ex_ext_inputs_proc folder, inspect ex_ext_inputs_proc.c. The


ex_ext_inputs_proc module reads the sensor data (by calling the accessor functions),
filters the data, and stores it in two global variables, PROC_INPUT_FLOW and
PROC_INPUT_TEMP. These global variables are defined in the file
ex_ext_proc_inputs.c and declared in ex_ext_proc_inputs.h.

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.

In the ex_ext_outputs_proc folder, inspect ex_ext_outputs_proc.c. This module


reads the PID output signals from global variables named CONTR_SIG_FLOW and
CONTR_SIG_TEMP. The ex_ext_ctrl_alg module (the generated code) must define
these variables. The ex_ext_outputs_proc module then filters these signals and passes
the filtered values to functions that represent device drivers for actuators (for example, a
valve and a heater filament).

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

Inspect Simulink Model and Determine Requirements for Generated Code

Open the example model ex_ext_ctrl_alg.


open_system('ex_ext_ctrl_alg')

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).

To complete the application by performing the function of the ex_ext_ctrl_alg


module, the code generated from this model must:

• 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.

Configure Model to Use Custom Data Types

Set your current folder to the shared folder.

26-65
26 Custom Storage Classes in Embedded Coder

Use the function Simulink.importExternalCTypes to generate


Simulink.AliasType objects that represent the custom data types dataPath_flow_T
and dataPath_temp_T.

cd('shared')
Simulink.importExternalCTypes('ex_ext_projTypes.h');

The objects appear in the base workspace.

In the ex_ext_ctrl_alg model, select View > Model Data Editor.

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.

Select the Signals tab.

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 Interface Data

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

Select the rows that correspond to the two Inport blocks.

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.

For the rows that correspond to the Outport blocks, set:

• Storage Class to ExportToFile


• Header file to ex_ext_ctrl_sigs.h
• Definition File to ex_ext_ctrl_sigs.c

With ExportToFile, the generated code defines the global variable.

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.

Select the Parameters tab and set Change view to Design.

26-67
26 Custom Storage Classes in Embedded Coder

In the model, select the Constant block labeled Flow Setpt.

In the Model Data Editor, set Value to PARAM_setpoint_flow.

Next to PARAM_setpoint_flow, click the action button (with three vertical dots) and
select Create.

In the Create New Data dialog box, set Value to Simulink.Parameter(3).

Set Location to Model Workspace and click Create.

In the PARAM_setpoint_flow property dialog box, set Storage class to Const.

Set HeaderFile to ex_ext_ctrl_params.h and DefinitionFile to


ex_ext_ctrl_params.c.

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')

clear temp PARAM_setpoint_flow PARAM_setpoint_temp mdlwks portHandles outportHandle

Configure Internal Data

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:

• $R represents the name of the model, ex_ext_ctrl_alg.


• $N represents the name of each model element to which the scheme applies, such as a
signal, block state, or standard data structure.
• $M represents name-mangling text that the code generator inserts, if necessary, to
avoid name clashes. For most naming rules, this token is required.

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');

Configure Organization of Code in Each Generated File

Set your current folder to the ex_ext_ctrl_alg folder.

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'))

Copy the ert_code_template.cgt file to your clipboard.

Return to the ex_ext_ctrl_alg folder. To avoid overwriting your clipboard, instead of


using the command prompt to navigate to the folder, you can use the Back button in
MATLAB.

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')

Generate and Inspect Code

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')

Generate code from the model.

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)

The setpoint parameters appear in ex_ext_ctrl_params.c.

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

Configure Generated Code According to Interface


Control Document Interactively
This example shows how to configure code generation settings for a model according to
specifications in an interface control document (ICD). Store necessary Simulink variables
and objects, such as Simulink.Parameter objects, in a data dictionary.

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.

In this example, the ICD is a Microsoft® Excel® workbook.

Explore Interface Control Document

Navigate to the folder matlabroot/examples/ecoder (open). Copy this file to a


writable, working folder:

• ex_ICD_PCG_inter.xls

In Microsoft® Excel® or another compatible program, open the


ex_ICD_PCG_inter.xls workbook and view the first worksheet, Signals. Each row of
the worksheet describes a signal that crosses the interface boundary.

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.

Write External Code

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__

typedef short s16En3;

typedef short s16En7;

typedef unsigned char u8En7;

typedef short s16En15;

/* Structure type for instrument measurements. */


typedef struct {
/* Throttle angle. */
s16En3 throttle;

/* 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"

EngSensors sensors; /* Instrument measurements. */

Create the header file ex_inter_sigs.h in your current folder.

#include "ex_inter_types.h"

extern EngSensors sensors; /* Instrument measurements. */

Explore Example Model

Run the script prepare_sldemo_fuelsys_dd_inter. For this example, the script


prepares a system model, sldemo_fuelsys_dd.

run(fullfile(matlabroot,'examples','ecoder','main','prepare_sldemo_fuelsys_dd_inter'))

Open the system model sldemo_fuelsys_dd.

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.

Open the controller model sldemo_fuelsys_dd_controller.

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.

The controller model is linked to a data dictionary,


sldemo_fuelsys_dd_controller.sldd. In the lower-left corner of the model, click
the dictionary badge to open the dictionary in the Model Explorer. Then, in the Model
Explorer Model Hierarchy pane, select the Design Data node.

The dictionary already stores:

• The parameter objects


• Simulink.NumericType objects such as u8En7
• A Simulink.Bus object, EngSensors
• The definition of an enumerated data type, sldemo_FuelModes

Configure Model According to ICD

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.

Select the Inports/Outports tab (which is selected by default).

In the model, select the Inport block labeled sensors. The Model Data Editor highlights
the corresponding row.

In the ICD, select the Signals tab.

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.

In the model, select the Outport block labeled fuel_rate.

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.

Inspect the Signals tab.

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.

Select View > Model Explorer > Model Explorer.

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.

Navigate to the root level of the model.

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 Model Hierarchy pane, select the Design Data node.

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.

In the ICD, select the Numeric Types tab.

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.

In the ICD, select the Structure Types tab.

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 ICD, select the Enumerated Types tab.

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.

Generate and Inspect Code

Configure the controller model to compile the generated code into an executable by
clearing the model configuration parameter Generate code only.

Generate code from the controller model.

### Starting build procedure for model: sldemo_fuelsys_dd_controller


### Successful completion of build procedure for model: sldemo_fuelsys_dd_controller

The generated header file sldemo_FuelModes.h defines the enumeration


sldemo_FuelModes.

typedef enum {
LOW = 1, /* Default value */
RICH,
DISABLED
} sldemo_FuelModes;

26-80
Configure Generated Code According to Interface Control Document Interactively

The file sldemo_fuelsys_dd_controller_types.h includes (#include) the external


header file ex_inter_types.h, which defines data types such as u8En7 and the
structure type EngSensors.

#include "ex_inter_types.h"

The file sldemo_fuelsys_dd_controller_private.h includes the header file


ex_inter_sigs.h. This external header file contains the extern declaration of the
signal sensors, which a different software component owns.

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.

/* Exported data declaration */

/* Declaration for custom storage class: ExportToFile */


extern u8En7 PressEst[855];
extern s16En15 PumpCon[551];
extern s16En15 RampRateKiZ[25];
extern s16En3 SpeedEst[1305];
extern s16En7 ThrotEst[551];
extern sldemo_FuelModes fuel_mode;
extern s16En7 fuel_rate;

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 } ;

The algorithm is in the model step function in the file


sldemo_fuelsys_dd_controller.c. The algorithm uses the global data that the ICD
identifies. For example, the algorithm uses the value of the signal fuel_mode in a
switch block to control the flow of execution.

/* SwitchCase: '<S10>/Switch Case' */


switch (fuel_mode) {
case LOW:

26-81
26 Custom Storage Classes in Embedded Coder

/* Outputs for IfAction SubSystem: '<S10>/low_mode' incorporates:


* ActionPort: '<S12>/Action Port'
*/
/* DiscreteFilter: '<S12>/Discrete Filter' incorporates:
* DiscreteIntegrator: '<S1>/Discrete Integrator'
*/
DiscreteFilter_tmp = (int16_T)(int32_T)((int32_T)((int32_T)((int32_T)
rtDWork.DiscreteIntegrator_DSTATE << 14) - (int32_T)(-12137 * (int32_T)
rtDWork.DiscreteFilter_states_g)) >> 14);

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

Configure Generated Code According to Interface


Control Document
Import specifications from an interface control document (ICD), configure code
generation settings for a model according to the specifications, and store the settings in
data dictionaries.

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.

In this example, the ICD is a Microsoft® Excel® workbook.

Explore Interface Control Document

Navigate to the folder matlabroot/examples/ecoder (open). Copy this file to a


writable, working folder:

• ex_ICD_PCG.xls

Navigate to the folder matlabroot/examples/ecoder/main (open). Copy this file to


the same writable, working folder:

• ex_importICD_PCG.m

In Microsoft® Excel® or another compatible program, open the ex_ICD_PCG.xls


workbook and view the first worksheet, Signals. Each row of the worksheet describes a
signal that crosses the interface boundary.

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.

Write External Code

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"

EngSensors sensors; /* Instrument measurements. */

Create the header file ex_inter_sigs.h in your current folder.

#include "ex_inter_types.h"

extern EngSensors sensors; /* Instrument measurements. */

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__

typedef short s16En3;

26-84
Configure Generated Code According to Interface Control Document

typedef short s16En7;

typedef unsigned char u8En7;

typedef short s16En15;

/* Structure type for instrument measurements. */


typedef struct {
/* Throttle angle. */
s16En3 throttle;

/* Engine speed. */
s16En3 speed;

/* EGO sensors. */
s16En7 ego;

/* Manifold pressure. */
u8En7 map;
} EngSensors;

#endif

Explore Example Model

Run the script prepare_sldemo_fuelsys_dd. The script prepares a system model,


sldemo_fuelsys_dd, for this example.

run(fullfile(matlabroot,'examples','ecoder','main','prepare_sldemo_fuelsys_dd'))

Open the system model, 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.

Open the controller model, sldemo_fuelsys_dd_controller.

sldemo_fuelsys_dd_controller

26-86
Configure Generated Code According to Interface Control Document

Data items in the controller model refer to Simulink.Signal and


Simulink.Parameter objects in the base workspace. For example, the input signal
sensors refers to a Simulink.Signal object that has the same name. These objects
store settings such as data types, block parameter values, and physical units. The names
of these data items and objects match the names of the signals and parameters in the
ICD.

Import ICD Specifications into Simulink

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.

Run the ex_importICD_PCG script.

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

Generate and Inspect Code

Configure the controller model to compile the generated code into an executable by
clearing the model configuration parameter Generate code only.

Generate code from the controller model.

### Starting build procedure for model: sldemo_fuelsys_dd_controller


### Successful completion of build procedure for model: sldemo_fuelsys_dd_controller

The generated header file sldemo_FuelModes.h defines the enumeration


sldemo_FuelModes.

typedef enum {
LOW = 1, /* Default value */
RICH,
DISABLED
} sldemo_FuelModes;

The file sldemo_fuelsys_dd_controller_types.h includes (#include) the external


header file ex_inter_types.h, which defines data types such as u8En7 and the
structure type EngSensors.

#include "ex_inter_types.h"

The file sldemo_fuelsys_dd_controller_private.h includes the header file


ex_inter_sigs.h. This external header file contains the extern declaration of the
signal sensors, which a different software component owns.

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.

/* Exported data declaration */

/* Declaration for custom storage class: ExportToFile */


extern u8En7 PressEst[855]; /* Lookup table to estimate pressure on sensor f
extern s16En15 PumpCon[551]; /* Lookup table to determine pumping constant ba
extern s16En15 RampRateKiZ[25]; /* Lookup table to determine throttle rate. */
extern s16En3 SpeedEst[1305]; /* Lookup table to estimate engine speed on sens
extern s16En7 ThrotEst[551]; /* Lookup table to estimate throttle angle on se
extern sldemo_FuelModes fuel_mode; /* Fueling mode of engine. Enrich air/fuel mixtu
extern int16_T fuel_rate; /* Fuel rate setpoint. */

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. */

The algorithm is in the model step function in the file


sldemo_fuelsys_dd_controller.c. The algorithm uses the global data that the ICD
identifies. For example, the algorithm uses the value of the signal fuel_mode in a
switch block to control the flow of execution.

/* SwitchCase: '<S10>/Switch Case' incorporates:


* Constant: '<S11>/shutoff'
*/
switch (fuel_mode) {
case LOW:
/* Outputs for IfAction SubSystem: '<S10>/low_mode' incorporates:
* ActionPort: '<S12>/Action Port'
*/
/* DiscreteFilter: '<S12>/Discrete Filter' incorporates:
* DiscreteIntegrator: '<S1>/Discrete Integrator'
*/
DiscreteFilter_tmp = (int16_T)(int32_T)((int32_T)((int32_T)((int32_T)
rtDWork.DiscreteIntegrator_DSTATE << 14) - (int32_T)(-12137 * (int32_T)
rtDWork.DiscreteFilter_states_g)) >> 14);

26-89
26 Custom Storage Classes in Embedded Coder

Change Ownership of Data in ICD

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.

Rerun the ex_importICD_PCG script.

ans =

'Cannot redefine enumerated type sldemo_FuelModes because open models and existing

Generate code from the model.


### Starting build procedure for model: sldemo_fuelsys_dd_controller
### Successful completion of build procedure for model: sldemo_fuelsys_dd_controller

The generated file exported_types.h defines the structure type EngSensors and the
fixed-point data types.

typedef int16_T s16En3;


typedef int16_T s16En7;
typedef uint8_T u8En7;

26-90
Configure Generated Code According to Interface Control Document

/* Structure type for instrument measurements. */


typedef struct {
s16En3 throttle;
s16En3 speed;
s16En7 ego;
u8En7 map;
} EngSensors;

typedef int16_T s16En15;

The file signals.c now includes the definition of the signal sensors.

/* Exported data definition */

/* Definition for custom storage class: ExportToFile */


sldemo_FuelModes fuel_mode; /* Fueling mode of engine. Enrich air/fuel mixtu
int16_T fuel_rate; /* Fuel rate setpoint. */
EngSensors sensors; /* Instrument measurements. */

Migrate Base Workspace Data to Data Dictionary

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.

Create Reference Dictionary

To establish clear ownership of the data that you store in a dictionary, create reference
dictionaries.

1 Open the controller model, sldemo_fuelsys_dd_controller. Select File >


Model Properties > Link to Data Dictionary. Click New.
2 Set the name of the new dictionary to ctrlDict.sldd and click Save. In the Model
Properties dialog box, click OK.
3 In response to the message about changing the dictionary or moving the data, click
Move Data. Click Yes in response to the message about migrating data.

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).

Store Enumerated Type Definition in Data Dictionary

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

Generate Local Variables with Localizable Custom


Storage Class
For signals, if possible, generate variables that are local to functions rather than in global
storage. Generating local variables prevents the code generator from implementing
optimizations that remove these variables from the generated code. Local variables
improve observability, readability, and are helpful in debugging the generated code.

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

Generate Code with Localizable Storage Class


1 Open the model.

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

Simulink.Signal. The Storage class parameter is set to Localizable


(Custom).
3 Build the model. The Debug_b function contains this code:
static void Debug_b(const real_T rtu_In1[6], const real_T rtu_In2[6], real_T
rtd_A[6])
{
real_T Debug;
int32_T i;
for (i = 0; i < 6; i++) {
Debug = rtu_In1[i] * rtu_In2[i];
rtd_A[i] += Debug;
}
}

The Latching function contains this code:


static void Latching(const real_T rtu_In1[36], real_T rty_Out1[6], real_T
rty_Out2[6], real_T rtd_A[6])
{
real_T Latch[6];
int32_T i;
int32_T i_0;
for (i = 0; i < 6; i++) {
rty_Out2[i] = -rtd_A[i];
Latch[i] = rtd_A[i];
}

for (i = 0; i < 6; i++) {


rty_Out1[i] = 0.0;
for (i_0 = 0; i_0 < 6; i_0++) {
rty_Out1[i] += rtu_In1[6 * i_0 + i] * Latch[i_0];
}
}
}

Both functions contain variables for holding intermediate values. The Debug_b
function contains the variable Debug. The Latching function contains the variable
Latch.

Generate Code Without Localizable Storage Class


1 Change the signal storage class from Localizable to ExportToFile. For each
signal, open the Signal Properties dialog box. On the Code Generation tab, for the
Storage class parameter, select ExportToFile. The
rtwdemo_localizable_csc.c file contains these two global variable declarations:

real_T Debug[6];
real_T Latch[6];

The Debug_b function contains this code:

26-96
Generate Local Variables with Localizable Custom Storage Class

static void Debug_b(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++) {
Debug[i] = rtu_In1[i] * rtu_In2[i];
rtd_A[i] += Debug[i];
}
}

The Latching function contains this code:


static void Latching(const real_T rtu_In1[36], real_T rty_Out1[6], real_T
rty_Out2[6], real_T rtd_A[6])
{
int32_T i;
int32_T i_0;
for (i = 0; i < 6; i++) {
Latch[i] = rtd_A[i];
rty_Out2[i] = -Latch[i];
}

for (i = 0; i < 6; i++) {


rty_Out1[i] = 0.0;
for (i_0 = 0; i_0 < 6; i_0++) {
rty_Out1[i] += rtu_In1[6 * i_0 + i] * Latch[i_0];
}
}
}

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];
}
}

The Latching function contains this code:


static void Latching(const real_T rtu_In1[36], real_T rty_Out1[6], real_T
rty_Out2[6], real_T rtd_A[6])
{
int32_T i;
int32_T i_0;
for (i = 0; i < 6; i++) {
rty_Out2[i] = -rtd_A[i];
rty_Out1[i] = 0.0;
for (i_0 = 0; i_0 < 6; i_0++) {
rty_Out1[i] += rtu_In1[6 * i_0 + i] * rtd_A[i_0];
}
}
}

26-97
26 Custom Storage Classes in Embedded Coder

Without the Localizable or ExportToFile custom storage classes, the code


generator removes the Debug and Latch variables. Without these variables, the
readability and observability of the generated code decreases.

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

Data Object Wizard in Embedded


Coder
27 Data Object Wizard in Embedded Coder

Create Data Objects for Code Generation with Data


Object Wizard
To specify code generation options for signal lines, block parameters, and states in a
model, you can use data objects that you store in a workspace or data dictionary. For
basic information about data objects, see “Data Objects” (Simulink).

You can use the Data Object Wizard to create data objects for:

• New or existing models that do not use data objects.


• Existing models to which you have added signal lines or blocks.

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.

Create Data Objects

Open the example model rtwdemo_basicsc.

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.

Click Select All.

Click Create. The data objects appear in the base workspace.

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).

Set Storage Class for Data Objects

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.

Open the Model Explorer.

In the Model Hierarchy pane, select Base Workspace.

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.

Specify the HeaderFile property for all of the objects as myExportedHdrFile.h.

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.

Generate and Inspect Code

Generate code from the model.

### Starting build procedure for model: rtwdemo_basicsc


### Successful completion of build procedure for model: rtwdemo_basicsc

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.

/* Exported data declaration */

/* Declaration for custom storage class: ExportToFile */


extern int8_T K1;
extern real_T K2;
extern real32_T LOWER;
extern real32_T T1Break[11];
extern real32_T T1Data[11];
extern real32_T T2Break[3];
extern real32_T T2Data[9];
extern real32_T UPPER;
extern real32_T X;
extern real32_T input1;
extern real32_T input2;
extern real32_T input3;
extern real32_T input4;
extern boolean_T mode;
extern real32_T output;

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.

/* Exported data definition */

/* Definition for custom storage class: ExportToFile */


int8_T K1 = 2;
real_T K2 = 3.0;

27-9
27 Data Object Wizard in Embedded Coder

real32_T LOWER = -10.0F;


real32_T T1Break[11] = { -5.0F, -4.0F, -3.0F, -2.0F, -1.0F, 0.0F, 1.0F, 2.0F,
3.0F, 4.0F, 5.0F } ;

real32_T T1Data[11] = { -1.0F, -0.99F, -0.98F, -0.96F, -0.76F, 0.0F, 0.76F,


0.96F, 0.98F, 0.99F, 1.0F } ;

real32_T T2Break[3] = { 1.0F, 2.0F, 3.0F } ;

real32_T T2Data[9] = { 4.0F, 16.0F, 10.0F, 5.0F, 19.0F, 18.0F, 6.0F, 20.0F,
23.0F } ;

real32_T UPPER = 10.0F;


real32_T X;
real32_T input1;
real32_T input2;
real32_T input3;
real32_T input4;
boolean_T mode;
real32_T output;

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

Entry-Point Functions and


Scheduling in Simulink Coder

• “Configure Code Generation for Model Entry-Point Functions” on page 28-2


• “Generate C++ Class Interface to Model or Subsystem Code” on page 28-9
• “Execution of Code Generated from a Model” on page 28-13
• “Rapid Prototyping Model Functions” on page 28-25
28 Entry-Point Functions and Scheduling in Simulink Coder

Configure Code Generation for Model Entry-Point


Functions

What Is an Entry-Point Function?


An entry point is a location in code where a transfer of program control (execution)
occurs. The main function (main()) is the entry point to a C/C++ program and is called
when the application starts executing. Calls to other functions, for example from the main
function, provide entry points to function code. Program control is transferred to the
called function. The function code executes, and when finished, returns control to the
main or other calling function.

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.

Categories and Types of Generated Entry-Point Functions


The entry-point functions that the code generator produces for a model and the calling
interface for the functions depends on whether the model is:

• Rate-based or is an export-function model


• Configured for reusable, multi-instance code generation

Depending on the style and configuration of a model, the code generator produces one or
more of these entry-point functions.

Function Function Description


Category
Initialize/ model_initialize Initialization code for a model. At the start of
Terminate the application code, call the function once.
Do not use this function to reset the real-time
model data structure (rtM).

28-2
Configure Code Generation for Model Entry-Point Functions

Function Function Description


Category
model_terminate Code for turning off a system. For ERT-based
models, you can suppress generation of this
function by clearing the model configuration
parameter “Terminate function required”
(Simulink Coder) (set by default).
Execution model_step For blocks in a rate-based model, output and
update code. If you clear the model
configuration parameter “Single output/
update function” (Simulink Coder) (selected
by default), instead of producing a
model_step function, the code generator
produces functions model_output and
model_update.
model_function-name For an exported-function model, the exported
function for a subsystem.
function-name For an exported-function model, the exported
function for a Simulink Function block.
model_reset If the model includes a Reset Function block,
reset code generated. To reset conditions or
state, call the function from the application
code.
ref-model For a reference model, output and update
code.
isr_numinterrupt- For an Async Interrupt block, interrupt
number_vecinterrupt service routine (ISR) code.
-vector-offset
Shared utility function-name For shared utility functions, output code.

Configure Whether Entry-Point Functions Are Reusable


By default, for top models, the code generator produces code that is not reusable or
reentrant. Entry-point functions have a void-void interface. Code communicates with
other code by directly accessing global data structures that reside in shared memory.

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.

Default Configurations for Single-Instance C Entry-Point Functions

By default, for GRT- and ERT-based system target files, the code generator produces
single-instance C entry-point functions. The generated code:

• Creates an execution function with no arguments (void).


• Allocates memory statically (at compile time) for model data structures.

The default model configuration parameter settings for configuring single-instance entry-
point function code are:

• “Language” (Simulink Coder) set to C.


• “Code interface packaging” (Simulink Coder) set to Nonreusable function.

Generate Reusable, Multi-Instance C Entry-Point Functions

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

System Target File Interface


GRT-based • Reusable, multi-instance C entry-point functions that are
reentrant.
• Packs values of model root-level Inport blocks and Output
blocks into the real-time model data structure. Passes that
structure to the execution function as an argument by
reference.
• Allocates memory dynamically at runtime for the data of a
model instance. Allocates the memory by calling a function,
such as malloc.
ERT-based • Reusable, multi-instance C entry-point functions that are
reentrant.
• Passes the value of each model root-level Inport block and
Outport block to the execution function as a separate
argument.
• Allocates memory statically for model data structures.

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.

Generate Reusable, Multi-Instance C++ Entry-Point Functions

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.

For Access Method Type Set “External I/O access” (Simulink


Coder) To
Noninlined Method
Inlined Inlined method
Noninlined structure-based Structure-based method
Inlined structured-based Inlined structure-based method

Configure Generated Entry-Point Function Declarations


Depending on application requirements, such as integration or compliance with code
standards, you might need to configure how the code generator produces declarations for
entry-point functions. Embedded Coder provides multiple configuration options.

• 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

• Configure a specific entry-point function interface, including function and argument


naming, use of C type qualifiers (for example, const), and argument order. See
“Generate Reusable, Multi-Instance C Entry-Point Functions” on page 28-4 and
“Generate Reusable, Multi-Instance C++ Entry-Point Functions” on page 28-5.

Configure Placement of Entry-Point Functions in Memory


If your application requires that you configure the placement of entry-point functions in
memory, for example, to optimize the generated code for specific hardware, you can apply
a default memory section to a category of functions across a model. In the Code Mapping
Editor, map a function category to a function customization template that is defined to use
a specific memory section. See Code Mapping Editor.

How to Interface with Generated Entry-Point Functions


1 After generating code for a model, open and review the Code Interface Report. The
report lists the generated entry-point functions and, if applicable, variables
representing external input and output ports.
2 Add #include statements to your external code that include the generated header
files that declare the model entry-point functions.
3 Add an #include statement that includes the generated file rtwtypes.h. This file
provides necessary type definitions, #define statements, and enumerations.
4 Initialize target-specific data structures and hardware, such as ADCs or DACs.
5 If applicable, initialize data for each instance of a reusable model.
6 If applicable, write input data to generated variables that represent model Inport
blocks.
7 Call the generated entry-point functions or, if appropriate, set up use of the
rt_OneStep function.
8 If applicable, read data from generated variables that represent model Outport
blocks.

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

Generate C++ Class Interface to Model or Subsystem


Code
On the Configuration Parameters dialog box, set the Code Generation > Interface
“Code interface packaging” (Simulink Coder) parameter to C++ class for generating a C
++ class interface to model code. The generated interface encapsulates required model
data into C++ class attributes and model entry point functions into C++ class methods.
The benefits of C++ class encapsulation include:

• Greater control over access to model data


• Ability to create multiple instances of model classes
• Easier integration of model code into C++ programming environments

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.)

Generate C++ Class Interface to Model Code


To generate encapsulated C++ class code from a GRT-based model:

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.

4 Generate code for the model.


5 Examine the C++ model class code in the generated files model.h and model.cpp.
For example, the following code excerpt from the H file generated for the example

28-9
28 Entry-Point Functions and Scheduling in Simulink Coder

model rtwdemo_secondOrderSystem shows the C++ class declaration for the


model.
/* Class declaration for model rtwdemo_secondOrderSystem */
class rtwdemo_secondOrderSystemModelClass {
/* public data and function members */
public:
/* External outputs */
ExtY_rtwdemo_secondOrderSyste_T rtwdemo_secondOrderSystem_Y;

/* Model entry point functions */

/* model initialize function */


void initialize();

/* model step function */


void step();

/* model terminate function */


void terminate();

/* Constructor */
rtwdemo_secondOrderSystemModelClass();

/* Destructor */
~rtwdemo_secondOrderSystemModelClass();

/* Real-Time Model get method */


RT_MODEL_rtwdemo_secondOrderS_T * getRTM();
...
};

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.

Generate C++ Class Interface to Nonvirtual Subsystem Code


You can generate 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.

28-10
Generate C++ Class Interface to Model or Subsystem Code

• 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:

1 Open the containing model and select the subsystem block.


2 Right-click the subsystem and select C/C++ Code > Build This Subsystem.
3 When the subsystem build completes, examine the C++ class interfaces in the
generated files and the HTML code generation report. For more information about
generating and calling model entry-point methods, 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, you can use the MATLAB command RTW.configSubsystemBuild to
customize the generated C++ class interface to subsystem code.

C++ Class Interface Limitations


• 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.
• 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. On the Simulink Signal Conversion block parameter dialog box,
select Exclude this block from 'Block reduction' optimization.
• You cannot 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


• Saves states

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

Execution of Code Generated from a Model


The code generator produces algorithmic code as defined by your model. You can include
external (for example, custom or legacy) code in a model by using techniques explained in
“Choose an External Code Integration Workflow” (Simulink Coder).

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.

Execution driver for model code,


operating system interface routines,
I/O dependent routines,
solver and data logging routines.
Model code
and S-functions

Run-Time Interface

The Object-Oriented View of a Real-Time Program

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.

The next figure illustrates interrupt timing.

28-14
Execution of Code Generated from a Model

Sample interval is appropriate for this model code execution.

time
Time to execute
the model code Time available to process background tasks

Sample interval is too short for this model code execution.

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).

External Mode Communication


External mode allows communication between the Simulink block diagram and the
standalone program that is built from the generated code. In this mode, the real-time
program functions as an interprocess communication server, responding to requests from
the Simulink engine.

28-15
28 Entry-Point Functions and Scheduling in Simulink Coder

Data Logging in Single-Tasking and Multitasking Model


Execution
“Debug” on page 31-34 explains how you can save system states, outputs, and time to a
MAT-file at the completion of the model execution. The LogTXY function, which performs
data logging, operates differently in single-tasking and multitasking environments.

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.

Another difference occurs when logging data in an enabled subsystem. Consider an


enabled subsystem that has a slow signal driving the enable port and fast blocks within
the enabled subsystem. In this case, the evaluation of the enable signal occurs in a slow
task, and the fast blocks see a delay of one sample period; thus the logged values will
show these differences.

To summarize differences in logged data between single-tasking and multitasking,


differences will be seen when

• 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

Non-Real-Time Single-Tasking Systems


The pseudocode below shows the execution of a model for a non-real-time single-tasking
system.
main()
{
Initialization
While (time < final time)
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
EndWhile
Termination
}

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.

Non-Real-Time Multitasking Systems


The pseudocode below shows the execution of a model for a non-real-time multitasking
system.
main()
{

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

Real-Time Single-Tasking Systems


The pseudocode below shows the execution of a model in a real-time single-tasking
system where the model is run at interrupt level.

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
}

Real-time single-tasking execution is very similar to non-real-time single-tasking


execution, except that instead of free-running the code, the rt_OneStep function is
driven by a periodic timer interrupt.

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.

Real-Time Multitasking Systems


The following pseudocode shows how a model executes in a real-time multitasking system
where the model is run at interrupt level.

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

Mask interrupts (Disable rtOneStep from executing.)


Complete any background tasks.
Shutdown
}

Running models at interrupt level in a real-time multitasking environment is very similar


to the previous single-tasking environment, except that overlapped interrupts are
employed for concurrent execution of the tasks.

The execution of a model in a single-tasking or multitasking environment when using real-


time operating system tasking primitives is very similar to the interrupt-level examples
discussed above. The pseudocode below is for a single-tasking model using real-time
tasking primitives.

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

In this single-tasking environment, the model executes as real-time operating system


tasking primitives. In this environment, create a single task (tSingleRate) to run the
model code. This task is invoked when a clock tick occurs. The clock tick gives a
clockSem (clock semaphore) to the model task (tSingleRate). The model task waits for
the semaphore before executing. The clock ticks occur at the fundamental step size (base
rate) for your model.

Multitasking Systems Using Real-Time Tasking Primitives


The pseudocode below is for a multitasking model using real-time tasking primitives.

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".

Start clock that does a "semGive" on a clockSem semaphore.


Wait on "model-running" semaphore.
Shutdown
}

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.

Rapid Prototyping and Embedded Model Execution


Differences
The rapid prototyping program framework provides a common application programming
interface (API) that does not change between model definitions.

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

Thus, model execution code eliminates Loop...EndLoop statements and groups


ModelOutputs, LogTXY, and ModelUpdate into a single statement, model_step.

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

Rapid Prototyping Model Functions


Rapid prototyping code defines the following functions that interface with the main
program (main.c or main.cpp):

• 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.

The function MdlStart has four basic sections:

• 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

Execution Loop MdlUpdate

model_Derivatives

MdlOutputs

model_Derivatives
Integration in Minor Time Steps

MdlTerminate

End

Rapid Prototyping Execution Flow Chart

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

Data View of the Generated Code

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

• Reusing the entries in the model_B structure


• Making other entries local variables

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

• Block parameters structure (model_P): The parameters structure contains block


parameters that can be changed during execution (for example, the parameter of a
Gain block).
• External inputs structure (model_U): The external inputs structure consists of all root-
level Inport block signals. Field names are determined by either the block's output
signal name, when present, or by the Inport block's name when the output signal is
left unlabeled.
• External outputs structure (model_Y): The external outputs structure consists of all
root-level Outport blocks. Field names are determined by the root-level Outport block
names in your model.
• Real work, integer work, and pointer work structures (model_RWork, model_IWork,
model_PWork): Blocks might have a need for real, integer, or pointer work areas. For
example, the Memory block uses a real work element for each signal. These areas are
used to save internal states or similar information.

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

Function and Class Interfaces in


Embedded Coder

• “Customize Generated C Function Interfaces” on page 29-2


• “Configure Names for Generated C Initialize and Step Functions” on page 29-5
• “Configure C Step Function Arguments” on page 29-9
• “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 Function Interfaces for Simulink Function and Function Caller
Blocks” on page 29-24
• “Customize Function Interfaces for Nonvirtual Subsystems” on page 29-32
• “Customize Generated C++ Class Interfaces” on page 29-36
• “Generate Modular Function Code” on page 29-65
29 Function and Class Interfaces in Embedded Coder

Customize Generated C Function Interfaces

Options for Configuring Generated C Function Interfaces


To facilitate integration of external and generated code and achieve compliance with code
standards and guidelines, you can configure how the code generator produces function
interfaces from a model or subsystem. For this level of customization, you must configure
the model with an ERT-based system target file.

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

Function Interface Customization Limitations for Rate-Based


Models
The following limitations apply to customizations for generated function interfaces:

• 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

Configure Names for Generated C Initialize and Step


Functions
You can configure a rate-based model so that the code generator produces custom names
for generated entry-point initialize (model_initialize) and step (model_step)
functions. For example, when you want to:

• 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.

1 Open an existing model or create a new model.


2 Open the Configure C/C++ Function Interface dialog box. On the Code
Generation>Interface pane of the Configuration Parameters dialog box, click
Configure Model Functions. Unless a function prototype was previously
configured, the dialog box opens showing a preview of the step function interface
with no arguments (void-void). The dialog box also shows current function names.

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

Configure C Step Function Arguments


You can configure a rate-based model so that the code generator produces custom
argument interfaces for a generated entry-point step (model_step) function. For
example, when you want to:

• Align the interface of code generated for a model that you are integrating with
external code.
• Comply with code standards or guidelines.

1 Open an existing model or create a model.


2 Open the Configure C/C++ Function Interface dialog box. On the Code Generation
> Interface pane in the Configuration Parameters dialog box, click Configure
Model Functions. Unless a function prototype was previously configured, the dialog
box opens showing a preview of an execution function prototype with no arguments
(void-void). The dialog box also shows the current initialize and step functions
names.

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

3 Decide whether to configure or reconfigure arguments. If your application requires a


void-void interface, clear Configure arguments for function prototype.
Otherwise, select Configure arguments for function prototype.
4 Display current default settings for the step function arguments by clicking Get
default. An update diagram is displayed and a table lists external I/O ports with
property settings.

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.

The step function preview for this model is:

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

Combine I/O Arguments in Model Step Interface


When using the Configure C/C++ Function Interface dialog box, you can combine an
input argument with an output argument for a model step function. This merging of input
and output arguments allows the code generator to reuse and eliminate buffers in the
generated code.

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:

1 Open the model.


2 In the Configuration Parameters dialog box, select the Code Generation >
Interface pane.
3 Open the Configure C/C++ Function Interface dialog box by clicking Configure
Model Functions or Configure C++ Class Interface.
4 Navigate to the view that allows you to modify model step function arguments. Select
Configure arguments for function prototype. Then, click Get default. An update
diagram is displayed and a table that lists external I/O ports with property settings.
5 Select an inport and outport pair. Properties of the two arguments must be the same,
including the type and dimension. If necessary, change settings for C Type Qualifier
and C Identifier Name so that they match. Make sure that the C Type Qualifier is
not set to Auto. For this example, set the C Type Qualifier for ports In3 and Out2
to Pointer. Set the C Identifier Name for the two arguments to sharedArg.
Validate the changes.

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;

Out1 = ((rtDWork.UnitDelay_DSTATE > 10.0) || (argIn1 < 2.0));

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

Configure C Initialize and Step Function Interfaces


Interactively
This example shows how to use the Configure C/C++ Function Interface dialog box to
configure interfaces for the initialize and step functions for the rate-based example model
rtwdemo_counter.

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.

/* Model step function */


void rtwdemo_counter_step(void)
{
...
}

/* Model initialize function */


void rtwdemo_counter_initialize(void)
{
...
}

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.

The function prototype preview reflects the change.

29-16
Configure C Initialize and Step Function Interfaces Interactively

6 Click Validate. A message indicates success. Validation found no failures.

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)
{
...
}

/* Model initialize function */


void rtwdemo_counter_cust_init(void)
{
...
}

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

Configure C Initialize and Step Function Interfaces


Programmatically
To configure initialize and step entry-point function interfaces for a rate-based model
programmatically, use these functions.

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

Typical uses of these functions include:

• Create and validate a function interface.


• Modify and validate an existing function interface.
• Create and validate a function interface, starting with default configuration
information from a model.
• Reset the model function interface to the default ERT function configuration.

29-20
Configure C Initialize and Step Function Interfaces Programmatically

Create and Validate Function Interface


1 Create a model-specific C function interface with obj =
RTW.ModelSpecificCPrototype, where obj returns a handle to a new, empty
function interface.
2 Add argument configuration information for your model ports by using
RTW.ModelSpecificCPrototype.addArgConf.
3 Attach the function interface to your loaded ERT-based model by using
RTW.ModelSpecificCPrototype.attachToModel.
4 Validate the function interface by using
RTW.ModelSpecificCPrototype.runValidation.
5 If validation succeeds, save your model. Then, generate code by using the rtwbuild
function.

Modify and Validate an Existing Function Interface


1 Get the handle to an existing model-specific C function interface that is attached to
your loaded ERT-based model with obj =
RTW.getFunctionSpecification(modelName). modelName is a character vector
specifying the name of a loaded ERT-based model. obj returns a handle to a function
interface attached to the specified model.

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

Create and Validate Function Interface Starting With Default


Configuration From Model
1 Create a model-specific C function interface by using obj =
RTW.ModelSpecificCPrototype, where obj returns a handle to a new, empty
function interface.
2 Attach the function interface to your loaded ERT-based model by using
RTW.ModelSpecificCPrototype.attachToModel.
3 Get default configuration information from your model by using
RTW.ModelSpecificCPrototype.getDefaultConf.
4 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.
5 Validate the function prototype by using
RTW.ModelSpecificCPrototype.runValidation.
6 If validation succeeds, save your model. Then, generate code by using the rtwbuild
function.

Reset Model Function Interface to Default ERT Function


Configuration
Create an object of the ERT default function interface. Reset the model function interface
and undo custom settings by calling the RTW.FcnDefault method, attachToModel:
obj = RTW.FcnDefault;
obj.attachToModel(model);

model must be a loaded ERT-based model.

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.

Sample Script for Configuring Function Interfaces


This example MATLAB script configures the model function interfaces for example model
rtwdemo_counter.

29-22
See Also

%% Open the rtwdemo_counter model


rtwdemo_counter

%% Select ert.tlc as the System Target File for the model


set_param(gcs,'SystemTargetFile','ert.tlc')

%% Create a model-specific C function prototype


a=RTW.ModelSpecificCPrototype

%% Add argument configuration information for Input and Output ports


addArgConf(a,'Input','Pointer','inputArg','const *')
addArgConf(a,'Output','Pointer','outputArg','none')

%% Attach the model-specific C function prototype to the model


attachToModel(a,gcs)

%% Rename the initialization function


setFunctionName(a,'InitFunction','init')

%% Rename the step function and change some argument attributes


setFunctionName(a,'StepFunction','step')
setArgPosition(a,'Output',1)
setArgCategory(a,'Input','Value')
setArgName(a,'Input','InputArg')
setArgQualifier(a,'Input','none')

%% Validate the function prototype against the model


[status,message]=runValidation(a)

%% if validation succeeded, generate code and build


if status
rtwbuild(gcs)
end

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

Customize Generated Function Interfaces for Simulink


Function and Function Caller Blocks
With Embedded Coder, you can customize the generated C/C++ function interfaces for
Simulink Function and Function Caller blocks. Function code interface configuration
supports easier integration of generated code with functions or function calls in external
code, and customizations for coding standards or design requirements.

You can customize the generated C/C++ function interfaces for:

• Global Simulink functions


• Exported scoped Simulink functions

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.

Configure Generated C/C++ Function Interface for Global


Simulink Function Block
This example shows you how to modify the generated C/C++ function interface for a
Simulink Function block, and generate C code with the specified changes.

29-24
Customize Generated Function Interfaces for Simulink Function and Function Caller Blocks

1 Open the example model rtwdemo_functions. Save it to a writable work area.


2 Right-click the Simulink Function block f3. In the right-click context menu, select
C/C++ Code > Configure C/C++ Function Interface. The Configure C/C++
Function Interface dialog box opens.

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).

Your modifications, whether made to a Simulink Function block or a Function Caller


block, affect code generation for the Simulink Function block and corresponding
Function Caller blocks in the model.

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

Configure Generated C/C++ Function Interface for Exported


Scoped Simulink Function Block
In this example, you modify the generated C/C++ function interface for an exported
scoped Simulink Function block, and generate C code with the specified changes.

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.

1 Open the example model rtwdemo_functions. Save it to a writable work area.


2 Change the visibility of the global function f3 from global to scoped. Open the
Simulink Function block f3. Inside the function block, double-click the Trigger Port
block f3. In the block parameters dialog box, change the Function visibility
parameter from global to scoped. Click Apply and OK.
3 At the top level of the model, right-click the Simulink Function block f3. In the right-
click context menu, select C/C++ Code > Configure C/C++ Function Interface.
The Configure C/C++ Function Interface dialog box opens.

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).

Your modifications, whether made to a Simulink Function block or a Function Caller


block, affect code generation for the Simulink Function block and corresponding
Function Caller blocks in the model.

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;
...
}

Simulink Function Code Interface Limitations


• For C++ code generation, global Simulink functions are incompatible with C++ class
interfaces for model entry-point functions.

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

Customize Function Interfaces for Nonvirtual


Subsystems
If you use the right-click build method to generate code for a nonvirtual subsystem that is
in a rate-based model configured with an ERT-based system target file, you can configure
the initialize and step function interfaces for the subsystem. You can configure the
function interfaces for these types of nonvirtual subsystem blocks:

• 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.

1 Open the model that contains the nonvirtual subsystem block.


2 Open the Model Interface for Subsystem dialog box by using the function
RTW.configSubsystemBuild.

RTW.configSubsystemBuild('rtwdemo_counter/Amplifier');

29-32
Customize Function Interfaces for Nonvirtual Subsystems

3 Choose a Function specification: default function prototypes or model-specific


prototypes. For this example, select Model specific C prototypes.I

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

Customize Generated C++ Class Interfaces


Using the Code interface packaging (Simulink Coder) option C++ class, on the Code
Generation > Interface pane of the Configuration Parameters dialog box, you can
generate a C++ class interface to model code. The generated interface encapsulates
required model data into C++ class attributes and model entry point functions into C++
class methods. The benefits of C++ class encapsulation include:

• Greater control over access to model data


• Ability to multiply instantiate model classes
• Easier integration of model code into C++ programming environments

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

Simple Use of C++ Class Control


This example illustrates a simple use of C++ class code interface packaging. It
generates C+ class code interfaces from an example model, without extensive
modifications to default settings.

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.

To generate C++ class interfaces for a Simulink model:

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

Click Apply and OK.


9 Generate code for the model. When the build completes, the code generation report
for rtwdemo_counter appears. Examine the report and observe that required model
data is encapsulated into C++ class attributes and model entry point functions are
encapsulated into C++ class methods. For example, click the link for
rtwdemo_counter.h to see the class declaration for the model.

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

Customize C++ Class Interfaces Using Graphical Interfaces


• “Select C++ Class Code Interface Packaging” on page 29-44
• “Configure Code Interface Options” on page 29-44
• “Configure Step Method for Your Model Class” on page 29-47
• “Use Namespaces to Scope C++ Model Classes” on page 29-53
• “Configure C++ Class Interfaces for Nonvirtual Subsystems” on page 29-55

Select C++ Class Code Interface Packaging

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:

Selecting this value:

• 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.

Configure Code Interface Options

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

• Multi-instance code error diagnostic

Specifies the severity level for diagnostics displayed when a model violates
requirements for generating multi-instance code.

• None — Proceed with build without displaying a diagnostic message.


• Warning — Proceed with build after displaying a warning message.
• Error (default) — Abort build after displaying an error message.
• Remove error status field in real-time model data structure

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 the block parameter structure as a public, private,


or protected data member of the C++ model class (private by default).
• Parameter access

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:

• Generate either noninlined or inlined access methods.


• Generate either per-signal or structure-based access methods. That is, you can
generate a series of set and get methods on a per-signal basis, or generate just one
set method that takes the address of an external input structure as an argument
and, for external outputs (if applicable), just one get method that returns a
reference to an external output structure. The generated code for structure-based
access methods has the following general form:
class ModelClass {
...

29-45
29 Function and Class Interfaces in Embedded Coder

// Root inports set method


void setExternalInputs(const ExternalInputs* pExternalInputs);

// Root outports get method


const ExternalOutputs & getExternalOutputs() const;
}

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:

• Terminate function required

Specifies whether to generate the model_terminate method (on by default). This


function contains model termination code and should be called as part of system
shutdown.
• Combine signal/state structures

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.

Configure Step Method for Your Model Class

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:

• “Passing Default Arguments” on page 29-48

29-47
29 Function and Class Interfaces in Embedded Coder

• “Passing I/O Arguments” on page 29-50

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.

Passing Default Arguments

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

• Step method name

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

• Step function preview

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 step function preview for this model is:


sldemo_mdlref_counter_paramargsModelClass :: step ( arg_input, * arg_output )

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.

Passing I/O Arguments

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

• Get Default Configuration

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:

• Step method name

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.

Use Namespaces to Scope C++ Model Classes

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

• TopNS for top-level model rtwdemo_cppclass


• MiddleNS for referenced model rtwdemo_cppclass_refmid
• BottomNS for referenced model rtwdemo_cppclass_refbot

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.

42 // Class declaration for model rtwdemo_cppclass_refmid


43 namespace MiddleNS {
44 class MiddleClass {
45 // public data and function members
46 public:
47 // Model entry point functions
...
52 // model step function
53 void StepMethod(const real_T *arg_In1, const real_T &arg_In2, real_T
54 *arg_Out1, real_T *arg_Out2);
...
87 };
88 }

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

Configure C++ Class Interfaces for Nonvirtual Subsystems

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:

1 Open the containing model and select the subsystem block.


2 Enter the following MATLAB command:

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.

Customize C++ Class Interfaces Programmatically


If you select the Code interface packaging option C++ class for your model, you can
use the C++ class interface control functions (listed in C++ Class Interface Control
Functions) to programmatically configure the step method for your model class.

Typical uses of these functions include:

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 Create a model-specific C++ class interface with obj =


RTW.ModelCPPDefaultClass or obj = RTW.ModelCPPArgsClass, where obj
returns a handle to an newly created, empty C++ class interface.
2 Attach the C++ class interface to your loaded ERT-based Simulink model using
attachToModel.
3 Get default C++ class interface configuration information from your model using
getDefaultConf.
4 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
you are using the I/O arguments style step method, you can test and reset
argument names, argument positions, argument categories, and argument type
qualifiers.
5 Validate the C++ class interface using runValidation. (If validation fails, use
the error message information thatrunValidation returns to address the
issues.)
6 Save your model and then generate code using the rtwbuild function.
• Modify and validate an existing step method interface for a 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

C++ Class Interface Control Functions

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

Configure Step Method for Model Class


The following sample MATLAB script configures the step method for the
rtwdemo_counter model class, using the C++ Class Interface Control Functions.
%% Open the rtwdemo_counter model
rtwdemo_counter

%% Select ert.tlc as the System Target File for the model


set_param(gcs,'SystemTargetFile','ert.tlc')

%% Select C++ as the target language for the model


set_param(gcs,'TargetLang','C++')

%% 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

%% Attach the C++ class interface to the model


attachToModel(a,gcs)

%% Get the default C++ class interface configuration from the model
getDefaultConf(a)

%% Move the Output port argument from position 2 to position 1


setArgPosition(a,'Output',1)

%% Reset the model step method name from step to StepMethod


setStepMethodName(a,'StepMethod')

%% Change the Input port argument name, category, and qualifier


setArgName(a,'Input','inputArg')
setArgCategory(a,'Input','Pointer')
setArgQualifier(a,'Input','const *')

%% Validate the function prototype against the model


[status,message]=runValidation(a)

29-59
29 Function and Class Interfaces in Embedded Coder

%% if validation succeeded, generate code and build


if status
rtwbuild(gcs)
end

Specify Custom Storage Class for C++ Class Code Generation


To configure a Simulink parameter, signal, or state to use a custom storage class (CSC)
with C++ class code generation:

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.

4 If the option Configuration Parameters > Ignore custom storage classes is


selected, clear it.

Apply the changes.


5 In the model, select a custom storage class for a parameter, signal, or state. For
example, select a signal, open its Properties dialog box, and view its code generation
options. In the Storage class drop-down list, select a custom storage class, and then
configure its attributes. Apply the changes.

Note C++ class code generation does not support the following CSCs:

• CSCs with Volatile specifications.


• CSCs of type Other, except GetSet.

6 Build the model.


7 In the code generation report, examine the files model.h and model.cpp to observe
the use of CSCs in the generated C++ code.

29-60
Customize Generated C++ Class Interfaces

Model Class Copy Constructor and Assignment Operator


Code generation automatically adds a copy constructor and an assignment operator to C+
+ class declarations when required to securely handle pointer members. The constructor
and operator are added as private member functions when both of the following
conditions exist:

• 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;
...

// Class declaration for model cppclass_top


class Top {
...
// private data and function members
private:
// Block signals
BlockIO_cppclass_top cppclass_top_B;

// Block states
D_Work_cppclass_top cppclass_top_DWork;

// Real-Time Model
RT_MODEL_cppclass_top cppclass_top_M;

// private member function(s) for subsystem '<Root>/Subsystem'


void cppclass_top_Subsystem_Init();
void cppclass_top_Subsystem_Start();
void cppclass_top_Subsystem();

29-61
29 Function and Class Interfaces in Embedded Coder

//Copy Constructor
Top(const Top &rhs);

//Assignment Operator
Top& operator= (const Top &rhs);

// model instance variable for '<S1>/Bottom model instance'


MiddleClass_ptr Bottom_model_instanceMDLOBJ1;
};

C++ Class Interface Control Limitations


• If a model has a custom model step function for which a scalar output is passed by
value and is updated in a conditionally executed context, configure the output to be
passed by pointer. In the model C++ class interface configuration dialog box, set
Category to Pointer. Examples of a conditionally executed context include:

• 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:

• Identifier format control subpane on the Symbols pane


• File customization template parameter on the Templates pane

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:

• Free-form text outside template sections


• Custom tokens
• TLC commands (<! > tokens)

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

Generate Modular Function Code


The Embedded Coder software provides a Subsystem Parameters dialog box option,
Function with separate data, that allows you to generate modular function code for
nonvirtual subsystems, including atomic subsystems and conditionally executed
subsystems.

By default, the generated code for a nonvirtual subsystem does not separate a
subsystem's internal data from the data of its parent Simulink model. This can make it
difficult to trace and test the code, particularly for nonreusable subsystems. Also, in large
models containing nonvirtual subsystems, data structures can become large and
potentially difficult to compile.

About Nonvirtual Subsystem Code Generation


Function with separate data allows you to generate subsystem function code in which
the internal data for a nonvirtual subsystem is separated from its parent model and is
owned by the subsystem. The subsystem data structure is declared independently from
the parent model data structures. A subsystem with separate data has its own block I/O
and DWork data structure. As a result, the generated code for the subsystem is easier to
trace and test. The data separation also tends to reduce the maximum size of global data
structures throughout the model, because they are split into multiple data structures.

To use the Function with separate data parameter,

• 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).

Configure Subsystem for Generating Modular Function Code


This section summarizes the steps to configure a nonvirtual subsystem in a Simulink
model for modular function code generation.
1 Verify that the Simulink model containing the subsystem uses an ERT-based system
target file (see the System target file parameter on the Code Generation pane of
the Configuration Parameters dialog box).
2 In your Simulink model, select the subsystem for which you want to generate
modular function code and open the Subsystem Parameters dialog box (for example,
right-click the subsystem and select Block Parameters (Subsystem)). The dialog
box for an atomic subsystem is shown below. (In the dialog box for a conditionally
executed subsystem, the dialog box option Treat as atomic unit is greyed out, and
you can skip Step 3.)

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

Modular Function Code for Nonvirtual Subsystems


To illustrate the selection of the Function with separate data option for a nonvirtual
subsystem, the following procedure generates atomic subsystem function code with and
without the option selected and compares the results.

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:

• Inline: Inline the subsystem code at the call sites


• Function: A void/void function with I/O and internal data in global data structure
• Reusable Function: A reentrant function with data passed in as part of
function arguments
• Auto: Let the code generator optimize the implementation based on context
2 Double-click the SS1 subsystem and examine the contents.

29-70
Generate Modular Function Code

Close the subsystem window when you are finished.


3 Right-click the SS1 subsystem, select Block Parameters (Subsystem) from the context
menu, and examine the settings. Simulink and the code generator can avoid
"artificial" algebraic loops when the subsystem is made atomic with the subsystem
option Minimize algebraic loop occurrences.

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

• On the Main tab, Treat as atomic unit is selected


• On the Code Generation tab, User specified is selected for Function
name options
• On the Code Generation tab, myfun is specified for Function name
b In the Subsystem Parameters dialog box, on the Code Generation tab verify
that

i Nonreusable function is selected for the Function packaging


parameter. After this selection, additional parameters and options appear.
ii Use function name is selected for the File name options parameter.
This selection is optional but simplifies the later task of code comparison by
causing the atomic subsystem function code to be generated into the files
myfun.c and myfun.h.

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

a In the rtwdemo_atomic1 model (or rtwdemo_atomic with step 3 reapplied),


right-click the SS1 subsystem and select Block Parameters (Subsystem). In
the Subsystem Parameters dialog box, verify that

• On the Main tab, Treat as atomic unit is selected


• On the Code Generation tab, Function is selected for Function
packaging
• On the Code Generation tab, User specified is selected for Function
name options
• On the Code Generation tab, myfun is specified for Function name
• On the Code Generation tab, Use function name is specified for File
name options
b In the Subsystem Parameters dialog box, on the Code Generation tab, select
the option Function with separate data. Click Apply to apply the change and
click OK to exit the dialog box.
c Save this model variant, using a different name than the first variant, to a
personal work directory, for example, rtwdemo_atomic2 in d:/atomic.
7 Generate code for each model, rtwdemo_atomic1 and rtwdemo_atomic2.
8 In the generated code directories, compare the model.c/.h and myfun.c/.h files
generated for the two models. For code comparison discussion, see “H File
Differences for Nonvirtual Subsystem Function Data Separation” on page 29-72 and
“H File Differences for Nonvirtual Subsystem Function Data Separation” on page 29-
72“C File Differences for Nonvirtual Subsystem Function Data Separation” on page
29-73.

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.

H File Differences for Nonvirtual Subsystem Function Data Separation

The differences between the H files generated for rtwdemo_atomic1 and


rtwdemo_atomic2 help illustrate the selection of the Function with separate data
option for nonvirtual subsystems.

1 Selecting Function with separate data causes typedefs for subsystem data to be
generated in the myfun.h file for rtwdemo_atomic2:

/* Block signals for system '<Root>/SS1' */


typedef struct {

29-72
Generate Modular Function Code

real_T Integrator; /* '<S1>/Integrator' */


} rtB_myfun;

/* Block states (auto storage) for system '<Root>/SS1' */


typedef struct {
real_T Integrator_DSTATE; /* '<S1>/Integrator' */
} rtDW_myfun;

By contrast, for rtwdemo_atomic1, typedefs for subsystem data belong to the


model and appear in rtwdemo_atomic1.h:
/* Block signals (auto storage) */
typedef struct {
...
real_T Integrator; /* '<S1>/Integrator' */
} BlockIO_rtwdemo_atomic1;

/* Block states (auto storage) for system '<Root>' */


typedef struct {
real_T Integrator_DSTATE; /* '<S1>/Integrator' */
} D_Work_rtwdemo_atomic1;
2 Selecting Function with separate data generates the following external
declarations in the myfun.h file for rtwdemo_atomic2:
/* Extern declarations of internal data for 'system '<Root>/SS1'' */
extern rtB_myfun rtwdemo_atomic2_myfunB;

extern rtDW_myfun rtwdemo_atomic2_myfunDW;

extern void myfun_initialize(void);

By contrast, the generated code for rtwdemo_atomic1 contains model-level external


declarations for the subsystem's BlockIO and D_Work data, in
rtwdemo_atomic1.h:
/* Block signals (auto storage) */
extern BlockIO_rtwdemo_atomic1 rtwdemo_atomic1_B;

/* Block states (auto storage) */


extern D_Work_rtwdemo_atomic1 rtwdemo_atomic1_DWork;

C File Differences for Nonvirtual Subsystem Function Data Separation

The differences between the C files generated for rtwdemo_atomic1 and


rtwdemo_atomic2 illustrate the selection of the Function with separate data option
for nonvirtual subsystems.

29-73
29 Function and Class Interfaces in Embedded Coder

1 Selecting Function with separate data causes a separate subsystem initialize


function, myfun_initialize, to be generated in the myfun.c file for
rtwdemo_atomic2:

void myfun_initialize(void) {
{
((real_T*)&rtwdemo_atomic2_myfunB.Integrator)[0] = 0.0;
}
rtwdemo_atomic2_myfunDW.Integrator_DSTATE = 0.0;
}

The subsystem initialize function in myfun.c is invoked by the model initialize


function in rtwdemo_atomic2.c:

/* Model initialize function */

void rtwdemo_atomic2_initialize(void)
{
...

/* Initialize subsystem data */


myfun_initialize();
}

By contrast, for rtwdemo_atomic1, subsystem data is initialized by the model


initialize function in rtwdemo_atomic1.c:

/* Model initialize function */

void rtwdemo_atomic1_initialize(void)
{
...
/* block I/O */
{
...
((real_T*)&rtwdemo_atomic1_B.Integrator)[0] = 0.0;
}

/* states (dwork) */

rtwdemo_atomic1_DWork.Integrator_DSTATE = 0.0;
...
}

29-74
Generate Modular Function Code

2 Selecting Function with separate data generates the following declarations in the
myfun.c file for rtwdemo_atomic2:

/* Declare variables for internal data of system '<Root>/SS1' */


rtB_myfun rtwdemo_atomic2_myfunB;

rtDW_myfun rtwdemo_atomic2_myfunDW;

By contrast, the generated code for rtwdemo_atomic1 contains model-level


declarations for the subsystem's BlockIO and D_Work data, in
rtwdemo_atomic1.c:

/* Block signals (auto storage) */


BlockIO_rtwdemo_atomic1 rtwdemo_atomic1_B;

/* Block states (auto storage) */


D_Work_rtwdemo_atomic1 rtwdemo_atomic1_DWork;
3 Selecting Function with separate data generates identifier naming that reflects the
subsystem orientation of data items. Notice the references to subsystem data in
subsystem functions such as myfun and myfun_update or in the model's
model_step function. For example, compare this code from myfun for
rtwdemo_atomic2
/* DiscreteIntegrator: '<S1>/Integrator' */
rtwdemo_atomic2_myfunB.Integrator = rtwdemo_atomic2_myfunDW.Integrator_DSTATE;

to the corresponding code from myfun for rtwdemo_atomic1.


/* DiscreteIntegrator: '<S1>/Integrator' */
rtwdemo_atomic1_B.Integrator = rtwdemo_atomic1_DWork.Integrator_DSTATE;

Nonvirtual Subsystem Modular Function Code Limitations


The nonvirtual subsystem option Function with separate data has the following
limitations:

• 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

• The nonvirtual subsystem cannot output function call signals.


• The nonvirtual subsystem cannot contain noninlined S-functions.
• The generated files for the nonvirtual subsystem will reference model-wide header
files, such as model.h and model_private.h.
• The Function with separate data option is incompatible with the Classic call
interface option, located on the Code Generation > Interface pane of the
Configuration Parameters dialog box. Selecting both generates an error.
• The Function with separate data option is incompatible with setting Code
interface packaging to Reusable function (Code Generation > Interface
pane). Selecting both generates an error.

• 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

Memory Sections in Embedded


Coder

• “Control Data and Function Placement in Memory by Inserting Pragmas”


on page 30-2
• “Protect Global Data with const and volatile Keywords” on page 30-17
30 Memory Sections in Embedded Coder

Control Data and Function Placement in Memory by


Inserting Pragmas
For some applications, you can use pragmas and other code decorations to control the
placement of data (global variables) and function definitions in memory. For example, a
linker configuration file can define named sections in a SECTIONS directive and map each
section to a range of memory addresses. In the C code, you include pragmas that assign
global variables and functions to these named sections and, by extension, to the memory
ranges. By controlling memory placement, you can:

• Generate code that is more efficient for your hardware.


• Modularize your application code for easier maintenance and modification later in the
development process and after deployment.

With Embedded Coder and memory sections, you can:

• 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.

Insert Pragmas by Using Memory Sections


In this example, you configure the default memory placement for all of the data and
functions of the algorithm represented by the example model rtwdemo_roll. Then, for
some signal data, you override the default placement.

30-2
Control Data and Function Placement in Memory by Inserting Pragmas

Explore Example Model and Inspect Default Generated Code

1 Open the example model.


open_system('rtwdemo_roll')

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;

The file also declares entry-point functions for the model.


/* Model entry point functions */
extern void rtwdemo_roll_initialize(void);

30-3
30 Memory Sections in Embedded Coder

extern void rtwdemo_roll_step(void);


extern void rtwdemo_roll_terminate(void);
4 Inspect rtwdemo_roll.c. This file defines global structure variables to store the
data. The file also defines the functions.

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.

• For a global variable named myVar, the pragma syntax is:

#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)

Create Memory Sections

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

Configure Default Pragmas for Data and Functions

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;

/* External inputs (root inport signals with default storage) */


#pragma SEC_MYALGORITHM_DATA("rtwdemo_roll_U")

ExtU_rtwdemo_roll_T rtwdemo_roll_U;

/* External outputs (root outports fed by signals with default storage) */


#pragma SEC_MYALGORITHM_DATA("rtwdemo_roll_Y")

ExtY_rtwdemo_roll_T rtwdemo_roll_Y;

Retain Default Memory Section After Applying a Default Storage Class or


Function Template

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.

/* Storage class 'STRUCT_DATA' */


#pragma SEC_MYALGORITHM_DATA("STRUCT_DATA_rtwdemo_roll")

rtwdemo_roll_STRUCT_DATA STRUCT_DATA_rtwdemo_roll;

Retain Default Memory Section After Directly Applying a Storage Class

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.

In rtwdemo_roll, in the BasicRollMode subsystem, the three Gain blocks represent


the parameters of a PID control algorithm. In this example, you configure the output

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.

To create the memory section and the storage class:

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

method, which the Simulink.Signal class already implements. The new


implementation specifies that objects of the myPackage.Signal class use custom
storage classes from the myPackage package instead of custom storage classes from
the built-in Simulink package.
9 Set your current folder to the folder that contains the +myPackage folder.
10 In the Custom Storage Class Designer for myPackage, select the Custom Storage
Class tab.
11 Click New.
12 For the new custom storage class, set these properties:

• 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.

To apply the storage class in the model:

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.

/* Definition for custom storage class: myCSC */


#pragma SEC_MYALGORITHM_DATA("DispGain")

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.

Configure Pragma to Surround Groups of Definitions


If your build toolchain requires that a pragma or other decoration surround multiple
definitions of variables or functions at once, in an Embedded Coder Dictionary or the
Custom Storage Class Designer, set Statements surround to Group of variables
(the default in the Custom Storage Class Designer).

Override Default Memory Placement for Individual Data


Elements
After you configure memory section defaults in the Code Mapping Editor (see “Configure
Default Code Generation for Categories of Model Data and Functions” on page 21-7), to
override these default settings for individual data elements (signals, parameters, and
states), create a storage class and any required memory sections by using the Custom
Storage Class Designer. In the Designer, when you create the storage class, set the
Memory section property to the appropriate memory section. Then, use the Model Data
Editor to apply the storage class to individual data elements.

30-9
30 Memory Sections in Embedded Coder

Choose Where to Create and Store Memory Section Definition


To define a memory section, you must choose where to create it: in an Embedded Coder
Dictionary or in a package (by using the Custom Storage Class Designer).

• 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.

Share Memory Section Definition Between Models


• If you define the memory section in the Embedded Coder Dictionary of a model, you
cannot use the memory section in other models. To share the memory section, migrate
the definition to a Simulink data dictionary (sldd). Then, share the dictionary between
the target models. For more information, see “Share Embedded Coder Dictionary
Definition Between Models” on page 20-6.
• If you define the memory section in a package, any model can use the memory section.
Add the folder containing the package folder to the MATLAB path (see “What Is the
MATLAB Search Path?” (MATLAB)).

Share Memory Section Between Packages (Package Memory


Sections Only)
Packages can access and use memory sections that are defined in other packages,
including custom packages and built-in packages such as Simulink. Only one copy of the
memory section exists, in the package that defines it. Other packages refer to the memory
section by pointing to it in its original location. Changes to the memory section, including
changes to a built-in memory section in later MathWorks product releases, are
immediately available in every referencing package.

30-10
Control Data and Function Placement in Memory by Inserting Pragmas

To configure a package to refer to a memory section that is defined in another package:


1 Open the Custom Storage Class Designer. At the command prompt, enter
cscdesigner.
2 Select the Memory Section tab.
3 Use Select Package to select the package in which you want to reference a class or
section defined in some other package.
4 In the Memory section definitions pane, select the existing definition below which
you want to insert the reference.
5 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 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.

Control Appearance of Memory Section Drop-Down List


(Package Memory Sections Only)
When you apply a package memory section, you select the memory section from a drop-
down list. To control the order of the memory sections in the list, in the Custom Storage
Class Designer, use the Up and Down buttons. The order of memory sections in drop-
down lists matches the order in the Custom Storage Class Designer.

Protect Definitions of Package Memory Sections (Package


Memory Sections Only)
When you click Save in the Custom Storage Class Designer, the Designer saves memory
section and custom storage class definitions into the csc_registration.m file in the
package folder. To determine the location of this file, in the Custom Storage Class
Designer, inspect the value of Filename.

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.

A best practice is to keep csc_registration.m and csc_registration.p in your


package folder. That way, if you need to modify the memory sections by using the
Designer, you can delete csc_registration.p and later regenerate it after you finish
the modifications. Because the P-coded version of the file takes precedence, while both
files exist in the package, the memory sections are protected.

Override Default Memory Placement for Subsystem Functions


and Data
When you use atomic subsystems to partition the generated code into functions (see
“Generate Subsystem Code as Separate Function and Files” on page 3-11), you can apply
different memory sections to the functions and data of each subsystem. You can also
specify that a subsystem use no memory section.

• 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.

Override Memory Section for Atomic Subsystem

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:

• Set Function packaging to Nonreusable function or Reusable function


(for reentrant code).
• If you set Function packaging to Nonreusable function, to enable
configuration of memory sections for the subsystem data, select Function with
separate data. If you do not select Function with separate data, the subsystem
data inherit memory sections from the model or, if applicable, a parent subsystem.
• Use parameters such as Memory section for initialize/terminate functions to
apply default memory sections to the subsystem functions and data.

Specify That Atomic Subsystem Use No Memory Section

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.

To specify that a subsystem use no memory section:

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

Limitations and Other Considerations

• 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).

Create Fewer Custom Storage Classes (Package Memory


Sections Only)
In the example “Insert Pragmas by Using Memory Sections” on page 30-2, to apply a
memory section to individual signal data items, you create a custom storage class by
using the Custom Storage Class Designer. Suppose you want to apply a different memory
section to each of the signals. Instead of copying the custom storage class (myCSC) and
associating a different memory section with the copy, which results in two very similar
custom storage classes, in the Custom Storage Class Designer, for myCSC, set Memory
section to Instance specific. Then, when you apply the custom storage class to a
data item, you can choose a memory section for that data item.

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.

Insert Pragmas for Functions and Data in Generated Code


This model shows how to insert pragmas for functions and data in generated code.

Explore Example Model

Open the example model.


open_system('rtwdemo_memsec')

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

Protect Global Data with const and volatile Keywords


In C, you use the keyword const to prevent any code in an application from assigning a
new value to a variable. In an application where an external actor (for example, a
hardware device) can manipulate the value of a variable, you use the keyword volatile
to prevent your compiler from optimizing the assembly code in a way that compromises
the integrity of the variable value. You can also use volatile to prevent your compiler
from eliminating storage for const data, such as a parameter whose value you want to
tune during execution.

• To apply the qualifiers to an individual data item in a model, including a custom


structure that you create by using a nonvirtual bus or a parameter structure, apply the
appropriate built-in custom storage class directly to the data item. The custom storage
class prevents optimizations such as Default parameter behavior from eliminating
storage for the data item. For an example, see “Type Qualifiers” on page 14-14. For
information about optimizations that a directly applied storage class prevents, see
“How Generated Code Stores Internal Signal, State, and Parameter Data” on page 22-
50.

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

Maintain const Correctness for Arguments of Entry-Point


Functions
When your external code calls a generated entry-point function and passes const data
through an argument (formal parameter) of the function, to make the corresponding
argument in the function definition const, use function prototype control.

• To configure function prototype control for a model entry-point function such as


model_step, see “Control Generation of Function Interfaces” on page 53-2.

• 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.

Incorrect Results or Undefined Behavior When Passing


Volatile Data to a Generated Function
The generated code can define and call functions other than the model entry-point
functions such as model_step and model_initialize. For example, you can configure
an atomic subsystem to appear in the code as a separate function. Also, lookup table
blocks such as n-D Lookup Table typically yield separate utility functions.

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

• “Create Tunable Calibration Parameter in the Generated Code” on page 22-121


• “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

30-19
Code Generation

21
31

Configuration for Simulink Coder

• “Code Generation Configuration” on page 31-2


• “Configure Code Generation Parameters for Model Programmatically” on page 31-5
• “Use Configuration Reference to Select Code Generation Target” on page 31-7
• “Check Model and Configuration for Code Generation” on page 31-15
• “Application Objectives Using Code Generation Advisor” on page 31-18
• “Simulink Coder Model Advisor Checks for Standards and Code Efficiency”
on page 31-22
• “Configure Code Comments” on page 31-24
• “Construction of Generated Identifiers” on page 31-26
• “Identifier Name Collisions and Mangling” on page 31-27
• “Specify Identifier Length to Avoid Naming Collisions” on page 31-28
• “Specify Reserved Names for Generated Identifiers” on page 31-29
• “Reserved Keywords” on page 31-30
• “Debug” on page 31-34
31 Configuration for Simulink Coder

Code Generation Configuration


When you are ready to generate code for a model, you can modify the model configuration
parameters specific to code generation. The code generation parameters determine how
the code generator produces code and builds an executable program from your model.

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.

Open the Model Configuration for Code Generation


To modify the model configuration parameters for code generation, open the Code
Generation pane. There are several different ways to open the Code Generation pane
from the Simulink editor:

• To open the Configuration Parameters dialog box, click the model configuration
parameters icon.

Then click Code Generation in the Select (left) pane.


• From the Simulation menu, select Model Configuration Parameters. When the
Configuration Parameters dialog box opens, click Code Generation in the Select
(left) pane.
• From the Code menu, select C/C++ Code > Code Generation Options.
• From the View menu in the model window, select Model Explorer, or from the
MATLAB command line, type daexplr and press Enter. In the Model Explorer,
expand the node for the current model in the left pane and click Configuration

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.

Goal Approach More Information


Automate At the MATLAB command “Configure Code Generation
configuration. line, use the set_param Parameters for Model
function Programmatically” on page 31-
5
Configure your model Embedded Coder Quick “Generate Code by Using the
for code generation Start tool Quick Start Tool” on page 37-10
quickly and easily
(Embedded Coder).
Use a template to Code generation templates • “Generate Code and Simulate
create a model Models in a Simulink Project”
configured for code (Simulink Coder)
generation, ready for • “Generate Code and Simulate
you to add your own Models in a Simulink Project”
blocks.
To configure your Code Generation Wizards “Configure and Optimize Model
model for code blocks with Configuration Wizard
generation, use Blocks” on page 32-23
Simulink blocks and
predefined or custom
MATLAB scripts.

31-3
31 Configuration for Simulink Coder

Goal Approach More Information


Verify that your model Model Advisor “Select and Run Model Advisor
meets standards and Checks” (Simulink)
guidelines.
Verify that your model Code Generation Advisor “Application Objectives Using
meets your application Code Generation Advisor” on
objectives. page 31-18

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

Configure Code Generation Parameters for Model


Programmatically
You can modify code generation parameters for the active configuration set in the
Configuration Parameters dialog box or from the MATLAB command line. Use the
command-line approach for creating a script that automates setting parameters for an
established model configuration.

Modify Parameters to Support Execution efficiency


In this example, you modify the configuration parameters to support the Code Generation
Advisor application objective, Execution efficiency.

Step 1. Open a model.


slexAircraftExample

Step 2. Get the active configuration set.


cs = getActiveConfigSet(model);

Step 3. Select the Generic Real-Time (GRT) target.


switchTarget(cs,'grt.tlc',[]);

Step 4. To optimize execution speed, modify parameters.

If your application objective is Execution efficiency, use set_param to modify these


parameters:
set_param(cs,'MatFileLogging','off');
set_param(cs,'SupportNonFinite','off');
set_param(cs,'RTWCompilerOptimization','on');
set_param(cs,'OptimizeBlockIOStorage','on');
set_param(cs,'EnhancedBackFolding','on');
set_param(cs,'ConditionallyExecuteInputs','on')
set_param(cs,'DefaultParameterBehavior','Inlined');
set_param(cs,'BooleanDataType','on');
set_param(cs,'BlockReduction','on');
set_param(cs,'ExpressionFolding','on');
set_param(cs,'LocalBlockOutputs','on');
set_param(cs,'EfficientFloat2IntCast','on');
set_param(cs,'BufferReuse','on');

31-5
31 Configuration for Simulink Coder

Step 5. Save the model configuration to a file.

Save the model configuration to a file, 'Exec_efficiency_cs.m', and view the


parameter settings.

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

Use Configuration Reference to Select Code Generation


Target
This example shows how to use a configuration reference to select a code generation
target for a model reference hierarchy without modifying individual models.

Open Example Model

Open the example model slexConfigSetRefExample.

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.

In the model editor, double-click the Model block, Amplifier.

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

Open the Referenced Configuration Set

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

In this example, the referenced configuration set is another configuration reference,


Configuration_ERT. To open this referenced configuration, in the right panel, click the
Open button. Model Explorer displays the configuration set Configuration_ERT.

31-11
31 Configuration for Simulink Coder

Generate Code for ERT Target

The referenced configuration set is customized for ERT code generation. To generate
code, press Ctrl+B.
rtwbuild('slexConfigSetRefExample');

### Starting build procedure for model: slexConfigSetRefMdlRef


### Successful completion of code generation for model: slexConfigSetRefMdlRef
### Starting build procedure for model: slexConfigSetRefExample
### Successful completion of code generation for model: slexConfigSetRefExample

The code generation report displays once code generation is complete.

31-12
Use Configuration Reference to Select Code Generation Target

Switch Targets and Generate Code for AUTOSAR 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

Check Model and Configuration for Code Generation


You can use the Model Advisor checks to assess model readiness to generate code. To
check and configure your model for code generation application objectives such as
traceability or debugging, use the Code Generation Advisor.

For information about See


Model Advisor “Run Model Checks” (Simulink)
Code Generation Advisor “Application Objectives Using Code
Generation Advisor” (Simulink Coder)
Checks available with Simulink Coder “Simulink Coder Checks” (Simulink Coder)
Checks available with Embedded Coder “Embedded Coder Checks”

Check Mode for Code Efficiency with Model Advisor


To check model rtwdemo_throttlecntrl for code efficiency, use the Model Advisor.

1 Open rtwdemo_throttlecntrl. Save a copy as throttlecntrl in a writable


location on your MATLAB path.
2 To start the Model Advisor, select Analysis > Model Advisor > Model Advisor. A
dialog box opens showing the model system hierarchy.
3 Click throttlecntrl and then click OK. The Model Advisor window opens.
4 Expand By Task > Code Generation Efficiency. To check your model for code
generation efficiency, use the checks in the folder. By default, checks that do not
trigger an Update Diagram are selected. The checks available for code generation
efficiency depend on whether you have a Simulink Coder or Embedded Coder license.
5 In the left pane, select the remaining checks, and then select Code Generation
Efficiency.
6 In the right pane, select Show report after run and click Run Selected Checks.
The report shows a Run Summary that flags check warnings.
7 Review the report. The warnings highlight issues that impact code efficiency. For
more information about the report, see “View Model Advisor Reports” (Simulink).

31-15
31 Configuration for Simulink Coder

Check Model During Code Generation with Code Generation


Advisor
To review a model as part of the code generation process, use the Code Generation
Advisor.
1 To specify your code generation objectives, on the Configuration Parameters >
Code Generation pane, choose a value for the Select objective parameter.
2 On the Configuration Parameters > Code Generation > General pane, select one
of the following from Check model before generating code:

• On (proceed with warnings)


• On (stop for warnings)
3 If you want to only generate code, select Generate code only. Otherwise clear the
check box to build an executable.
4 Apply your changes, and then click Generate Code/Build. The Code Generation
Advisor starts and reviews the top model and subsystems.

If the Code Generation Advisor issues failures or warnings, and you specified:

• On (proceed with warnings) — The Code Generation Advisor window opens


while the build process proceeds. After the build process is complete, you can
review the results.
• On (stop for warnings) — The build process halts and displays the
Diagnostic Viewer. To continue, you must review and resolve the Code Generation
Advisor results or clear the Check model before generating code parameter.
5 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.
6 After reviewing the check results, you can choose to fix warnings and failures as
described in “Fix a Model Check Warning or Failure” (Simulink).

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

Application Objectives Using Code Generation Advisor

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

High-Level Code Generation Objectives


Depending on the type of application that your model represents, you are likely to have
specific high-level code generation objectives. For example, safety and traceability might
be more critical than efficient use of memory. If you have specific objectives, you can
quickly configure your model to meet those objectives by selecting and prioritizing from
these code generation objectives:

• 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.

Configure Model for Code Generation Objectives Using Code


Generation Advisor
This example shows how to use the Code Generation Advisor to check and configure your
model to meet code generation objectives:

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.

Check model configuration settings against code generation objectives


triggers a warning for these issues:

• 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.

Click Modify Parameters to set:

• Parameters to the value recommended for the specified code generation


objectives.
• Code generation objectives in the model to the objectives specified in the Code
Generation Advisor.
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).

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

Configure Model for Code Generation Objectives by Using


Configuration Parameters Dialog Box
This example shows how to check and configure the code generation objectives in the
Configuration Parameters dialog box:

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

Simulink Coder Model Advisor Checks for Standards and


Code Efficiency
To check that your model meets standards and is ready to generate code, you can use the
Model Advisor checks available with 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.

By Task folder Model Advisor checks


Code “Identify blocks using one-based indexing” (Simulink Coder)
Generation
Efficiency
Modeling “Check solver for code generation” (Simulink Coder)
Standards for
DO-178C/ “Check for blocks that have constraints on tunable parameters”
DO-331 (Simulink Coder)

“Check sample times and tasking mode” (Simulink Coder)


Model “Check for model reference configuration mismatch” (Simulink Coder)
Referencing
“Check for code generation identifier formats used for model
reference” (Simulink Coder)

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

• “Modeling Guidelines for Model Configuration” (Simulink Coder)

31-23
31 Configuration for Simulink Coder

Configure Code Comments


Configure how the code generator inserts comments into generated code by modifying
parameters on the Code Generation > Comments pane.

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.

If you do not select this parameter, parameter comments are generated if


less than 1000 parameters are declared. This reduces the size of the
generated file for models with a large number of parameters.
Include MATLAB user MATLAB user comments (Simulink Coder). Selecting this parameter
comments includes function description comments and other user comments from
MATLAB code as comments in the generated code.
Specify comment style Comment style (Simulink Coder). Select Auto, Multi-line or Single-
line as the style of comments in the generated code.

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 &#x30A2;.
For more information, see “Internationalization and Code Generation” (Simulink Coder).

31-25
31 Configuration for Simulink Coder

Construction of Generated Identifiers


For GRT and RSim targets, the code generator automatically constructs identifiers for
variables and functions in the generated code. These identifiers represent:

• Signals and parameters that have Auto storage class


• Subsystem function names that are not user-defined
• Stateflow names

The components of a generated identifier include

• The root model name, followed by


• The name of the generating object (signal, parameter, state, and so on), followed by
• Unique name-mangling text

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:

• “Specify Identifier Length to Avoid Naming Collisions” on page 31-28


• “Specify Reserved Names for Generated Identifiers” on page 31-29

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

Identifier Name Collisions and Mangling


In identifier generation, a circumstance that would cause generation of two or more
identical identifiers is called a name collision. When a potential name collision exists,
unique name-mangling text is generated and inserted into each of the potentially
conflicting identifiers. Each set of name-mangling characters is unique for each generated
identifier.

Identifier Name Collisions with Referenced Models


Referenced models can introduce additional naming constraints. Within a model that uses
referenced models, collisions between the names of the models cannot exist. When you
generate code from a model that includes referenced models, the Maximum identifier
length parameter must be large enough to accommodate the root model name and name-
mangling text. A code generation error occurs if Maximum identifier length is too
small.

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.

For more information on referenced models, see “Parameterize Instances of a Reusable


Referenced Model” (Simulink).

31-27
31 Configuration for Simulink Coder

Specify Identifier Length to Avoid Naming Collisions


The length of a generated identifier is limited by the Maximum identifier length
parameter specified on the Symbols pane of the Configuration Parameters dialog box.
The Maximum identifier length field allows you to limit the number of characters in
function, type definition, and variable names. The default is 31 characters. This is also the
minimum length you can specify. The maximum is 256 characters.

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

Specify Reserved Names for Generated Identifiers


You can specify a set of reserved keywords that the code generation process should not
use, facilitating code integration where functions and variables from external
environments are unknown in the Simulink model. To create a list of reserved names,
open the Configuration Parameters dialog box. On the Code Generation > Symbols
pane, enter the keywords in the “Reserved names” (Simulink Coder) field.

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

C++ Reserved Keywords


catch friend protected try
class inline public typeid
const_cast mutable reinterpret_cast typename
delete namespace static_cast using
dynamic_cast new template virtual
explicit operator this wchar_t
export private throw

Reserved Keywords for Code Generation


abs int8_T MAX_uint8_T* rtInf
asm int16_T MAX_uint16_T* rtMinusInf
bool int32_T MAX_uint32_T* rtNaN
boolean_T int64_T MAX_uint64_T SeedFileBuffer
byte_T INTEGER_CODE MIN_int8_T* SeedFileBufferLen
char_T LINK_DATA_BUFFER_SIZ MIN_int16_T* single
E
cint8_T LINK_DATA_STREAM MIN_int32_T* TID01EQ
cint16_T localB MIN_int64_T time_T
cint32_T localC MODEL true
creal_T localDWork MT uint_T
creal32_T localP NCSTATES uint8_T
creal64_T localX NULL uint16_T
cuint8_T localXdis NUMST uint32_T
cuint16_T localXdot pointer_T uint64_T
cuint32_T localZCE PROFILING_ENABLED UNUSED_PARAMETER
ERT localZCSV PROFILING_NUM_SAMPLES USE_RTMODEL
false matrix real_T VCAST_FLUSH_DATA

31-31
31 Configuration for Simulink Coder

fortran MAX_int8_T* real32_T vector


HAVESTDIO MAX_int16_T* real64_T
id_t MAX_int32_T* RT
int_T MAX_int64_T RT_MALLOC
*Not reserved if you specify a replacement identifier.

Code Generation Code Replacement Library Keywords


The list of code replacement library reserved keywords for your development
environment varies depending on which libraries are registered. The list of available code
replacement libraries varies depending on other installed products (for example, a target
product), or if you used Embedded Coder to create and register custom code replacement
libraries.

To generate a list of reserved keywords for libraries currently registered in your


environment, use the following MATLAB function:
lib_ids = RTW.TargetRegistry.getInstance.getTflReservedIdentifiers()

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')

Here is a partial example of the function output:


>> 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.

set_param(model, 'TLCAssertion', 'on|off')

To check the current setting, use get_param.

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:

• none — Loss of tunability can occur without notification.


• warning — Loss of tunability generates a warning (default).
• error — Loss of tunability generates an error.

For a list of supported operators and functions, see “Tunable


Expression Limitations” (Simulink Coder)

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:

• User local settings


• Enable All
• Disable All

For Assertion blocks not disabled, generated code for a model


includes one of the following statements, depending on the
blocks input signal type (Boolean, real, or integer, respectively).

utAssert(input_signal);
utAssert(input_signal != 0.0);
utAssert(input_signal != 0);

By default, utAssert does not change generated code. For


assertions to abort execution, you must enable them by
specifying the following make_rtw command for Code
Generation > “Make command” (Simulink Coder) parameter:

make_rtw OPTS="-DDOASSERTS"

Use the following variant if you want triggered assertions to


print the assertion statement instead of aborting execution:

make_rtw OPTS="-DDOASSERTS -DPRINT_ASSERTS"

utAssert is defined as #define utAssert(exp)


assert(exp).

To customize assertion behavior, provide your own definition of


utAssert in a handwritten header file that overrides the
default utAssert.h. For details on how to include a
customized header file in generated code, see “Integrate

31-36
See Also

To... Select...
External Code by Using Model Configuration Parameters”
(Simulink Coder).

When running a model in accelerator mode, the Simulink


engine calls back to itself to execute assertion blocks instead of
using generated code. Thus, user-defined callbacks are still
called when assertions fail.

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

Configuration in Embedded Coder

• “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

Configure Model for Code Generation Objectives by


Using Code Generation Advisor
In this section...
“High-Level Code Generation Objectives” on page 32-3
“Specify Objectives in Referenced Models” on page 32-3
“Configure Model Using Code Generation Advisor” on page 32-4
“Configure Model for Code Generation Objectives by Using Configuration Parameters
Dialog Box” on page 32-6

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

High-Level Code Generation Objectives


Depending on the type of application that your model represents, you are likely to have
specific high-level code generation objectives. For example, safety and traceability are
more critical than efficient use of memory. If you have specific objectives, you can quickly
configure your model to meet those objectives by selecting and prioritizing from these
code generation objectives:

• 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.

Specify Objectives in Referenced Models


When you check a model during the code generation process, you must specify the same
objectives in the top model and referenced models. If you specify different objectives for
the top model and referenced model, the build process generates an error.

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.

Configure Model Using Code Generation Advisor


This example shows how to use the Code Generation Advisor to check and configure your
model to meet code generation objectives:

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:

a In Available objectives, double-click Execution efficiency. Execution


efficiency is added to Selected objectives - prioritized.
b In Available objectives, double-click Traceability. Traceability is added
to Selected objectives - prioritized under Execution efficiency.

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

Check model configuration settings against code generation objectives


triggers a warning for these issues:

• 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.

Click Modify Parameters to set:

• Parameters to the value recommended for the specified code generation


objectives.
• Code generation objectives in the model to the objectives specified in the Code
Generation Advisor.

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.

Configure Model for Code Generation Objectives by Using


Configuration Parameters Dialog Box
This example shows how to configure and check your model to meet code generation
objectives via the Configuration Parameters dialog box:

1 Open the Configuration Parameters dialog box. Select Code Generation.


2 Specify a system target file. If you specify an ERT-based target, more objectives are
available. For this example, choose an ERT-based target such as ert.tlc.
3 Click Set Objectives.
4 In the “Set Objectives — Code Generation Advisor Dialog Box” (Simulink Coder),
specify your objectives. For example, if your objectives are execution efficiency and
traceability, in that priority, do the following:

a In Available objectives, double-click Execution efficiency. Execution


efficiency is added to Selected objectives - prioritized.
b In Available objectives, double-click Traceability. Traceability is added
to Selected objectives - prioritized under Execution efficiency.

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

Configure Code Generation Objectives Programmatically


This example shows how to configure code generation objectives by writing a MATLAB
script or entering commands at the command line.

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, 'SystemTargetFile', 'ert.tlc');


2 Specify your objectives. For example, if your objectives are execution efficiency and
traceability, in that priority, enter:

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

Check Model and Configuration for Code Generation


You can use the Model Advisor checks to assess model readiness to generate code. To
check and configure your model for code generation application objectives such as
traceability or debugging, use the Code Generation Advisor.

For information about See


Model Advisor “Run Model Checks” (Simulink)
Code Generation Advisor “Configure Model for Code Generation
Objectives by Using Code Generation
Advisor” on page 32-2
Checks available with Simulink Coder “Simulink Coder Checks” (Simulink Coder)
Checks available with Embedded Coder “Embedded Coder Checks”

To check model rtwdemo_throttlecntrl for code efficiency, use the Model Advisor.

1 Open rtwdemo_throttlecntrl. Save a copy as throttlecntrl in a writable


location on your MATLAB path.
2 To start the Model Advisor, select Analysis > Model Advisor > Model Advisor. A
dialog box opens showing the model system hierarchy.
3 Click throttlecntrl and then click OK. The Model Advisor window opens.
4 Expand By Task > Code Generation Efficiency. To check your model for code
generation efficiency, use the checks in the folder. By default, checks that do not
trigger an Update Diagram are selected. The checks available for code generation
efficiency depend on whether you have a Simulink Coder or Embedded Coder license.
5 In the left pane, select the remaining checks, and then select Code Generation
Efficiency.
6 In the right pane, select Show report after run and click Run Selected Checks.
The report shows a Run Summary that flags check warnings.
7 Review the report. The warnings highlight issues that impact code efficiency. For
more information about the report, see “View Model Advisor Reports” (Simulink).

Check Model During Code Generation


To review a model as part of the code generation process, use the Code Generation
Advisor .

32-10
Check Model and Configuration for Code Generation

1 To select and prioritize your code generation objectives, on the Configuration


Parameters > Code Generation pane, click Set Objectives.
2 On the Configuration Parameters > Code Generation > General pane, select one
of the following from Check model before generating code:

• On (proceed with warnings)


• On (stop for warnings)
3 If you want to only generate code, select Generate code only. Otherwise clear the
check box to build an executable.
4 Apply your changes. In the model window, press Ctrl+B to generate code or build
the model.

If the Code Generation Advisor issues failures or warnings, and you specified:

• On (proceed with warnings) — The Code Generation Advisor window opens


while the build process proceeds. After the build process is complete, you can
review the results.
• On (stop for warnings) — The build process halts and displays the
Diagnostic Viewer. To continue, you must review and resolve the Code Generation
Advisor results or clear the Check model before generating code parameter.
5 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.
6 After reviewing the check results, you can choose to fix warnings and failures as
described in “Fix a Model Check Warning or Failure” (Simulink).

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

Embedded Coder Model Advisor Checks for Standards,


Guidelines, and Code Efficiency
To check that your model meets guidelines, standards, and is ready to generate code, you
can use the Model Advisor checks available with 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.

By Task folder Model Advisor checks


Modeling Check for blocks not recommended for C/C++ production code
Standards for deployment
MAAB
Code Generation Identify lookup table blocks that generate expensive out-of-range
Efficiency checking code

Check output types of logic blocks

Identify questionable software environment specifications

Identify questionable code instrumentation (data I/O)

Identify blocks that generate expensive fixed-point and saturation


code

Identify blocks that generate expensive rounding code

Identify questionable fixed-point operations

32-12
Embedded Coder Model Advisor Checks for Standards, Guidelines, and Code Efficiency

By Task folder Model Advisor checks


Modeling Check for blocks not recommended for C/C++ production code
Standards for deployment

• IEC 61508, IEC


62304, ISO
26262, and EN
50128
Modeling Check for blocks not recommended for C/C++ production code
Standards for deployment
DO-178C/DO-331
Check the hardware implementation

Identify questionable subsystem settings


Modeling Check configuration parameters for MISRA C:2012
Guidelines for
MISRA C:2012 Check for blocks not recommended for C/C++ production code
deployment

Check for blocks not recommended for MISRA C:2012

Check for unsupported block names

Check usage of Assignment blocks

Check for switch case expressions without a default case

Check for missing error ports for AUTOSAR receiver interfaces

Check for bitwise operations on signed integers

Check for recursive function calls

Check for equality and inequality operations on floating-point


values

Check for missing const qualifiers in model functions

Check bus object names that are used as element names

32-13
32 Configuration in Embedded Coder

By Task folder Model Advisor checks


Modeling Check configuration parameters for secure coding standards
Guidelines for
secure coding Check for blocks not recommended for C/C++ production code
standards (CERT deployment
C, CWE, ISO/IEC
TS 17961) Check for blocks not recommended for secure coding standards

Check usage of Assignment blocks

Check for switch case expressions without a default case

Check for bitwise operations on signed integers

Check for equality and inequality operations on floating-point


values

Check integer word length

If you have a Simulink Design Verifier™ license, the following


checks are also available.

Detect Dead Logic

Detect Integer Overflow

Detect Division by Zero

Detect Out Of Bound Array Access

Detect Violation of Specified Minimum and Maximum Values

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

• “Modeling Guidelines for Model Configuration” on page 2-46

32-15
32 Configuration in Embedded Coder

Create Custom Code Generation Objectives

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.

To 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.

Specify Parameters in Custom Objectives


When you create a custom objective, you specify the values of configuration parameters
that the Code Generation Advisor reviews. You can use the following methods:

• 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

Specify Checks in Custom Objectives


Objectives include the Check model configuration settings against code generation
objectives check by default. When you create a custom objective, you specify the list of
additional checks that are associated with the custom objective. You can use the following
methods:

• 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.

Determine Checks and Parameters in Existing Objectives


When you base a new objective on an existing objective, you can determine what checks
and parameters the existing objective contains. The Code Generation Advisor contains the
list of checks in each 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.

Steps to Create Custom Objectives


To create a custom objective:
1 Create an sl_customization.m file.

• Specify custom objectives in a single sl_customization.m file only or the


software generates an error. This issue is true even if you have more than one
sl_customization.m file on your MATLAB path.

32-18
Create Custom Code Generation Objectives

• Except for the matlabroot/work folder, do not place an sl_customization.m


file in your root MATLAB folder or its subfolders. Otherwise, the software ignores
the customizations that the file specifies.
2 Create an sl_customization function that takes a single argument. When the
software invokes the function, the value of this argument is the Simulink
customization manager. In the function:

• To create a handle to the code generation objective, use the


ObjectiveCustomizer constructor.
• To register a callback function for the custom objectives, use the
ObjectiveCustomizer.addCallbackObjFcn method.
• To add a call to execute the callback function, use the
ObjectiveCustomizer.callbackFcn method.

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:

• Creates code generation objective objects by using the


rtw.codegenObjectives.Objective constructor.
• Adds, modifies, and removes configuration parameters for each objective by using
the addParam, modifyInheritedParam, and removeInheritedParam
methods.
• Includes and excludes checks for each objective by using the addCheck,
excludeCheck, and removeInheritedCheck methods.
• Registers objectives by using the register method.

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

% Create the custom objective


obj = rtw.codegenObjectives.Objective('ex_ram_1');

32-19
32 Configuration in Embedded Coder

setObjectiveName(obj, 'Reduce RAM Example');

% Add parameters to the objective


addParam(obj, 'DefaultParameterBehavior', 'Inlined');
addParam(obj, 'BooleanDataType', 'on');
addParam(obj, 'OptimizeBlockIOStorage', 'on');
addParam(obj, 'EnhancedBackFolding', 'on');
addParam(obj, 'BooleansAsBitfields', 'on');

% Add additional checks to the objective


% The Code Generation Advisor automatically includes 'Check model
% configuration settings against code generation objectives' in every
% objective.
addCheck(obj, 'mathworks.design.UnconnectedLinesPorts');
addCheck(obj, 'mathworks.design.Update');

%Register the objective


register(obj);

end

The following example shows you how to create an objective My Traceability


Example based on the existing Traceability objective. The custom objective modifies,
removes, and adds parameters that the Code Generation Advisor reviews. It also adds
and removes checks from the Code Generation Advisor.
function addObjectives

% Create the custom objective from an existing objective


obj = rtw.codegenObjectives.Objective('ex_my_trace_1', 'Traceability');
setObjectiveName(obj, 'My Traceability Example');

% Modify parameters in the objective


modifyInheritedParam(obj, 'GenerateTraceReportSf', 'Off');
removeInheritedParam(obj, 'ConditionallyExecuteInputs');
addParam(obj, 'MatFileLogging', 'On');

% Modify checks in the objective


addCheck(obj, 'mathworks.codegen.SWEnvironmentSpec');
removeInheritedCheck(obj, 'mathworks.codegen.CodeInstrumentation');

%Register the objective


register(obj);

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.

Multiple configuration sets can be useful in embedded systems development. By defining


multiple configuration sets in a model, you can easily retarget code generation from that
model. For example, one configuration set can specify the default ERT target with
external mode support enabled for rapid prototyping. Another configuration set can
specify the ERT-based target for Visual C++® to generate production code for
deployment of the application. Activation of either configuration set fully reconfigures the
model for that type of code generation.

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

Configure and Optimize Model with Configuration


Wizard Blocks
The Embedded Coder software provides a library of Configuration Wizard blocks and
scripts to help you configure and optimize code generation from your models.

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

Configuration Wizard Block Library


The library provides a Configuration Wizard block that you can customize. It also provides
four preset Configuration Wizard blocks that update the active configuration parameters
for a specified goal.

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:

• Fixed-point code generation with the ERT target


• Floating-point code generation with the ERT target
• Fixed-point or floating-point code generation with TLC debugging parameters enabled,
with the GRT target.
• Fixed-point or floating-point code generation with the GRT target

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.

Add a Configuration Wizard Block


The Configuration Wizard blocks are available in the Embedded Coder block library. To
use a Configuration Wizard block:

1 Open the model that you want to configure.

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.

Use Configuration Wizard Blocks to Configure Your Model


After you add a Configuration Wizard block to your model, to configure your model,
double-click the block. The script associated with the block sets parameters of the active
configuration set that are relevant to code generation (including selection of the target).
You can see that the parameters have changed by opening the Configuration Parameters
dialog box and examining the parameter settings.

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.

Create a Custom Configuration Wizard Block


The Custom Configuration Wizard block and the associated MATLAB file script,
matlabroot/toolbox/rtw/rtw/rtwsampleconfig.m, provide a starting point for
customization.

Set Up a Configuration Wizard Block

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.

To begin, make a copy of the example script for later customization:

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).

The example refers to this folder as /my_wizards.


2 Add the folder to the MATLAB path. Save the path for future sessions.
3 Copy the example script rtwsampleconfig.m in the folder matlabroot/
toolbox/rtw/rtw (open) to the /my_wizards folder that you created. Then,
rename the script. This example uses the name my_configscript.m.
4 Open the example script into the MATLAB editor. Scroll to the end of the file and
enter the following line of code:

disp('Custom Configuration Wizard Script completed.');

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.

Test your block and script in a model.

1 Open the vdp model by typing the command:

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:

Custom Configuration Wizard Script completed.

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 a Configuration Wizard Script

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 Configuration Function

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.

Access Configuration Set Parameters

To set parameters or obtain parameter values, use the Simulink set_param and
get_param functions.

Option names are passed in to set_param and get_param as character vectors


specifying an internal option name. The internal option name can be different from the
option label on the UI (for example, the Configuration Parameters dialog box). The
example configuration accompanies each set_param and get_param call with a
comment that correlates internal option names to UI option labels. For example:

set_param(cs,'LifeSpan','1'); % Application lifespan (days)

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:

if strcmp(get_param(cs, 'GenerateReport'), 'on')


...

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:

• isValidParam(cs, 'option'): The option argument is an internal option name.


isValidParam returns true if option is a valid option in the context of the active
configuration set.
• getPropEnabled(cs, 'option'): The option argument is an internal option
name. Returns true if this option is enabled (that is, writable).
• IsERTTarget property: Your code can detect whether the currently selected target is
derived from the ERT target by checking the IsERTTarget property, as follows:
isERT = strcmp(get_param(cs,'IsERTTarget'),'on');

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

Invoke a Configuration Wizard Script from the Command Line

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

Create a Model Configured for Code Generation Using


Model Templates
Model templates provide you with a starting point for quickly developing models for code
generation. Embedded Coder templates provide starting models for the following
applications:

• 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

To create a model using a model template:

1 On the MATLAB home tab, click Simulink.


2 In the Simulink start page, expand Embedded Coder.
3 Select a template.
4 Click Create. A new model that uses the template contents and settings appears in
the Simulink Editor window.

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

System Target File Configuration

• “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
• “Compare System Target File Support” on page 33-21
33 System Target File Configuration

Configure a System Target File


To configure a model for code generation, follow the steps in “Select a Solver That
Supports Code Generation” (Simulink Coder) and “Select a System Target File from STF
Browser” (Simulink Coder). When you select a system target file, other model
configuration parameters change to serve requirements of the execution environment.
For example:

• Code interface parameters


• Build process parameters, such as the toolchain or template makefile
• Target hardware parameters, such as word size and byte ordering

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

Select a Solver That Supports Code Generation


To build a model, the model configuration must select a solver that is compatible with
code generation for the system target file. Few system target files support code
generation with variable-step solvers or for models with a nonzero start time.

• 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.

Select a System Target File from STF Browser


After you select a solver (see “Select a Solver That Supports Code Generation” (Simulink
Coder)), use Configuration Parameters > Code Generation > System target file and
click the Browse button to open the System Target File Browser. Select a system target
file from the list. Your selection appears in the System target file field (target.tlc).

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.

System Target File Browser

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.

Select a System Target File Programmatically


Simulink models store model-wide parameters and system target file-specific data in
configuration sets. Every configuration set contains a component that defines the

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.

To program system target file selection:

1 Obtain a handle to the active configuration set with a call to the


getActiveConfigSet function.
2 Define character vector variables that correspond to the required system target file,
toolchain or template makefile, and/or make command settings. For example, for the
ERT system target file, you would define variables for the character vectors
'ert.tlc', 'ert_default_tmf', and 'make_rtw'.
3 Select the system target file with a call to the switchTarget function. In the
function call, specify the handle for the active configuration set and the system target
file.
4 Set the TemplateMakefile and MakeCommand configuration parameters to the
corresponding variables created in step 2.

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.

Develop Custom System Target Files


You can create your own system target files that interface with external code or operating
environments.

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

Configure STF-Related Code Generation Parameters


Many model configuration parameters for code generation are specific to GRT, ERT, or
ERT-based system target files. For more information, see the following topics.

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

Specify Generated Code Interfaces


Use interface model configuration parameters to control which libraries to use when
generating code, whether to include support for an API in generated code, and other
interface options.

To... Select or Enter...


Specify the standard math Select C89/C90 (ANSI), C99 (ISO), or C++03 (ISO) for the
library that the code Standard math library parameter.
generator uses when
generating code. Selecting C89/C90 (ANSI) provides the ANSIa C set of library
functions. For example, selecting C89/C90 (ANSI) results in
generated code that calls sin() whether the input argument is
double precision or single precision. However, if you select C99
(ISO), the generated code calls the function sinf() when the input
argument is single precision. If your compiler supports the ISO®b C
math extensions, selecting the ISO C library can result in more
efficient code.

For more information, see “Standard math library” (Simulink Coder).

The options for this parameter have dependencies. See Interface


Dependencies.

33-7
33 System Target File Configuration

To... Select or Enter...


Specify an application- If you generate application-specific C or C++ code for math functions
specific library that the code or operations, select a value for Code replacement library.
generator uses when Otherwise, specify None.
generating code.
For more information about code replacement libraries, see “Choose a
Code Replacement Library” on page 40-8 and “Code replacement
library” (Simulink Coder).

The options for this parameter have dependencies. See Interface


Dependencies.
Direct where the code Select Auto or Shared location for Shared code placement. The
generator places fixed-point shared location directs code for utilities to be placed within the slprj
and other utility code. folder in your working folder, which is used for building referenced
models. If you select Auto,

• 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

To... Select or Enter...


Specify data exchange APIs Select one or more C API options, the ASAP2 interface option, or
to be included in generated the External mode option. When you select External mode, other
code. options appear. The data exchange APIs are independent, and you can
select combinations of these APIs. For example, you could choose C
API and external mode.

For more information on working with these interfaces, see


“Exchange Data Between Generated and External Code Using C API”
on page 46-2, “Export ASAP2 File for Data Measurement and
Calibration” on page 47-2, and “Host-Target Communication with
External Mode Simulation” (Simulink Coder).

The options for this parameter have dependencies. See Interface


Dependencies.
a. ANSI is a registered trademark of the American National Standards Institute, Inc.
b. ISO is a registered trademark of the International Organization for Standardization.

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).

Several interface parameters have dependencies on settings of other parameters. The


following table summarizes the dependencies.

33-9
33 System Target File Configuration

Interface Dependencies

Parameter Dependencies? Dependency Details


Standard math library Yes Available values depend on Language
selection.
Code replacement library Yes Available values depend on product
licensing and other parameters. For
more information, see “Code
replacement library” (Simulink Coder).
Shared code placement No
Support: floating-point numbers No
(ERT system target files only)
Support: non-finite numbers Yes (ERT) For ERT system target files, enabled by
No (GRT) Support floating-point numbers
Support: complex numbers (ERT No
system target files only)
Support: absolute time (ERT No
system target files only)
Support: continuous time (ERT Yes Requires that you disable Remove error
system target files only) status field in real-time model data
structure.
Support: non-inlined S- Yes Requires that you enable Support
functions (ERT system target files floating-point numbers and Support
only) non-finite numbers
Classic call interface Yes Requires that you disable Single
output/update function. For ERT
system target files, requires that you
enable Support floating-point
numbers.
Single output/update function Yes Disable for Classic call interface
Terminate function required Yes
(ERT system target files only)
Code interface packaging Yes Available values depend on Language
selection.

33-10
Configure STF-Related Code Generation Parameters

Parameter Dependencies? Dependency Details


Multi-instance code error Yes Set Code interface packaging to
diagnostic Reusable function or C++ class
Pass root-level I/O as (ERT system Yes Set Code interface packaging to
target files only) Reusable function
Use dynamic memory allocation Yes Set Code interface packaging to
for model initialization (ERT Reusable function
system target files only)
MAT-file logging Yes For GRT system target files, requires
that you enable Support non-finite
numbers; for ERT system target files,
requires that you enable Support
floating-point numbers, Support non-
finite numbers, and Terminate
function required
MAT-file file variable name Yes Enabled by MAT-file logging
modifier
Remove error status field in Yes Requires that you disable Support:
real-time model data structure continuous time.
(ERT system target files only)
Generate C API for: signals No
Generate C API for: parameters No
Generate C API for: states No
Generate C API for: root-level No
I/O
ASAP2 interface No
External mode No
Transport layer Yes Enable External mode
MEX-file arguments Yes Enable External mode
Static memory allocation Yes Enable External mode
Static memory buffer size Yes Enable Static memory allocation

33-11
33 System Target File Configuration

Configure Numeric Data Support


By default, ERT system target files support code generation for integer, floating-point,
nonfinite, and complex numbers.

To Generate Code That Do...


Supports...
Integer data only Clear Support floating-point numbers. If noninteger data or
expressions are encountered during code generation, an error
message reports the offending blocks and parameters.
Floating-point data Select Support floating-point numbers.
Nonfinite values (for example, Select Support floating-point numbers and Support non-
NaN, Inf) finite numbers.
Complex data Select Support complex numbers.

For more information, see “Model Configuration Parameters: Code Generation Interface”
(Simulink Coder).

Configure Time Value Support


Certain blocks require the value of absolute time, elapsed time, or continuous time.
Absolute time is the time from the start of program execution to the present time. Elapsed
time is the time elapsed between two trigger events. Depending on the blocks used, your
model could require adjustment of the configuration settings for supported time values.

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

Configure Noninlined S-Function Support


To generate code for noninlined S-Functions in a model, select Support noninlined S-
functions. The generation of noninlined S-functions requires floating-point and nonfinite
numbers. Thus, when you select Support non-inlined S-functions, the ERT system
target file selects Support floating-point numbers and Support non-finite numbers.

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.

Inlining S-functions is highly advantageous in production code generation, for example in


implementing device drivers. To enforce the use of inlined S-functions for code
generation, clear Support non-inlined S-functions.

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:

• Model configuration parameter GenCodeOnly is set to off or Configuration


Parameters > Code Generation > Generate code only is cleared.
• Model configuration parameter ProdEqTarget is set to off.

To avoid such a mismatch, set ProdEqTarget to on or select Configuration


Parameters > Code Generation > Generate code only (or set GenCodeOnly to on).

Configure Model Function Generation and Argument Passing


For ERT system target files, you can configure model for how functions are generated and
how arguments are passed to the functions.

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.

Do not select this parameter if you select the MAT-file logging


option. The two options are incompatible.

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).

Configure Code Reuse Support


For GRT, ERT, GRT-based, and ERT-based system target files, you can configure how a
model reuses code by setting the Configuration Parameters > Code Generation >
Code interface packaging parameter value to Reusable function.

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, selecting Code interface packaging as Reusable function can generate


code that compiles but is not reentrant. For example, if a signal, DWork structure, or
parameter data has a storage class other than Auto, global data structures are
generated. To handle such cases, use the Multi-instance code error diagnostic
parameter to choose the severity levels for diagnostics.

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.

• An S-function that is not code-reuse compliant


• A subsystem triggered by a wide function-call trigger

In these cases, the build terminates after reporting the problem.

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

Configure a Code Replacement Library


You can configure the code generator to change the code that it generates for functions
and operators such that the code meets application requirements. Configure the code
generator to apply a code replacement library (CRL) during code generation. If you have
Embedded Coder, you can develop and apply custom code replacement libraries.

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

Configure Standard Math Library for Target System


Specify standard library extensions that the code generator uses for math operations.
When you generate code for a new model or with a new configuration set object, the code
generator uses the ISO®/IEC 9899:1999 C (C99 (ISO)) library by default. For preexisting
models and configuration set objects, the code generator uses the library specified by the
Standard math library parameter.

If your compiler supports the ISO®/IEC 9899:1990 (C89/C90 (ANSI)) or ISO/IEC


14882:2003(C++03 (ISO)) math library extensions, you can change the standard math
library setting. The C++03 (ISO) library is an option when you select C++ for the
programming language.

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().

To change the library setting, use the Configuration Parameters>Standard math


library parameter. The command-line equivalent is TargetLangStandard.

Generate and Inspect ANSI C Code

1. Open the example model rtwdemo_clibsup.

33-18
Configure Standard Math Library for Target System

2. Generate code.

### Starting build procedure for model: rtwdemo_clibsup


### Successful completion of code generation for model: rtwdemo_clibsup

3. Examine the code in the generated file rtwdemo_clibsup.c. Note that the code calls
the sqrt function.

if (rtb_Abs2 < 0.0F) {


rtb_Abs2 = -(real32_T)sqrt((real32_T)fabs(rtb_Abs2));
} else {
rtb_Abs2 = (real32_T)sqrt(rtb_Abs2);
}

33-19
33 System Target File Configuration

Generate and Inspect ISO C Code

1. Change the setting of Standard math library to C99 (ISO). Alternatively, at the
command line, set TargetLangStandard to C99 (ISO).

2. Regenerate the code.

### Starting build procedure for model: rtwdemo_clibsup


### Successful completion of code generation for model: rtwdemo_clibsup

3. Reexamine the code in the generated file rtwdemo_clibsup.c. Now the generated
code calls the function sqrtf instead of sqrt.

if (rtb_Abs2 < 0.0F) {


rtb_Abs2 = -sqrtf(fabsf(rtb_Abs2));
} else {
rtb_Abs2 = sqrtf(rtb_Abs2);
}

Related Information

• “Standard math library” (Simulink Coder)


• “Configure a System Target File” (Simulink Coder)
• “Configure STF-Related Code Generation Parameters” (Simulink Coder)
• “Configure a Code Replacement Library” (Simulink Coder)
• “Compare System Target File Support” (Simulink Coder)
• “Replace Code Generated from Simulink Models” (Simulink Coder)

33-20
Compare System Target File Support

Compare System Target File Support


When you select a system target file (such as grt.tlc), the selection defines the run-
time environment and the code generation features. To identify the system target file
features that match your development process goals, see:

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:

• Certain data structures (for example, SimStruct or rtModel)


• Static or dynamic memory allocation code
• Calling interface for generated model functions

For custom system target file development, follow these guidelines:

• 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.

%assign CodeFormat = "Embedded-C"

/%
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).

The real-time model data structure (rtModel) encapsulates model-specific information in


a much more compact form than the SimStruct. Many efficiencies related to generated
code depend on generation of rtModel rather than SimStruct, including:

• Integer absolute and elapsed timing services


• Independent timers for asynchronous tasks
• Generation of improved C API code for signal, state, and parameter monitoring
• Pruning the data structure to minimize its size (ERT-derived system target files only)

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

Evaluate Product System Target Files


The following table lists supported system target files.

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

System Target Files Available from System Target File Browser

System Target File File Names Reference


Embedded Coder (for PC or ert.tlc “Configure a System Target File” on
UNIXa platforms) ert_shrlib.tlc page 33-2
Create Visual C++b Solution ert.tlc “Configure a System Target File” on
File for Embedded Coder page 33-2
(Requires RTW.MSVCBuild
as TMFc)
Embedded Coder for autosar.tlc “Getting Started with AUTOSAR Code
AUTOSAR Generation”
Generic Real-Time (for PC or grt.tlc “Compare Generated Code Features
UNIX platforms) by STF” on page 33-29
Create Visual C++ Solution grt.tlc “Compare Generated Code Features
File by STF” on page 33-29
(Requires RTW.MSVCBuild
as TMFc)
Rapid Simulation (default for rsim.tlc “Accelerate, Refine, and Test Hybrid
PC or UNIX platforms) Dynamic System on Host Computer
by Using RSim System Target File” on
page 49-2
Rapid Simulation for LCC rsim.tlc “Accelerate, Refine, and Test Hybrid
compiler Dynamic System on Host Computer
by Using RSim System Target File” on
page 49-2
Rapid Simulation for UNIX rsim.tlc “Accelerate, Refine, and Test Hybrid
platforms Dynamic System on Host Computer
by Using RSim System Target File” on
page 49-2
Rapid Simulation for Visual C+ rsim.tlc “Accelerate, Refine, and Test Hybrid
+ compiler Dynamic System on Host Computer
by Using RSim System Target File” on
page 49-2

33-24
Compare System Target File Support

System Target File File Names Reference


S-Function for PC or UNIX rtwsfcn.tlc “Accelerate Simulation, Reuse Code,
platforms or Protect Intellectual Property by
Using S-Function Target” (Simulink
Coder)
S-Function for LCC rtwsfcn.tlc “Accelerate Simulation, Reuse Code,
or Protect Intellectual Property by
Using S-Function Target” (Simulink
Coder)
S-Function for UNIX platforms rtwsfcn.tlc “Accelerate Simulation, Reuse Code,
or Protect Intellectual Property by
Using S-Function Target” (Simulink
Coder)
S-Function for Visual C++ rtwsfcn.tlc “Accelerate Simulation, Reuse Code,
compiler or Protect Intellectual Property by
Using S-Function Target” (Simulink
Coder)
ASAM-ASAP2 Data Definition asap2.tlc “Export ASAP2 File for Data
Measurement and Calibration” on
page 47-2
Simulink Desktop Real-Time sldrt.tlc “Set External Mode Code Generation
sldrtert.tlc Parameters” (Simulink Desktop Real-
Time)
Simulink Real-Time slrt.tlc “Simulink Real-Time Options Pane”
(Simulink Real-Time)
IDE Link capability idelink_grt.tlc Embedded IDE or target topics such
idelink_ert.tlc as “Model Setup” on page 75-2
a. UNIX is a registered trademark of The Open Group in the United States and other countries.
b. Visual C++ is a registered trademark of Microsoft Corporation.
c. Set RTW.MSVCBuild in the “Template makefile” (Simulink Coder) field. This creates and builds Visual C++ Solution
(.sln) file with Debug configuration.

Compare Code Styles and STF Support


The code generator produces two styles of code. One code style is suitable for rapid
prototyping (and simulation by using code generation). The other style is suitable for

33-25
33 System Target File Configuration

embedded applications. The following table maps system target files to corresponding
code styles.

Code Styles Listed by System Target File

System Target File Code Style Purpose


Embedded Coder Embedded A starting point for embedded application
embedded real-time development of C/C++ generated code
(ERT)
Simulink Coder generic Rapid A starting point for creating a rapid
real-time (GRT) prototyping prototyping target hardware that does not
use real-time operating system tasking
primitives and for verifying the generated
C/C++ code on your desktop computer
Rapid simulation (RSim) Rapid Provides non-real-time simulation on your
prototyping desktop computer and a high-speed or
batch simulation tool
S-function Rapid Creates a C MEX S-function for simulation
prototyping within another Simulink model
Simulink Desktop Real- Rapid Runs model in real time at interrupt level
Time prototyping while your desktop computer runs
Microsoft Windows in the background
Simulink Real-Time Rapid Runs model in real time on a desktop
prototyping computer running the Simulink Real-Time
kernel

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.

Compare Generated Code Features by Product


The code generation process for real-time system target files (such as GRT) provides
many embedded code optimizations. GRT and ERT system target files have many common
features. But, selecting an ERT-based system target file offers more extensive features.
The system target file selection determines the available features for the code generation
product. The following table compares code features available with Simulink Coder and
features available with Embedded Coder.

33-26
Compare System Target File Support

Compare Code Generation Features for Simulink Coder Versus Embedded Coder

Feature Simulink Coder Embedded Coder


rtModel data • Full rtModel structure • rtModel is optimized for the
structure generated model
• GRT variable declaration: • Optional suppression of error
rtModel_model model_M_; status field and data logging
fields
• ERT variable declaration:
RT_MODEL_model model_M_;
Custom storage Code generation ignores CSCs; Code generation with CSCs is
classes (CSCs) objects are assigned a CSC default supported
to Auto storage class
HTML code generation Basic HTML code generation report Enhanced report with additional
report detail and hyperlinks to the model
Symbol formatting Symbols (for signals, parameters, Detailed control over generated
and so on) are generated in symbols.
accordance with hard-coded default
User-defined maximum Supported Supported
identifier length for
generated symbols
Generation of Generated Option to suppress the terminate
terminate function function
Combined output/ Separate output/update functions Option to generate combined output/
update function are generated update function
Optimized data Not available Options to suppress generation of
initialization unnecessary initialization code for
zero-valued memory, I/O ports, and
so on
Comments generation Basic options to include or suppress Options to include Simulink block
comment generation descriptions, Stateflow object
descriptions, and Simulink data
object descriptions in comments

33-27
33 System Target File Configuration

Feature Simulink Coder Embedded Coder


Module Packaging Not supported Extensive code customization
Features (MPF) features (See “Control Data Type
Names in Generated Code” on page
24-2 and “MPT Data Object
Properties” on page 25-2.)
System target file- Requires full tmwtypes.h header Generates optimized rtwtypes.h
optimized data types file header file, including definitions
header file required by the system target file
User-defined types User-defined types default to base User-defined data type aliases are
types in code generation supported in code generation
Rate grouping Not supported Supported
Auto-generation of Not supported; static main program Automated and customizable
main program module module is provided. generation of main program module
is supported (static main program
also available)
Reusable (multi- Option to generate reusable code Option to generate reusable code
instance) code with dynamic memory allocation with static or dynamic memory
generation allocation
Software constraint Support for floating point, complex, Options to enable or disable support
options and nonfinite numbers is enabled for floating-point, complex, and
nonfinite numbers
Application life span Defaults to inf User-specified; determines most
efficient word size for integer timers
Software-in-the-loop Model reference simulation target Additional SIL testing support by
(SIL) testing can be used for SIL testing using auto-generation of SIL block
ANSIa-C/C++ code Supported Supported
generation
ISOb-C/C++ code Supported Supported
generation
GNU®c-C/C++ code Supported Supported
generation

33-28
Compare System Target File Support

Feature Simulink Coder Embedded Coder


Generate scalar Not supported Supported
inlined parameters as
#DEFINE statements
MAT-file variable name Supported Supported
modifier
Data exchange: C API, Supported Supported
ASAP2, external mode
a. ANSI is a registered trademark of the American National Standards Institute, Inc.
b. ISO is a registered trademark of the International Organization for Standardization.
c. GNU is a registered trademark of the Free Software Foundation.

Compare Generated Code Features by STF


The code generator supports a selection of generated code features for different types of
system target files. In each system target file, the value of the CodeFormat TLC variable
identifies the set of features.

The following table summarizes how different system target files support applications:

Application System Target File (STF)


Fixed- or variable-step acceleration RSIM, S-Function, Model Reference
Fixed-step real-time deployment GRT, ERT, Simulink Real-Time, Simulink Desktop
Real-Time, ...

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

Features Supported in Code Generated for System Target Files (STF)

System Target Files (STF)


Feature grt.tlc ert.tlc ert_shrlib.tl rtwsfcn.tlc1 rsim.tlc1 sldrt.tlc slrt.tlc1 Other1
1 1
c1 1

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

System Target Files (STF)


Feature grt.tlc ert.tlc ert_shrlib.tl rtwsfcn.tlc1 rsim.tlc1 sldrt.tlc slrt.tlc1 Other1
1 1
c1 1

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

Internationalization and Code Generation


Internationalization support in software development tooling is vital for enabling efficient
globalization. If there is any possibility of future collaboration with others across locales,
consider internationalization from project inception. Internationalization can prevent
rework or having to develop a new model design. The relevant requirement concerns
locale settings.

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).

Prepare to Generate Code for Mixed Languages and Locales


To prepare to generate code for a model, identify:

34-2
Internationalization and Code Generation

• The operating system locale.


• The locale of the MATLAB session.
• Code generation requirements for:

• Target Language Compiler files


• Code generation template files that include comments (requires Embedded Coder)

Character Set Limitations


Target language compiler files support user default encoding only. To produce
international, custom generated code that is portable, use the 7-bit ASCII character set.

XML Escape Sequence Replacements


The code generator replaces characters that are not represented in the character set
encoding of a model with XML escape sequences. Escape sequence replacements occur
for block, signal, and Stateflow object names that appear in:

• Generated code comments


• Code generation reports
• Block paths logged to MAT-files
• Block paths logged to C API files model_capi.c (or .cpp) and model_capi.h

Generate and Review Code with Mixed Languages and Mixed


Locales
This example shows how to use the code generator to generate and review code for use in
mixed languages and mixed locales.

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:

• C and C++ API interfaces


• Code generation template (CGT) files (requires Embedded Coder®)
• Target Language Compiler (TLC) files that apply code customizations (requires
Embedded Coder®)

Open the example model rtwdemo_unicode.

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 Locale Settings

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:

• “Set Locale on Windows Platforms” (MATLAB)


• “Set Locale on Linux Platforms” (MATLAB)
• “Set Locale on Mac Platforms” (MATLAB)

34-4
Internationalization and Code Generation

Verify Model for Use of Foreign Characters

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.

4. Select Check model for foreign characters

5. Click Run This Check.

6. Review the results. Several warnings appear. Verify that the characters in the model
can be represented in the current character set encoding.

7. Close the Model Advisor.

Code Generation Template Files

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.

1. Open the Configuration Parameters dialog box.

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">

3. Open the file /toolbox/rtw/rtwdemos/rtwdemo_unicode.cgt.

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">

5. Close the file /toolbox/rtw/rtwdemos/rtwdemo_unicode.cgt.

Generated File Customization Template

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.

1. Open the Configuration Parameters dialog box.

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.

3. Open the file /toolbox/rtw/rtwdemos/example_file_process.tlc.

edit example_file_process.tlc

4. Before generating code, uncomment the following line of code:

%% %assign ERTCustomFileTest = TLC_TRUE%

5. Close the file /toolbox/rtw/rtwdemos/example_file_process.tlc.

Generate C Code

Generate C code and a code generation report.


evalc('rtwbuild(''rtwdemo_unicode'')');

Review the Generated 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')

2. Review the generated code in rtwdemo_unicode.c and rtwdemo_unicode.h.


Names of model elements appear in code comments as replacement names in the local
language.

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');

Generate C++ Code

Generate C++ code and a code generation report.

1. Open the model.

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');

4. Generate C++ code and a code generation report.

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

Internationalization and Code Generation


Internationalization support in software development tooling is vital to enabling efficient
globalization. If there is a remote possibility that you could collaborate in the future with
others across locales, consider internationalization from project inception.
Internationalization can prevent rework or having to develop a new model design. The
relevant requirement concerns locale settings.

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

Prepare to Generate Code for Mixed Languages and Locales


To prepare to generate code for a model, identify:

• The operating system locale.


• The locale of the MATLAB session.
• Code generation requirements for:

• Target Language Compiler files


• Code generation template files that include comments (requires Embedded Coder)

Character Set Limitations


Target language compiler files support user default encoding only. To produce
international, custom generated code that is portable, use the 7-bit ASCII character set.

XML Escape Sequence Replacements


The code generator replaces characters that are not represented in the character set
encoding of a model with XML escape sequences. Escape sequence replacements occur
for block, signal, and Stateflow object names that appear in:

• Generated code comments


• Code generation reports
• Block paths logged to MAT-files
• Block paths logged to C API files model_capi.c (or .cpp) and model_capi.h

CGT Files and XML Escape Sequence Replacements


The code generator replaces characters that are not represented in the character set
encoding for a model with XML escape sequences. Escape sequence replacements occur
for block, signal, and Stateflow object names that appear in Comments in code generation
template (CGT) files.

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.

Generate and Review Code with Mixed Languages and Mixed


Locales
This example shows how to use the code generator to generate and review code for use in
mixed languages and mixed locales.

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

• C and C++ API interfaces


• Code generation template (CGT) files (requires Embedded Coder®)
• Target Language Compiler (TLC) files that apply code customizations (requires
Embedded Coder®)

Open the example model rtwdemo_unicode.

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 Locale Settings

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:

• “Set Locale on Windows Platforms” (MATLAB)


• “Set Locale on Linux Platforms” (MATLAB)
• “Set Locale on Mac Platforms” (MATLAB)

35-5
35 Internationalization Support in Embedded Coder

Verify Model for Use of Foreign Characters

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.

4. Select Check model for foreign characters

5. Click Run This Check.

6. Review the results. Several warnings appear. Verify that the characters in the model
can be represented in the current character set encoding.

7. Close the Model Advisor.

Code Generation Template Files

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.

1. Open the Configuration Parameters dialog box.

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">

3. Open the file /toolbox/rtw/rtwdemos/rtwdemo_unicode.cgt.

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">

5. Close the file /toolbox/rtw/rtwdemos/rtwdemo_unicode.cgt.

Generated File Customization Template

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.

1. Open the Configuration Parameters dialog box.

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.

3. Open the file /toolbox/rtw/rtwdemos/example_file_process.tlc.

edit example_file_process.tlc

4. Before generating code, uncomment the following line of code:

%% %assign ERTCustomFileTest = TLC_TRUE%

5. Close the file /toolbox/rtw/rtwdemos/example_file_process.tlc.

Generate C Code

Generate C code and a code generation report.


evalc('rtwbuild(''rtwdemo_unicode'')');

Review the Generated 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')

2. Review the generated code in rtwdemo_unicode.c and rtwdemo_unicode.h.


Names of model elements appear in code comments as replacement names in the local
language.

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');

Generate C++ Code

Generate C++ code and a code generation report.

1. Open the model.

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');

4. Generate C++ code and a code generation report.

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

Source Code Generation in Simulink


Coder

• “Configure Model, Generate Code, and Simulate” on page 36-2


• “Configure Model and Generate Code” on page 36-13
• “Configure Data Interface” on page 36-20
• “Call External C Functions” on page 36-29
• “Reload Generated Code” on page 36-36
• “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
• “Add Build Process Dependencies” on page 36-64
• “Enable Build Process for Folder Names with Spaces” on page 36-71
• “Code Generation of Matrices and Arrays” on page 36-77
• “Cross-Release Shared Utility Code Reuse” on page 36-82
• “Cross-Release Code Integration” on page 36-85
• “Generate Code Using Simulink® Coder™” on page 36-101
36 Source Code Generation in Simulink Coder

Configure Model, Generate Code, and Simulate

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

About This Example


Learning Objectives

• Learn about the functional behavior of the example model.


• Learn about the role of the example test harness and its components.
• Run simulation tests on a model.

Prerequisites

• Ability to open and modify Simulink models and subsystems.


• Understand subsystems and how to view subsystem details.
• Understand referenced models and how to view referenced model details.
• Ability to set model configuration parameters.

Required Files

Before you use each example model file, place a copy in a writable location and add it to
your MATLAB path.

• rtwdemo_throttlecntrl model file


• rtwdemo_throttlecntrl_testharness model file

36-2
Configure Model, Generate Code, and Simulate

Functional Design of the Model


This example uses a simple, but functionally complete, example model of a throttle
controller. The model features redundant control algorithms. The model highlights a
standard model structure and a set of basic blocks in algorithm design.

View the Top Model


Open rtwdemo_throttlecntrl and save a copy as throttlecntrl in a writable
location on your MATLAB path.

Note This model uses Stateflow software.

The top level of the model consists of the following elements:

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

Top-level output pos_cmd_one


pos_cmd_two
ThrotComm1
Signal routing
Omit blocks that change the value of a
signal, such as Sum and Integrator

The layout uses a basic architectural style for models:

• Separation of calculations from signal routing (lines and buses)


• Partitioning into subsystems

You can apply this style to a wide range of models.

View the Subsystems


Explore two of the subsystems in the top model.
1 If not already open, open throttlecntrl.

Two subsystems in the top model represent proportional-integral (PI) controllers,


PI_ctrl_1 and PI_ctrl_2. At this stage, these identical subsystems, use identical
data. If you have Embedded Coder, you can use these subsystems in an example that
shows how to “Partition and Modularize Generated Code”.
2 Open the PI_ctrl_1 subsystem.

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.

Simulation Test Environment


To test the throttle controller algorithm, incorporate it into a test harness. A test harness
is a model that evaluates the control algorithm and offers the following benefits:

• Separates test data from the control algorithm.


• Separates the plant or feedback model from the control algorithm.
• Provides a reusable environment for multiple versions of the control algorithm.

The test harness model for this example implements a common simulation testing
environment consisting of the following parts:

• Unit under test

36-5
36 Source Code Generation in Simulink Coder

• Test vector source


• Evaluation and logging
• Plant or feedback system
• Input and output scaling

Explore the simulation testing environment.

1 Open the test harness model rtwdemo_throttlecntrl_testharness and save a


copy as throttlecntrl_testharness in a writable location on your MATLAB
path.

2 Set up your throttlecntrl model as the control algorithm of the test harness.

a Open the Unit_Under_Test block and view the control algorithm.


b View the model reference parameters by right-clicking the Unit_Under_Test
block and selecting Block Parameters (ModelReference).

36-6
Configure Model, Generate Code, and Simulate

rtwdemo_throttlecntrl appears as the name of the referenced model.


c Change the value of Model name to throttlecntrl.
d Update the test harness model diagram by clicking Simulation > Update
Diagram.

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:

• Simulation time is faster for large models.

36-7
36 Source Code Generation in Simulink Coder

• You can directly simulate compiled functions.


• Simulation requires less memory. Only one copy of the compiled model is in
memory, even when the model is referenced multiple times.
3 Open the test vector source, implemented in this test harness as the Test_Vectors
subsystem.

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:

• Select input signals to route to the unit under test.


• Select output signals to route to the plant.
• Rescale signals between engineering units and units that are writable for the unit
under test.
• Handle rate transitions between the plant and the unit under test.
7 Save and close throttlecntrl_testharness.

Run Simulation Tests


1 Check that your working folder is set to a writable folder, such as the folder into
which you placed copies of the example model files.
2 Open your copy of the test harness model, throttlecntrl_testharness.
3 Start a test harness model simulation. When the simulation is complete, the following
results appear.

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

• A test harness is a model that evaluates a control algorithm. Typically, a harness


consists of a unit under test, a test vector source, evaluation and logging, a plant or
feedback system, and input and output scaling components.
• The unit under test is the control algorithm being tested.
• The test vector source provides the data that drives the simulation which generates
results used for verification.
• During verification, the test harness compares control algorithm simulation results
against golden data and logs the results.
• The plant or feedback component of a test harness models the environment that is
being controlled.
• When developing a test harness,

• Scale input and output components.


• Select input signals to route to the unit under test.
• Select output signals to route to the plant.
• Rescale signals between engineering units and units that are writable for the unit
under test.
• Handle rate transitions between the plant and the unit under test.
• Before running simulation or completing verification, consider checking a model with
the Model Advisor.

Learn More
• “Support Model Referencing” (Simulink Coder)
• “Code Generation” (Simulink Coder)
• “Signal Groups” (Simulink)

36-12
Configure Model and Generate Code

Configure Model and Generate Code


In this section...
“About This Example” on page 36-13
“Configure the Model for Code Generation” on page 36-14
“Save Your Model Configuration as a MATLAB Function” on page 36-15
“Check Model Conditions and Configuration Settings” on page 36-16
“Generate Code for the Model” on page 36-16
“Review the Generated Code” on page 36-17
“Generate an Executable” on page 36-18
“Key Points” on page 36-18

About This Example


Learning Objectives

• Configure a model for code generation.


• Apply model checking tools to discover conditions and configuration settings resulting
in generation of inaccurate or inefficient code.
• Generate code from a model.
• Locate and identify generated code files.
• Review generated code.

Prerequisites

• Ability to open and modify Simulink models and subsystems.


• Ability to set model configuration parameters.
• Ability to use the Simulink Model Advisor.
• Ability to read C code.
• An installed, supported C compiler.

Required Files

rtwdemo_throttlecntrl model file

36-13
36 Source Code Generation in Simulink Coder

Configure the Model for Code Generation


Model configuration parameters determine the method for generating the code and the
resulting format.
1 Open rtwdemo_throttlecntrl and save a copy as throttlecntrl in a writable
location on your MATLAB path.
2 Open the Configuration Parameters dialog box, Solver pane. To generate code for a
model, you must configure the model to use a fixed-step solver. The following table
shows the solver configuration for this example.

Parameter Setting Effect on Generated


Code
Type Fixed-step Maintains a constant
(fixed) step size, which is
required for code
generation
Solver discrete (no Applies a fixed-step
continuous states) integration technique for
computing the state
derivative of the model
Fixed-step size .001 Sets the base rate; must
be the lowest common
multiple of the rates in
the system

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.

Save Your Model Configuration as a MATLAB Function


You can save the settings of model configuration parameters as a MATLAB function by
using the getActiveConfigSet function. In the MATLAB Command Window, enter:

thcntrlAcs = getActiveConfigSet('throttlecntrl');
thcntrlAcs.saveAs('throttlecntrlModelConfig');

You can then use the resulting function (for example, throttlecntrlModelConfig) to:

• Archive the model configuration.


• Compare different model configurations by using differencing tools.
• Set the configuration of other models.

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

Check Model Conditions and Configuration Settings


Before generating code for a model, use the Simulink Model Advisor to check the model
for conditions and configuration settings. This check finds issues that can result in
inaccurate or inefficient code.
1 Open throttlecntrl.
2 Start the Model Advisor by selecting Analysis > Model Advisor > Model Advisor.
A dialog box opens showing the model system hierarchy.
3 Click throttlecntrl and then click OK. The Model Advisor window opens.
4 Expand By Product and Embedded Coder. By default, checks that do not trigger an
Update Diagram, with one exception, are selected.
5 In the left pane, select the remaining checks and select Embedded Coder.
6 In the right pane, select Show report after run and click Run Selected Checks.
The report shows a Run Summary that flags check warnings.
7 Review the report. The warnings highlight issues for embedded systems. At this
point, you can ignore them. For more information about reports, see “View Model
Advisor Reports” (Simulink).

Generate Code for the Model


1 Open throttlecntrl.
2 In the Configuration Parameters dialog box, select Code Generation > Generate
code only and click Apply.
3 On the Code Generation > Report pane, select Create code generation report
and click Apply.
4 With the model open, initiate code generation and the build process for the model by
using any of the following options:

• Click the Build Model button.


• Press Ctrl+B.
• Select Code > C/C++ Code > Build Model.
• Invoke the rtwbuild command from the MATLAB command line.
• Invoke the slbuild command from the MATLAB command line.

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.

Review the Generated Code


1 Open Model Explorer, and in the Model Hierarchy pane, expand the node for the
throttlecntrl model, and select the Code for node.
2 In the Contents pane, select HTML Report. Model Explorer displays the HTML
code generation report for the throttle controller model.
3 In the HTML report, click the link for the generated C model file and review the
generated code. Look for these items in the report:

• Identification, version, timestamp, and configuration comments.


• Links to help you navigate within and between files
• Data definitions
• Scheduler code
• Controller code
• Model initialization and termination functions
• Call interface for the GRT system target file — output, update, initialization, start,
and terminate
4 Save and close throttlecntrl.

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.

The program produces one line of output in the Command Window:

** starting the model **

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

• After debugging a model, consider configuring a model with parameter inlining


enabled.
• Use the getActiveConfigSet function to save a model configuration for future use
or to apply it to another model.
• Before generating code, consider checking a model with the Model Advisor.
• The code generator places generated files in a subfolder (model_grt_rtw) of your
working folder.

See Also

More About
• “Code Generation” (Simulink Coder)
• “Configuration Reuse” (Simulink)
• “Run Model Checks” (Simulink)

36-19
36 Source Code Generation in Simulink Coder

Configure Data Interface

About This Example


Learning Objectives

• Configure the data interface for code generated for a model.


• Control the name, data type, and data storage class of signals and parameters in
generated code.

Prerequisites

• Understanding ways to represent and use data and signals in models.


• Familiarity with representing data constructs as data objects.
• Ability to read C code.

Required File

rtwdemo_throttlecntrl_datainterface model file

Declare Data
Most programming languages require that you declare data before using it. The
declaration specifies the following information:

Data Attribute Description


Scope The region of the program that has access to the data
Duration The period during which the data is resident in memory
Data type The amount of memory allocated for the data
Initialization An initial value, a pointer to memory, or NULL. If you do not provide
an initial value, most compilers assign a zero value or a null pointer.

The following data types are supported for code generation.

36-20
Configure Data Interface

Supported Data Types


Name Description
double Double-precision floating point
single Single-precision floating point
int8 Signed 8-bit integer
uint8 Unsigned 8-bit integer
int16 Signed 16-bit integer
uint16 Unsigned 16-bit integer
int32 Signed 32-bit integer
uint32 Unsigned 32-bit integer
Fixed-point data types 8-, 16-, 32-bit word lengths

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.

Use Data Objects


In Simulink models and Stateflow charts, the following methods are available for
declaring data: data objects and direct specification. This example uses the data object
method. Both methods allow full control over the data type and storage class. You can mix
the two methods in a single model.

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:

1 Open rtwdemo_throttlecntrl_datainterface and save a copy as


throttlecntrl_datainterface in a writable location on your MATLAB path.
2 Open Model Explorer.
3 Select Base Workspace.
4 Select the pos_cmd_one signal object for viewing.

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 =

Signal with properties:

CoderInfo: [1x1 Simulink.CoderInfo]


Description: 'Throttle position command from the first PI controller'
DataType: 'double'
Min: -1
Max: 1
Unit: ''
Dimensions: -1
DimensionsMode: 'auto'
Complexity: 'auto'
SampleTime: -1
InitialValue: '0'
5 To view other signal objects, in Model Explorer, click the object name or in the
MATLAB Command Window, enter the object name. The following table summarizes
object characteristics for some of the data objects in this model.

36-23
36 Source Code Generation in Simulink Coder

Object pos_cmd_on pos_rqst P_InErrMap ThrotComm* ThrottleCommands


Characteristics e *
Description Top-level Top-level Calibration Top-level Bus definition
output input parameter output
structure
Data type Double Double Auto Auto Structure
Storage class Exported Imported Constant Exported None
global extern global
pointer

* ThrottleCommands defines a Bus object; ThrotComm is an instantiation of the


bus. If the bus is a nonvirtual bus, the signal generates a structure in the C code.

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.

Add New Data Objects


You can create data objects for named signals, states, and parameters. To associate a data
object with a construct, the construct must have a name.

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.

To find the signals and create data objects for them:


1 In the model window, select Code > Data Objects > Data Object Wizard. The Data
Object Wizard dialog box opens.
2 To find candidate constructs, click Find. Constructs fbk_1 and pos_cmd_two appear
in the dialog box.

36-24
Configure Data Interface

3 To select both constructs, click Select All.


4 In the table, under Class, make sure that each proposed data object uses the class
Simulink.Signal. To change the class of the objects, click Change Class.
5 To create the data objects, click Create. Constructs fbk_1 and pos_cmd_two are
removed from the dialog box.
6 Close the Data Object Wizard.
7 In the Contents pane of the Model Explorer, find the newly created objects fbk_1
and pos_cmd_two.

Enable Data Objects for Generated Code


1 Enable a signal to appear in generated code.

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.

Effects of Simulation on Data Typing


In the throttle controller model, the data types are set to double. Because Simulink
software uses the double data type for simulation, do not expect changes in the model
behavior when you run the generated code. You verify this effect by running the test
harness.

36-25
36 Source Code Generation in Simulink Coder

Before you run your test harness, update it to include the


throttlecntrl_datainterface model.

Note The following procedure requires a Stateflow license.

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

7 Save and close throttlecntrl_testharness.

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:

• One model, multiple data sets:

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:

• Sharing data between models in a system


• Sharing data between projects (for example, transmission, engine, and wheel
controllers can use the same CAN message 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

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

About This Example


Learning Objectives

• Evaluate a C function as part of a model simulation.


• Call an external C function from generated code.

Prerequisites

• Ability to open and modify Simulink models and subsystems.


• Ability to set model configuration parameters.
• Ability to read C code.
• An installed, supported C compiler.

Required Files

• rtwdemo_throttlecntrl_extfunccall model file


• rtwdemo_ValidateLegacyCodeVrsSim model file
• /toolbox/rtw/rtwdemos/EmbeddedCoderOverview/stage_4_files/
SimpleTable.c
• /toolbox/rtw/rtwdemos/EmbeddedCoderOverview/stage_4_files/
SimpleTable.h

36-29
36 Source Code Generation in Simulink Coder

Include External C Functions in a Model


Simulink models are one part of Model-Based Design. For many applications, a design
also includes a set of pre-existing C functions created, tested (verified), and validated
outside of a MATLAB and Simulink environment. You can integrate these functions easily
into a model and the generated code. You can use external C code in the generated code
to access hardware devices and external data files during rapid simulation runs.

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.

Create a Block That Calls a C Function


To specify a call to an external C function, use an S-Function block. You can automate the
process of creating the S-Function block by using the Simulink Legacy Code Tool. Using
this tool, specify an interface for your external C function. The tool then uses that
interface to automate creation of an S-Function block.
1 Make copies of the files SimpleTable.c and SimpleTable.h, located in the folder
matlabroot/toolbox/rtw/rtwdemos/EmbeddedCoderOverview/
stage_4_files (open). Put the copies in your working folder.
2 Create an S-Function block that calls the specified function at each time step during
simulation:
a In the MATLAB Command Window, create a function interface definition
structure:
def=legacy_code('initialize')

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)

A new model window opens that contains the SimpTableWrap block.

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.

For more information on using the Legacy Code Tool, see:

• “Integrate C Functions Using Legacy Code Tool” (Simulink)


• “Import Calls to External Code into Generated Code with Legacy Code Tool” (Simulink
Coder)

36-31
36 Source Code Generation in Simulink Coder

Validate External Code in the Simulink Environment


When you integrate external C code with a Simulink model, before using the code,
validate the functionality of the external C function code as a standalone component.

1 Open the model rtwdemo_ValidateLegacyCodeVrsSim. This model validates the


S-function block that you created.

• 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

4 Close the validation model.

Validate C Code as Part of a Model


After you validate the functionality of the external C function code as a standalone
component, validate the S-function in the model. Use the test harness model to complete
the validation.

Note The following procedure requires a Stateflow license.

1 Open rtwdemo_throttlecntrl_extfunccall and save a copy to


throttlecntrl_extfunccall in a writable folder on your MATLAB path.
2 Examine the PI_ctrl_1 and PI_ctrl_2 subsystems.
a Lookup blocks have been replaced with the block you created using the Legacy
Code Tool.

36-33
36 Source Code Generation in Simulink Coder

b Note the block parameter settings for SimpTableWrap and SimpTableWrap1.


c Close the Block Parameter dialog boxes and the PI subsystem windows.
3 Open the test harness model, right-click the Unit_Under_Test Model block, and
select Block Parameters (ModelReference).
4 Set Model name to throttlecntrl_extfunccall. Click OK.
5 Update the test harness model diagram.
6 Simulate the test harness.

The simulation results match the expected golden values.

7 Save and close throttlecntrl_extfunccall and


throttlecntrl_testharness.

36-34
See Also

Call a C Function from Generated Code


The code generator uses a TLC file to process the S-Function block. Calls to C code
embedded in an S-Function block:

• Can use data objects.


• Are subject to expression folding, an operation that combines multiple computations
into a single output calculation.

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

Reload Generated Code


You can reload the code generated for a model from the Model Explorer.

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

Manage Build Process Folders


The build process places generated files from Simulink diagram updates and model builds
into a hierarchy of folders that is specified by default. You can change the default
specification for build process folders, if, for example:

• 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.

The MATLAB session parameters CacheFolder, CodeGenFolder, and


CodeGenFolderStructure are file generation control parameters that specify the folder
locations for the build process. At the start of a MATLAB session, these Simulink
preferences determine the values of the parameters:

Simulation cache folder (Simulink) – CacheFolder

Code generation folder (Simulink) – CodeGenFolder

Code generation folder structure (Simulink) – CodeGenFolderStructure

To modify the parameters during a MATLAB session, use Simulink.fileGenControl.


The parameter values that you set expire at the end of the MATLAB session.

File Generation Control Parameters


This table provides information about how you can use the parameters to manage build
process folders.

36-37
36 Source Code Generation in Simulink Coder

MATLAB Session Simulink Description


Parameter Preference
CacheFolder Simulation cache The build process places generated files from
folder (Simulink) Simulink diagram updates and model build
artifacts for simulation in the simulation cache
folder simulationCacheFolder. The folder
is a root folder.

By default (CacheFolder = ''),


simulationCacheFolder is the current
working folder, pwd.

You can use the parameter to specify another


folder. For example, if you want to:

• Separate generated files from the models


and other source material.
• Reuse or share previously built simulation
targets without having to set the current
working folder back to a previous working
folder.

36-38
Manage Build Process Folders

MATLAB Session Simulink Description


Parameter Preference
CodeGenFolder Code generation The build process, which uses system target
folder (Simulink) files to generate production code from a
Simulink model, places the production code in
the code generation folder
codeGenerationFolder. The folder is a root
folder.

If you choose to generate an executable


program file, the build process writes the file
model.exe (Windows) or model (UNIX) to
the folder.

By default (CodeGenFolder = ''),


codeGenerationFolder is the current
working folder, pwd.

You can use the parameter to specify another


folder. For example, if you want to separate
generated production code from:

• Models and other source material.


• Generated simulation artifacts.

If you specify the root folder of a drive as the


code generation folder, the build process
cannot generate code for your model. For
example, C:\.
CodeGenFolderS Code generation To specify the folder structure within the code
tructure folder structure generation folder, use the parameter. For
(Simulink) example, if you configure models for different
target environments, you can specify a
separate subfolder for the generated code
from each model.

36-39
36 Source Code Generation in Simulink Coder

Build Process Folders


This table provides information about how CodeGenFolderStructure controls the
folder structure within the simulation cache folder and the code generation folder.

Folder Name when Folder Name when Description


CodeGenFolderStructur CodeGenFolderStructur
e = 'ModelSpecific' e=
'TargetEnvironmentSub
folder'
codeGenerationFolder/ codeGenerationFolder/ Build folder, which stores
model_target_rtw targetSpecific/model generated source code and
other files created by the
The default for target is The build process uses build process.
the name of the selected configuration information
system target file, for for the system target file Contains the generated code
example, grt, ert, and and the hardware device to modules, model.c and
rsim. You can change produce a unique label for model.h, and the generated
target with the the subfolder, makefile, model.mk.
rtwgensettings.BuildD targetSpecific.
irSuffix field in the model is the name of the
system target file. source model.
codeGenerationFolder/ codeGenerationFolder/ Code generation report folder
model_target_rtw/html targetSpecific/model/ that contains report files
html generated by the build
process.
codeGenerationFolder/ codeGenerationFolder/ Model reference target files.
slprj/target/model targetSpecific/_ref/
model
codeGenerationFolder/ codeGenerationFolder/ Header files from models
slprj/target/model/ targetSpecific/_ref/ referenced by model.
referenced_model_incl model/
udes referenced_model_incl
udes
codeGenerationFolder/ codeGenerationFolder/ MAT-files used during code
slprj/target/model/ targetSpecific/_ref/ generation.
tmwinternal model/tmwinternal

36-40
See Also

Folder Name when Folder Name when Description


CodeGenFolderStructur CodeGenFolderStructur
e = 'ModelSpecific' e=
'TargetEnvironmentSub
folder'
codeGenerationFolder/ codeGenerationFolder/ Utility functions for model
slprj/target/ targetSpecific/ reference system target files,
_sharedutils _shared which are shared across
models.
simulationCacheFolder simulationCacheFolder Simulation target files for
/slprj/sim/model /slprj/sim/model referenced models.
simulationCacheFolder simulationCacheFolder MAT-files used during code
/slprj/sim/model/ /slprj/sim/model/ generation.
tmwinternal tmwinternal
simulationCacheFolder simulationCacheFolder Utility functions for simulation
/slprj/sim/ /slprj/sim/ system target files, which are
_sharedutils _sharedutils shared across models.

If the system target file is ERT-based, then these configuration parameters also control
the location of shared utility code:

• Shared code placement (Simulink Coder) (UtilityFuncGeneration)


• Existing shared code (ExistingSharedCode)

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

• “Build Process Workflow for Real-Time Systems” (Simulink Coder)


• “Generate Code for Referenced Models” (Simulink Coder)
• “Cross-Release Shared Utility Code Reuse” (Simulink Coder)
• “Cross-Release Code Integration” (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-42
Manage Build Process Files

Manage Build Process Files


To apply generated code source and header files from the build process, it is helpful to
understand the files that the build process generates and the conditions that control file
generation. This information provides access to generated code resources, such as:

• Public interface to the model entry points


• Enumerated types corresponding to built-in data types
• Data structures that describe the model signals, states, and parameters

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.

A model build generates this file when one or more of these


conditions apply:

• Your model contains a Stateflow chart that uses messages.


• Your model configuration enables MAT-file logging.
• Your model configuration enables C API options in Code
Generation > Interface.
modelsources.txt Lists additional sources to include in the compilation.
model.bat Contains Windows batch file commands that set the compiler
environment and invoke the make utility.

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:

• Include files model.h and model_private.h


• Data, except data placed in model_data.c
• Model-specific scheduler code
• Model-specific solver code
• Model registration code
• Algorithm code
• Optional GRT wrapper functions
model.exe (Windows Executable program file.
platform)
A model build generates this file unless you explicitly specify that the
model (UNIX and Macintosh code generator produce code only. The build generates the
platforms) executable in the current folder (not the build folder) under control
of the make utility of your development system.

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.

Subsystem .c or .cpp files in the model include model.h. This file


includes:

• Exported Simulink data symbols


• Exported Stateflow machine parented data
• Model data structures, including rtM
• Model entry-point functions

For more information, see “model.h” (Simulink Coder).


model.mk Generated makefile that controls compiling and linking the
generated code into the final binary file by the make utility of your
development system.

If you set the MAKEFLAGS environment variable, do not select options


with this variable that conflict with the current make utility used by
the build process.
model.rtw Represents the compiled model.

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:

• Constant block I/O parameters


• Include files model.h and model_private.h
• Definitions for the zero representations for user-defined structure
data types that the model uses
• Constant parameters
model_dt.h (optional file) Declares structures that contain data type and data
type transition information for generated model data structures for
supporting external mode.
model_private.h Contains local define constants and local data for the model and
subsystems.

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:

• Imported Simulink data symbols


• Imported Stateflow machine parented data
• Stateflow entry points
• Simulink Coder details (various macros, enums, and so forth, that
are private to the code)

For more information, see “Manage Build Process File


Dependencies” (Simulink Coder).
model_reference_types. Contains type definitions for timing bridges.
h
A model build generates this file for a referenced model or a model
containing model reference blocks.

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.

A model build generates this file when one or more of these


conditions apply:

• Your model uses multiword data types.


• Your model configuration enables MAT-file logging.
• Your model configuration enables Code Generation > Interface
> External mode.
rtGetInf.c Declares and initializes global nonfinite values for inf, minus inf,
and nan. Provides nonfinite comparison functions.
rtGetInf.h
A model build generates these files when one or more of these
rtGetNaN.c conditions apply:

• The model contains S-functions.


rtGetNaN.h
• The generated code from the model requires nonfinite numbers.
rt_nonfinite.c • Your model configuration enables MAT-file logging.
• Your model configuration selects grt.tlc as the System target
rt_nonfinite.h
file and enables the Classic call interface.
rtmodel.h Contains #include directives required by static main program
modules such as rt_main.c.

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.

For GRT-based system target files, rtwtypes.h includes


simstruc_types.h which, in turn, includes tmwtypes.h.

For ERT-based system target files that do not generate a GRT


interface and do not have noninlined S-functions, rtwtypes.h does
not include simstruc_types.h.

For more information, see “rtwtypes.h” (Simulink Coder) and


“Manage Build Process File Dependencies” (Simulink Coder).
rtw_proj.tmw Marker files.

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:

>> system('model.bat info')

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:

>> system('gmake -f model.mk info')

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:

• Exported global signals

extern int32_T INPUT; /* '<Root>/In' */


• Global structure definitions

/* Block parameters (auto storage) */


extern Parameters_mymodel mymodel_P;
• Real-time model (RTM) macro definitions

#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

extern void mymodel_initialize(void);


extern void mymodel_step(void);
extern void mymodel_terminate(void);

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

Manage Build Process File Dependencies


An important control of the size of generated code is managing the number and size of
included files (dependencies). To reduce the number of system header files and generated
header files that generated code requires, it is helpful to understand the dependencies
that the build process generates and the conditions that lead to 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.

In the figure, files model.h, model_private.h, and subsystem.h depend on the


header file rtwtypes.h. If you use system target files that are not based on the ERT
system target file, the source files that you generate can have additional dependencies on
tmwtypes.h and simstruc_types.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

System Header Files


The system header files make function declarations, type definitions, and macro
definitions available to the legacy or external code. Some code generation scenarios
require including header files that are specific to the code generator product.

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

GRT—Generated code does not include this file.

ERT—Generated code includes this file when the code honors your
model configuration for solver Stop time and either:

• Your model configuration enables MAT-file logging. See “MAT-


file logging” (Simulink Coder).
• Your model configuration enables Code Generation > Interface
> External mode.
<float.h> Provides floating-point math functions

GRT—Generated code includes this file when your model contains a


floating-point math function.

ERT—Generated code includes this file when your model contains a


floating-point math function, unless a code replacement library entry
overrides the function. For more information, see “Choose a Code
Replacement Library” (Simulink Coder).
<stddef.h> Defines NULL

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

GRT—Generated code includes this file when your model includes a


To File block.

ERT—Generated code includes this file when either:

• Your model includes a To File block.


• Your model configuration enables MAT-file logging. See “MAT-
file logging” (Simulink Coder).
<stdlib.h> Provides utility functions such as the integer versions of div() and
abs()

GRT—Generated code includes this file when either:

• Your model includes a Stateflow chart.


• Your model includes a math function block configured for mod()
or rem(), which generate calls to div().

ERT—Generated code includes this file when either:

• Your model includes a Stateflow chart, and you select Support:


floating-point numbers.
• Your model includes a math function block configured for mod()
or rem(), which generate calls to div().

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()

GRT—Generated code includes this file when your model


initialization code calls memset().

ERT—Generated code includes this file when a block or model


initialization code calls memcpy() or memset().

For a list of relevant blocks, in the Command Window, type:

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.

Code Generator Header Files


Dependencies in the table for generated header files apply to the system target files
grt.tlc and ert.tlc. System target files derived from these base system target files
can have additional header dependencies. Code generation for blocks from blocksets,
embedded targets, and custom S-functions can introduce additional header dependencies.

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:

• Your model contains a Stateflow chart that uses messages.


• Your model configuration enables: MAT-file logging. See “MAT-
file logging” (Simulink Coder).
• Your model configuration selects C API options at Code
Generation > Interface.

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—Generated code includes this file.

ERT—Generated code includes this file when either:

• Your model uses noninlined S-functions.


• Your model configuration selects Classic call interface.
model_reference_types. Contains type definitions for timing bridges
h
GRT and ERT—Generated code includes this file when building a
reference model or building a model that contains model blocks.
model_types.h Defines model-specific data types

GRT and ERT—Generated code includes this file.


multiword_types.h Contains type definitions for multiword-wide data types and their
word-size chunks

GRT and ERT—Generated code includes this file when one or more of
these conditions apply:

• Your model uses multiword data types.


• Your model configuration enables MAT-file logging. See “MAT-
file logging” (Simulink Coder).
• Your model configuration enables Code Generation > Interface
> External mode.

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.

ERT—Generated code includes this file when one or more of these


conditions apply:

• Your model contains S-functions.


• The generated code requires nonfinite numbers.
• Your model configuration enables MAT-file logging. See “MAT-
file logging” (Simulink Coder).
rt_defines.h Contains type definitions for special mathematical constants (such as
π and e) and defines the UNUSED_PARAMETER macro

GRT and ERT—Generated code includes this file when either:

• The generated code requires a mathematical constant definition.


• The function body does not access a required model function
argument.

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—Generated code includes this file.

ERT—Generated code includes this file when you model


configuration enables MAT-file logging. See “MAT-file logging”
(Simulink Coder).
rt_mxclassid.h Defines mxArray class ID enumerations

GRT and ERT—Generated code includes this file when the code
includes rt_logging.c.
rtw_continuous.h Supports continuous time

GRT—Generated code includes this file when the code includes


simstruc_types.h.

ERT—Generated code includes this file when your model


configuration selects Support: continuous time and when the code
does not already include simstruc.h.
rtw_extmode.h Supports external mode

GRT—Generated code includes this file when the code includes


simstruc_types.h.

ERT—Generated code includes this file when your model


configuration selects external mode and when the code does not
already include simstruc.h.

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

GRT—Generated code includes this file when the code includes


simstruc_types.h and rt_logging.h.

ERT—Generated code includes this file when the code includes


rt_logging.h.
rtw_solver.h Supports continuous states

GRT—Generated code includes this file when the code includes


simstruc_types.h.

ERT—Generated code includes this file when your model


configuration selects Support: continuous time and when the code
does not already include simstruc.h.
rtwtypes.h Defines code generator data types

GRT—Generated code includes this file. Use the complete version of


the file, which includes tmwtypes.h and simstruc_types.h. See
simstruc_types.h for dependencies.

ERT—Generated code includes this file. Use the complete or


optimized version of the file. See “rtwtypes.h” on page 36-50.

If you include rtwtypes.h and tmwtypes.h in external code that


you integrate with generated code, the #include for rtwtypes.h
must precede the #include for tmwtypes.h. This ordering of
#include statements preserves target-specific type definitions. If
you reverse the order, a compiler error occurs.

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

GRT—Generated code includes this file.

ERT—Generated code includes this file when either:

• Your model uses noninlined S-functions.


• Your model configuration selects Classic call interface.
simstruc_types.h Provides definitions that the generated code uses and includes the
header files:

rtw_matlogging.h
rtw_extmode.h
rtw_continuous.h
rtw_solver.h
sysran_types.h

GRT—Generated code includes this file when the code includes


rtwtypes.h.

ERT—Generated code does not include this file. For ERT,


rtwtypes.h contains definitions, and model.h contains header
files.
sysran_types.h Supports external mode

GRT—Generated code includes this file when the code includes


simstruc_types.h.

ERT—Generated code includes this file when your model


configuration selects external mode and when the code does not
already include simstruc.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.

ERT—Generated code includes this file when a model has a


conditionally executed subsystem where a trigger uses zero crossing
detection.

If generated, the content of zero_crossing_types.h is always the


same.

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

Add Build Process Dependencies


When you specify a system target file for code generation, the code generator can build a
standalone executable program that can run on the development computer. To build the
executable program, the code generator uses the selected compiler and the generated
makefile for a toolchain approach or for a template makefile (TMF) approach build
processes. Part of the makefile generation process is to add source file, header file, and
library file information (the dependencies) in the generated makefile for a compilation. Or,
for a specific application, you can add the generated files and file dependencies through a
configuration management system.

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:

• Header file inclusions


• Macro declarations
• Function calls
• Variable declarations

The model or external code introduces dependencies for various reasons:

• 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

• External code specifies 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

File Dependency Information for the Build Process


The code generator provides several mechanisms to input file dependency information
into the build process. The mechanisms depend on whether your dependencies are block-
based or are model- or system target file-based.

For block dependencies, consider using:

• S-functions and blocksets

• 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 more information on applying these approaches to legacy or external code


integration, see “Import Calls to External Code into Generated Code with Legacy Code
Tool” (Simulink Coder).
• S-Function Builder block, which provides its own UI for specifying dependency
information

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

• TLC functions LibAddToCommonIncludes() and LibAddToModelSources(). You


can specify dependencies during the TLC phase. See
“LibAddToCommonIncludes(incFileName)” (Simulink Coder) and
“LibAddSourceFileCustomSection(file, builtInSection, newSection)” (Simulink Coder).
The Embedded Coder product also provides a TLC-based customization template for
generating additional source files.

Generated Makefile Dependencies

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).

The generated makefile contains:

• Names of the source file dependencies


• Folders where source files are located
• Location of the header files
• Precompiled library dependencies
• Libraries that the make utility compiles and creates

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).

Another approach to determining the dependencies is using linker information, such as a


linker map file, to determine the symbol dependencies. The map file provides the location

36-66
Add Build Process Dependencies

of code generator and blockset source and header files to help in locating the
dependencies.

Code Generator Static File 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

These folders contain additional header file dependencies such as tmwtypes.h,


simstruc_types.h, and simstruc.h.

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 Static File Dependencies

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

Folder Dependency Information for the Build Process


You can add #include statements to generated code. Such references can come from
several sources, including TLC scripts for inlining S-functions, custom storage classes,
bus objects, and data type objects. The included files consist of header files for external
code or other customizations. You can specify compiler include paths with the -I
compiler option. The build process uses the specified paths to search for included header
files.

Usage scenarios for the generated code include, but are not limited to, the following:

• A custom build process compiles generated code that requires an environment-specific


set of #include statements.

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

Use #include Statements and Include Paths

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.

Assume that additional header files are:


c:\work\feature1\foo.h
c:\work\feature2\bar.h

• 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 ...

• Another approach is to use relative paths in #include statements and provide an


anchor folder for these relative paths using an include path, for example:
#include "feature1\foo.h"
#include "feature2\bar.h"

Then, specify the anchor folder (for example \work) to the compiler:
cc -Ic:\work ...

Avoid These Folder Dependencies

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

The model.c file has #include statements of the form:


#include "..\feature1\foo.h"
#include "..\feature2\bar.h"

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

Enable Build Process for Folder Names with Spaces


The code generator uses alternate folder name support, which is specific to your Windows
or UNIX operating system, to process folder names that include spaces. On Windows
systems, the code generator maps a drive corresponding to the MATLAB installation
folder for either of these conditions:

• The matlabroot folder is a UNC location.


• The path the matlabroot folder contains spaces, and the system has no alternate
name support.

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).

Spaces in folder names can appear in the paths to build-related locations:

• matlabroot—path to your MATLAB installation folder.

An example is a matlabroot similar to C:\Program Files\MATLAB\R2015b.


• pwd—current working folder from which you start the build.

An example is a pwd at the start of a build similar to C:\Users\username


\Documents\My Work.
• The installation folder for a compiler that the build process uses.

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.

addAttribute(toolchainObject, 'TransformPathsWithSpaces', true);


• For Windows systems with 8.3 name creation disabled, the toolchain manages
spaces in folder names by mapping a network drive using a batch file (.bat). This

36-71
36 Source Code Generation in Simulink Coder

operation requires adding the RequiresBatchFile attribute to the toolchain


definition.

addAttribute(toolchainObject, 'RequiresBatchFile', true);

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

Build Process Folder Support on Windows


Build Process Approach for Paths with UNC or Support for Windows Platform
Folders Spaces
matlabroot During a build, a UNC location Build process folder support
folder such as: available independent of file
\\networkdrive\matlab\R20xxb
system (NTFS or ReFS) or file
Note: The system configuration for short file
matlabroot could be remapped as: name support.
value is derived
from the T:\ Limitations:
MATLAB
During a build on a Windows On systems that require drive
installation
system with short file name (8.3) mapping for the installation
location.
support (default for Windows location, the build process
using NTFS), the build process requires that a drive letter is
uses the Windows API available for mapping.
getShortPathName() for the
folder location. On systems without short file
name (8.3) support (using ReFS or
During a build on a Windows using NTFS with 8.3 support
system without short file name disabled), the final folder in the
(8.3) support (systems using ReFS installation location cannot contain
or using NTFS with 8.3 support spaces. For example, a final folder
disabled), a location with spaces in name:
the path such as:
C:\Program Files\MATLAB\R20xxb sp1
C:\Program Files\MATLAB\R20xxb
is not supported.
could be remapped as:
T:\R20xxb

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

• Configuratio Limitations: Build process does


n not support spaces in the path to
Parameters these folders for:
> Code
Generation • NTFS file system with short
> Custom path name support disabled
Code >
• ReFS file system (this file
Additional
system does not support short
build
path names)
information
• Code
replacement
library

Troubleshooting Errors When Folder Names Have Spaces


On Windows, when there is an issue with support for creation of short file names, build
process errors can occur. When this issue affects a build, you see an error message
similar to:
NMAKE : fatal error U1073: don't know how to make 'C:\Work\My'

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.

To set the short name, the syntax is:


> fsutil file setshortname <FileName> <ShortName>

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

The C:\Program Files folder name is in quotations because it has spaces.


5 To verify that the short name was created, use the dir command with /x option to
show short names.
> dir C:\ /x

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

Code Generation of Matrices and Arrays


In this section...
“Code Generator Matrix Parameters” on page 36-79
“Internal Data Storage for Complex Number Arrays” on page 36-80

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

translates to an array of length 9 in the following order:

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.

In column-major format, the next element of an array in memory is accessed by


incrementing the first index of the array. For example, these element pairs are stored
sequentially in memory:

• A(i) and A(i+1)


• B(i,j) and B(i+1,j)
• C(i,j,k) and C(i+1,j,k)

For more information on the internal representation of MATLAB data, see “MATLAB
Data” (MATLAB) in the MATLAB External Interfaces document.

Code generation software uses column-major format for several reasons:

• 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

• A column is equivalent to a channel in frame-based processing. In this case, column-


major storage is more efficient.
• A column-major array is self-consistent with its component submatrices:

• A column-major 2–D array is a simple concatenation of 1–D arrays.


• A column-major 3–D array is a simple concatenation of 2–D arrays.
• The stride is the number of memory locations to index to the next element in the
same dimension. The stride of the first dimension is one element. The stride of the
nth dimension element is the product of sizes of the lower dimensions.
• Row-major n-D arrays have their stride of 1 for the highest dimension. Submatrix
manipulations are typically accessing a scattered data set in memory, which does
not allow for efficient indexing.

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

Code Generator Matrix Parameters


The compiled model file, model.rtw, represents matrices as character vectors in
MATLAB syntax, without an implied storage format. This format allows you to copy the
character vector out of an .rtw file, paste it into a MATLAB file, and have it recognized
by MATLAB.

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
}
}

and results in this definition in model.h.

typedef struct Parameters_tag {


real_T s1_Look_Up_Table_2_D_Table[9];
/* Variable:s1_Look_Up_Table_2_D_Table
* External Mode Tunable:yes
* Referenced by block:

36-79
36 Source Code Generation in Simulink Coder

* <S1>/Look-Up Table (2-D


*/

[ ... other parameter definitions ... ]

} 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 ...]
};

Internal Data Storage for Complex Number Arrays


Simulink and code generator internal data storage formatting differs from MATLAB
internal data storage formatting only in the storage of complex number arrays. In
MATLAB, the real and imaginary parts are stored in separate arrays. In Simulink and the
code generator, the parts are stored in an "interleaved" format. The numbers in memory
alternate real, imaginary, real, imaginary, and so forth. This convention allows efficient
implementations of small signals on Simulink lines, for Mux blocks, and other "virtual"
signal manipulation blocks. For example, the signals do not actively copy their inputs, just
the references.

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

Cross-Release Shared Utility Code Reuse


In this section...
“Workflow to Reuse Shared Utility Code” on page 36-82
“Required Edits to Reuse Shared Utility Code” on page 36-83

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.

Integrated code that includes functionally identical shared files:

• Is more expensive to verify because each shared file requires verification.


• Produces compilation errors if the shared files define duplicate symbols.

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.

Workflow to Reuse Shared Utility Code


1 In the Configuration Parameters > Code Generation > Interface > Advanced
parameters > Existing shared code field, enter the full path to your shared code
folder.
2 Verify that the Configuration Parameters > Diagnostics > Advanced parameters
> Use only existing shared code diagnostic is set to error (default).
3 Remove the slprj folder or move to a new working folder.
4 Build your model. If you do not see an error, your shared code folder contains the
required shared utility files.

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:

a Set Configuration Parameters > Diagnostics > Advanced parameters >


Use only existing shared code to warning.
b Rebuild your model. The code generation process uses a locally generated
version of the missing shared utility files.
c Provide the administrator of the verified code library with your model and
information about missing shared utility files. With the model, the administrator
generates the required shared utility files. Using sharedCodeUpdate, the
administrator adds the files to the existing shared code folder.

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).

Required Edits to Reuse Shared Utility Code


For most shared utility code files, you can specify master copies that you can reuse across
releases without modifying the files. With some files, for example, rtwtypes.h, and
zero_crossing_types.h, there are situations where manual editing is required to
produce master copies that you can use with generated code from different releases. For
example:

36-83
36 Source Code Generation in Simulink Coder

• The rtwtypes.h file generated by R2010a contains a checksum.

/* This ID is used to detect inclusion


of an incompatible rtwtypes.h */
#define RTWTYPES_ID_C08S16I32L64N64F0

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"

Remove definitions from rtwtypes.h that zero_crossing_types.h provides.

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

Cross-Release Code Integration


In this section...
“Workflow” on page 36-85
“Limitations” on page 36-88
“Simulink.Bus Support” on page 36-89
“Root-Level I/O Through Global Variables in Generated Code” on page 36-92
“Communicate Between Current and Previous Release Components Through Global Data
Stores” on page 36-95
“Parameter Tuning” on page 36-96
“Use Multiple Instances of Code Generated from Reusable Referenced Model” on page
36-97
“Compare Simulation Behavior of Model Component in Current Release and Generated
Code from Previous Release” on page 36-99
“Import AUTOSAR Code from Previous Releases” on page 36-100

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:

1 Register previous releases with sharedCodeMATLABVersions

Use sharedCodeMATLABVersions to specify locations of the previous MATLAB


releases, R2015b, R2016a, and R2016b.
2 Export components from previous releases

In the current release, enter the commands:


P1ArtifactsLocation = crossReleaseExport(folderPathForP1_ert_rtw);
P2ArtifactsLocation = crossReleaseExport(folderPathForP2_ert_rtw);
P3ArtifactsLocation = crossReleaseExport(folderPathForP3);

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

P1ArtifactsLocation , P2ArtifactsLocation , and P3ArtifactsLocation


are paths to the export artifact folders, P1_R2015b, P2_R2016a, and P3_R2016b,
which are created in step 2.

In the current working folder, the crossReleaseImport function creates the xrel
subfolder that contains software-in-the-loop (SIL) blocks and subfolders:

• P1_R2015b_sil and P1_R2015b_sil_resources


• P2_R2016a_sil and P2_R2016a_sil_resources
• P3_R2016b_sil and P3_R2016b_sil_resources
5 Incorporate components into current release model

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.

When you build the Controller model (rtwbuild('Controller')), the code


generator does not generate new code for the components represented by the SIL or
PIL blocks. The model code calls code generated by previous releases.

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:

• Export-function models for ERT code.


• Simulink Function and Function Caller blocks across the boundaries of ERT code
generated by different releases.

36-88
Cross-Release Code Integration

• The integration of generated code from releases before R2010a.


• The import of generated code from the current release into a previous release
(forward compatibility).
• The export of files located in the MATLAB root folder of the previous release, for
example, blockset library files.
• The export and import of generated code from models with non-inlined S-functions.
• C-API on page 46-2.

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.

If your model has:

• 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.

You can run:

• 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

Appr Code Export Code Import


oach
In the previous release, before In the current release, before running
generating code, set the DataScope crossReleaseImport, set the
property of the Simulink.Bus object DataScope property of the
to Auto. Do not assign a value to the Simulink.Bus object to Auto.
HeaderFile property.
Auto When you build the integration model,
matic The code generator creates the the build process uses the
Simulink.Bus data type definition in Simulink.Bus data type from the
the default header file on page 37-18, header file in the imported code.
which is located in the code generation
folder for the model.

36-90
Cross-Release Code Integration

Appr Code Export Code Import


oach
In the previous release, before In the current release, before running
generating code, specify these crossReleaseImport, set the
properties of the Simulink.Bus object: DataScope property of the
Simulink.Bus object to Imported.
• DataScope — Set to Exported.
• HeaderFile — Specify a file name, When you build the integration model
for example, prevRelBusType. that incorporates the imported SIL or
PIL block, the build process uses the
The code generator creates Simulink.Bus data type definition in
prevRelBusType.h in the shared prevRelBusType.h.
utility code folder. This header file
contains the definition for the If the imported code is from R2010a or
Expor Simulink.Bus data type. Use R2010b, specify these properties of the
ted sharedCodeUpdate to add Simulink.Bus object:
bus prevRelBusType.h to the shared code
• DataScope — Set to Imported.
folder that ExistingSharedCode
specifies. • HeaderFile — Set to file path for
modelName_types.h, which is in
For R2010a and R2010b, the the imported code folder.
DataScope property is not available.
Do not assign a value to the When you build the integration model,
HeaderFile property. The code the build process uses the
generator creates the Simulink.Bus Simulink.Bus data type definition in
data type definition in modelName_types.h.
modelName_types.h, which is located
in the code generation folder for the
model.

36-91
36 Source Code Generation in Simulink Coder

Appr Code Export Code Import


oach
In the previous release, before In the current release, after importing
generating code, specify these generated code, you do not have to
properties of the Simulink.Bus object: change the Simulink.Bus.

• DataScope — Set to Imported. When you build the integration model


• HeaderFile — Specify a path to a that incorporates the imported SIL or
file that contains the Simulink.Bus PIL block, the build process uses the
data type definition, for example, Simulink.Bus data type definition
aBusType.h. from aBusType.h.
Impor
ted For R2010a and R2010b, the If the imported code is from R2010a or
bus DataScope property is not available. R2010b, specify these properties of the
For the HeaderFile property, specify a Simulink.Bus object:
path to a file that contains the
• DataScope — Set to Imported.
Simulink.Bus data type definition, for
example, aBusType.h. • HeaderFile — Set to aBusType.h.

When you build the integration model,


the build process uses the
Simulink.Bus data type definition in
aBusType.h.

Root-Level I/O Through Global Variables in Generated Code


When imported ERT code from a previous release implements an input or output port
through a global variable, the code that is generated from the integration model depends
on the properties of the signal connected to the port in the integration model.

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:

• Defines the variable if it is declared but undefined in the imported code.


• Creates additional code to copy data between the variable generated from the
integration model and the variable in the imported 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

Storage Class Property Property Value Support


Type Unstructured only
Data access Cannot connect a port implemented as a
Pointer variable in the imported code to a
signal of the same name that is
implemented through a Direct storage
class in the integration model

Cannot connect a port implemented as a


Direct variable in the imported code to a
signal of the same name that is
implemented as a Pointer in the
integration model

36-93
36 Source Code Generation in Simulink Coder

Storage Class Property Property Value Support


Data scope If the imported code declares but does not
define the variable (i.e. code is generated
from a signal that uses the Imported
value), then one of the following is
required:

• The integration model uses the


Exported value.
• External code defines the variable.

If the imported code defines the variable


(i.e. code is generated from a signal that
uses the Exported value):

• For signals in the integration model that


are connected to root-level I/O ports:

• Set the EnableDataOwnership


configuration parameter to on.
• Use a custom storage class with
these properties:

• 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:

• Data scope - Imported


• Data access - Direct

36-94
Cross-Release Code Integration

Communicate Between Current and Previous Release


Components Through Global Data Stores
Current and previous release components can communicate through global data stores
associated with Simulink.Signal objects in the MATLAB base workspace or a Simulink
data dictionary. The workflow described here applies to cross-release ERT 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

In the current release, before you run crossReleaseImport, define a


Simulink.Signal object in the MATLAB base workspace or a Simulink data dictionary
for each global data store of the component that you want to import:
1 For the object name and the Data type, Complexity, and Dimensions object
properties, specify values that match values of the corresponding object in the
component that you want to import.
2 For the Storage class property, specify a value that is compatible. If the previous
release value is ImportedExtern, specify one of these values for the current
release:

36-95
36 Source Code Generation in Simulink Coder

• ImportedExtern
• ExportedGlobal
• ImportFromFile or ExportToFile custom storage class.

If the previous release value is ImportedExternPointer, then specify


ImportedExternPointer for the current release.
3 For the Alias property, specify a matching value only if the property is specified for
the object in the component that you want to import.
4 Save the Simulink.Signal objects. The objects are required each time you
simulate or build the imported SIL or PIL block.

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:

1 Define a Simulink.Parameter object in the MATLAB base workspace or a Simulink


data dictionary.
2 For the object name and the Data type, Complexity, and Dimensions object
properties, specify values that match the exported object values. If the variable in the
imported source code does not have the same name as the object, for the Alias
property, specify a value that matches the variable name.
3 If the exported object uses the GetSet custom storage class, specify:

• A matching value for the Storage class object property.


• The header file that defines the get and set access functions. For details, see
“Control Data Representation by Configuring Custom Storage Class Properties”
on page 26-31 and “Access Data Through Functions with Custom Storage Class
GetSet” on page 26-42.

Support of the GetSet custom storage class from a previous release applies only for
R2011a and later releases.

36-96
Cross-Release Code Integration

For code generated by a top-model or subsystem build process in a previous release,


these limitations apply:

• If a tunable parameter specified by a Simulink.Parameter object is exported from


the previous release with storage class set to ExportedGlobal and the storage class
of the Simulink.Parameter object in the current release is also ExportedGlobal,
an error occurs when you build the integration model.
• On a Mac operating system, if a tunable parameter specified by a
Simulink.Parameter object is exported from a previous release with storage class
set to ExportedGlobal, you cannot build the integration model if the storage class of
the Simulink.Parameter object in the current release (with the same name or alias)
is ImportedExtern. To work around this limitation, modify the default settings:

1 Get the build tool from the default toolchain.


tc = coder.make.getDefaultToolchain;
cComp = tc.getBuildTool('C Compiler');
2 Extract the C compiler standard options.
stdMaps = cComp.SupportedStandard.getLangStandardMaps;
optionValues = stdMaps.getCompilerOptions('*');
3 Remove -fno-common from the standard options for the C and C++ compilers.
optionToRemove = '-fno-common';
optionsToKeep = strrep(optionValues, optionToRemove, '');
c_standard_opts_id = '$(C_STANDARD_OPTS)';

custToolChainOpts = get_param(model,'CustomToolchainOptions');
custToolChainOpts{2} = ...
strrep(custToolChainOpts{2}, c_standard_opts_id, optionsToKeep);

set_param(model, 'CustomToolchainOptions',custToolChainOpts);

Use Multiple Instances of Code Generated from Reusable


Referenced Model
Using a reusable referenced model, you can specify unique model argument values
(Simulink) for each instance of the referenced model in a parent model. You can export
previously generated code for the reusable referenced model, import the code into the
current release as a parameterized cross-release SIL or PIL block, and then insert
multiple instances of the block into an integration model. For each block instance, you
can specify unique model argument values.

1 Export generated code for the reusable referenced model.

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.

handleSILBlock = crossReleaseImport(artifactLocation, ...


configSetIntegrationModel, 'SimulationMode', 'SIL');
4 In the integration model, replace, for example, two instances of the referenced model
with instances of the cross-release 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.

pathToBlockInstanceName1 = [integrationModel, '/', blockInstanceName1];


pathToBlockInstanceName2 = [integrationModel, '/', blockInstanceName2];

set_param(pathToBlockInstanceName1, 'paramA', 'paramA_instName1');


set_param(pathToBlockInstanceName1, 'paramB', 'paramB_instName1');

set_param(pathToBlockInstanceName2, 'paramA', 'paramA_instName2');


set_param(pathToBlockInstanceName2, 'paramB', 'paramB_instName2');
6 To specify unique model argument values for the block instances in the integration
model, assign values to the workspace variables, paramA_instName1,
paramB_instName1, paramA_instName2, and paramB_instName2.

36-98
Cross-Release Code Integration

Compare Simulation Behavior of Model Component in Current


Release and Generated Code from Previous Release
In a previous release, suppose that you developed a model component, generated code for
the component, and tested and deployed the generated code. Now, in the current release,
you want to add features to the model component and use the model component in system
development and code generation. Before you proceed, you can compare the functional
behavior of the model component and the generated code from the previous release.

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:

• Set Simulation mode to Software-in-the-loop (SIL) or Processor-in-the-


loop (PIL).
• Set Code interface to Top model.

36-99
36 Source Code Generation in Simulink Coder

Import AUTOSAR Code from Previous Releases


If you install the Embedded Coder Support Package for AUTOSAR Standard, you can
import into the current release AUTOSAR component code that you generated in a
previous release.

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.

These limitations apply:

• 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™

Generate Code Using Simulink® Coder™


This example shows how to select a system target file for a Simulink® model, generate C
code for real-time simulation, and view generated files.

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.

Alternately, type the following commands at the MATLAB® command prompt.

cs = getActiveConfigSet(model);
openDialog(cs);

3. Select the Code Generation node.

4. In the Target Selection pane, click Browse to select a target.

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™

5. Select the Generic Real-Time (GRT) target and click Apply.

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

• Click the Build Model button.


• Press Ctrl+B.
• Select Code > C/C++ Code > Build Model.
• Invoke the rtwbuild command from the MATLAB command line.
• Invoke the slbuild command from the MATLAB command line.

7. View the code generation report that appears.

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™

The figure below contains a portion of rtwdemo_rtwintro.c

36-105
36 Source Code Generation in Simulink Coder

36-106
Generate Code Using Simulink® Coder™

8. Close the model.

bdclose(model)
rtwdemoclean;

Related Topics

• “Configure Model, Generate Code, and Simulate” (Simulink Coder)


• “Configure a System Target File” (Simulink Coder)
• “Generate Code Using Embedded Coder®”
• “Generate Code and Simulate Models in a Simulink Project” (Simulink Coder)
• “Generate Code and Simulate Models with Simulink Project API”

36-107
37

Source Code Generation in


Embedded Coder

• “Generate Code Using Embedded Coder®” on page 37-2


• “Generate Code by Using the Quick Start Tool” on page 37-10
• “Manage File Packaging of Generated Code Modules” on page 37-14
• “Generate Reentrant Code from Top-Level Models” on page 37-21
37 Source Code Generation in Embedded Coder

Generate Code Using Embedded Coder®


This example shows how to select a target for a Simulink® model, configure options,
generate C code for embedded systems, and view generated files.

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.


model='rtwdemo_rtwecintro';
open_system(model)

2. Open the Configuration Parameters dialog box from the model editor by clicking
Simulation > Model Configuration Parameters.

37-2
Generate Code Using Embedded Coder®

Alternately, type the following commands at the MATLAB® command prompt.

cs = getActiveConfigSet(model);
openDialog(cs);

3. Select the Code Generation node.

4. In the Target Selection pane, click Browse to select a target.

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®

5. Select the Embedded Real-Time (ERT) target and click Apply.

The ERT target includes a utility to specify and prioritize code generation settings based
on your application objectives.

6. In the Code Generation Advisor pane, click Set 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:

• Click the Build Model button.


• Press Ctrl+B.
• Select Code > C/C++ Code > Build Model.
• Invoke the rtwbuild command from the MATLAB command line.
• Invoke the slbuild command from the MATLAB command line.

9. View the code generation report that appears.

The report includes rtwdemo_rtwecintro.c, associated utility and header files, and
traceability and validation reports.

37-6
Generate Code Using Embedded Coder®

The figure below contains a portion of rtwdemo_rtwecintro.c

37-7
37 Source Code Generation in Embedded Coder

37-8
See Also

10. Close the model.

bdclose(model)
rtwdemoclean;

Related Topics

• “Configure Model, Generate Code, and Simulate” (Simulink Coder)


• “Configure a System Target File” (Simulink Coder)
• “Generate Code Using Embedded Coder®”
• “Generate Code and Simulate Models in a Simulink Project” (Simulink Coder)
• “Generate Code and Simulate Models with Simulink Project API”

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

Generate Code by Using the Quick Start Tool


The Quick Start tool helps you prepare a model for generating readable, efficient code. To
start the tool, from the model window, select Code > C/C++ > Embedded Coder Quick
Start.

After you start the tool, you must answer these questions about the code that you want to
generate:

• What is the model or subsystem for code generation?


• What is the type of code output for your generated code?
• Does your application require reentrant, multi-instance code?
• What is the target hardware processor type?
• What is your primary code generation objective?

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.

Quick Start Model Analysis


At each step of the quick start process, the tool validates your model against your
selections. The tool determines if there are model conditions that prevent you from
proceeding with code generation. During the analysis step, the tool must also examine
your model or subsystem for answers to the following questions. The answers help
determine the best configuration for the deployment of your code.

How many sample rates are in your system?

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.

If you choose to generate multitasking code, the code generator produces


multiple entry-point functions. These functions run as multiple tasks. Each entry-
point function is called at an interval defined by the sample rate that is
configured in the model.

Note If your model contains an asynchronous rate, an additional entry-point function is


generated to run at the specific interrupt time.

For more information about sample rates, see “Time-Based Scheduling and Code
Generation” (Simulink Coder).

Does your system contain continuous states?

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.

For more information on solvers, see “Solver Types” (Simulink).

Did you configure your system for export function calls?

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.

For more information, see “Export-Function Models” (Simulink).

Does your system contain referenced 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).

Configuration Parameter Changes for Models with a


Configuration Reference
To apply configuration parameter changes to a model with an active configuration
reference, the Quick Start tool:

• Creates a Simulink.ConfigSet object, QuickStart_timestamp, in the workspace


or data dictionary that contains the original configuration set. The new object is a copy
of the original configuration set that has the parameter changes applied.
• Creates a Simulink.ConfigSetRef object that points to the new configuration set
object.
• Attaches the new configuration reference to the model and makes it the active
configuration.

To restore the original configuration set, activate the original Simulink.ConfigSetRef


object.

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:

• “Open Code Generation Report” on page 38-8


• “Code Appearance”
• “Build Process”
• “Application Objectives Using Code Generation Advisor” (Simulink Coder)
• “Manage a Configuration Set” (Simulink)
• “Configure Model and Generate Code” (Simulink Coder)
• “Relocate Code to Another Development Environment” (Simulink Coder)

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

Manage File Packaging of Generated Code Modules


The code generator produces code modules. The file packaging configuration controls
where the code generator places code into code modules and header files.

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

Generated Code Modules


The code generator creates a build folder in your working folder to store generated
source code. The build folder contains object files, a makefile, and other files created
during the code generation process. The default name of the build folder is
model_ert_rtw.

Code Modules and Header Files Affected by File Packaging summarizes the structure of
source code that the code generator produces.

You can customize the generated set of files in several ways:

• 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.

• Nonvirtual subsystem code generation: Instruct the code generation software to


generate separate functions within separate code files for nonvirtual subsystems. You
can control the names of the functions and of the code files. For further information,
see “Control Generation of Subsystem Functions” (Simulink Coder).
• Custom storage classes: Use custom storage classes to partition generated data
structures into different files based on file names that you specify. For further

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

Code Modules and Header Files Affected by File Packaging

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.

The code generator:

• Produces a separate header file for each Simulink Function block


in a model.
• Includes model.h in the subsystem .c or .cpp files of a model.

If you interface handwritten code to generated code for one or more


models, include model.h for each of those models.
model_data.c or .cpp Contains (if conditionally generated) the declarations for the
parameters data structure, the constant block I/O data structure, and
any zero representations for the model structure data types. If the
model does not use these data structures and zero representations,
model_data.c or .cpp is not generated. These structures and zero
representations are declared extern in model.h.
model_types.h Provides forward declarations for the real-time model data structure
and the parameters data structure. Function declarations of reusable
functions can require these declarations. Provides type definitions
for user-defined types that the model uses.
rtwtypes.h Defines data types, structures, and macros required by generated
code. For more information, see “Control Placement of rtwtypes.h for
Shared Utility Code” (Simulink Coder).

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”.

Contains #include directives required by the rt_main.c or


rt_cppclass_main.cpp static main program module. Includes
rtmodel.h to access model-specific data structures and entry
points, because the static main program module is not created at
code generation time.

For more information, see “Static Main Program Module” on page


52-11.

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).

User-Written Code Modules


Code that you write to interface with generated model code usually includes a customized
main module. Base this module on a main program provided by the code generation
software. This customized main module can also include interrupt handlers, device driver
blocks and other S-functions, and other supervisory or supporting code. Steps to set up
the development environment to support a customized main module include:

1 Establish a working folder for your own code modules.


2 Put your working folder on the MATLAB path.
3 At minimum, inform the build process about the location of your source and object
files with Additional build information in the Code Generation > Custom Code
pane.
4 Your development process could require generating code for a particular
microprocessor or development board and deploying the code on target hardware
with a cross-development system. To accomplish these goals, make more extensive
modifications to the ERT-based system target file.

For information on how to customize your ERT-based system target file for your
production requirements, see “Target Development” (Simulink Coder).

Customize Generated Code Modules


A configuration parameter is available to specify how the code generator packages
generated source code into files. The configuration parameter File packaging format
options are located in the Configuration Parameter dialog box, on the Code Generation
> Code Placement pane, in the Code packaging section. The options are Modular,
Compact (with separate data file), and Compact. The table describes the
generated files and the removed files for each file packaging format.

37-18
Manage File Packaging of Generated Code Modules

Generated Files According to File Packaging Format

File Packaging Format Generated Files Removed Files


Modular (default) model.c None

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)

The table describes content placement from the removed files.

Removed Files According to File Packaging Format

Removed File Generated Content In File


model_private.h model.c and model.h
model_types.h model.h
model_data.c model.c

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.

• Modular: Some shared utility files are in the build folder.


• Compact (with separate data file): Utility code is generated in model.c.
• Compact: Utility code is generated in model.c.

File packaging formats Compact and Compact (with separate data file)
generate model_types.h for models containing:

• A Model Variants block or a Variant Subsystem block. The model_types.h file


includes preprocessor directives defining the variant objects associated with a variant
block.
• Custom storage classes generating a separate header file.

File packaging formats Compact and Compact (with separate data file) are not
compatible with:

• A model containing a subsystem, which is configured to generate separate source files


• A model containing a noninlined S-function
• A model for which Shared code placement is set to Auto, which uses data objects
for which Data scope is set to Exported

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

Generate Reentrant Code from Top-Level Models


In this section...
“Configure Model” on page 37-21
“Share Data Between Instances” on page 37-22

To generate reentrant multi-instance code from a model, select Reusable function


code interface packaging. When you select the Reusable function code interface for
an ERT-based model:

• 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.

Share Data Between Instances


When your code calls a reentrant model entry-point function multiple times, each call
represents an instance of the model. By default, Embedded Coder generates code that
assumes each instance reads from and writes to a separate copy of the signals, block
states, and parameters in the model.

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

Report Generation in Embedded


Coder

• “Reports for Code Generation” on page 38-2


• “Generate a Code Generation Report” on page 38-5
• “Generate Code Generation Report After Build Process” on page 38-6
• “Open Code Generation Report” on page 38-8
• “Generate Code Generation Report Programmatically” on page 38-10
• “View Code Generation Report in Model Explorer” on page 38-11
• “Package and Share the Code Generation Report” on page 38-13
• “Web View of Model in Code Generation Report” on page 38-15
• “Analyze the Generated Code Interface” on page 38-19
• “Static Code Metrics” on page 38-33
• “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
• “Analyze Code Replacements in Generated Code” on page 38-48
• “Document Generated Code with Simulink Report Generator” on page 38-50
• “Get Code Description of Generated Code” on page 38-57
38 Report Generation in Embedded Coder

Reports for Code Generation


In this section...
“HTML Code Generation Report Location” on page 38-2
“HTML Code Generation Report for Referenced Models” on page 38-3
“HTML Code Generation Report Extensions” on page 38-3

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.

For an example, see “Generate a Code Generation Report” on page 38-5.

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.

HTML Code Generation Report Location


The default location for the code generation report files is in the html subfolder of the
build folder, model_target_rtw/html/. target is the name of the System target file
specified on the Code Generation pane. The default name for the top-level HTML report
file is model_codegen_rpt.html or subsystem_codegen_rpt.html. For more

38-2
Reports for Code Generation

information on the location of the build folder, see “Manage Build Process Folders”
(Simulink Coder).

HTML Code Generation Report for Referenced Models


To generate a code generation report for a top model and code generation reports for
each referenced model, you need to specify the Create code generation report on the
Code Generation > Report pane for the top model and each referenced model. You can
open the code generation report of a referenced model in one of two ways:

• 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)

HTML Code Generation Report Extensions


If you have an Embedded Coder license, the code generator enhances the HTML code
generation report. Configure your model to include the following sections in the report:

• 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

replacement. For more information, see “Analyze Code Replacements in Generated


Code” on page 38-48.
• The model Web view displays an interactive model diagram within the code generation
report and supports traceability between the source code and the model. Therefore,
you can share your model and generated code outside of the MATLAB environment.
For more information, see “Web View of Model in Code Generation Report” on page
38-15.

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

Generate a Code Generation Report


To generate a code generation report when the model is built:

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

Generate Code Generation Report After Build Process


After generating code, if you did not configure your model to create a code generation
report, you can generate a code generation report without rebuilding your model.

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.

Click Generate Report.


3 If the code generation files are not in your current working directory, 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

The software generates a report, model_codgen_rpt.html, from the code generation


files in the build folder you specified.

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

Open Code Generation Report


You can refer to existing code generation reports at any time. If you generated a code
generation report, in the Simulink Editor, you can open the report by selecting the menu
option Code > C/C++ Code > Code Generation Report > Open Model Report. If you
are opening a report for a subsystem, select Open Subsystem Report. A Simulink Coder
license is required to view the code generation report. An Embedded Coder license is
required to view a code generation report enhanced with Embedded Coder features.

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.

Alternatively, you can open the code generation report (model_codegen_rpt.html or


subsystem_codegen_rpt.html) manually into a MATLAB Web browser window, or in
another Web browser. For the location of the generated report files, see “HTML Code
Generation Report Location” on page 38-2.

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.

To regenerate the code generation report, do one of the following:

• Rebuild your model.


• Generate the report using the coder.report.generate function.

38-9
38 Report Generation in Embedded Coder

Generate Code Generation Report Programmatically


At the MATLAB command line, you can generate, open, and close an HTML Code
Generation Report with the following functions:

• coder.report.generate generates the code generation report for the specified


model.
• coder.report.open opens an existing code generation report.
• coder.report.close closes the code generation report.

38-10
View Code Generation Report in Model Explorer

View Code Generation Report in Model Explorer


After generating an HTML code generation report, you can view the report in the right
pane of the Model Explorer. You can also browse the generated files directly in the 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.

In this example, the file S:/rtwdemo_counter_grt_rtw/rtwdemo_counter.c is


being displayed. To view a file in the Contents pane, click it once.

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

Package and Share the Code Generation Report


In this section...
“Package the Code Generation Report” on page 38-13
“View the Code Generation Report” on page 38-14

Package the Code Generation Report


To share the code generation report, you can package the code generation report files
and supporting files into a zip file for transfer. The default location for the code
generation report files is in two folders:

• /slprj
• html subfolder of the build folder, model_target_rtw, for example
rtwdemo_counter_grt_rtw/html

To create a zip file from the MATLAB command window:

1 In the Current Folder browser, select the two folders:

• /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

View the Code Generation Report


To view the code generation report after transfer, unzip the file and save the two folders
at the same folder level in the hierarchy. Navigate to the model_target_rtw/html/
folder and open the top-level HTML report file named model_codgen_rpt.html or
subsystem_codegen_rpt.html in a Web browser.

38-14
Web View of Model in Code Generation Report

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

About Model Web View


To review and analyze the generated code, it is helpful to navigate between the code and
model. You can include a Web view of the model within the HTML code generation report.
You can then share your model and generated code outside of the MATLAB environment.
When you generate the report, the Web view includes the block diagram attributes
displayed in the Simulink Editor, such as, block sorted execution order, signal properties,
and port data types.

A Simulink Report Generator license is required to include a Web view (Simulink Report
Generator) of the model in the code generation report.

Browser Requirements for Web View

Web view requires a Web browser that supports Scalable Vector Graphics (SVG). Web
view uses SVG to render and navigate models.

You can use the following Web browsers:

• 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

Generate HTML Code Generation Report with Model Web View


This example shows how to create an HTML code generation report which includes a Web
view of the model diagram.

38-15
38 Report Generation in Embedded Coder

1 Open the rtwdemo_mdlreftop model.


2 Open the Configuration Parameters dialog box or Model Explorer and navigate to the
Code Generation pane.
3 Specify ert.tlc for the System target file parameter.
4 Open the Code Generation > Report pane.
5 Select the following parameters:

• Create code generation report


• Open report automatically
• Generate model Web view
6 Select the parameters Code-to-model and Model-to-code.

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.

Model Web View Limitations


The HTML code generation report includes the following limitations when using the
model Web view:

• 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

Analyze the Generated Code Interface


In this section...
“Code Interface Report Overview” on page 38-19
“Generating a Code Interface Report” on page 38-20
“Navigating Code Interface Report Subsections” on page 38-22
“Interpreting the Entry-Point Functions Subsection” on page 38-23
“Interpreting the Inports and Outports Subsections” on page 38-26
“Interpreting the Interface Parameters Subsection” on page 38-28
“Interpreting the Data Stores Subsection” on page 38-30
“Code Interface Report Limitations” on page 38-31

Code Interface Report Overview


When you select the Create code generation report option for an ERT-based model, a
Code Interface Report section is automatically included in the generated HTML report.
The Code Interface Report section provides documentation of the generated code
interface, including model entry-point functions and interface data, for consumers of the
generated code. The information in the report can help facilitate code review and code
integration.

The code interface report includes the following subsections:

• Entry-Point Functions — interface information about each model entry-point


function, including model_initialize, model_step, and (if applicable)
model_reset and model_terminate.
• Inports and Outports — interface information about each model inport and outport.
• Interface Parameters — interface information about tunable parameters that are
associated with the model.
• Data Stores — interface information about global data stores and data stores with
non-auto storage that are associated with the model.

For limitations that apply to code interface reports, see “Code Interface Report
Limitations” on page 38-31.

For illustration purposes, this section uses the following models:

38-19
38 Report Generation in Embedded Coder

• rtwdemo_basicsc (with the ExportedGlobal Storage Class button selected in the


model window) for examples of report subsections
• rtwdemo_mrmtbb for examples of timing information
• rtwdemo_fcnprotoctrl for examples of function argument and return value
information

Generating a Code Interface Report


To generate a code interface report for your model:

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:

set_param(bdroot, 'GenerateReport', 'on')

If the Code-to-model parameter is selected, the generated report contains


hyperlinks to the model. Leave this value selected unless you plan to use the report
outside the MATLAB environment.
3 Build the model. If you selected the Report pane option Open report
automatically, the code generation report opens automatically after the build
process is complete. (Otherwise, you can open it manually from within the model
build folder.)
4 To display the code interface report for your model, go to the Contents pane of the
HTML report and click the Code Interface Report link. For example, here is the
generated code interface report for the model rtwdemo_basicsc (with the
ExportedGlobal Storage Class button selected in the model window).

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.

Navigating Code Interface Report Subsections


To help you navigate code interface descriptions, the code interface report provides
collapse/expand tokens and hyperlinks, as follows:

• 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

Interpreting the Entry-Point Functions Subsection


The Entry-Point Functions subsection of the code interface report provides the
following interface information about each model entry-point function, including
model_initialize, model_step, and (if applicable) model_reset and
model_terminate.

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

Interpreting the Inports and Outports Subsections


The Inports and Outports subsections of the code interface report provide the following
interface information about each inport and outport in the model.

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:

• If the data is defined in the generated code, the field displays


the identifier text.
• If the data is declared but not defined in the generated code —
for example, if the data is resolved with an imported storage
class — the field displays the identifier text prefixed with the
label 'Imported data:'.
• If the data is neither defined nor declared in the generated
code — for example, if Reusable function code interface
packaging is selected for the model — the field displays the
text 'Defined externally'.
Data Type Lists the data type of the inport or outport.
Scaling For fixed-point entries, lists the data type and fraction length
using Simulink fixed-point data type notation.

Note You must have a Fixed-Point Designer license to see fixed-


point scaling information in the report. For more information on
how scaling is represented in the table, see “Fixed-Point Data
Type and Scaling Notation” (Fixed-Point Designer).
Dimension Lists the dimensions of the inport or outport (for example, 1 or
[4, 5]).

For example, here are the Inports and Outports subsections for the model
rtwdemo_basicsc.

38-27
38 Report Generation in Embedded Coder

Interpreting the Interface Parameters Subsection


The Interface Parameters subsection of the code interface report provides the following
interface information about tunable parameters that are associated with the model.

Field Description
Parameter Source Lists the source of the parameter value, as follows:

• If the source of the parameter value is a block, the field


displays the block name, such as <Root>/Gain2 or <S1>/
Lookup1. If you selected the Code-to-model parameter for
your model, you can click the Parameter Source value to go
to the parameter's location in the model display.
• If the source of the parameter value is a workspace variable,
the field displays the name of the workspace variable.

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:

• If the data is defined in the generated code, the field displays


the identifier text.
• If the data is declared but not defined in the generated code —
for example, if the data is resolved with an imported storage
class — the field displays the identifier text prefixed with the
label 'Imported data:'.
• If the data is neither defined nor declared in the generated
code — for example, if Reusable function code interface
packaging is selected for the model — the field displays the
text 'Defined externally'.
Data Type Lists the data type of the tunable parameter.
Scaling For fixed-point entries, lists the data type and fraction length
using Simulink fixed-point data type notation.

Note You must have a Fixed-Point Designer license to see fixed-


point scaling information in the report. For more information on
how scaling is represented in the table, see “Fixed-Point Data
Type and Scaling Notation” (Fixed-Point Designer).
Dimension Lists the dimensions of the tunable parameter (for example, 1 or
[4, 5, 6]).

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

Interpreting the Data Stores Subsection


The Data Stores subsection of the code interface report provides the following interface
information about global data stores and data stores with non-auto storage that are
associated with the model.

Field Description
Data Store Source Lists the source of the data store memory, as follows:

• If the data store is defined using a Data Store Memory block,


the field displays the block name, such as <Root>/DS1. If you
selected the Code-to-model parameter for your model, you
can click on the Data Store Source value to go to the data
store's location in the model display.
• If the data store is defined using a Simulink.Signal object,
the field displays the name of the Simulink.Signal object.

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:

• If the data is defined in the generated code, the field displays


the identifier text.
• If the data is declared but not defined in the generated code —
for example, if the data is resolved with an imported storage
class — the field displays the identifier text prefixed with the
label 'Imported data:'.
• If the data is neither defined nor declared in the generated
code — for example, if Reusable function code interface
packaging is selected for the model — the field displays the
text 'Defined externally'.
Data Type Lists the data type of the data store.
Scaling For fixed-point entries, lists the data type and fraction length
using Simulink fixed-point data type notation.

Note You must have a Fixed-Point Designer license to see fixed-


point scaling information in the report. For more information on
how scaling is represented in the table, see “Fixed-Point Data
Type and Scaling Notation” (Fixed-Point Designer).
Dimension Lists the dimensions of the data store (for example, 1 or [1, 2]).

For example, here is the Data Stores subsection for the model rtwdemo_basicsc (with
the ExportedGlobal Storage Class button selected in the model window).

Code Interface Report Limitations


The following limitations apply to the code interface section of the HTML code generation
reports.

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

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

About Static Code Metrics


The code generator performs static analysis on page 38-34 of the generated C or C++
code and provides these metrics in the Static Code Metrics Report section of the HTML
Code Generation Report.

You can use the information in the report to:

• Find the number of files and lines of code in each file.


• Estimate the number of lines of code and stack usage per function.
• Compare the difference in terms of how many files, functions, variables, and lines of
code are generated every time you change the model or MATLAB algorithm.
• Determine a target platform and allocation of RAM to the stack, based on the size of
global variables plus the estimated stack size.
• Determine possible performance slow points, such as the largest global variables or
the most costly call path in terms of stack usage.
• View the cyclomatic complexity of a function, which counts the number of linearly
independent paths through a function.
• View the function call tree. Determine the longest call path to estimate the worst case
execution timing.
• View how target functions, provided by the selected code replacement library, are
used in the generated code.

For examples, see

• “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

Static Code Metrics Analysis


Static analysis of the generated code is performed only on the source code without
executing the program. The results of the static code metrics analysis are included in the
Static Code Metrics section of the HTML Code Generation Report. The report is not
available if you generate a MEX function from MATLAB code.

Static analysis of the generated source code files:

• 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

The following constructs add a decision:

• 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.

View Static Code Metrics and Definitions Within the


Generated Code
When you view code in the code generation report, to get access to code metrics and
definitions, you can use the following tools:

• 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

Generate Static Code Metrics Report for Simulink Model


The Static Code Metrics Report is a section included in the HTML Code Generation
Report. For more information on the static analysis of the generated code, see “Static
Code Metrics Analysis” on page 38-34.

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.

Click [+] to expand structures.

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:

• If a function is called by multiple functions, all functions are listed.


• If a function has no called function, this column is empty.

38-40
Generate Static Code Metrics Report for Simulink Model

For example, Fueling_Mode is called by Fail and fuel_rate_control_step. The


number of call sites is included in parentheses. Fail calls Fueling_Mode twice.

38-41
38 Report Generation in Embedded Coder

Generate a Static Code Metrics Report for MATLAB Code

Generate a Static Code Metrics Report Using the MATLAB


Coder App
This example shows how to generate a static code metrics report for a static C library
that is generated from MATLAB code using the MATLAB Coder app.

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.

Create the Example File

In a local, writable folder, create a MATLAB file, moving_average.m, that contains:

function [avg,z] = moving_average(x,z)


%#codegen
z(2:end) = z(1:end-1); % Update buffer
z(1) = x; % Add new value
avg = mean(z); % Compute moving average
end

Create a Test File

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

Set Up the MATLAB Coder Project

1 To open the MATLAB Coder app and set up a project, at the command line, enter:

coder -new moving_average.prj

38-42
Generate a Static Code Metrics Report for MATLAB Code

The app adds moving_average to the list of entry-point functions.


2 Click Next to go to the Define Input Types step.

Define Input Types

1 To automatically define the input types, select or enter the test file
moving_average_test.m. Click Autodefine Input Types.

The app determines that x is double(1x1) and z is double(10x1).


2 Click Next to go to the Check for Run-Times Issues step.

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.

Check for Run-Time Issues

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.

The app does not detect issues.


3 Click Next to go to the Generate Code step.

Configure the Build Settings

1 On the Generate Code page, to open the Generate dialog box, click the Generate
arrow .
2 Set Build type to Static library.

The default output file name is moving_average.


3 Click More Settings.
4 On the Debugging tab, verify that the Static code metrics check box is selected.
5 Click Close.

38-43
38 Report Generation in Embedded Coder

Generate C Code

1 To generate the library, click Generate.

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.

View the Static Code Metrics Report

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.

Enable a Static Code Metrics Report at the Command Line


To enable a static code metrics report at the command line:

1 Create a code generation configuration object for standalone code generation. For
example, to generate a static library, use:

cfg = coder.config('lib', 'ecoder', true);


2 Generate code, passing the configuration object as a parameter and specifying the -
report option. For example:

codegen -config cfg -report foo

Alternatively, you can:

1 Create a code generation configuration object for standalone code generation. For
example, to generate a static library:

cfg = coder.config('lib', 'ecoder', true);


2 Set the configuration object GenerateReport and GenerateCodeMetricsReport
parameters to true.

38-46
See Also

cfg.GenerateReport = true;
cfg.GenerateCodeMetricsReport = true;
3 Generate code, passing the configuration object as a parameter. For example:

codegen -config cfg foo

See Also

More About
• “Code Generation Reports” (MATLAB Coder)

38-47
38 Report Generation in Embedded Coder

Analyze Code Replacements in Generated Code


When you select the check box Summarize which blocks triggered code
replacements (Simulink Coder) for an ERT-based model, a Code Replacements Report
section is automatically included in the generated HTML report. The Code Replacements
Report section documents the code replacement library (CRL) functions that were used
for code replacements during code generation, providing a mapping between each
replacement instance and the Simulink block that triggered the replacement. To enable
display of the Simulink block information, select the Code Generation > Comments
check box Include comments. On the same pane, select either the Simulink block
comments checkbox or the Simulink block descriptions check box if present, or both.

You can use the report to:

• Determine which replacement functions were used in the generated code.


• Trace each replacement instance back to the block that triggered the replacement.

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

Document Generated Code with Simulink Report


Generator
In this section...
“Generate Code for the Model” on page 38-51
“Open the Report Generator” on page 38-51
“Set Report Name, Location, and Format” on page 38-53
“Include Models and Subsystems in a Report” on page 38-54
“Customize the Report” on page 38-55
“Generate the Report” on page 38-56

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:

• System snapshots (model and subsystem diagrams)


• Block execution order list
• Simulink Coder and model version information for generated code
• List of generated files
• Optimization configuration parameter settings
• System target file selection and build process configuration parameter settings
• Subsystem map
• File name, path, and generated code listings for the source code

To adjust Simulink Report Generator settings to include custom code and then generate a
report for a model, complete the following tasks:

1 “Generate Code for the Model” on page 38-51


2 “Open the Report Generator” on page 38-51
3 “Set Report Name, Location, and Format” on page 38-53
4 “Include Models and Subsystems in a Report” on page 38-54
5 “Customize the Report” on page 38-55

38-50
Document Generated Code with Simulink Report Generator

6 “Generate the Report” on page 38-56

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.

Generate Code for the Model


Before you use the Report Generator to document your project, generate code for the
model.
1 In the MATLAB Current Folder browser, navigate to a folder where you have write
access.
2 Create a working folder from the MATLAB command line by typing:
mkdir report_ex
3 Make report_ex your working folder:
cd report_ex
4 Open the slexAircraftExample model by entering the model name on the
MATLAB command line.
5 In the model window, choose File > Save As, navigate to the working folder,
report_ex, and save a copy of the slexAircraftExample model as myModel.
6 Open the Configuration Parameters dialog box by selecting Model Configuration
Parameters from the Simulation menu.
7 Select the Solver pane. In the Solver selection section, specify the Type parameter
as Fixed-step.
8 Select the Code Generation pane. Select Generate code only.
9 Click Apply.
10 In the model window, press Ctrl+B. The build process generates code for the model.

Open the Report Generator


After you generate the code, open the Report Generator.
1 In the model diagram window, select Tools > Report Generator.
2 In the Report Explorer window, in the options pane (center), click the folder rtw
(\toolbox\rtw). Click the setup file that it contains, codegen.rpt.

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

Set Report Name, Location, and Format


Before generating a report, you can specify report output options, such as the folder, file
name, and format. For example, to generate a Microsoft Word report named
MyCGModelReport.rtf:

1 In the properties pane, under Report Options, review the options listed.

38-53
38 Report Generation in Embedded Coder

2 Leave the Directory field set to Present working directory.


3 For Filename, select Custom: and replace index with the name
MyModelCGReport.
4 For File format, specify Rich Text Format and replace Standard Print with
Numbered Chapters & Sections.

Include Models and Subsystems in a Report


Specify the models and subsystems that you want to include in the generated report by
setting options in the Model Loop component.

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

3 In the outline pane, click Report - codegen.rpt*.

Customize the Report


After specifying the models and subsystems to include in the report, you can customize
the sections included in the report.

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

Generate the Report


After you adjust the report options, from the Report Explorer window, generate the
report by clicking File > Report. A Message List dialog box opens, which displays
messages that you can monitor as the report is generated. Model snapshots also appear
during report generation. The Message List dialog box might be hidden behind other
dialog boxes.

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

Get Code Description of Generated Code


You can use the code descriptor API to obtain meta-information about the generated code.
For each model build, the code generator, by default, creates a codedescriptor.dmr
file in the build folder. When simulating the model in Accelerator and Rapid Accelerator
modes, the codedescriptor.dmr is not generated.

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:

• Data Interfaces: inports, outports, parameters, and global data stores.


• Function Interfaces: initialize, output, update, and terminate.
• Run-time information of the data and function interfaces, such as timing requirements
of each interface entity.
• Model hierarchy information and code description of referenced models.

Get Data Interface Information


The coder.descriptor.DataInterface object describes various properties for a
specified data interface in the generated code. In the model rtwdemo_comments, there
are four inports, one outport, and a tunable global parameter. For more information about
the data interfaces in your model, use the coder.codedescriptor.CodeDescriptor
object and its methods.

1 Build the model.

rtwbuild('rtwdemo_comments')

38-57
38 Report Generation in Embedded Coder

2 Create a coder.codedescriptor.CodeDescriptor object for the required model


by calling the getCodeDescriptor function.

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()

A list of all the data interface types in rtwdemo_comments model is returned.

{'Inports' }
{'Outports' }
{'Parameters' }
{'GlobalParameters'}

38-58
Get Code Description of Generated Code

To obtain a list of all the supported data interfaces, call the


getAllDataInterfaceTypes method.
4 To obtain more information about a particular data interface type, call the
getDataInterfaces method.

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)

The first coder.descriptor.DataInterface object corresponding to the In1


block in the model is returned with its properties.

Type: [1×1 coder.descriptor.types.Double]


SID: 'rtwdemo_comments:1'
GraphicalName: 'In1'
VariantInfo: [0×0 coder.descriptor.VariantInfo]
Implementation: [1×1 coder.descriptor.StructExpression]
Timing: [1×1 coder.descriptor.TimingInterface]

Get Function Interface Information


The function interfaces are the entry-point functions in the generated code. In the model
rtwdemo_roll, the entry-point functions are model_initialize, model_step, and
model_terminate. For more information about the function interfaces in your model,
use the coder.codedescriptor.CodeDescriptor object.

1 Build the model.

rtwbuild('rtwdemo_roll')

38-59
38 Report Generation in Embedded Coder

2 Create a coder.codedescriptor.CodeDescriptor object for the required model


by calling the getCodeDescriptor function. Use the code descriptor object to call
the methods currently available in the API.

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()

A list of all the function interface types in rtwdemo_roll model is returned.

{'Initialize'}
{'Output' }
{'Terminate' }

To obtain a list of all the supported function interfaces, call the


getAllFunctionInterfaceTypes method.
4 To obtain more information about a particular function interface type, call the
getFunctionInterfaces method.

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

5 functionInterface is a coder.descriptor.FunctionInterface object. The


properties of the rtwdemo_roll_initialize function are returned.

Prototype: [1×1 coder.descriptor.types.Prototype]


ActualReturn: [0×0 coder.descriptor.DataInterface]
VariantInfo: [0×0 coder.descriptor.VariantInfo]
Timing: [1×1 coder.descriptor.TimingInterface]
ActualArgs: [1x0 coder.descriptor.DataInterface List]
6 You can further expand on the properties to obtain detailed information. To get the
function return value, name, and arguments:

functionInterface.Prototype

The object of coder.descriptor.types.Prototype is returned with properties.

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]

Get Model Hierarchy Information


Use the coder.codedescriptor.CodeDescriptor object to get the entire model
hierarchy information. The model rtwdemo_async_mdlreftop has model
rtwdemo_async_mdlrefbot as the referenced model.

1 Build the root model.

rtwbuild('rtwdemo_async_mdlreftop')

38-61
38 Report Generation in Embedded Coder

2 Create a coder.codedescriptor.CodeDescriptor object for the root model by


calling getCodeDescriptor function.

codeDescriptor = coder.getCodeDescriptor('rtwdemo_async_mdlreftop')
3 Get a list of all the referenced models by calling the getReferencedModelNames
method.

refModels = codeDescriptor.getReferencedModelNames()

refModels has the list of referenced model.

{'rtwdemo_async_mdlrefbot'}

38-62
See Also

4 To obtain the coder.codedescriptor.CodeDescriptor object for the referenced


model, call the getReferencedModelCodeDescriptor(refModelName) method.
refCodeDescriptor = codeDescriptor.getReferencedModelCodeDescriptor('rtwdemo_async_mdlrefbot')

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

Code Appearance in Embedded


Coder

• “Add Custom Comments to Generated Code” on page 39-3


• “Add Custom Comments for Variables in the Generated Code” on page 39-5
• “Add Global Comments” on page 39-8
• “Customize Generated Identifier Naming Rules” on page 39-14
• “Identifier Format Control” on page 39-22
• “Control Name Mangling in Generated Identifiers” on page 39-30
• “Avoid Identifier Name Collisions with Referenced Models” on page 39-32
• “Maintain Traceability for Generated Identifiers” on page 39-34
• “Exceptions to Identifier Formatting Conventions” on page 39-35
• “Identifier Format Control Parameters Limitations” on page 39-36
• “Control Code Style” on page 39-38
• “Customize Code Organization and Format” on page 39-56
• “Specify Templates For Code Generation” on page 39-59
• “Code Generation Template (CGT) Files” on page 39-60
• “Custom File Processing (CFP) Templates” on page 39-66
• “Change the Organization of a Generated File” on page 39-68
• “Customize Generated File Names” on page 39-70
• “Generate Source and Header Files with a Custom File Processing (CFP) Template”
on page 39-73
• “Comparison of a Template and Its Generated File” on page 39-81
• “Code Template API Summary” on page 39-85
• “Generate Custom File and Function Banners” on page 39-89
• “Template Symbols and Rules” on page 39-97
• “Annotate Code for Justifying Polyspace Checks” on page 39-106
39 Code Appearance in Embedded Coder

• “Enhance Readability of Code for Flow Charts” on page 39-108


• “Generate Inlined Subsystem Code” on page 39-122

39-2
Add Custom Comments to Generated Code

Add Custom Comments to Generated Code


You can include auto-generated comments in the generated code as described in
“Configure Code Comments” (Simulink Coder). For ERT targets, include additional
custom comments by setting parameters on the Code Generation > Comments pane in
the Configuration Parameters dialog box. With these parameters, you can enable or
suppress generation of descriptive information in comments for blocks and other model
elements.

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.

When you select Simulink block descriptions:

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
&#x30A2;. 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.

For more information, see “Model Configuration Parameters: Code Generation


Comments” (Simulink Coder).

39-4
Add Custom Comments for Variables in the Generated Code

Add Custom Comments for Variables in the Generated


Code
To control code generation options for signals, states, and parameters in a model, you can
create data objects in a workspace or data dictionary. You can generate comments in the
code that help you to document the purpose and properties of the data in each object.
Associate handwritten comments with each object, or write a function that generates
comments based on the properties of the object.

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

Embed Handwritten Comments for Signals or Parameters


To embed handwritten comments in the generated code near the definition of a signal,
state, or parameter:

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.

myParam.Description = 'This parameter represents wind speed.';


4 Set Configuration Parameters > Code Generation > System target file to an
ERT-based target such as ert.tlc.

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.

/* Exported block parameters */


real_T myParam = 15.23; /* Variable: myParam
* Referenced by: '<S1>/Gain'
* This parameter represents wind speed.
*/

Generate Dynamic Comments Based on Data Properties


You can generate dynamic comments that include the properties of the data object such
as data type, units, and dimensions. If you change the properties of the data object in
Simulink, the code generator maintains the accuracy of the comments. For example, this
comment displays some of the property values for a data object named MAP:

/* 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

Add Global Comments


In this section...
“Use a Simulink DocBlock to Add a Comment” on page 39-8
“Use a Simulink Annotation to Add a Comment” on page 39-11
“Use a Stateflow Note to Add a Comment” on page 39-11
“Use Sorted Notes to Add Comments” on page 39-12

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.

Use a Simulink DocBlock to Add a Comment


1 With the model open, from the View menu, select Library Browser.
2 Drag the DocBlock from Model-Wide Utilities in the Simulink library into the
model.
3 Double-click the DocBlock and type the comment that you want in the editor. Save
and close the editor.
4 Right-click the DocBlock and select Mask > Mask Parameters.
5 In the Code generation template symbol box, type one of the following:

• Abstract
• Description
• History
• ModifiedHistory

39-8
Add Global Comments

• Notes

Click OK. Template symbol names are case-sensitive.

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

Use a Simulink Annotation to Add a Comment


1 Double-click the unoccupied area on the model where you want to place the
comment. See “Describe Models Using Annotations” (Simulink).
2 Type <S:Symbol_name> followed by the comment. Symbol_name is one of the
following:

• Abstract
• Description
• History
• ModifiedHistory
• Notes

For example, type <S:Description>This is the description I want.


Template symbol names are case-sensitive. (The "S" before the colon indicates
"symbol.") If you want the code generator to sort multiple comments for the Notes
symbol name, replace the next step with “Use Sorted Notes to Add Comments” on
page 39-12.
3 Click outside the rectangle and 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. If you want the code generator to sort multiple comments for the Notes symbol
name, replace the next step with “Use Sorted Notes to Add Comments” on page 39-
12.
4 To add one or more other comments to the generated files, repeat steps 1–3.

Use a Stateflow Note to Add a Comment


1 Right-click the unoccupied area on the Stateflow chart where you want to place the
comment.
2 Select the annotation icon from the palette.
3 Type <S:Symbol_name> followed by the comment. Symbol_name is one of the
following:

• Abstract

39-11
39 Code Appearance in Embedded Coder

• Description
• History
• ModifiedHistory
• Notes

For example, type <S:Description>This is the description I want.


Template symbol names are case-sensitive. If you want the code generator to sort
multiple comments for the Notes symbol name, replace the next step with “Use
Sorted Notes to Add Comments” on page 39-12.
4 Click outside the note and 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.
5 To add one or more other comments to the generated files, repeat steps 1–4.

Use Sorted Notes to Add Comments


The sorted-notes capability allows you to add automatically sorted comments to the
generated files. The code generator places these comments in each generated file at the
location that corresponds to where the Notes symbol is located in the template file.

The code generator uses the following sorting order:

• Numbers before letters.


• Among numbers, 0 is first.
• Among letters, uppercases are before lowercases.

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

** Note1: This is the first comment I want


associated with the Notes symbol.
Note2: This is the second comment I want under Notes.
Noteb: This is the third comment.

**

39-13
39 Code Appearance in Embedded Coder

Customize Generated Identifier Naming Rules


In this section...
“Apply Naming Rules to Identifiers Globally” on page 39-14
“Apply Naming Rules to Simulink Data Objects” on page 39-16

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).

Apply Naming Rules to Identifiers Globally


Goal Specify
Set the maximum number of characters that the An integer value for the “Maximum identifier
code generator uses for function, typedef, and length” (Simulink Coder) parameter. For more
variable names (default 31). information, see “Specify Identifier Length to
Avoid Naming Collisions” (Simulink Coder). If
you expect your model to generate lengthy
identifiers (due to use of long signal or
parameter names, for example), or if identifiers
are mangled more than you expect, increase the
value of this parameter.

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:

• Provides more space for user names.


• Provides a more predictable and consistent
naming system that uses camel case.
• Does not include underscores or plurals.
• Provides consistent abbreviations for both a
type and a variable.

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.

• Literals: If you set Default parameter


behavior to Inlined, parameters are
expressed as numeric constants.
• Macros: Parameters are expressed as
variables (with #define macros). This
setting makes code more readable.

Apply Naming Rules to Simulink Data Objects


When your model uses Simulink data objects from the Simulink package, identifiers in
generated code copy the names of the objects by default. For example, a
Simulink.Signal object named Speed appears as the identifier Speed in generated
code.

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.

Specify Naming Rule Using a Function

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.
%

5. ANSI is a registered trademark of the American National Standards Institute, Inc.

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.

Specify Naming Rule for Storage Class Define

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

Override Data Object Naming Rules

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.

1 Open the model rtwdemo_namerules.


2 In the model, select View > Model Data Editor.
3 In the Model Data Editor, on the Parameters tab, click the Show/refresh
additional information button.
4 In the data table, find the row that corresponds to the Simulink.Parameter object
G1, which resides in the base workspace.
5
In the row, double-click the parameter icon .
6 In the Model Explorer Dialog pane (the right pane), for G1, specify the Alias
property as mySpecialParam. Click Apply.

39-18
Customize Generated Identifier Naming Rules

7 Generate code for the model.


8 In the code generation report, confirm the alias for the parameter object G1. The
generated file rtwdemo_namerules.h represents G1 with the variable
mySpecialParam.

Apply Custom Naming Conventions to Identifiers

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

Identifier Format Control


You can customize generated identifiers by specifying the Identifier format control
parameters on the Code Generation > Symbols pane in the Configuration Parameters
dialog box. For each parameter, you can enter a macro that specifies whether, and in what
order, certain text is included within generated identifiers. For example, you can specify
that the root model name be inserted into each identifier using the $R token.

The macro can include:

• 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

Identifier Format Tokens

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 System Hierarchy Number in


Identifiers option in previous releases.
$A Insert data type acronym (for example, i32 for integers) to signal and work
vector identifiers. This token is available for local block output variables,
local temporary variables, 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

This token is required for Header files and Source files.

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

Identifier Format Control Parameter Values

Parameter Default Supported Restrictions


Value Tokens
Global variables $R$N$M $M, $R, $G,$N, $F, $H, $A, $E, and $I are not
(Simulink Coder) $U allowed.
Global types $N$R$M_T $M, $R, $G,$N, $F, $H, $A, $E, and $I are not
(Simulink Coder) $U allowed.
Field name of $N$M $M, $N, $H, $R, $F, $G, $E, and $I are not
global types $A, $U allowed.
(Simulink Coder)
Subsystem $R$N$M$F $M, $R, $N, $F and $H are empty for Stateflow
methods (Simulink $H, $F, $U functions; $A, $G, $E, and $I are not
Coder) allowed.
Subsystem method rt$I$N$M $M, $N, $I, $U $R, $F, $H, $G, $E, and $A are not
arguments allowed.
(Simulink Coder)
Local temporary $N$M $M, $R, $N, $F, $H, $G, $E, and $I are not
variables (Simulink $A, $U allowed.
Coder)
Local block output rtb_$N$M $M, $N, $A, $U $R, $F, $H, $G, $E, and $I are not
variables (Simulink allowed.
Coder)
Constant macros $R$N$M $M, $R, $N, $U $F, $H, $A, $G, $E, and $I are not
(Simulink Coder) allowed.
Shared utilities $N$C $N, $C, $R, $U $C is required. $M, $F, $H, $A, $G,
identifier format $E, and $I are not allowed.
(Simulink Coder)
EMX array utility emx$M$N $M, $N,$R $C, $U, $F, $H, $A, $G, $E, and $I
functions identifier are not allowed.
format (Simulink
Coder)
EMX array types emxArray_ $M, $N,$R $C, $U, $F, $H, $A, $G, $E, and $I
identifier format $M$N are not allowed.
(Simulink Coder)

39-26
Identifier Format Control

Parameter Default Supported Restrictions


Value Tokens
Header files $R$E $R,$U,$E $C, $M, $N, $F, $H, $A, $G, and $I
are not allowed.
Source files $R$E $R,$U,$E $C, $M, $N, $F, $H, $A, $G, and $I
are not allowed.
Data files $R_data $R,$U $C, $M, $N, $F, $H, $A, $G, $E, and
$I are not allowed.

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.

Control Case with Token Decorators


On the Code Generation > Symbols pane, you can use token decorators to control the
case of generated identifiers. Place a decorator immediately after the target token and
enclose the decorator in square brackets [ ]. For example, you can set Global variables
to $R[uL]$N$M, which capitalizes the first letter of the model name and forces the
remaining characters in the model name to lowercase.

The table shows how to manipulate the expansion of the $R token for a model whose
name is modelName.

Desired Description Token and Decorator


Expansion
ModelName First letter of model name is $R[u]
uppercase. Remaining characters
are not modified.
Modelname First letter of model name is $R[uL]
uppercase. Remaining characters
are lowercase.

39-27
39 Code Appearance in Embedded Coder

Desired Description Token and Decorator


Expansion
MODELNAME All characters are uppercase. $R[U]
modelname All characters are lowercase. $R[L]
mODELNAME First letter of model name is $R[lU]
lowercase. Remaining characters
are uppercase.
modelName First letter of model name is $R[l]
lowercase. Remaining characters
are not modified.

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.

Control Formatting of Identifiers


This example shows how you can customize generated identifiers by specifying the
Identifier format control parameters on the Code Generation > Symbols pane in the
Configuration Parameters dialog box.

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

Control Name Mangling in Generated Identifiers


The position of the $M token in the Identifier format control parameter specification
determines the position of the name-mangling text in the generated identifiers. 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 “Identifier Format
Control” on page 39-22.

Name-Mangling Text Per Object


Object Type Source of Mangling Text
Block diagram Name of block diagram
Simulink block Simulink identifier (for details, see “Locate Diagram Components
Using Simulink Identifiers” (Simulink))
Simulink parameter Full name of parameter owner (model or block) and parameter
name
Simulink signal Signal name, full name of source block, and port number
Stateflow objects Complete path to Stateflow block and Stateflow computed name
(unique within chart)

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.

Minimize Name Mangling


The length of generated identifiers is limited by the Maximum identifier length
(Simulink Coder) parameter. When a name collision exists, the $M token is expanded to
the minimum number of characters required to avoid the collision. Other tokens are
expanded in the order listed in Identifier Format Tokens. If the Maximum identifier
length is not large enough to accommodate full expansions of the other tokens, partial
expansions are used. To avoid partial expansions, it is good practice to:

• 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

Avoid Identifier Name Collisions with Referenced Models


Within a model that uses referenced models, collisions between the names of the models
are not allowed. When generating code from a model that uses model referencing:

• 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.

Use Model Advisor to Detect Identifier Names Changed During


Code Generation
For a referenced model, if the following Configuration Parameters > Code Generation
> Symbols parameters have settings that do not contain a $R token (which represents
the name of the reference model), code generation prepends the $R token to the identifier
format.

• 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.

1 In the Simulink Editor, select Analysis > Model Advisor.

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

Maintain Traceability for Generated Identifiers


To verify your model, you can trace back and forth between generated identifiers and
corresponding entities within the model. To maintain traceability, it is important that
incremental revisions to a model have minimal impact on the identifier names that appear
in generated code. There are two ways to minimally impact the identifier names:

• 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

Exceptions to Identifier Formatting Conventions


There are some exceptions to the identifier formatting conventions described in
“Identifier Format Control” on page 39-22.

• 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:

• $C is specified without $N.


• The length of $N plus the length of the text that you specify exceeds the Maximum
identifier length. Code generation truncates $N and inserts an 8-character
checksum where you specified $C in the formatting scheme.

39-35
39 Code Appearance in Embedded Coder

Identifier Format Control Parameters Limitations


The following limitations apply to the Identifier format control parameters:

• 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

• The applicable format scheme is $R$F, and the longest $F is _derivatives,


which is 12 characters long. The model name can be up to 19 characters
without exceeding the default Maximum identifier length of 31.
• Local functions generated by S-functions or by add-on products such as DSP
System Toolbox that rely on S-functions
• Local variables generated by S-functions or by add-on products such as DSP
System Toolbox that rely on S-functions
• DW identifiers generated by S-functions in referenced models
• Fixed-point shared utility macros or shared utility functions
• Simulink rtm macros

• 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

• Header file guards, such as _RTW_HEADER_$(filename)_h_, which can


exceed the default Maximum identifier length of 31 given a filename such as
$R_private.h.
• Include file guards, such as _$R_COMMON_INCLUDES_.
• typedef guards, such as _CSCI_$R_CHARTSTRUCT_.
• In some situations, the following identifiers potentially can conflict with others.

• Model methods
• Reentrant model function arguments

39-36
Identifier Format Control Parameters Limitations

• Local functions generated by S-functions or by add-on products such as DSP


System Toolbox that rely on S-functions
• Local variables generated by S-functions or by add-on products such as DSP
System Toolbox that rely on S-functions
• Fixed-point shared utility macros or shared utility functions
• Include header guard macros
• The following external identifiers that are unknown to the Simulink software might
conflict with autogenerated identifiers.

• Identifiers defined in custom code


• Identifiers defined in custom header files
• Identifiers introduced through a non-ANSI C standard library
• Identifiers defined by custom TLC code
• Identifiers generated for simulation targets might exceed the Maximum identifier
length. Simulation targets include the model reference simulation target, the
accelerated simulation target, the RSim target, and the S-function target.
• Identifiers generated using a model name and bus object data type name, which are
both long names, might exceed the Maximum identifier length. For example, a
ground value variable name is generated as <model_name>_rtZ<bus_name>. If the
model_name and bus_name are close to the maximum identifier length, the name
exceeds the maximum identifier length.

39-37
39 Code Appearance in Embedded Coder

Control Code Style


In this section...
“Control Parentheses in Generated Code” on page 39-39
“Optimize Code by Reordering Commutable Operands” on page 39-41
“Suppress Generation of Default Cases for Unreachable Stateflow Switch Statements” on
page 39-42
“Replace Multiplication by Powers of Two with Signed Bitwise Shifts” on page 39-45
“Generate Code with Right Shifts on Signed Integers” on page 39-47
“Control Indentation Style in Generated Code” on page 39-48
“Control Cast Expressions in Generated Code” on page 39-50
“Control Newline Style in Generated Code” on page 39-54

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.

Control Parentheses in Generated Code


C code contains some syntactically required parentheses, and can contain additional
parentheses that change semantics by overriding default operator precedence. C code
can also contain optional parentheses that have no functional significance, but only
increase the readability of the code. Optional C parentheses vary between two stylistic
extremes:

• Include the minimum parentheses required by C syntax and precedence overrides so


that C precedence rules specify all semantics unless overridden by parentheses.
• Include the maximum parentheses that can exist without duplication so that C
precedence rules become irrelevant. Parentheses alone completely specify all
semantics.

Understanding code with minimum parentheses can require applying nonobvious


precedence rules. Maximum parentheses can hinder code reading by belaboring obvious
precedence rules. Various parenthesization standards exist that specify one or the other
extreme, or define an intermediate style useful to people who read code.

For more information on this parameter, see “Parentheses level”.

Control Use of Parentheses

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)

Optimize Code by Reordering Commutable Operands


This example shows how to reorder commutable operands to make expressions left-
recursive. This optimization improves code efficiency.

Example Model

To reorder commutable operands, create the following model and name it


operand_order. In this model, the output signal is the result of multiplying the signal
from Inport block In1 by the sum of the signals from Inport blocks In2 and In3.

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.

In the operand_order.c file, the operand_order_step function contains the following


code:
operand_order_Y.Out1 = operand_order_U.In1 * (operand_order_U.In2 +
operand_order_U.In3);

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.

Generate Code with Optimization

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.

In the operand_order.c file, the operand_order_step function contains the following


code:

operand_order_Y.Out1 = (operand_order_U.In2 + operand_order_U.In3) *


operand_order_U.In1;

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”.

Suppress Generation of Default Cases for Unreachable


Stateflow Switch Statements
This example shows how to specify whether to generate default cases for switch-case
statements in the code for Stateflow charts. Generated code that does not contain default
cases conserves ROM consumption and enables better code coverage because every
branch in the generated code is falsifiable.

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

Figures 1, 2, and 3 show relevant portions of the sldemo_fuelsys model, a closed-loop


system containing a plant and controller. The Air-fuel rate controller logic is a Stateflow
chart that specifies the different operation modes.

39-42
Control Code Style

Figure 1: Top-level model of the plant and controller

Figure 2: Fuel rate controller subsystem

39-43
39 Code Appearance in Embedded Coder

Figure 3: Fuel rate controller logic

Generate Code with Default Cases for Unreachable Stateflow Switch Statements

1 In the MATLAB Command Window, to open sldemo_fuelsys via rtwdemo_fuelsys


enter:

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;

Suppress Default Cases for Unreachable Stateflow Switch Statements

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”.

Replace Multiplication by Powers of Two with Signed Bitwise


Shifts
This example shows how to generate code that replaces multiplication by powers of two
with signed bitwise shifts. Code that contains bitwise shifts is more efficient than code
that contains multiplication by powers of two.

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.

Generate Code with Signed Bitwise Shifts


1 Open the Model Configuration Parameters dialog box and select the Code Style tab.
The Replace multiplications by powers of two with signed bitwise shifts
parameter is on by default.
2 Generate code for the model.

In the bitwise_multiplication.c file, the bitwise_multiplication step function


contains this code:
bitwise_multiplication_Y.Out1 = (int16_T)(bitwise_multiplication_U.In1 << 3);

The signed integer, bitwise_multiplication_U.In1, is shifted three bits to the left.

Generate Code with Multiplication by Powers of Two


1 Open the Model Configuration Parameters dialog box and select the Code Style tab.
2 Clear the Replace multiplications by powers of two with signed bitwise shifts
parameter.
3 Generate code for the model.

In the bitwise_multiplication.c file, the bitwise_multiplication step function


contains this code:
bitwise_multiplication_Y.Out1 = (int16_T)(bitwise_multiplication_U.In1 * 8);

The signed integer bitwise_multiplication_U.In1 is multiplied by 8.

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”.

Generate Code with Right Shifts on Signed Integers


This example shows how to control whether the generated code contains right shifts on
signed integers. Generated code that does not contain right shifts on signed integers first
casts the signed integers to unsigned integers, and then right shifts the unsigned
integers.

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.

Generate Code with Right Shifts on Signed Integers

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.

In the rightshift.c file, the rightshift_step function contains this code:


rightshift_Y.Out1 = (int16_T)(rightshift_U.In1 >> 3);

39-47
39 Code Appearance in Embedded Coder

The signed integer rightshift_U.In1 is shifted three bits to the right.

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.

In the rightshift.c file, the rightshift_step function contains this code:


rightshift_Y.Out1 = (int16_T)asr_s32(rightshift_U.In1, 3U);

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”.

Control Indentation Style in Generated Code


For code indentation, you can set the following parameters:

• Indent style controls the placement of braces in generated code.


• Indent size controls the number of characters per indent level in generated code (2–8
characters).

You can set Indent style to K&R or Allman style.

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;
}

Control Cast Expressions in Generated Code


You can choose how the code generator specifies data type casts in the generated code. In
the Configuration Parameters dialog box, select Code Generation > Code Style. From
the Casting modes drop-down list, three parameter options control how the code
generator casts data types.

• 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.

For more information, see “MISRA C Guidelines” on page 12-6.


• Explicit instructs the code generator to cast data type values explicitly when it
generates code. You can see how a value is stored, which tells you how much memory
space the code uses for the variable. The data type informs you how much precision is
possible in calculations involving the variable.

Open the example model rtwdemo_rtwecintro.

39-50
Control Code Style

Enable Nominal Casting Mode and Generate Code

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;

/* Sum: 'XRootX/Sum' incorporates:


* Constant: 'XRootX/INC'
* UnitDelay: 'XRootX/X'
*/
rtDWork.X++;

/* RelationalOperator: 'XRootX/RelOpt' incorporates:


* Constant: 'XRootX/LIMIT'
*/
rtb_equal_to_count = (rtDWork.X != 16);

/* Outputs for Triggered SubSystem: 'XRootX/Amplifier' incorporates:


* TriggerPort: 'XS1X/Trigger'

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;
}

rtPrevZCSigState.Amplifier_Trig_ZCE = (uint8_T)(rtb_equal_to_count ? (int32_T)


POS_ZCSIG : (int32_T)ZERO_ZCSIG);

/* End of Outputs for SubSystem: 'XRootX/Amplifier' */

/* Switch: 'XRootX/Switch' */
if (!rtb_equal_to_count) {
/* Update for UnitDelay: 'XRootX/X' incorporates:
* Constant: 'XRootX/RESET'
*/
rtDWork.X = 0U;
}

/* End of Switch: 'XRootX/Switch' */


}

Enable Standards Compliant Casting Mode and Generate Code

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;

/* Sum: '<Root>/Sum' incorporates:


* Constant: '<Root>/INC'
* UnitDelay: '<Root>/X'
*/
rtDWork.X++;

/* RelationalOperator: '<Root>/RelOpt' incorporates:


* Constant: '<Root>/LIMIT'
*/
rtb_equal_to_count = (boolean_T)(int32_T)((int32_T)rtDWork.X != (int32_T)16);

/* Outputs for Triggered SubSystem: '<Root>/Amplifier' incorporates:


* TriggerPort: '<S1>/Trigger'

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);

/* End of Outputs for SubSystem: '<Root>/Amplifier' */

/* Switch: '<Root>/Switch' */
if (!rtb_equal_to_count) {
/* Update for UnitDelay: '<Root>/X' incorporates:
* Constant: '<Root>/RESET'
*/
rtDWork.X = 0U;
}

/* End of Switch: '<Root>/Switch' */


}

Enable Explicit Casting Mode and Generate Code

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;

/* Sum: '<Root>/Sum' incorporates:


* Constant: '<Root>/INC'
* UnitDelay: '<Root>/X'
*/
rtDWork.X = (uint8_T)(1U + (uint32_T)(int32_T)rtDWork.X);

/* RelationalOperator: '<Root>/RelOpt' incorporates:


* Constant: '<Root>/LIMIT'
*/
rtb_equal_to_count = (boolean_T)((int32_T)rtDWork.X != 16);

/* Outputs for Triggered SubSystem: '<Root>/Amplifier' incorporates:


* TriggerPort: '<S1>/Trigger'
*/

39-53
39 Code Appearance in Embedded Coder

if (((int32_T)rtb_equal_to_count) && ((int32_T)((int32_T)


rtPrevZCSigState.Amplifier_Trig_ZCE != (int32_T)POS_ZCSIG))) {
/* Outport: '<Root>/Output' incorporates:
* Gain: '<S1>/Gain'
* Inport: '<Root>/Input'
*/
rtY.Output = rtU.Input << 1;
}

rtPrevZCSigState.Amplifier_Trig_ZCE = (uint8_T)(rtb_equal_to_count ? (int32_T)


POS_ZCSIG : (int32_T)ZERO_ZCSIG);

/* End of Outputs for SubSystem: '<Root>/Amplifier' */

/* Switch: '<Root>/Switch' */
if (!(int32_T)rtb_equal_to_count) {
/* Update for UnitDelay: '<Root>/X' incorporates:
* Constant: '<Root>/RESET'
*/
rtDWork.X = 0U;
}

/* End of Switch: '<Root>/Switch' */


}

Control Newline Style in Generated Code


In the generated code, the newline character differs according to the operating system
that the code is generated on. You can now customize the newline character irrespective
of the operating system. Set the style of the newline character by using the Newline
style parameter. Default is the default option. You can customize the newline character
irrespective of the operating system.

You can set Newline style to any of these options:

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

CR+LF (Carriage Return + Line Feed)

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

Customize Code Organization and Format


In this section...
“Custom File Processing Components” on page 39-56
“Custom File Processing Configuration” on page 39-57

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:

• Emits code to standard generated files---model.c or .cpp and model.h


• Produces files that are independent of model code
• Organize generated code into sections (such as includes, typedefs, functions, and
more). Your CFP template can emit code (for example, functions), directives (such as
#define or #include statements), or comments into each section.
• Generate custom file banners (comment sections) at the start and end of generated
code files and custom function banners that precede functions in the generated code.
• Generate code to call model functions, such as model_initialize, model_step,
and so on.
• Generate code to read and write model inputs and outputs.
• Generate a main program module.
• Obtain information about the model and the generated files from the model.

Custom File Processing Components


The custom file processing features are based on the following interrelated components:

• 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).

Custom File Processing Configuration


Customize generated code by specifying code and data templates on the Code
Generation > Templates pane:

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

Specify Templates For Code Generation


To use custom file processing features, create CGT files and CFP templates. These files
are based on default templates provided by the code generation software. Once you have
created your templates, you must integrate them into the code generation process.

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 options related to custom file processing are:

• 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

Code Generation Template (CGT) Files


Code Generation Template (CGT) files define the top-level organization and formatting of
generated source code and header files. CGT files have the following applications:

• Generation of custom banners (comments sections) in code files. See “Generate


Custom File and Function Banners” on page 39-89.
• Generation of custom code using a CFP template requires a CGT file. To use CFP
templates, you must understand the CGT file structure. In many cases, however, you
can use the default CGT file without modifying it.

Default CGT file


The code generation software provides a default CGT file, matlabroot/toolbox/rtw/
targets/ecoder/ert_code_template.cgt. Base your custom CGT files on the
default file.

CGT File Structure


A CGT file consists of one required section and four optional sections:

Code Insertion Section

(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.

File Banner Section

(Optional) This section contains comments and tokens you use in generating a custom file
banner.

Function Banner Section

(Optional) This section contains comments and tokens for use in generating a custom
function banner.

Shared Utility Function Banner Section

(Optional) This section contains comments and tokens for use in generating a custom
shared utility function banner.

File Trailer Section

(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.

Built-In Tokens and Sections


The following code extract shows the required code insertion section of the default CGT
file with the required built-in tokens.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Code insertion section (required)
%% These are required tokens. You can insert comments and other tokens in
%% between them, but do not change their order or remove them.

39-61
39 Code Appearance in Embedded Coder

%%
%<Includes>
%<Defines>
%<Types>
%<Enums>
%<Definitions>
%<Declarations>
%<Functions>

Note the following requirements for customizing a CGT file:

• Do not remove required built-in tokens.


• Built-in tokens must appear in the order shown because each successive section has
dependencies on previous sections.
• Only one token per line.
• Do not repeat tokens.
• You can add custom tokens and comments to the code insertion section as long as you
do not violate the previous requirements.

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

Built-In CGT Tokens and Corresponding Code Sections

Token and Section Description


Name
Includes #include directives section
Defines #define directives section
Types typedef section.Typedefs can depend on a previously defined
type
Enums Enumerated types section
Definitions Data definitions (for example, double x = 3.0;)
Declarations Data declarations (for example, extern double x;)
Functions C or C++ functions

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

Subsections Defined for Built-In Sections

Section Subsections Subsection Description


Includes N/A
Defines N/A
Types IntrinsicTypes Intrinsic typedef section. Intrinsic types depend
only on intrinsic C or C++ types.
Types PrimitiveTypedefs Primitive typedef section. Primitive typedefs
depend only on intrinsic C or C++ types and on
typedefs previously defined in the
IntrinsicTypes section.
Types UserTop You can place any type of code in this section,
including code that has dependencies on the
previous sections.
Types Typedefs typedef section. Typedefs can depend on
previously defined types
Enums N/A
Definitions N/A
Declarations N/A
Functions C or C++ functions
Functions CompilerErrors #error directives
Functions CompilerWarnings #warning directives
Functions Documentation Documentation (comment) section
Functions UserBottom You can place any code in this section.

Format Generated Code Files Using Templates


This example shows how to use code generation templates to add custom code banners,
rearrange data and functions, and insert additional code segments and documentation
into generated code files.

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

Custom File Processing (CFP) Templates


The files provided to support custom file processing are:

• matlabroot/rtw/c/tlc/mw/codetemplatelib.tlc: A TLC function library that


implements the code template API. codetemplatelib.tlc also provides the
comprehensive documentation of the API in the comments headers preceding each
function.
• matlabroot/toolbox/rtw/targets/ecoder/example_file_process.tlc: An
example custom file processing (CFP) template, which you should use as the starting
point for creating your own CFP templates. Guidelines and examples for creating a
CFP template are provided in “Generate Source and Header Files with a Custom File
Processing (CFP) Template” on page 39-73.
• TLC files supporting generation of single-rate and multirate main program modules
(see “Customizing Main Program Module Generation” on page 39-77).

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.

Custom File Processing (CFP) Template Structure


A custom file processing (CFP) template imposes a simple structure on the code
generation process. The template, a code generation template (CGT) file, partitions the
code generated for each file into a number of sections. These sections are summarized in
Built-In CGT Tokens and Corresponding Code Sections and Subsections Defined for Built-
In Sections.

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

LibSetSourceFileSection(fileH, section, tmpBuf)

where

• fileH is a file reference to a file being generated.

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.

Determine the section argument as follows:

• 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

Change the Organization of a Generated File


The files created during code generation are organized according to the general code
generation template. This template has the filename ert_code_template.cgt, and is
specified by default in Code Generation > Templates pane of the Configuration
Parameters dialog box.

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

This model shows how to define data storage class as part of


the diagram.
** Model Version: 1.299
** Model Author: The MathWorks, Inc. - Mon Nov 27 14:36:56 2000
**
** MODIFICATION HISTORY:
** Model at Code Generation: user - Fri Aug 19 12:47:36 2016
**
** Last Saved Modification: The MathWorks, Inc. - Sat Aug 06 14:37:49 2016
**
**
*******************************************************************************
**/

39-69
39 Code Appearance in Embedded Coder

Customize Generated File Names


The code generator creates model.* files during the code generation and build process.
When you generate C/C++ code for ERT-based models, you can customize the names of
the generated header, source, and data files. Custom file names enable you to:

• Comply with naming standards of the company or industry.


• Integrate with external code.

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.

1 Open any ERT-based model, for example, rtwdemo_dynamicio. In the Configuration


Parameters dialog box, change the System target file to ert.tlc.
2 On the Code Generation > Code Placement pane, select File packaging format
as Compact(with separate date file).
3 Specify custom file names by using the naming rules for these parameters:

• Header files: $R$E_header


• Source files: $R$E_source
• Data files: $R_data

$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:

Type of Token Specification Custom Text Generated File


File Name
Header $R$E header rtwdemo_dynami
file cio_header.h
Header $R$E header rtwdemo_dynami
file cio_private_he
ader.h
Source $R$E source rtwdemo_dynami
file cio_source.c
Header $R$E header rtwdemo_dynami
file cio_types_head
er.h

39-71
39 Code Appearance in Embedded Coder

Type of Token Specification Custom Text Generated File


File Name
Data file $R data rtwdemo_dynami
cio_data.c

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

Generate Source and Header Files with a Custom File


Processing (CFP) Template
In this section...
“Generate Code with a CFP Template” on page 39-73
“Analysis of the Example CFP Template and Generated Code” on page 39-75
“Generate a Custom Section” on page 39-78
“Custom Tokens” on page 39-80

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.

The example CFP template, matlabroot/toolbox/rtw/targets/ecoder/


example_file_process.tlc, demonstrates some of the capabilities of the code
template API, including

• Generation of simple source (.c or .cpp) and header (.h) files


• Use of buffers to generate file sections for includes, functions, and so on
• Generation of includes, defines, into the standard generated files (for example,
model.h)
• Generation of a main program module

Generate Code with a CFP Template


This section sets up a CFP template and configures a model to use the template in code
generation. The template generates (in addition to the standard model files) a source file
(timestwo.c or .cpp) and a header file (timestwo.h).

Follow the steps below to become acquainted with the use of CFP templates:

1 Copy the example CFP template, matlabroot/toolbox/rtw/targets/ecoder/


example_file_process.tlc, to a folder outside of the MATLAB folder structure
(that is, not under matlabroot). If the folder is not on the MATLAB path or the TLC
path, then add it to the MATLAB path. It is good practice to locate the CFP template
in the same folder as your system target file, which is on the TLC path.

39-73
39 Code Appearance in Embedded Coder

2 Rename the copied example_file_process.tlc to


test_example_file_process.tlc.
3 Open test_example_file_process.tlc into the MATLAB editor.
4 Uncomment the following line:

%% %assign ERTCustomFileTest = TLC_TRUE

It now reads:

%assign ERTCustomFileTest = TLC_TRUE

If ERTCustomFileTest is not assigned as shown, the CFP template is ignored in


code generation.
5 Save your changes to the file. Keep test_example_file_process.tlc open, so
you can refer to it later.
6 Open the rtwdemo_udt model.
7 Open the Simulink Model Explorer. Select the active configuration set of the model,
and open the Code Generation pane of the active configuration set.
8 On the Templates tab, in the File customization template field, specify
test_example_file_process.tlc. This is the file you previously edited and is
now the specified CFP template for your model.
9 On the General tab, select the Generate code only check box.
10 Click Apply.
11 In the model window, press Ctrl+B. During code generation, notice the following
message in the Diagnostic Viewer:

Warning: Overriding example ert_main.c!

This message is displayed because test_example_file_process.tlc generates


the main program module, overriding the default action of the ERT target. This is
explained in greater detail below.
12 The rtwdemo_udt model is configured to generate an HTML code generation report.
After code generation is complete, view the report.

Notice that the Generated Code list contains the following files:

• Under Main file, ert_main.c.


• Under Other files, timestwo.c and timestwo.h.

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.

Analysis of the Example CFP Template and Generated Code


This section examines excerpts from test_example_file_process.tlc and some of
the code it generates. Refer to the comments in matlabroot/rtw/c/tlc/mw/
codetemplatelib.tlc while reading the following discussion.

Generating Code Files

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.

File Sections and Buffers

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

/* Times two function */


real_T timestwofcn(real_T input) {
return (input * 2.0);
}

%closefile tmpBuf

%<LibSetSourceFileSection(cFile,"Functions",tmpBuf)>

These two sections generate the entire timestwo.c or .cpp file:

#include "rtwtypes.h"

/* Times two function */


FLOAT64 timestwofcn(FLOAT64 input)
{
return (input * 2.0);
}

Adding Code to Standard Generated Files

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

%assign pubName = LibGetMdlPubHdrBaseName()


%assign modelH = LibCreateSourceFile("Header", "Simulink", pubName)

%openfile tmpBuf

#define ACCELERATION 9.81

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.

Customizing Main Program Module Generation

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:

• bareboard_srmain.tlc: TLC code to generate an example single-rate main


program module for a bareboard target environment. Code is generated by a single
TLC function, FcnSingleTaskingMain.
• bareboard_mrmain.tlc: TLC code to generate a multirate main program module for
a bareboard target environment. Code is generated by a single TLC function,
FcnMultiTaskingMain.

In the example CFP template file matlabroot/toolbox/rtw/targets/ecoder/


example_file_process.tlc, the following code generates either a single- or
multitasking ert_main.c or .cpp module. The logic depends on information obtained
from the code template API calls LibIsSingleRateModel and LibIsSingleTasking:
%% Create a simple main. Files are located in MATLAB/rtw/c/tlc/mw.

%if LibIsSingleRateModel() || LibIsSingleTasking()


%include "bareboard_srmain.tlc"
%<FcnSingleTaskingMain()>
%else
%include "bareboard_mrmain.tlc"
%<FcnMultiTaskingMain()>
%endif

Note that bareboard_srmain.tlc and bareboard_mrmain.tlc use the code template


API to generate ert_main.c or .cpp.

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

Alternatively, you can implement a SelectCallback function for your target. A


SelectCallback function is a MATLAB function that is triggered during model loading,
and also when the user selects a target with the System Target File browser. Your
SelectCallback function should deselect and disable the Generate an example main
program option. This prevents the TLC variable GenerateSampleERTMain from being
set to TLC_TRUE.

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.

slConfigUISetVal(hDlg, hSrc, 'GenerateSampleERTMain', 'off');


slConfigUISetEnabled(hDlg, hSrc, 'GenerateSampleERTMain',0);

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.

Generate a Custom Section


You can define custom tokens on page 39-80 in a CGT file and direct generated code into
an associated built-in section. This feature gives you additional control over the
formatting of code within each built-in section. For example, you could add subsections to
built-in sections that do not already define subsections. Custom sections must be
associated with one of the built-in sections: Includes, Defines, Types, Enums,
Definitions, Declarations, or Functions. To create custom sections, you must

• 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

• Assemble code to be generated to the custom section into a buffer.


• Declare an association between the custom section and a built-in section, with the
code template API function LibAddSourceFileCustomSection.
• Emit code to the custom section with the code template API function
LibSetSourceFileCustomSection.

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:

%% Add a custom section to the model's C file model.c

%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)>

The LibAddSourceFileCustomSection function call declares an association between


the built-in section Includes and the custom section Myincludes. Myincludes is a
subsection of Includes. The LibSetSourceFileCustomSection function call directs
the code in the tmpBuf buffer to the Myincludes section of the generated file.
LibSetSourceFileCustomSection is syntactically identical to
LibSetSourceFileSection.

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

Comparison of a Template and Its Generated File


This figure shows part of a user-modified custom file processing (CFP) template and the
resulting generated code. The figure illustrates how you can use a template to:

• 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

Template and Generated File


Portion of
Example Template Corresponding Portion of Generated File
. .
. .
. .
/*#INCLUDES*/ (1) 26 /*#INCLUDES*/
%<Includes> 27 #include "rtwdemo_codetemplate.h"
/*#DEFINES*/ (2) None 28 #include "rtwdemo_codetemplate_private.h"
%<Defines> 29
#pragma string1 (3) 30 /*#DEFINES*/
31 #pragma string1
/*DEFINITIONS*/ (4) 32 /*DEFINITIONS*/
%<Definitions> 33 /* Block states (auto storage) */
#pragma string2 (5) 34 rtDWork;
%<Declarations> (6) 35
%<Functions> (7) 36 /* External output ( fed by signals with auto storage) */
37 rtY;
38
39 /* Real-time model */
40 rtM_;
41 *rtM = &rtM_;
42 #pragma string2
43
None 44 /* Model step function */
45 void rtwdemo_codetemplate_step(void)
46 {
47
48 /* local block i/o variables */
49
50 rtb_Switch;
51 rtb_RelOpt;
52
53 /* Sum: '' incorporates:
54 * UnitDelay: ''
55 */
56 rtb_Switch = ()(()rtDWork.X + 1U);
57
58 /* RelationalOperator: '' */
59 rtb_RelOpt = (rtb_Switch != 16U);
60
61 /* Outport: '' */
62 rtY.Out = rtb_RelOpt;
63
64 /* Switch: '' */
65 if(rtb_RelOpt) {
66 } else {
67 rtb_Switch = 0U;
68 }
69
70 /* Update for UnitDelay: '' */
71 rtDWork.X = rtb_Switch;
72
73 /* (no update code required) */
74 }
.
.
.

39-82
Comparison of a Template and Its Generated File

Mapping Template Specification to Code Generation

This part of the template... Generates in the file... Explanation


Line Description
(1) /*#INCLUDES*/ 26–28 An /*#INCLUDES*/ The code generator adds the C/C
%<Includes> comment, followed by ++ comment as a header, and
#include statements then interprets the %<Includes>
template symbol to list the
required #include statements in
the file. This code is first in this
section of the file because the
template entries are first.
(2) /*#DEFINES*/ 30 A /*#DEFINES*/ Next, the code generator places
%<Defines> comment, but no the comment as a header for
#define statements #define statements, but the file
does not need #define. No code
is added.
(3) #pragma string1 31 #pragma statements While the code generator
(5) #pragma string2 42 requires %<> delimiters for
template symbols, it can also
interpret C/C++ statements in
the template without delimiters.
In this case, the generator adds
the specified statements to the
code, following the order in which
the statements appear in the
template.
(4) /*DEFINITIONS*/ 32–41 /*DEFINITIONS*/ The code generator places the
%<Definitions> comment, followed by comment and definitions in the
definitions file between the #pragma
statements, according to the
order in the template. It also
inserts comments (lines 33 and
36) that are preset in the model's
Configuration Parameters dialog
box.

39-83
39 Code Appearance in Embedded Coder

This part of the template... Generates in the file... Explanation


Line Description
(6) %<Declarations> 43 No declarations The file needs no declarations, so
the code generator does not
generate declarations for this file.
The template does not have a
comment to provide a header.
Line 43 is left blank.
(7) %<Functions> 44–74 Functions Finally, the code generator adds
functions from the model, plus
comments that are preset in the
Configuration Parameters dialog
box. But it adds no comments as a
header for the functions, because
the template does not have one.
This code is last because the
template entry is last.

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

Code Template API Summary


Code Template API Functions summarizes the code template API. See the source code in
matlabroot/rtw/c/tlc/mw/codetemplatelib.tlc for detailed information on the
arguments, return values, and operation of these calls.

39-85
39 Code Appearance in Embedded Coder

Code Template API Functions

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

Generate Custom File and Function Banners


Using code generation template (CGT) files, you can specify custom file banners and
function banners for the generated code files. File banners are comment sections in the
header and trailer sections of a generated file. Function banners are comment sections
for each function in the generated code. Use these banners to add a company copyright
statement, specify a special version symbol for your configuration management system,
remove time stamps, and for many other purposes. These banners can contain characters,
which propagate to the generated code.

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.

The options for function and file banner generation are:

• “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

Create a Custom File and Function Banner Template


To customize a CGT file for custom banner generation, make a local copy of the default
code template and edit it, as follows:

1 Activate the configuration set that you want to work with.


2 Open the Code Generation pane of the active configuration set.
3 Click the Templates tab.
4 By default, the code template specified in the Code templates: Source file (*.c)
template and Code templates: Header file (*.h) template fields is matlabroot/
toolbox/rtw/targets/ecoder/ert_code_template.cgt.
5 If you want to use a different template as your starting point, click Browse to locate
and select a CGT file.
6 Click Edit button to open the CGT file into the MATLAB editor.
7 Save a local copy of the CGT file. Store the copy in a folder that is outside of the
MATLAB folder structure, but on the MATLAB path. If required, add the folder to the
MATLAB path.
8 If you intend to use the CGT file with a custom target, locate the CGT file in a folder
under your target root folder.
9 Rename your local copy of the CGT file. When you rename the CGT file, update the
associated Code templates: Source file (*.c) template or Code templates:
Header file (*.h) template field to match the new file name.
10 Edit and customize the local copy of the CGT file for banner generation, using the
information provided in “Customize a Code Generation Template (CGT) File for File
and Function Banner Generation” on page 39-91.
11 Save your changes to the CGT file.
12 Click Apply to update the configuration set.
13 Save your model.
14 Generate code. Examine the generated source and header files to confirm that they
contain the banners specified by the template or templates.

39-90
Generate Custom File and Function Banners

Customize a Code Generation Template (CGT) File for File and


Function Banner Generation
This section describes how to edit a CGT file for custom file and function banner
generation. For a description of CGT files, see “Code Generation Template (CGT) Files” on
page 39-60.

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.

CGT File Section Open Tag Close Tag


File Banner on page 39-93 <FileBanner> </FileBanner>
Function Banner on page 39- <FunctionBanner> </FunctionBanner>
95
Shared-utility Banner on page <SharedUtilityBanner> </SharedUtilityBanner>
39-95
File Trailer on page 39-96 <FileTrailer> </FileTrailer>

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.

The open tag syntax is as follows:

39-91
39 Code Appearance in Embedded Coder

<OpenTag style = “style_value” width = “num_width”>

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.

The built-in style options for the style attribute are:

• classic

/* single line comments */


/*
* multiple line comments
* second line
*/
• classic_cpp

// single line comments


//
// multiple line comments
// second line
//
• box

/**********************************************************/
/* banner contents */
/**********************************************************/
• box_cpp

////////////////////////////////////////////////////////////
// banner contents //
////////////////////////////////////////////////////////////
• open_box

/**********************************************************
* banner contents
**********************************************************/
• open_box_cpp

39-92
Generate Custom File and Function Banners

////////////////////////////////////////////////////////////
// banner contents
////////////////////////////////////////////////////////////
• doxygen

/** single line comments */

/**
* multiple line comments
* second line
*/
• doxygen_cpp

/// single line comments

///
/// multiple line comments
/// second line
///
• doxygen_qt

/*! single line comments */

/*!
* multiple line comments
* second line
*/
• doxygen_qt_cpp

//! single line comments

//!
//! 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>

Code generated for Simulink model %<ModelName>.

Model version : %<ModelVersion>


Simulink Coder version : %<RTWFileVersion>
TLC version : %<TLCVersion>
C/C++ source code generated on : %<SourceGeneratedOn>
%<CodeGenSettings>
</FileBanner>

Summary of Tokens for File Banner Generation

FileName Name of the generated file (for example,


"rtwdemo_udt.c").
FileType Either "source" or "header". Designates whether
generated file is a .c or .cpp file or an .h file.
FileTag Given file names file.c or .cpp and file.h; the file
tags are "file_c" and "file_h", respectively.
ModelName Name of generating model.
ModelVersion Version number of model.
RTWFileVersion Version number of model.rtw file.
RTWFileGeneratedOn Timestamp of model.rtw file.
TLCVersion Version of Target Language Compiler.
SourceGeneratedOn Timestamp of generated file.
CodeGenSettings Code generation settings for model: target language,
target selection, production hardware selection, test
hardware selection, code generation objectives (in priority
order), and Code Generation Advisor validation result.

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>

Summary of Tokens for Function Banner Generation


FunctionName Name of function
Arguments List of function arguments
ReturnType Return type of function
ModelName Name of generating model
FunctionDescription Short abstract about the function
GeneratedFor Full block path for the generated function
BlockDescription User input from the Block Description parameter of the
block properties dialog box. BlockDescription contains
an optional token attribute, style. The only valid value
forstyle is content_only, which is case-sensitive and
enclosed in double quotes. Use the content_only style
when you want to include only the block description
content that you entered in the block parameter dialog.
The syntax for the token attribute style is:

%<BlockDescription style = "content_only">

Shared Utility Function Banner

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>

Summary of Tokens for Shared Utility Function Banner Generation

FunctionName Name of function


Arguments List of function arguments
ReturnType Return type of function
FunctionDescription Short abstract about function

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

Template Symbols and Rules


In this section...
“Introduction” on page 39-97
“Template Symbol Groups” on page 39-98
“Template Symbols” on page 39-101
“Rules for Modifying or Creating a Template” on page 39-104

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

Template Symbol Groups


Symbol Group Symbol Names in This Group
Base (Parents) Declarations

Defines

Definitions

Documentation

Enums

Functions

Includes

Types
Declarations ExternalCalibrationLookup1D

ExternalCalibrationLookup2D

ExternalCalibrationScalar

ExternalVariableScalar
Defines LocalDefines

LocalMacros

39-98
Template Symbols and Rules

Symbol Group Symbol Names in This Group


Definitions FilescopeCalibrationLookup1D

FilescopeCalibrationLookup2D

FilescopeCalibrationScalar

FilescopeVariableScalar

GlobalCalibrationLookup1D

GlobalCalibrationLookup2D

GlobalCalibrationScalar

GlobalVariableScalar

39-99
39 Code Appearance in Embedded Coder

Symbol Group Symbol Names in This Group


Documentation Abstract

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

Symbol Name* Symbol Group Symbol Symbol Description (What


Scope the symbol puts in the
generated file)
Documentation Base N/A Comments about how to
interpret the generated files.
Enums Base File Enumerated data type
definitions.
ExternalCalibrationLookup1D Declarations External ***
ExternalCalibrationLookup2D Declarations External ***
ExternalCalibrationScalar Declarations External ***
ExternalVariableScalar Declarations External ***
FileName Documentation N/A Name of the generated file.
FilescopeCalibrationLookup1 Definitions File ***
D
FilescopeCalibrationLookup2 Definitions File ***
D
FilescopeCalibrationScalar Definitions File ***
FilescopeVariableScalar Definitions File ***
Functions Base File Generated function code.
GlobalCalibrationLookup1D Definitions Global ***
GlobalCalibrationLookup2D Definitions Global ***
GlobalCalibrationScalar Definitions Global ***
GlobalVariableScalar Definitions Global ***
History Documentation N/A User-supplied revision history
of the generated files. Placed in
the generated file based on the
Stateflow note, Simulink
annotation, or DocBlock on the
model.**
Includes Base File #include preprocessor
directives.

39-102
Template Symbols and Rules

Symbol Name* Symbol Group Symbol Symbol Description (What


Scope the symbol puts in the
generated file)
LastModifiedDate Documentation N/A Date when model was last
saved. From Last saved on
field on Model Properties dialog
box.
LastModifiedBy Documentation N/A User who last saved model.
From Last saved by field on
Model Properties dialog box.
LocalDefines Defines File #define preprocessor
directives from code-generation
data objects.
LocalMacros Defines File C/C++ macros local to the file.
ModelName Documentation N/A Name of the model.
ModelVersion Documentation N/A Version number of the Simulink
model. From Model version
field on Model Properties dialog
box.
ModifiedBy Documentation N/A Name of user who last modified
the model.
ModifiedComment Documentation N/A Comment user enters in the
Modified Comment field on
the Log Change dialog box. For
more information, see “Log
Comments History” (Simulink).
ModifiedHistory Documentation N/A Text from Model history field
on Model Properties dialog
box.**
Notes Documentation N/A User-supplied miscellaneous
notes about the model or
generated files. Placed in the
generated file based on the
Stateflow note, Simulink
annotation, or DocBlock on the
model.**

39-103
39 Code Appearance in Embedded Coder

Symbol Name* Symbol Group Symbol Symbol Description (What


Scope the symbol puts in the
generated file)
ToolVersion Documentation N/A A list of the versions of the
toolboxes used in generating
the code.
Types Base Data types of generated code.

* 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.

Rules for Modifying or Creating a Template


The following are the rules for creating an MPF template. “Comparison of a Template and
Its Generated File” on page 39-81 illustrates several of these rules.

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

5 Note that %% $Revision: 1.1.4.10.4.1 $ appears at the top of the MathWorks


supplied templates. This is for internal MathWorks use only. It does not need to be
placed on a user-defined template and does not show in a generated file.
6 Place a comment on the template between /* */ as in standard ANSI C6. This
results in /*comment*/ on the generated file.
7 Each MPF template must have all of the Base group symbols, in predefined order.
They are listed in “Template Symbol Groups” on page 39-98. Each symbol in the Base
group is a parent. For example, Declarations is a parent symbol.
8 Each symbol in a non-Base group is a child. For example, LocalMacros is a child.
9 Except for Documentation children, children must be placed after their parent,
before the next parent, and before the Functions symbol.
10 Documentation children can be located before or after their parent in any order
anywhere in the template.
11 If a non-Documentation child is missing from the template, the code generator places
the information associated with this child at its parent location in the generated file.
12 If a Documentation child is missing from the template, the code generator omits the
information associated with that child from the generated file.

6. ANSI is a registered trademark of the American National Standards Institute, Inc.

39-105
39 Code Appearance in Embedded Coder

Annotate Code for Justifying Polyspace Checks


With the Polyspace Code Prover product you can apply Polyspace verification to
Embedded Coder generated code. The software detects run-time errors in the generated
code and helps you to locate and fix model faults.

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.

32 /* Sum: '<Root>/Sum' incorporates:


33 * Inport: '<Root>/In1'
34 * Inport: '<Root>/In2'
35 */
36 qY_0 = sat_add_U.In1 + sat_add_U.In2;
37 if ((sat_add_U.In1 < 0) && ((sat_add_U.In2 < 0) && (qY_0 >= 0))) {
38 qY_0 = MIN_int32_T;
39 } else {
40 if ((sat_add_U.In1 > 0) && ((sat_add_U.In2 > 0) && (qY_0 <= 0))) {
41 qY_0 = MAX_int32_T;
42 }
43 }

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.

To justify overflows from operators that are legitimate, on the Configuration


Parameters > Code Generation > Comments pane:

39-106
See Also

• Under Overall control, select the Include comments check box.


• Under Auto generate comments, select the Operator annotations check box.

The code generator annotates generated code with comments for Polyspace. For example:

32 /* Sum: '<Root>/Sum' incorporates:


33 * Inport: '<Root>/In1'
34 * Inport: '<Root>/In2'
35 */
36 qY_0 = sat_add_U.In1 +/*MW:OvOk*/ sat_add_U.In2;

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

Enhance Readability of Code for Flow Charts


In this section...
“Appearance of Generated Code for Flow Charts” on page 39-108
“Convert If-Elseif-Else Code to Switch-Case Statements” on page 39-111
“Example of Converting Code to Switch-Case Statements” on page 39-113

Appearance of Generated Code for Flow Charts


If you have an Embedded Coder license and you generate code for models that include
Stateflow objects, the code from a flow chart resembles the samples that follow.

The following characteristics apply:

• By default, the generated code uses if-elseif-else statements to represent


switch patterns. To convert the code to use switch-case statements, see “Convert
If-Elseif-Else Code to Switch-Case Statements” on page 39-111.
• By default, variables that appear in the flow chart do not retain their names in the
generated code. Modified identifiers make sure that no naming conflicts occur.
• Traceability comments for the transitions appear between each set of /* and */
markers. To learn more about traceability, see “Trace Stateflow Elements in Generated
Code” on page 64-13.

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;
}
}

Sample Code for a Decision Logic Pattern

39-109
39 Code Appearance in Embedded Coder

for (sf_i = 0; sf_i < 10; sf_i++) {


/* Transition: '<S1>:40' */
/* Transition: '<S1>:41' */
modelname_B.y = modelname_B.y +
modelname_U.In1;

/* Transition: '<S1>:39' */
}

Sample Code for an Iterative Loop Pattern

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;
}
}

Sample Code for a Switch Pattern

Convert If-Elseif-Else Code to Switch-Case Statements


When you generate code for embedded real-time targets, you can choose to convert if-
elseif-else code to switch-case statements. This conversion can enhance
readability of the code. For example, when a flow chart contains a long list of conditions,
the switch-case structure:

• Reduces the use of parentheses and braces


• Minimizes repetition in the generated code

How to Convert If-Elseif-Else Code to Switch-Case Statements

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

Step Task Reference


1 Verify that your flow chart follows the “Verify the Contents of the Flow Chart”
rules for conversion. on page 39-116
2 Enable the conversion. “Enable the Conversion” on page 39-
116
3 Generate code for your model. “Generate Code for Your Model” on
page 39-117
4 Troubleshoot the generated code. “Troubleshoot the Generated Code” on
page 39-117
• If you see switch-case statements
for your flow chart, you can stop.
• If you see if-elseif-else
statements for your flow chart,
update the chart and repeat the
previous step.

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.

Construct Rules to Follow


Flow chart Must have two or more unique conditions, in addition to a default.

For more information, see “How the Conversion Handles Duplicate


Conditions” on page 39-113.
Each condition Must test equality only.
Must use the same variable or expression for the LHS.

Note You can reverse the LHS and RHS.


Each LHS Must be a single variable or expression.
Cannot be a constant.
Must have an integer or enumerated data type.

39-112
Enhance Readability of Code for Flow Charts

Construct Rules to Follow


Cannot have any side effects on simulation.

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.

How the Conversion Handles Duplicate Conditions

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.

Example of Generated Code Code After Conversion


if (x == 1) { switch (x) {
block1 case 1:
} else if (x == 2) { block1; break;
block2 case 2:
} else if (x == 1) { // duplicate block2; break;
block3 case 3:
} else if (x == 3) { block4; break;
block4 default:
} else if (x == 1) { // duplicate block6; break;
block5 }
} else {
block6
}
if (x == 1) { No change, because only one
block1 unique condition exists
} else if (x == 1) { // duplicate
block2
} else {
block3
}

Example of Converting Code to Switch-Case Statements


Suppose that you have the following model with a single chart.

39-113
39 Code Appearance in Embedded Coder

The chart contains a flow chart and four MATLAB functions:

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

MATLAB Function Code


stop function stop
%#codegen
coder.extrinsic('disp');
disp('Not moving.')

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:

classdef TrafficLights < Simulink.IntEnumType


enumeration
RED(0)
YELLOW(5)
GREEN(10)
end
end

For more information, see “Define Enumerated Data Types” (Stateflow).

39-115
39 Code Appearance in Embedded Coder

Verify the Contents of the Flow Chart

Check that the flow chart in your chart follows the rules in “Rules of Conversion” on page
39-112.

Construct How the Construct Follows the Rules


Flow chart Two unique conditions exist, in addition to the default:

• [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:

• Contains a single expression


• Is the output of a function call and therefore not a constant
• Is of enumerated type TrafficLights, which you define in
TrafficLights.m on the MATLAB path (see “Define
Enumerated Data Types” (Stateflow))
• Uses a function call that does not have side effects
Each RHS Each RHS:

• Is an enumerated value and therefore a constant


• Is of enumerated type TrafficLights

Enable the Conversion

1 Open the Model Configuration Parameters dialog box.


2 In the Code Generation pane, select ert.tlc for the System target file.

This step specifies an ERT-based target for your model.


3 In the Code Generation > Code Style pane, select the Convert if-elseif-else
patterns to switch-case statements check box.

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:

• Flow charts in all charts of a model


• MATLAB functions in all charts of a model
• All MATLAB Function blocks in that model

Generate Code for Your Model

In the model, select Code > C/C++ Code > Build Model to generate source code from
the model.

Troubleshoot the Generated Code

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:

if (ifelse_using_enums_U.In1 < 20.0) {


....
} else if ((ifelse_using_enums_U.In1 >= 20.0) &&
(ifelse_using_enums_U.In1 < 25.0)) {
....

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.

Change the Inlining Property for the Function

If you do not want to modify your flow chart, change the inlining property for the function
light:

1 Right-click the function box for light and select Properties.

The properties dialog box appears.


2 For Function Inline Option, select Function.

39-118
Enhance Readability of Code for Flow Charts

3 Click OK to close the dialog box.

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:

• The code reduces the use of parentheses and braces.


• The LHS expression ifelse_using_enums_light(ifelse_using_enums_U.In1)
appears only once, minimizing repetition in the code.

Modify the Flow Chart to Ensure Switch-Case Statements

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.

The chart should now look something like this:

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

Generate Inlined Subsystem Code


You can configure a nonvirtual subsystem to inline the subsystem code with the model
code. In the Subsystem Parameters dialog box, the Function packaging parameter
specifies the format of the subsystem’s generated code. This parameter has four settings:
Auto, Inline, Nonreusable function, and Reusable function. The code
generator can generate inlined code for the Auto or Inline settings.

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.

Configure Subsystem to Inline Code


To configure your subsystem for inlining:
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 Click the Code Generation tab and select Auto or Inline from the Function
packaging parameter.
4 Click Apply and close the dialog box.

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

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.

• If a noninlined S-function calls a function-call subsystem, the code generator ignores


the Inline setting. Because noninlined S-functions use function pointers to make
function calls, the code generator must generate a function with all arguments
present.
• In a feedback loop involving function-call subsystems, the code generator generates a
function instead of inlined code for one of the subsystems. Based on the internal,
sorted order of the subsystems, the code generator selects which subsystem to
generate a function.
• If an S-function, an Async Interrupt, or a Task Sync block with the option
SS_OPTION_FORCE_NONINLINED_FCNCALL set to TRUE calls a subsystem, the code
generator generates a function instead of inlined code for the subsystem. The VxWorks
block library (vxlib1), contains the user-defined Async Interrupt and Task Sync
blocks.7

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)

7. VxWorks is a registered trademark of Wind River Systems, Inc.

39-123
40

Code Replacement in Simulink


Coder

• “What Is Code Replacement?” on page 40-2


• “Choose a Code Replacement Library” on page 40-8
• “Replace Code Generated from Simulink Models” on page 40-10
40 Code Replacement in Simulink Coder

What Is Code Replacement?


Code replacement is a technique to change the code that the code generator produces for
functions and operators to meet application code requirements. For example, you can
replace generated code to meet requirements such as:

• 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:

• Installed support packages.


• System target file, language, standard math library, and device vendor configuration.
• Whether you have created and registered libraries, using the Embedded Coder
product.

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.

Code Replacement Libraries


A code replacement library consists of one or more code replacement tables that specify
application-specific implementations of functions and operators. For example, a library for

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.

Table Entry Description


Component
Conceptual Identifies the table entry and contains match criteria for the code
representation generator. Consists of:

• Function name or a key. The function name identifies most


functions. For operators and some functions, a series of
characters, called a key identifies a function or operator. For
example, function name 'cos' and operator key
'RTW_OP_ADD'.
• Conceptual arguments that observe code generator naming
('y1', 'u1', 'u2', ...), with corresponding I/O types (output or
input) and data types.
• Other attributes, such as an algorithm, fixed-point saturation,
and rounding modes, which identify matching criteria for the
function or operator.

40-3
40 Code Replacement in Simulink Coder

Table Entry Description


Component
Implementation Specifies replacement code. Consists of:
representation
• Function name. For example, 'cos_dbl' or 'u8_add_u8_u8'.
• Implementation arguments, with corresponding I/O types
(output or input) and data types.
• Parameters that provide additional implementation details, such
as header and source file names and paths of build resources.
Priority Defines the entry priority relative to other entries in the table. The
value can range from 0 to 100, with 0 being the highest priority. If
multiple entries have the same priority, the code generator uses the
first match with that priority.

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.

Code Replacement Terminology


Term Definition
Cache hit A code replacement entry for a function or operator,
defined in the specified code replacement library,
for which the code generator finds a match.
Cache miss A conceptual representation of a function or
operator for which the code generator does not find
a match.

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:

• Function or operator name or key


• Conceptual arguments with type, dimension, and
complexity specification for inputs and output
• Attributes, such as an algorithm and fixed-point
saturation and rounding modes
Implementation argument Represents an input or output argument for a C or
C++ replacement function. Implementation
arguments observe C/C++ name and data type
specifications.
Implementation representation Specifies C or C++ replacement function prototype.
Consists of:

• Function name (for example, 'cos_dbl' or


'u8_add_u8_u8')
• Implementation arguments specifying type, type
qualifiers, and complexity for the function inputs
and output
• Parameters that provide build information, such
as header and source file names and paths of
build resources and compile and link flags
Key Identifies a function or operator that is being
replaced. A function name or key appears in the
conceptual representation of a code replacement
entry. The key RTW_OP_ADD identifies the addition
operator.

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 Limitations


Code replacement verification — It is possible that code replacement behaves differently
than you expect. For example, data types that you observe in code generator input might
not match what the code generator uses as intermediate data types during an operation.
Verify code replacements by examining generated code.

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

Choose a Code Replacement Library


In this section...
“About Choosing a Code Replacement Library” on page 40-8
“Explore Available Code Replacement Libraries” on page 40-8
“Explore Code Replacement Library Contents” on page 40-8

About Choosing a Code Replacement Library


By default, the code generator does not use a code replacement library.

If you are considering using a code replacement library:

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.

Explore Available Code Replacement Libraries


Select the “Code replacement library” (Simulink Coder) to use for code generation from
the Configuration Parameters > Code Generation > Interface pane (Simulink
Coder). To view a description of a library, select and hover your cursor over the library
name. A tooltip describes the library and lists the tables that it contains. The tooltip lists
the tables in the order that the code generator searches for a function or operator match.

Explore Code Replacement Library Contents


Use the Code Replacement Viewer to explore the content of a code replacement library.

1 At the command prompt, type crviewer.

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

Replace Code Generated from Simulink Models


This example shows how to replace generated code, using a code replacement library.
Code replacement is a technique you can use to change the code that the code generator
produces for functions and operators to meet application code requirements.

Prepare for Code Replacement

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.

To install MathWorks products, see the MATLAB installation documentation. If you


have installed MATLAB and want to see which other MathWorks products are
installed, in the Command Window, enter ver .
2 Identify an existing or create a Simulink model for which you want the code
generator to replace code.

Choose a Code Replacement Library

If you are not sure which library to use, explore the available libraries.

Configure Code Generator To Use Code Replacement Library

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 >


Interface pane, select a library for the “Code replacement library” (Simulink
Coder) parameter.
• Set the CodeReplacementLibrary parameter at the command line or
programmatically.
2 Configure the code generator to produce code only (not build an executable) so you
can verify your code replacements before building an executable. 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

Include Code Replacement Information In Code Generation Report

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.

1 Configure the code generator to generate a report. In the Configuration Parameters


dialog box, on the Code Generation > Report pane, select “Create code generation
report” (Simulink Coder). Consider having the report open automatically. Select
“Open report automatically” (Simulink Coder).
2 Include the code replacement section in the report. Select “Summarize which blocks
triggered code replacements” (Simulink Coder).

Generate Replacement Code

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

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

Code Replacement for Simulink


Models in Embedded Coder

• “What Is Code Replacement?” on page 41-2


• “Choose a Code Replacement Library” on page 41-8
• “Replace Code Generated from Simulink Models” on page 41-10
41 Code Replacement for Simulink Models in Embedded Coder

What Is Code Replacement?


Code replacement is a technique to change the code that the code generator produces for
functions and operators to meet application code requirements. For example, you can
replace generated code to meet requirements such as:

• 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:

• Installed support packages.


• System target file, language, standard math library, and device vendor configuration.
• Whether you have created and registered libraries, using the Embedded Coder
product.

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.

Code Replacement Libraries


A code replacement library consists of one or more code replacement tables that specify
application-specific implementations of functions and operators. For example, a library for

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.

Table Entry Description


Component
Conceptual Identifies the table entry and contains match criteria for the code
representation generator. Consists of:

• Function name or a key. The function name identifies most


functions. For operators and some functions, a series of
characters, called a key identifies a function or operator. For
example, function name 'cos' and operator key
'RTW_OP_ADD'.
• Conceptual arguments that observe code generator naming
('y1', 'u1', 'u2', ...), with corresponding I/O types (output or
input) and data types.
• Other attributes, such as an algorithm, fixed-point saturation,
and rounding modes, which identify matching criteria for the
function or operator.

41-3
41 Code Replacement for Simulink Models in Embedded Coder

Table Entry Description


Component
Implementation Specifies replacement code. Consists of:
representation
• Function name. For example, 'cos_dbl' or 'u8_add_u8_u8'.
• Implementation arguments, with corresponding I/O types
(output or input) and data types.
• Parameters that provide additional implementation details, such
as header and source file names and paths of build resources.
Priority Defines the entry priority relative to other entries in the table. The
value can range from 0 to 100, with 0 being the highest priority. If
multiple entries have the same priority, the code generator uses the
first match with that priority.

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.

Code Replacement Terminology


Term Definition
Cache hit A code replacement entry for a function or operator,
defined in the specified code replacement library,
for which the code generator finds a match.
Cache miss A conceptual representation of a function or
operator for which the code generator does not find
a match.

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:

• Function or operator name or key


• Conceptual arguments with type, dimension, and
complexity specification for inputs and output
• Attributes, such as an algorithm and fixed-point
saturation and rounding modes
Implementation argument Represents an input or output argument for a C or
C++ replacement function. Implementation
arguments observe C/C++ name and data type
specifications.
Implementation representation Specifies C or C++ replacement function prototype.
Consists of:

• Function name (for example, 'cos_dbl' or


'u8_add_u8_u8')
• Implementation arguments specifying type, type
qualifiers, and complexity for the function inputs
and output
• Parameters that provide build information, such
as header and source file names and paths of
build resources and compile and link flags
Key Identifies a function or operator that is being
replaced. A function name or key appears in the
conceptual representation of a code replacement
entry. The key RTW_OP_ADD identifies the addition
operator.

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 Limitations


Code replacement verification — It is possible that code replacement behaves differently
than you expect. For example, data types that you observe in code generator input might
not match what the code generator uses as intermediate data types during an operation.
Verify code replacements by examining generated code.

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

Choose a Code Replacement Library


In this section...
“About Choosing a Code Replacement Library” on page 41-8
“Explore Available Code Replacement Libraries” on page 41-8
“Explore Code Replacement Library Contents” on page 41-8

About Choosing a Code Replacement Library


By default, the code generator does not use a code replacement library.

If you are considering using a code replacement library:

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.

Explore Available Code Replacement Libraries


Select the “Code replacement library” (Simulink Coder) to use for code generation from
the Configuration Parameters > Code Generation > Interface pane (Simulink
Coder). To view a description of a library, select and hover your cursor over the library
name. A tooltip describes the library and lists the tables that it contains. The tooltip lists
the tables in the order that the code generator searches for a function or operator match.

Explore Code Replacement Library Contents


Use the Code Replacement Viewer to explore the content of a code replacement library.

1 At the command prompt, type crviewer.

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

Replace Code Generated from Simulink Models


This example shows how to replace generated code, using a code replacement library.
Code replacement is a technique you can use to change the code that the code generator
produces for functions and operators to meet application code requirements.

Prepare for Code Replacement

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.

To install MathWorks products, see the MATLAB installation documentation. If you


have installed MATLAB and want to see which other MathWorks products are
installed, in the Command Window, enter ver .
2 Identify an existing or create a Simulink model for which you want the code
generator to replace code.

Choose a Code Replacement Library

If you are not sure which library to use, explore the available libraries.

Configure Code Generator To Use Code Replacement Library

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 >


Interface pane, select a library for the “Code replacement library” (Simulink
Coder) parameter.
• Set the CodeReplacementLibrary parameter at the command line or
programmatically.
2 Configure the code generator to produce code only (not build an executable) so you
can verify your code replacements before building an executable. 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

Include Code Replacement Information In Code Generation Report

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.

1 Configure the code generator to generate a report. In the Configuration Parameters


dialog box, on the Code Generation > Report pane, select “Create code generation
report” (Simulink Coder). Consider having the report open automatically. Select
“Open report automatically” (Simulink Coder).
2 Include the code replacement section in the report. Select “Summarize which blocks
triggered code replacements” (Simulink Coder).

Generate Replacement Code

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

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

External Code Integration in


Simulink Coder

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.

For guidance on choosing an approach based on your application, see “Choose an


External Code Integration Workflow” (Simulink Coder) .

• “What Is External Code Integration?” on page 42-3


• “Choose an External Code Integration Workflow” on page 42-4
• “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
• “Apply Function and Operator Code Replacements” on page 42-41
• “Build Integrated Code Within the Simulink Environment” on page 42-42
• “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 External Code Integration in Simulink Coder

• “Build Integrated Code Outside the Simulink Environment” on page 42-83


• “Exchange Data Between External C/C++ Code and Simulink Model or Generated
Code” on page 42-90
• “Exchange Data Between External Calling Code and Generated Code” on page 42-102
• “Generate Code That Matches Appearance of External Code” on page 42-106

42-2
What Is External Code Integration?

What Is External Code Integration?


Software projects typically involve combining code from multiple sources. A typical
system structure for a code generation application consists of a framework that combines
code from multiple sources, including external code and code generated from Simulink
models.

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

Choose an External Code Integration Workflow


In this section...
“Choose a Software Execution Framework” on page 42-4
“Evaluate Characteristics of External Code” on page 42-7
“Identify Integration Requirements” on page 42-8
“Choose a Workflow” on page 42-10

Completing these tasks helps you choose external code integration workflows and tooling
that align with your project.

Task Action More Information


1 Partition your application, map “Design Models for Generated
algorithms to components, and identify Embedded Code Deployment” on page
integration points. 1-2
2 Determine whether you can rely on “Choose a Software Execution
scheduling code that the code generator Framework” on page 42-4
produces, or whether you must integrate
generated code with scheduling
mechanisms that are specific to your
run-time environment.
3 Evaluate the characteristics of the “Evaluate Characteristics of External
external code that you are importing or Code” on page 42-7
to which you are exporting generated
code.
4 Identify integration requirements, which “Identify Integration Requirements” on
assists with choosing optimal tooling for page 42-8
your integration.
5 Based on the results of tasks 1–4, choose “Choose a Workflow” on page 42-10
a workflow.

Choose a Software Execution Framework


The code generator supports two types of software execution frameworks—single top
model and multiple top-level, as described in “Design Models for Generated Embedded

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.

• Single top model

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.

• Single top model or multiple top-level models

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.

Based on goals and requirements, external code integration is characterized in several


ways, requiring different workflows and integration tooling:

• Import existing external code into generated 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

• Export generated code for inclusion in external code base.

• Generate component source code for export.


• Generate shared library for export.

Next, see “Evaluate Characteristics of External Code” on page 42-7.

Evaluate Characteristics of External Code


Before choosing an external integration workflow, evaluate these characteristics of the
external code. To interface with external code, generated C or C++ code handles one or
more of the external code characteristics. An understanding of these characteristics and
your requirements for modeling, simulation, and code generation helps you choose the
optimal workflow for your integration scenario. (See “Identify Integration Requirements”
on page 42-8.)

Characteristic What to Consider


Hardware Is the external code hardware-dependent? Utility functions, lookup
dependency tables, and filters are examples of hardware-independent code.

Device drivers interact directly with hardware. They depend on


characteristics of the hardware. For example, a device driver for an
analog-to-digital converter initializes, reads data from, and writes
data to hardware registers. Hardware differences and dependencies
concern data type size, endianess, shift operations, compiler
directives, and optimized function and operator support. Other code
interfaces with device drivers by using an API and data mapped to
specific memory addresses. Typically, simulation on a development
computer is not possible. Reading from and writing to a register
during simulation on a development computer produces unexpected
and unwanted results.
Reusable Is the external code a reusable software module? Examples include
utility functions, lookup tables, filters, specialized integrators, and
proportional-integral-derivative (PID) control modules.

42-7
42 External Code Integration in Simulink Coder

Characteristic What to Consider


Dependency on Does the external code require persistent data? For example, a call
data persistence to a first order filter function uses the output of the previous call to
between function the function to calculate a new output value. You have the option of
calls defining the data as global or using shared memory outside the
context of the function.
Data typing and How complex is the data that the external code uses? What does the
interface data interface look like? It consists of arguments, a return value,
global variables, and access functions. What data types does the
code use? Are the types limited to basic ANSI C integers, floating-
point types, arrays of integers or floating-point types, and pointers
to these types? Does the interface include structures or pointers to
structures?
Fixed-point code Is the external code designed to run on integer-only processors? If
yes, the code exchanges and uses data represented as integers only.
Data can be associated with fixed-point scaling or offsets.
External resource Does the external code use data, functions, or macros defined
dependencies outside the scope of the code? For example, the function can use a
standard ANSI function, a shared library, or predefined constants.
In these cases, you must inform the compiler and linker of the paths
and file names of the external resources.
External solver Are you using the external function for advanced development or
required rapid prototyping to describe a system with a continuous transfer
function or a set of differential equations? If yes, the external code
relies on an external solver.

Next, see “Identify Integration Requirements” on page 42-8.

Identify Integration Requirements


Before choosing an external integration workflow, review these integration requirements.
An understanding of these requirements and the characteristics of your external code
helps you choose the optimal workflow for your integration scenario. (See “Evaluate
Characteristics of External Code” on page 42-7.)

42-8
Choose an External Code Integration Workflow

Requirement What to Consider


Effort What level of effort is planned for the integration project—low,
medium, or high?
Learning effort What is the programming experience of assigned project resources?
How much experience do assigned resources have with Simulink
and MathWorks C/C++ code generation products?
Simulation and Do you want to take advantage of Model-Based Design? To take full
code generation advantage of Model-Based Design, convert code to modeling
behaviors elements, which you can then use in the Simulink and Stateflow
simulation environment. Then, simulate and generate code for the
integrated component. Use software-in-the-loop (SIL) or processor-
in-the-loop (PIL) testing to verify whether algorithm behavior is the
same in both environments.
Data interface and • Does your model or generated code need to exchange data with
typing the external function? If so, map inputs, outputs, and parameters
to the external function interface. Typical function interfaces
involve function arguments and return values, global variables,
and access functions, such as getRPM.
• Do you want to represent arrays, structures, or enumerated
types? In the Simulink environment, you can represent these
types as vectors, buses, and IntEnum, respectively.
• Is fixed-point support required? If you use the Simulink fixed-
point interface, you can scale and specify offsets.
• Does the external code use company-specific data types? If yes
and you have Embedded Coder software, create alias types to
represent those external types. The code generator uses the
alias types in the code that it produces. For example, once
defined, you can specify an alias type in a function prototype, for
a temporary variable, or for block output.
• Does the code exchange data with shared memory? If yes, define
and use memory sections.
Direct function call Do you want to call C external code directly from a model? You can
choose from mechanisms, such as the Legacy Code Tool, Stateflow
external code interface and chart action language, and the MATLAB
Function block.

42-9
42 External Code Integration in Simulink Coder

Requirement What to Consider


Insertion of Do you want to control the placement of external code within
external code into generated code? Do you want to insert code into generated entry-
generated code point functions? You can place code within generated code by using
model configuration parameters or custom code blocks.
Code generation Do you want to optimize the code that the code generator produces?
optimization If so, you can configure the model for the code generator to
support optimize the code it produces based on application objectives, such
as execution, ROM, and RAM efficiency. You also have the option of
using code replacement libraries.
Files required Do you want to minimize the number of files that you maintain?
Some external code integration tools require that you maintain
separate files for defining simulation and code generation.

Next, see “Choose a Workflow” on page 42-10.

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

Call Reusable External Algorithm Code for Simulation


and Code Generation
Code reuse offers business and technological advantages. From a business perspective,
code reuse saves time and resources. From a technological perspective, code reuse
promotes consistency and reduces memory requirements. Other considerations include:

• Modularizing an application
• Reusing an optimized algorithm
• Interfacing with a predefined dataset
• Developing application variants

Examples of reusable hardware-independent algorithmic code to consider importing into


the Simulink environment for simulation and code generation include:

• 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.

Task Action More Information


1 Review your assessment of external “Choose an External Code Integration
code characteristics and integration Workflow” on page 42-4
requirements.
2 Based on the programming “Choose an Integration Approach” on page
language of the external code, 42-14
choose an integration approach to
add the external code to a Simulink
model.

42-13
42 External Code Integration in Simulink Coder

Task Action More Information


3 Verify algorithm behavior and “Simulation” (Simulink)
performance by simulating the
model.
4 Define the representation of model “Exchange Data Between External C/C++
data for code generation. Code and Simulink Model or Generated
Code” on page 42-90
5 Configure the model for code “Generate Code That Matches Appearance
generation. of External Code” on page 42-106 and
“Model Configuration”
6 Generate code and a code “Code Generation”
generation report.
7 Review the generated code interface “Analyze the Generated Code Interface” on
and static code metrics. page 38-19 and “Static Code Metrics” on
page 38-33
8 Build an executable program from “Build Integrated Code Within the Simulink
the model. Environment” on page 42-42
9 Verify that executable program “Numerical Equivalence Testing”
behaves as expected.
10 Verify that executable program “Code Execution Profiling”
performs as expected.

Choose an Integration Approach


Several approaches are available for integrating reusable algorithmic code into the
Simulink environment for code generation. Some approaches integrate external code
directly. Other approaches convert the external code to Simulink or Stateflow modeling
elements for simulation, and later for code generation from the modeled design. The
integration approach that you choose depends on:

• Programming language of the external code — MATLAB, C, C++, or Fortran


• Your programming language experience and preference
• Performance requirements
• Whether the algorithm must model continuous time dynamics or you are integrating
the algorithm into an application that uses discrete and continuous time

42-14
Call Reusable External Algorithm Code for Simulation and Code Generation

• Whether you want to take advantage of Model-Based Design


• Level of control required over the code that the code generator produces

To choose an approach for a reusable algorithm, see the subsection that matches the
programming language of your external algorithm code.

• “Integration Approaches for External MATLAB Code” on page 42-15


• “Integration Approaches for External C or C++ Code” on page 42-18
• “Integration Approaches for External Fortran Code” on page 42-24

Integration Approaches for External MATLAB 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

Condition or Action More Information


Requirement
1 The algorithm must Write a MATLAB S-function • “MATLAB S-Functions” (Simulink)
model continuous state and, for generating code, a • “Write S-Function and TLC Files By
dynamics. corresponding TLC file for Hand” on page 11-67
the algorithm. Add the S-
function to your model. • “Target Language Compiler”
(Simulink Coder)

42-16
Call Reusable External Algorithm Code for Simulation and Code Generation

Condition or Action More Information


Requirement
2 External code complies Add a MATLAB Function • “Integrate C Code Using the
with the MATLAB code block to the model. Embed MATLAB Function Block” (Simulink)
for code generation the MATLAB code in that • MATLAB Function
subset and you want to block.
call MATLAB code from
a Simulink model.
3 External code complies Add a MATLAB System • “Integrate C Code Using the
with the MATLAB code block to the model. Embed MATLAB Function Block” (Simulink)
for code generation the MATLAB code in that • MATLAB System
subset, you want to call block as a System object™.
MATLAB code from a
Simulink model, and
your algorithm includes
iterative computations
that process large
streams of data.
4 External code complies Add a Stateflow chart to the • “Chart Programming Basics”
with the MATLAB code model. Call the external (Stateflow)
for code generation code from the chart, using • “Insert External Code into Stateflow
subset, you want to call MATLAB as the action Charts” on page 42-24
MATLAB code from a language.
Simulink model, and
your algorithm includes
design logic that is
based on state
machines and flow
charts.
5 You want to use the Use MATLAB Coder • “C Code Generation Using the
parfor function for software to generate C MATLAB Coder App” (MATLAB
parallel computing or code. Then, call that Coder)
interface data types generated code as external • “Getting Started with MATLAB
that are available to C code. Coder” (MATLAB Coder)
MATLAB Coder but are
not available to
Simulink Coder or
Embedded Coder.

42-17
42 External Code Integration in Simulink Coder

Condition or Action More Information


Requirement
6 You have C or C++ Manually convert the “Integration Approaches for External C
programming MATLAB code to C or C++ or C++ Code” on page 42-18
experience and the code. Choose an integration
external MATLAB code approach for C or C++
is compact and code.
primarily uses C or C+
+ constructs.
7 Sections of the external Develop the algorithm in • “Model Editing Fundamentals”
MATLAB code map to the context of a model, (Simulink) and “Component-Based
built-in blocks. using the applicable built-in Modeling” (Simulink)
blocks. • “Blocks and Products Supported for
C Code Generation” (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)

Integration Approaches for External C or C++ Code

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

• The external code uses global variables to exchange data.


• Programming experience is limited.
• The algorithm must model discrete and continuous state dynamics.
• You want to include the integrated external code in a Stateflow chart.
• The external code requires a fixed-point interface.
• You want maximum flexibility for controlling what code the code generator produces.
• You quickly want to embed a call to the external code in a call to the coder.ceval
function that is embedded in the MATLAB Function block, and performance is not an
issue.

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

Condition or Action More Information


Requirement
1 You want to integrate Match the language “Modify Programming Language of
external C code with choice for the generated External Code to Match Generated
generated C++ code or code by modifying the Code” on page 42-23
conversely language of the external
code.
2 Your algorithm includes Add a Stateflow chart to “Insert External Code into Stateflow
design logic that is the model. Call the Charts” on page 42-24
based on state machines external code from the
and flow charts. Or, a chart, using C as the
function that you want to action language. In the
integrate must exchange chart, write code that
data with a model by calls the external function
using global variables. and reads from and
The function defines the writes to the global
global variables and uses variables. To perform
them to write output calculations with output
rather than returning a of the external code, the
value (return) or writing model must read from the
output to an argument. global variable during
execution.
3 You want to include Configure the model that • “Custom Code Algorithm” (Stateflow)
external C or C++ code contains the chart to • “Call C Functions in C Charts”
in a Stateflow chart for apply the external C or C (Stateflow)
simulation and code ++ code.
generation. • “Insert External Code into Stateflow
Charts” on page 42-24
4 You quickly want to Call the C or C++ code • coder.ceval function
embed a call to external with the coder.ceval • “Integrate C Code Using the MATLAB
C or C++ code in a function from within a Function Block” (Simulink)
model. Performance is MATLAB Function block.
not an issue. • MATLAB Function block

42-21
42 External Code Integration in Simulink Coder

Condition or Action More Information


Requirement
5 The application requires Manually write an S- • “S-Function Basics” (Simulink)
more entry-point function and TLC file. • “S-Functions and Code Generation”
functions than the code on page 11-2
generator typically
produces—for example, • “C S-Function Examples” (Simulink)
more than model_step, and “C++ S-Function Examples”
model_initialize, (Simulink)
and model_terminate.
You want maximum
flexibility for controlling
what code the code
generator produces.
6 You want to simulate and Generate S-function and • “Integrate C Functions Using Legacy
generate external code TLC files by using the Code Tool” (Simulink)
for a discrete time Legacy Code Tool. If • “Import Calls to External Code into
application. Optimizing necessary, refine the Generated Code with Legacy Code
generated code is generated code manually Tool” (Simulink Coder)
essential. You want ease to meet application
of use with moderate requirements. (If you
flexibility for controlling change the generated
what code the code code, you lose the
generator produces. You changes if you regenerate
have C or C++ the S-function and TLC
programming files.)
experience, but you
prefer to generate the
files for adding the code
to a model.

42-22
Call Reusable External Algorithm Code for Simulation and Code Generation

Condition or Action More Information


Requirement
7 The algorithm must Generate S-function and • “Build S-Functions Automatically”
model discrete and TLC files by using the S- (Simulink)
continuous state Function Builder. If • “Generate S-Function from
dynamics for simulation necessary, refine the Subsystem” on page 11-62
and rapid prototyping. generated code manually
The external code to meet application
requires a fixed-point requirements. (If you
interface. Programming change the generated
experience is limited. code, you lose the
You want ease of use changes if you regenerate
with basic flexibility for the S-function and TLC
controlling what code files.)
the code generator
produces for rapid
prototyping.

Modify Programming Language of External Code to Match Generated Code

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()
{
...
}
}

Integration Approaches for External Fortran Code

To integrate external Fortran code, write an S-function and corresponding TLC file.

See “S-Function Basics” (Simulink), “Fortran S-Functions” (Simulink), “S-Functions and


Code Generation” on page 11-2, and“Fortran S-Function Examples” (Simulink).

Insert External Code into Stateflow Charts


• “Integrate External Code for Library Charts” on page 42-24
• “Integrate External Code for All Charts” on page 42-25

Integrate External Code for Library Charts

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.

Integrate External Code for All Charts

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

Place External C/C++ Code in Generated Code


In this section...
“Workflow” on page 42-27
“Choose an Integration Approach” on page 42-28
“Integrate External Code by Using Custom Code Blocks” on page 42-30
“Integrate External Code by Using Model Configuration Parameters” on page 42-33
“Integrate External C Code Into Generated Code By Using Custom Code Blocks and
Model Configuration Parameters” on page 42-35

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.

Task Action More Information


1 If you want to integrate external C “Modify Programming Language of External
code with generated C++ code or Code to Match Generated Code” (Simulink
conversely, modify the language of Coder)
the external code to match the
language choice for the generated
code.

42-27
42 External Code Integration in Simulink Coder

Task Action More Information


2 Review your assessment of external “Choose an External Code Integration
code characteristics and integration Workflow” on page 42-4
requirements.
3 If necessary, rewrite code in C or C+
+.
4 Choose an integration approach to “Choose an Integration Approach” on page
add the external code to a Simulink 42-28
model.
5 Define the representation of model “Exchange Data Between External C/C++
data for code generation. Code and Simulink Model or Generated
Code” on page 42-90
6 Configure the model for code “Generate Code That Matches Appearance
generation. of External Code” on page 42-106 and
“Model Configuration”
7 Generate code and a code “Code Generation”
generation report.
8 Review the generated code interface “Analyze the Generated Code Interface” on
and static code metrics. page 38-19 and “Static Code Metrics” on
page 38-33
9 Build an executable program from “Build Integrated Code Within the Simulink
the model. Environment” on page 42-42
10 Verify that executable program “Numerical Equivalence Testing” and “Code
performs as expected. Execution Profiling”

Choose an Integration Approach


Within the Simulink modeling environment, two approaches are available for placing
external C or C++ code into sections of code that the code generator produces:

• 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.

Requirement Blocks Model Configuration


Parameters
Include a representation of your external code in ✓
the modeling canvas
Place code in functions generated for root ✓ ✓
models
Place code in functions generated for atomic ✓
subsystems
Save code placement in a model configuration ✓
set
Place code at the top and bottom of the header ✓ ✓
and source files generated for a model
Place code within declaration, execution, and ✓ ✓
exit sections of the SystemInitialize
andSystemTerminate functions that the code
generator creates
Place code within declaration, execution, and ✓
exit sections of the SystemStart,
SystemEnable, SystemDisable,
SystemOutputs, SystemUpdate,
orSystemDerivatives functions that the code
generator creates
Add preprocessor macro definitions to generated ✓
code
Use the custom code settings that are specified ✓
for the simulation target
Configure a library model to use custom code ✓
settings of the parent model to which the library
is linked

42-29
42 External Code Integration in Simulink Coder

Integrate External Code by Using Custom Code Blocks


• “Custom Code Block Library” on page 42-30
• “Add Custom Code Blocks to the Modeling Canvas” on page 42-31
• “Add External Code to Generated Start Function” on page 42-31

Custom Code Block Library

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.

To Customize Code That Use This Block


Computes continuous states System Derivatives
Disables state System Disable
Enables state System Enable
Resets state System Initialize
Produces output System Outputs
Executes once System Start
Saves data, free memory, reset target System Terminate
hardware
Requires updates at each major time step System Update

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).

Add Custom Code Blocks to the Modeling Canvas

To add the Custom Code library blocks to a model:

1 In the Simulink Library Browser, open the Custom Code block library. You can gain
access to the library by:

• Navigating to Simulink Coder > Custom Code in the browser.


• Entering the MATLAB command custcode.
2 Drag the blocks that you want into your model or subsystem. Drag Model Header and
Model Source blocks into root models only. Drag function-based Custom Code blocks
into root models or atomic subsystems.

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.

Add External Code to Generated Start Function

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.

1 Create the following model.

42-31
42 External Code Integration in Simulink Coder

2 Configure the model for code generation.


3 Double-click the System Start block.
4 In the block parameters dialog box, in the System Start Function Declaration
Code field, enter this code:

unsigned int *ptr = 0xFFEE;


5 In the System Start Function Execution Code field, enter this code:

/* 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;

/* user code (Start function Body) */


/* System '<Root>' */
/* Initialize hardware */
*ptr = 0;
}
}

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

Integrate External Code by Using Model Configuration


Parameters
Model configuration parameters provide a way to place external C or C++ code into
specific locations and functions within code that the code generator produces.

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

Integrate External C Code Into Generated Code By Using


Custom Code Blocks and Model Configuration Parameters
This example shows how to place external code in generated code by using custom code
blocks and model configuration parameters.

1. Open the model rtwdemo_slcustcode.

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.

4. Close the dialog box.

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.

7. Generate code and a code generation report.

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_INT2 = -1;

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.

int_T *intPtr = &GLOBAL_INT1;

*intPtr = -1;

rtwdemo_slcustcode_Y.Output = rtwdemo_slcustcode_U.Input << 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

Call External Device Drivers


Device drivers for protocols and target hardware are essential to many real-time
development projects. For example, you can have a working device driver that you want
to integrate with algorithmic code that has to read data from and write data to the I/O
device that the driver supports. The code generator can produce a single set of
application source files from an algorithm model and integrated driver code written in C
or C++.

To call external device driver code from the Simulink environment, iterate through the
tasks in this table.

Task Action More Information


1 Review your assessment of external “Choose an External Code Integration
code characteristics and integration Workflow” on page 42-4
requirements.
2 Define the representation of model “Exchange Data Between External C/C++
data for code generation. Code and Simulink Model or Generated
Code” on page 42-90
3 Generate S-function and TLC files by • “Integrate C Functions Using Legacy
using the Legacy Code Tool. If Code Tool” (Simulink)
necessary, refine the generated code • “Import Calls to External Code into
manually to meet application Generated Code with Legacy Code Tool”
requirements. (Simulink Coder)
4 Verify algorithm behavior and “Simulation” (Simulink)
performance by simulating the
model.
5 Configure the model for code “Generate Code That Matches Appearance
generation. of External Code” on page 42-106 and
“Model Configuration”
6 Generate code and a code “Code Generation”
generation report.
7 Review the generated code interface “Analyze the Generated Code Interface” on
and static code metrics. page 38-19 and “Static Code Metrics” on
page 38-33

42-39
42 External Code Integration in Simulink Coder

Task Action More Information


8 Build an executable program from “Build Integrated Code Within the Simulink
the model. Environment” on page 42-42
9 Verify that executable program “Numerical Equivalence Testing”
behaves and performs as expected.
10 Verify that executable program “Code Execution Profiling”
performs as expected.

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

Apply Function and Operator Code Replacements


If your generated code must use functions and operators that are consistent with external
code, configure the code generator to use a code replacement library (CRL). By default,
the code generator does not apply a code replacement library. You can choose from
several libraries that MathWorks provides, including GNU C99 extensions, AUTOSAR 4.0,
and several Intel® platform-specific IPP and IPP/SSE libraries. Depending on the products
that you have, other libraries might be available. If you have Embedded Coder software,
you can view and choose from additional libraries and you can create custom code
replacement libraries.

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

Build Integrated Code Within the Simulink Environment

Workflow
To build executable programs that integrate generated code and external C or C++ code,
iterate through the tasks in this table.

Task Action More Information


1 Choose whether to use the toolchain “Choose Build Approach and Configure Build
approach or template makefile Process” on page 43-14
approach build process.
For an example, see “Build Process
Workflow for Real-Time Systems” on page
43-32.
2 Configure build process support for “Configure Parameters for Integrated Code
your external code. Build Process” on page 42-43
3 Configure S-Function build support “Build Support for S-Functions” on page 42-
for your external code. 45

“Use makecfg to Customize Generated


Makefiles for S-Functions” on page 73-24

For examples, see “Call External C Code


from Model and Generated Code” and “Call
Reusable External Algorithm Code for
Simulation and Code Generation” on page
42-13.
4 Configure build process to find the “Manage Build Process File Dependencies”
external code source, library, and on page 36-53
header files.
“Control Library Location and Naming
During Build” on page 73-7

42-42
Build Integrated Code Within the Simulink Environment

Task Action More Information


5 Set up custom build processing For the build process customization
required for your external code workflow, see “Customize Post-Code-
integration. Generation Build Processing” on page 73-
14.

To automate applying build customizations


to a toolchain approach build, see
“Customize Build Process with
sl_customization.m” on page 73-36.

To automate applying build customizations


to a template makefile approach build, see
“Customize Build Process with
STF_make_rtw_hook File” on page 73-31.

Configure Parameters for Integrated Code Build Process


The table provides a guide to configuration parameters that support the build process for
external code integration. For information about folders for your external code, see
“Manage Build Process Folders” on page 36-37. If you choose to place your external code
in the “Code generation folder” (Simulink), see “Preserve External Code Files in Build
Folder” on page 42-45.

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.

If you specify relative paths, the paths must be relative to the


folder containing your model files, not relative to the build
folder. The order in which you specify the folders is the order
in which they are searched for header, source, and library
files.

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

Preserve External Code Files in Build Folder


By default, the build process deletes foreign source files. You can preserve foreign source
files by following these guidelines.

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.

Build Support for S-Functions


User-written S-Function blocks provide a powerful way to incorporate external code into
the Simulink development environment. In most cases, you use S-functions to integrate
existing external code with generated code. Several approaches to writing S-functions are
available:

• “Write Noninlined S-Function and TLC Files” on page 11-67


• “Write Wrapper S-Function and TLC Files” on page 11-69
• “Write Fully Inlined S-Functions” on page 11-78
• “Write Fully Inlined S-Functions with mdlRTW Routine” on page 11-79
• “S-Functions That Support Code Reuse” on page 11-105
• “S-Functions for Multirate Multitasking Environments” on page 11-106

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.

There are different ways of adding S-functions to the build process.

Implicit Build Support

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.

Specify Additional Source Files for an S-Function

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

• In the S-function block dialog box, specify sfun_main, sfun_module1, and


sfun_module2 in the S-function modules field.
• At the MATLAB command prompt, enter:
set_param(sfun_block,'SFunctionModules','sfun_module1 sfun_module2')

Alternatively, you can define a variable to represent the parameter value.


modules = 'sfun_module1 sfun_module2'
set_param(sfun_block,'SFunctionModules', modules)

The S-function modules field and SFunctionModules parameter do not support


complete source file path specifications. To use the parameter, the code generator must
find the additional source files when executing the makefile. For the code generator to
locate the additional files, place them in the same folder as the S-function MEX-file. You
can then leverage the implicit build support described in “Implicit Build Support” on page
42-46.

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.

Use TLC Library Functions

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.

Another useful TLC library function is LibAddToCommonIncludes. Use this function in a


#include statement to include S-function header files in the generated model.h header
file. For details, see “LibAddToCommonIncludes(incFileName)” (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.

42-47
42 External Code Integration in Simulink Coder

Precompile S-Function Libraries

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

Precompiler Libraries (PRECOMP_LIBRARIES)


Library Suffix Library Suffix
Library Suffix Integer- Only Optimize for Library
S-Function Code Speed Extension
COMPILER (EXPAND (EXPAND (EXPAND (EXPAND
_TOOL_CHAIN _LIBRARY _LIBRARY _LIBRARY _LIBRARY
TMF File Value _NAME Value) _NAME Value) _NAME Value) _NAME Value)
ert_lcc64.tmf lcc _rtwsfcn_lcc _int_ert_lcc _ert_lcc .lib
ert_vcx64.tmf vcx64 _rtwsfcn_vcx64 _int_ert_vcx64 _ert_vcx64 .lib
ert_unix.tmf unix _rtwsfcn _int_ert _ert .a
grt_lcc64.tmf lcc n/a n/a _lcc .lib
grt_vcx64.tmf vcx64 n/a n/a _vcx64 .lib
grt_unix.tmf unix n/a n/a _std .a
2 Set the precompiled library folder.

Use one of the following methods to set the precompiled library folder:

• Set the TargetPreCompLibLocation parameter, as described in “Specify the


Location of Precompiled Libraries” on page 73-8.
• Set the makeInfo.precompile field in an rtwmakecfg.m function file. (For
more information, see “Use rtwmakecfg.m API to Customize Generated Makefiles”
on page 73-26.)

If you set TargetPreCompLibLocation and makeInfo.precompile, the setting


for TargetPreCompLibLocation takes precedence.

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:

• libName — the name of the library without a suffix


• libLoc — the location for the precompiled library

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

Generate Component Source Code for Export to External


Code Base
In this section...
“Modeling Options” on page 42-52
“Requirements” on page 42-53
“Limitations for Export-Function Subsystems” on page 42-54
“Workflow” on page 42-55
“Choose an Integration Approach” on page 42-56
“Generate C Function Code for Export-Function Model” on page 42-58
“Generate C++ Function and Class Code for Export-Function Model” on page 42-64
“Generate Code for Export-Function Subsystems” on page 42-69

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:

• Export-function models (model containing functional blocks that consist exclusively of


function-call subsystems, function-call model blocks, or other export-function models,
as described in “Export-Function Models” (Simulink))
• Export-function subsystems (virtual subsystem that contains function-call subsystems)

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:

• Function-call blocks (such as Function-Call Subsystem, Simulink Function, S-


Functions, and Function-Call Model blocks at the root level if the solver parameter
Tasking and sample time options > Periodic sample time constraint is set to
Ensure sample time independent)
• Inport and Outport blocks (ports)
• Constant blocks (including blocks that resolve to constants, such as Add)
• Blocks with a sample time of Inf
• Merge and data store memory blocks
• Virtual connection blocks (such as, Function-Call Split, Mux, Demux, Bus Creator,
Bus Selector, Signal Specification, and virtual subsystems that contain these
blocks)
• Signal-viewer blocks, such as Scope blocks (export-function subsystems only)
• When a constant block appears at the top level of the model or subsystem, you must
set the model configuration parameter Optimization > Default parameter behavior
for the model or containing model to Inlined.
• Blocks inside the model or subsystem must support code generation.
• Blocks that use absolute or elapsed time must be inside a periodic function-call
subsystem with a discrete sample time specified on the corresponding function-call
root-level Inport block. See “Export Functions That Use Absolute or Elapsed Time” on
page 42-54.
• Data signals that cross the boundary of an exported system cannot be a virtual bus
and cannot be implemented as a Goto-From connection. Data signals that cross the
export boundary must be scalar, muxed, or a nonvirtual bus.

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.

For export-function subsystems, the following additional requirements apply:

• A trigger signal that crosses the boundary of an export-function subsystem must be


scalar. Input and output data signals that do not act as triggers do not have to be
scalar.
• When a constant signal drives an output port of an export-function subsystem, the
signal must specify a storage class.

Export Functions That Use Absolute or Elapsed Time

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:

• You configure for periodic execution


• You configure the root-level Inport block with a discrete sample time

To configure a function-call subsystem for periodic execution:


1 In the function-call subsystem, right-click the Trigger block and choose Block
Parameters from the context menu.
2 In the Sample time type field, specify periodic.
3 Set the Sample time to the same granularity specified (directly or by inheritance) in
the function-call initiator.
4 Click OK or Apply.

For more information, see “Absolute and Elapsed Time Computation” (Simulink Coder).

Limitations for Export-Function Subsystems


• Subsystem block parameters do not control the names of the files containing the
generated code. The file names begin with the name of the exported subsystem.
• Subsystem block parameters do not control the names of top-level functions in the
generated code. Each function name reflects the name of the signal that triggers the
function or (for an unnamed signal) reflects the block from which the signal originates.
• The code generator cannot export reusable code for export-function subsystems. The
Code interface packaging value Reusable function does not apply for export-
function subsystems.

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.

Task Action More Information


1 Review your assessment of external “Choose an External Code Integration
code characteristics and integration Workflow” on page 42-4
requirements.
2 Verify that the model or subsystem “Requirements” on page 42-53
that you are exporting satisfies
function exporting requirements.
3 Address data interface requirements “Exchange Data Between External C/C++
by modifying the model or Code and Simulink Model or Generated
subsystem. Code” on page 42-90

42-55
42 External Code Integration in Simulink Coder

Task Action More Information


4 If necessary, configure function “Customize Generated Function Interfaces
prototype. for Simulink Function and Function Caller
Blocks” on page 29-24 and, for fixed-step
rate-based models, “Customize Generated C
Function Interfaces” on page 29-2 or
“Customize Generated C++ Class
Interfaces” on page 29-36
5 If necessary , update the model to “Place External C/C++ Code in Generated
place external application-specific Code” on page 42-27
code in generated system functions.
6 Verify that the functions behave and “Configure Model, Generate Code, and
perform as expected during Simulate” on page 36-2 and, if you have
simulation by creating and using a Simulink Test software, “Unit Testing”
test harness model. The test harness (Simulink Test)
model schedules execution of the
functions during simulation.
7 Configure the model or subsystem “Generate Code Using Embedded Coder®”,
for code generation. “Generate Code That Matches Appearance
of External Code” on page 42-106,
and“Model Configuration”
8 Generate code and a code “Code Generation”
generation report.
9 Review the generated code interface “Analyze the Generated Code Interface” on
and static code metrics. page 38-19 and “Static Code Metrics” on
page 38-33
10 Build an executable program that “Build Integrated Code Outside the Simulink
includes the exported function code. Environment” on page 42-83
11 Verify that executable program
behaves and performs as expected.

Choose an Integration Approach


Multiple approaches are available for generating function code for export to an external
development environment. The following table compares approaches. Choose the
approach that aligns best with your integration requirements. For more information on

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.

Condition or Requirement Use More Information


• Traceability between Function-call • “Generate C Function Code for Export-
modeling elements and subsystem Function Model” on page 42-58
generated code • “Generate C++ Function and Class
• Local inputs (Inport block) Code for Export-Function Model” on
and outputs (Outport block) page 42-64
• “Using Function-Call Subsystems”
(Simulink)
• Function-Call Subsystem
• Control over generated Simulink Function • “Customize Generated Function
function prototype block Interfaces for Simulink Function and
• Formal input arguments Function Caller Blocks” on page 29-24
(Argument Inport blocks) and • “Simulink Function Blocks and Code
output arguments (Argument Generation” (Simulink Coder)
Outport blocks) • “Generate Code for a Simulink
• Local inputs (Inport block) Function and Function Caller” on page
and outputs (Outport block) 6-20
• “Simulink Functions in Simulink
Models” (Simulink)
• Simulink Function
Code responds to an Initialize Function • “Generate C Function Code for Export-
initialization event block Function Model” on page 42-58
• “Generate C++ Function and Class
Code for Export-Function Model” on
page 42-64
• “Generate Code That Responds to
Initialize, Reset, and Terminate Events”
on page 9-2
• “Customize Initialize, Reset, and
Terminate Functions” (Simulink)

42-57
42 External Code Integration in Simulink Coder

Condition or Requirement Use More Information


Code responds to a reset event Reset Function block • “Generate C Function Code for Export-
Function Model” on page 42-58
• “Generate C++ Function and Class
Code for Export-Function Model” on
page 42-64
• “Generate Code That Responds to
Initialize, Reset, and Terminate Events”
on page 9-2
• “Customize Initialize, Reset, and
Terminate Functions” (Simulink)
Code includes entry-point S-function “Write S-Function and TLC Files By Hand”
functions beyond what the code on page 11-67
generator produces by default
(model_initialize,
model_step, and
model_terminate)
Single-model execution Export-function • “Control Generation of Subsystem
framework to use as test harness subsystem Functions” on page 3-2
and to export code generated for • “Systems and Subsystems” (Simulink)
portions of a model
• “Using Function-Call Subsystems”
(Simulink)
• Function-Call Subsystem

Generate C Function Code for Export-Function Model


This example shows how to generate function code for individual Simulink function blocks
and function-call subsystems in a model without generating scheduling code.

To generate function code for export:

1 Create a model that contains the functions for export.


2 Create a test harness model that schedules execution of the functions during
simulation.
3 Simulate the model that contains the functions by using the test harness model.

42-58
Generate Component Source Code for Export to External Code Base

4 Generate code for the model that contains the functions.

Create Model That Contains Functions for Export

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.

For exporting functions, model rtwdemo_functions contains two function-call


subsystems (f1_alg and f2_alg) and a Simulink Function block (f3) for exporting
functions. The model also contains an Initialize Function block (Initialize Function)
and a Reset Function block (Reset Function). To calculate initial conditions for blocks
with state in other parts of the model, the State Writer blocks are used inside the
Initialize and Reset Function blocks.

open_system('rtwdemo_functions')

42-59
42 External Code Integration in Simulink Coder

Create Model That Contains Function Caller Block

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.

The model rtwdemo_caller exports a function-call subsystem that contains a Function


Caller block.

open_system('rtwdemo_caller')

42-60
Generate Component Source Code for Export to External Code Base

Create Test Harness Model for Simulation

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.

Model rtwdemo_export_functions is a test harness. The model:

• 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

Simulate the Test Harness Model

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 Function Code and Report

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')

### Starting build procedure for model: rtwdemo_functions


### Successful completion of code generation for model: rtwdemo_functions

Review Generated Code

From the code generation report, review the generated code.

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.

Write Interface Code

Open and review the Code Interface Report. To write the interface code for your
execution framework, use the information in that report.

1 Include the generated header files by adding directives #include


rtwdemo_functions.h, #include f3.h, and #include rtwtypes.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:

• rtU.U1 of type real_T with dimension 1


• rtU.U2 of type real_T with dimension 1

Entry-point functions:

• Initialize entry-point function, void rtwdemo_functions_initialize(void). At


startup, call this function once.
• Reset entry-point function, void rtwdemo_functions_reset(void). Call this
function as needed.
• Exported function, void f1(void). Call this function as needed.
• Exported function, void f2(void). Call this function as needed.
• Simulink function, void f3(real_T rtu_u, real_T *rty_y). Call this function
as needed.

42-63
42 External Code Integration in Simulink Coder

Output ports:

• rtY.Accumulator1 of type int8_T with dimension [2]


• rtY.Accumulator2 of type int8_T with dimension [2]
• rtY.TicToc10 of type int8_T with dimension 1

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)

Close Example Models

bdclose('rtwdemo_export_functions')
bdclose('rtwdemo_functions')
bdclose('rtwdemo_caller')

Generate C++ Function and Class Code for Export-Function


Model
This example shows how to generate function code for an export-function model that
includes a function-call subsystem. The code generator produces function and class code
that does not include scheduling code.

To generate function code for export:

1 Create a model that contains the functions for export.


2 Create a test harness model that schedules execution of the functions during
simulation.
3 Simulate the model that contains the functions by using the test harness model.
4 Generate code for the model that contains the functions.

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.

Model rtwdemo_cppclass_functions contains function-call subsystems f1, f2, and


f3 for exporting functions.

open_system('rtwdemo_cppclass_functions')

42-65
42 External Code Integration in Simulink Coder

Create Test Harness Model for Simulation

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.

Model rtwdemo_cppclass_export_functions is a test harness. The model provides


function-call signals to other models in this example to schedule the model contents.

open_system('rtwdemo_cppclass_export_functions')

42-66
Generate Component Source Code for Export to External Code Base

Simulate the Test Harness Model

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 Function Code and Report

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')

### Starting build procedure for model: rtwdemo_cppclass_functions


### Successful completion of build procedure for model: rtwdemo_cppclass_functions

Review Generated Code

From the code generation report, review the generated code.

42-67
42 External Code Integration in Simulink Coder

• ert_main.cpp 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_cppclass_functions.cpp calls the initialization function, including
Initialize Function, and exported functions for model subsystem components f1,
f2, and f3.
• rtwdemo_cppclass_functions.h declares model data structures and a public
interface to the exported entry-point functions and data structures.
• rtwtypes.h defines data types, structures, and macros that the generated code
requires.

Write Interface Code

Open and review the Code Interface Report. To write the interface code for your
execution framework, use the information in that report.

1 Include the generated header files by adding directives #include


rtwdemo_cppclass_functions.h and #include rtwtypes.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:

• rtU.U1 of type real_T with dimension 1


• rtU.U2 of type real_T with dimension 1
• rtU.U3 of type real_T with dimension 1

Entry-point functions:

• Initialize entry-point function, void initialize(void). At startup, call this


function once.
• Exported function, void t_1tic_A(void). Call this function as needed.
• Exported function, void t_1tic_B(void). Call this function as needed.
• Exported function, void t_1tic_C(void). Call this function as needed.

Output ports:

42-68
Generate Component Source Code for Export to External Code Base

• rtY.TicToc1 of type int8_T with dimension [2]


• rtY.TicToc2 of type int8_T with dimension [2]
• rtY.TicToc10 of type int8_T with dimension 1

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)

Close Example Models


bdclose('rtwdemo_cppclass_export_functions')
bdclose('rtwdemo_cppclass_functions')

Generate Code for Export-Function Subsystems


• “Specify a Custom Initialize Function Name” on page 42-70
• “Specify a Custom Description” on page 42-70
• “Optimize Code Generated for Export-Function Subsystems” on page 42-71

To generate code for an export-function subsystem:


1 Verify that the subsystem for which you are generating code satisfies exporting
requirements on page 42-53.
2 In the Configuration Parameters dialog box:
a On the Code Generation pane, specify an ERT-based system target file, such as
ert.tlc.
b If you want a SIL block with the generated code, for verification purposes, from
the Configuration Parameters > Code Generation > Verification >
Advanced parameters > Create block drop-down list, select SIL.
c Click OK or Apply.
3 Right-click the subsystem block and choose C/C++ Code > Export Functions from
the context menu.

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.

Specify a Custom Initialize Function Name

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:

/* Model initialize function */


void myinitfcn(void){
...
}

Specify a Custom Description

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)
{
...
}

Optimize Code Generated for Export-Function Subsystems

To optimize the code generated for an export-function subsystem, specify a separate


storage class for each input signal and output signal that crosses the boundary of the
subsystem.

For each function-call subsystem that you are exporting:

1 Right-click the subsystem.


2 From the context menu, choose Block Parameters (Subsystem).
3 Select the Code Generation tab.
4 Set Function packaging to Auto.
5 Click OK or Apply.

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

• “Using Triggered Subsystems” (Simulink)


• “Using Function-Call Subsystems” (Simulink)
• “Export-Function Models” (Simulink)

42-72
Generate Shared Library for Export to External Code Base

Generate Shared Library for Export to External Code


Base
In this section...
“About Generated Shared Libraries” on page 42-73
“Workflow” on page 42-73
“Generate Shared Libraries” on page 42-74
“Create Application Code That Uses Generated Shared Libraries” on page 42-75
“Limitations” on page 42-78
“Interface to a Development Computer Simulator By Using a Shared Library” on page
42-79

About Generated Shared Libraries


If you have Embedded Coder software, you can generate a shared library—Windows
dynamic link library (.dll), UNIX shared object (.so), or Macintosh OS X dynamic
library (.dylib)— from a model component. You or others can integrate the shared
library into an application that runs on a Windows, UNIX, or Macintosh OS X
development computer. Uses of shared libraries include:

• Adding a software component to an application for system simulation


• Reusing software modules among applications on a development computer
• Hiding intellectual property associated with software that you share with vendors

When producing a shared library, the code generator exports:

• Variables and signals of type ExportedGlobal as data


• Real-time model structure (model_M) as data
• Functions essential to executing the model code

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

Task Action More Information


1 Review your assessment of external • “Choose an External Code Integration
code characteristics and integration Workflow” on page 42-4
requirements. • “Shared Library Limitations” on page 50-
7
2 Configure the model for code “Generate Code That Matches Appearance
generation. of External Code” on page 42-106 and
“Model Configuration”
3 Configure the model for the code “Generate Shared Libraries” on page 42-74
generator to produce a shared
library and initiate code generation.
4 Verify that the generated shared
library meets requirements. For
example, review the code generation
report and view the list of symbols
in the library.

• On Windows, use the


Dependency Walker utility,
downloadable from
www.dependencywalker.com
• On UNIX, use nm -D model.so
• On Macintosh OS X, use nm -g
model.dylib
5 Use the shared library in application “Create Application Code That Uses
code. Generated Shared Libraries” on page 42-75
6 Compile and link application code “Build Integrated Code Outside the Simulink
that loads and uses the generated Environment” on page 42-83
shared library.
7 Verify that executable program
behaves and performs as expected.

Generate Shared Libraries


1 When configuring the model for code generation, select the system target file
ert_shrlib.tlc.

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.

Create Application Code That Uses Generated Shared


Libraries
This example application code is generated for the example “Interface to a Development
Computer Simulator By Using a Shared Library” on page 42-79.

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:

#if (defined(_WIN32)||defined(_WIN64)) /* WINDOWS */


#include <windows.h>
#define GETSYMBOLADDR GetProcAddress
#define LOADLIB LoadLibrary
#define CLOSELIB FreeLibrary

#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:

• Variables and signals of type ExportedGlobal


• Real-time model structure (model_M)
• Code generation for the ert_shrlib.tlc system target file supports the C language
only (not C++). When you select ert_shrlib.tlc, language selection is unavailable
on the Code Generation pane in the Configuration Parameters dialog box.
• To reconstruct a model simulation by using a generated shared library, the application
author must maintain the timing between system and shared library function calls in
the original application. The timing must be consistent so that you can compare the
simulation and integration results. Additional simulation considerations apply if
generating a shared library from a model that enables model configuration
parameters Support: continuous time and Single output/update function. For
more information, see Single output/update function (Simulink Coder) dependencies.

42-78
Generate Shared Library for Export to External Code Base

Interface to a Development Computer Simulator By Using a


Shared Library
This example generates a shared library for interfacing to a simulator that runs on your
development computer. Generate the shared library by using the system target file
ert_shrlib.tlc.

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

values 1, 4, and 0, respectively. When signal equal_to_count is true, the subsystem


amplifies its input signal by a gain factor K=3 and the output signal is updated.

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

• “Manage Build Process Files” on page 36-43


• “Model Protection”

42-82
Build Integrated Code Outside the Simulink Environment

Build Integrated Code Outside the Simulink Environment


Identify required files and interfaces for calling generated code in an external build
process.

Learn how to:

• Collect files required for building integrated code outside of Simulink®.


• Interface with external variables and functions.

For information about the example model and related examples, see “Generate C Code
from a Control Algorithm for an Embedded System”.

Collect and Build Required Data and Files

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.

Open the example model, rtwdemo_PCG_Eval_P5.

This model is configured to run packNGo after code generation.

Generate code from the entire model.

To generate the zip file manually:

1 Load the file buildInfo.mat (located in the rtwdemo_PCG_Eval_P5_ert_rtw


subfolder).
2 At the command prompt, enter the command packNGo(buildInfo).

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

Integrating the Generated Code into an Existing System

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.

Overview of Integration Environment

A full embedded controls system consists of multiple hardware and software components.
Control algorithms are just one type of component. Other components can be:

• An operating system (OS)


• A scheduling layer
• Physical hardware I/O
• Low-level hardware device drivers

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:

• Defines function interfaces (function prototypes).


• Includes files that declare external data.
• Defines extern data.
• Initializes data.
• Calls simulated hardware.
• Calls algorithmic functions.

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

Match System Interfaces

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.

Connect Input Data

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

Connect Output Data

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.

Access Additional Data

The generated code contains several structures that store commonly used data including:

• Block state values (integrator, transfer functions)


• Local parameters
• Time

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

Constants |model_cP| Constant parameters


Constants |model_cB| Constant block I/O
Output |model_U| Root and atomic subsystem input
Output |model_Y| Root and atomic subsystem output
Internal data |model_B| Value of block output
Internal data |model_D| State information vectors
Internal data |model_M| Time and other system level data
Internal data |model_Zero| Zero-crossings
Parameters |model_P| Parameters

Match Function Call Interfaces

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.

Calls to the function PI_Cntrl_Reusable use a mixture of separate, unstructured global


variables and Simulink® Coder™ data structures. The handwritten code defines these
variables. The structure types are defined in rtwdemo_PCG_Eval_P5.h.

Build Project in Eclipse™ Environment

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:

• Eclipse™ SDK 3.2


• Eclipse™ CDT 3.3
• Cygwin™/GCC 3.4.4-1
• Cygwin™/GDB 20060706-2

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:

Set up the build folder.

Alternatively, to install the files manually:

1 Create a build folder (Eclipse_Build_P5).


2 Unzip the file rtwdemo_PCG_Eval_P5.zip into the build folder.
3 Delete the files rtwdemo_PCG_Eval_P5.c, ert_main.c and rt_logging.c, which
are replaced by example_main.c.

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

Exchange Data Between External C/C++ Code and


Simulink Model or Generated Code
Whether you import your external code into a Simulink model (for example, by using the
Legacy Code Tool) or export the generated code to an external environment, the model or
the generated code typically exchange data (signals, states, and parameters) with your
code.

Functions in C or C++ code, including your external functions, can exchange data with a
caller or a called function through:

• Arguments (formal parameters) of functions. When a function exchanges data through


arguments, an application can call the function multiple times. Each instance of the
called function can manipulate its own independent set of data so that the instances
do not interfere with each other.
• Direct access to global variables. Global variables can:

• Enable different algorithms (functions) and instances of the same algorithm to


share data such as calibration parameters and error status.
• Enable the different rates (functions) of a multitasking system to exchange data.
• Enable different algorithms to exchange data asynchronously.

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.

Import External Code into Model


To exchange data between your model and your external function, choose an exchange
mechanism based on the technique that you chose to integrate the function.

• 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.

Technique for Mechanism to Examples and More Information


Integrating Exchange Data with
External Model
Function
S-Function block Function arguments To call your function through an S-function that you
create by using the Legacy Code Tool, see “Integrate C
Functions into Simulink Models with Legacy Code
Tool” (Simulink).
Stateflow chart Function arguments To call your function and access global variables in a
and direct access to Stateflow chart, see “Integrate Custom C/C++ Code
global variables for Simulation” (Stateflow). For information about
creating data items in a chart (which you can pass to
your function as arguments), see “Add Stateflow Data”
(Stateflow).

42-91
42 External Code Integration in Simulink Coder

Technique for Mechanism to Examples and More Information


Integrating Exchange Data with
External Model
Function
coder.ceval in Function arguments To call your function in a MATLAB Function block by
MATLAB Function using coder.ceval, see “Integrate C Code Using the
block MATLAB Function Block” (Simulink). For information
about creating data items in a MATLAB Function block
(which you can pass to your function as arguments),
see “Ports and Data Manager” (Simulink).

Export Generated Code to External Environment


To export the generated code into your external code, see “Exchange Data Between
External Calling Code and Generated Code” (Simulink Coder).

Simulink Representations of C Data Types and Constructs


To model and reuse your custom C data such as structures, enumerations, and typedef
aliases, use the information in these tables.

42-92
Exchange Data Between External C/C++ Code and Simulink Model or Generated Code

Modeling Patterns for Matching Data in External C Code

C Data Type Example C Code Simulink Equivalent More Information


or Construct
Primitive type typedef float mySinglePrec_T; Create a For information about
alias Simulink.AliasType defining custom data
(typedef) object. Use the object to: types for your model,
see
• Set the data types of Simulink.AliasTy
signals and block pe and “Control Data
parameters in a model. Type Names in
• Configure data type Generated Code” on
replacements for code page 24-2.
generation.
For an example that
Generating code that uses shows how to export
an alias data type requires the generated code
Embedded Coder. into your external
code, see “Replace
and Rename Data
Types to Conform to
Coding Standards” on
page 24-27.

42-93
42 External Code Integration in Simulink Coder

C Data Type Example C Code Simulink Equivalent More Information


or Construct
Array int myArray[6]; Specify signal and For information about
parameter dimensions as how the generated
described in “Signal code stores nonscalar
Dimensions” (Simulink). data (including
limitations), see
The generated code “Code Generation of
defines and accesses Matrices and Arrays”
multidimensional data, (Simulink Coder).
including matrices, as
column-major serialized For an example that
vectors. If your external shows how to export
code uses a different the generated code
format, consider using into your external
alternative techniques to code, see “Reuse
integrate the generated Parameter Data from
code. See “Code External Code in the
Generation of Matrices Generated Code” on
and Arrays” on page 36- page 26-2.
77.
To model lookup
tables, see
Simulink.LookupT
able.

42-94
Exchange Data Between External C/C++ Code and Simulink Model or Generated Code

C Data Type Example C Code Simulink Equivalent More Information


or Construct
Enumeration typedef enum myColorsType { Define a Simulink To use enumerated
Red = 0, enumeration that data in a Simulink
Yellow, corresponds to your model, see “Use
Blue enumeration definition. Enumerated Data in
} myColorsType;
Use the Simulink Simulink Models”
enumeration to set data (Simulink).
types in a model.
For an example that
shows how to
generate enumerated
parameter data, see
“Enumeration” on
page 14-23.

For an example that


shows how to export
the generated code
into your external
code by exchanging
enumerated data, see
“Exchange
Structured and
Enumerated Data
Between Generated
and External Code”
on page 24-34.

42-95
42 External Code Integration in Simulink Coder

C Data Type Example C Code Simulink Equivalent More Information


or Construct
Structure typedef struct myStructType { Create a Simulink.Bus For information about
int count; object that corresponds to bus signals, see
double coeff; your structure type. “Getting Started with
} myStructType; Buses” (Simulink).
To create structured signal For information about
or state data, package structures of
multiple signal lines in a parameters, see
model into a single “Organize Related
nonvirtual bus signal. Block Parameter
Definitions in
To create structured Structures”
parameter data, create a (Simulink).
parameter object (such as
Simulink.Parameter) For an example that
that stores a MATLAB shows how to import
structure. Use the bus your external code
object as the data type of into a model by using
the parameter object. the Legacy Code Tool,
see “Integrate C
To package lookup table Function Whose
data into a structure, use Arguments Are
Simulink.LookupTable Pointers to
and, optionally, Structures”
Simulink.Breakpoint (Simulink).
objects.
For examples that
show how to export
the generated code
into your external
code, see “Exchange
Structured and
Enumerated Data
Between Generated
and External Code”
on page 24-34 and
“Access Structured
Data Through a
Pointer That External

42-96
Exchange Data Between External C/C++ Code and Simulink Model or Generated Code

C Data Type Example C Code Simulink Equivalent More Information


or Construct
Code Defines” on
page 26-12.

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

Additional Modeling Patterns for Code Generation (Embedded Coder)

C Data Type Example C Code Simulink Equivalent More Information


or Construct
Macro #define myParam 9.8 Apply the custom “Macro Definitions
storage classes (#define)” on page 14-
Define and 71
ImportedDefine to
parameters. With
macros, you can reuse
a parameter value in
multiple locations in
an algorithm and
change the parameter
value between code
compilations without
consuming memory to
store the value.
Typically, macros
represent engineering
constants that you do
not expect to change
during code execution.

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

C Data Type Example C Code Simulink Equivalent More Information


or Construct
Bit field typedef struct myBitField { • Apply the custom “Bitfields” on page 14-
unsigned short int MODE : 1; storage class 89
unsigned short int FAIL : 1; BitField to
unsigned short int OK : 1; signals, states, and “Optimize Generated
} myBitField Code By Packing
parameters whose
data type is Boolean Data Into
boolean. Bitfields” on page 60-
16
• Use a model
configuration
parameter to
aggregate Boolean
data into bit fields.

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.

algorithmInput = get_inSig(); This technique


requires Embedded
Coder.

42-99
42 External Code Integration in Simulink Coder

Considerations for Other Modeling Goals

Goal Considerations and More Information


Use Simulink to run and You can use SIL, PIL, and external mode simulations to connect your
interact with the model to the corresponding generated application for simulation. When
generated code you import parameter data from your external code:

• 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

Exchange Data Between External Calling Code and


Generated Code
To export the generated code into your external code, you configure the generated code
to match the data interface of your external code. For example, if your external code
defines a global variable for storing output data and you need the generated code to read
that data as input, you can configure a corresponding Inport block so that the generated
code interacts with the existing variable.

• 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).

Data Exchange for Reentrant Generated Code


When you generate reentrant code, the model entry-point functions exchange data
through arguments. You can control some of the characteristics of the arguments. For
more information, see “Control Data and Function Interface in 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

Data Exchange for Nonreentrant Generated Code


To make the generated code read or write to an item of signal, state, or parameter data as
a global variable, apply a storage class or custom storage class to the data in the model.
The storage class also determines whether the generated code exports the variable
definition to your external code or imports the definition from your code. For general
information about controlling the data interface of a model that you configure to generate
nonreentrant code, see “Control Data Interface for Nonreentrant Code” (Simulink Coder).
For examples, see “Design Data Interface by Configuring Inport and Outport Blocks”
(Simulink Coder) and “Integrate External Application Code with Code Generated from
PID Controller” on page 26-62.

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.

Control File Placement of Exported Global Data (Embedded Coder)

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.

By default, the definition (memory allocation) of exported data typically appears in


model.c.

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.

Prevent Duplicate Initialization Code for Global Variables

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.

Protect Global Data with Keywords const and volatile

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:

• Apply const to a calibration parameter.


• Apply volatile to a global variable that stores the output of a hardware device
operating asynchronously.
• Apply const and volatile to signals, states, and parameters that represent data
defined by your external code. Then, the generated code declares and interacts with
the external data by using the correct storage type qualifiers.

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

Generate Code That Matches Appearance of External


Code
A key aspect of code integration, especially for larger projects, is adherence to guidelines
and standards for code appearance. If code appearance requirements apply to your
project, review the requirements in this table. To learn more, see the relevant
information.

Requirement More Information


Thoroughly document code or document • “Configure Code Comments” on page 31-24
code in a specific way. • “Add Custom Comments to Generated Code” on
page 39-3
• “Add Custom Comments for Variables in the
Generated Code” on page 39-5
• “Add Global Comments” on page 39-8
• “Annotate Code for Justifying Polyspace Checks”
on page 39-106
Control the length and naming of code • “Identifier Format Control” on page 39-22
identifiers (symbols), including the use of • “Specify Identifier Length to Avoid Naming
reserved names. Collisions” on page 31-28
• “Specify Reserved Names for Generated
Identifiers” on page 31-29
• “Customize Generated Identifier Naming Rules” on
page 39-14
• “Avoid Identifier Name Collisions with Referenced
Models” on page 39-32
• “Control Name Mangling in Generated Identifiers”
on page 39-30
• “Specify Boolean and Data Type Limit Identifiers”
on page 24-42

42-106
Generate Code That Matches Appearance of External Code

Requirement More Information


Control style aspects of code: “Control Code Style” on page 39-38

• 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

Requirement More Information


Apply code templates to control • “Customize Code Organization and Format” on
organization of code and use of banners page 39-56
• “Template Symbols and Rules” on page 39-97
• “Specify Templates For Code Generation” on page
39-59
• “Generate Custom File and Function Banners” on
page 39-89
• “Change the Organization of a Generated File” on
page 39-68
• “Generate Source and Header Files with a Custom
File Processing (CFP) Template” on page 39-73
• “Customize Generated File Names” on page 39-70

See Also

More About
• “Code Appearance”
• “Choose an External Code Integration Workflow” on page 42-4

42-108
43

Program Building, Interaction, and


Debugging in Simulink Coder

• “Select C or C++ Programming Language” on page 43-2


• “Select and Configure C or C++ Compiler or IDE” on page 43-3
• “Troubleshoot Compiler Issues” on page 43-9
• “Choose Build Approach and Configure Build Process” on page 43-14
• “Template Makefiles and Make Options” on page 43-26
• “Build Process Workflow for Real-Time Systems” on page 43-32
• “Rebuild a Model” on page 43-41
• “Control Regeneration of Top Model Code” on page 43-43
• “Reduce Build Time for Referenced Models” on page 43-45
• “Relocate Code to Another Development Environment” on page 43-56
• “Executable Program Generation” on page 43-69
• “Profile Code Performance” on page 43-72
43 Program Building, Interaction, and Debugging in Simulink Coder

Select C or C++ Programming Language


The default programming language selection for code generation is C language. In the
code generation workflow, after the steps in “Select a Solver That Supports Code
Generation” (Simulink Coder) and “Select a System Target File from STF Browser”
(Simulink Coder), an optional step is to change the programming language selection for
code generation.

To change the programming language setting:

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.

For more information, see “Language” (Simulink Coder).


2 Check whether you must choose and configure a compiler. If you select C++, you
must choose and configure a compiler. For details, see “Select and Configure C or C+
+ Compiler or IDE” (Simulink Coder).
3 Check whether the standard math library is configured for your compiler. By default,
the code generator uses the ISO/IEC 9899:1999 C (C99 (ISO)) library for the C
language and the ISO/IEC 14882:2003 C++ (C++03 (ISO)) library for the C++
language.

For more information, see “Standard math library” (Simulink Coder).

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

Select and Configure C or C++ Compiler or IDE


The build process requires a supported compiler. Compiler, in this context, refers to a
development environment (IDE) containing a linker and make utility, and a high-level
language compiler. For details on supported compiler versions, see:

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

Language Standards Compliance


The code generator produces code that is compliant with the following standards:

43-3
43 Program Building, Interaction, and Debugging in Simulink Coder

Language Supported Standard


C ISO/IEC 9899:1990, also known as C89/C90
C++ ISO/IEC 14882:2003

Code that the code generator produces from these sources is ANSI C/C++ compliant:

• Simulink built-in block algorithmic code


• Generated system-level code (task ID [TID] checks, management, functions, and so on)
• Code from other blocksets, including the Fixed-Point Designer product and the
Communications System Toolbox product
• Code from other code generators, such as MATLAB functions

Also, the code generator can incorporate code from:

• 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.

Programming Language Considerations


The code generator produces C and C++ code. Consider the following as you choose a
programming language:

• 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.

C++ Language Support Limitations


To use C++ language support, you could need to configure the code generator to use a
specific compiler. For example, if a supported compiler is not installed on your Microsoft
Windows computer, the default compiler is the lcc C compiler shipped with the MATLAB
product. This compiler does not support C++. If you do not configure the code generator
to use a C++ compiler before you specify C++ for code generation, the software
produces an error message.

Code generator limitations on C++ support include:

• 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

Code Generator Assumes Wrap on Signed Integer Overflows


The code generator reduces memory usage and enhances generated code execution by
assuming signed integer C operations wrap on overflow. A signed integer overflow occurs
when the result of an arithmetic operation is outside the range of values that the output
data type can represent. The C programming language does not define the results of such
operations. Some C compilers aggressively optimize signed operations for in-range values
at the expense of overflow conditions. Other compilers preserve the full wrap-on-overflow
behavior. For example, the gcc and MinGW compilers provide an option to wrap on
overflow reliably for signed integer overflows. The generated program image for a model
can produce results that differ from model simulation results because the handling of
overflows varies, depending on your compiler.

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:

• Verify that the compiled code produces expected results.


• 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, configure the build process to
use the compiler option -fwrapv.
• Choose a compiler that wraps on integer overflow.
• If you have Embedded Coder installed, develop and apply a custom code replacement
library to replace code generated for signed integers. For more information, see “Code
Replacement Customization”.

Choose and Configure Compiler


The compiler for your model build appears in the build process parameters in
Configuration Parameters > Code Generation. To view the installed compilers and
select the default compiler, in the Command Window type:

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.)

Include S-Function Source Code


When the code generator builds models with S-functions, source code for the S-functions
can be either in the current folder or in the same folder as their MEX-file. The code
generator adds an include path to the generated makefiles whenever it finds a file named
sfncname.h in the same folder as the S-function MEX-file. This folder must be on the
MATLAB path.

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

Troubleshoot Compiler Issues


In this section...
“Compiler Version Mismatch Errors” on page 43-9
“Results for Model Simulation and Program Execution Differ” on page 43-9
“Generates Expected Code and Produces Unexpected Results” on page 43-10
“Compile-Time Issues” on page 43-11
“LCC Compiler Does Not Support Ampersands in Source Folder Paths” on page 43-12
“LCC Compiler Might Not Support Line Lengths of Rapid Accelerator Code” on page 43-
13

Compiler Version Mismatch Errors


Description

The build process produces a compiler version mismatch error.

Action

1 Check the list of supported and compatible compilers available at


www.mathworks.com/support/compilers/current_release/.
2 Upgrade or change your compiler. For more information, see “Choose and Configure
Compiler” on page 43-6.
3 Rebuild the model.

Results for Model Simulation and Program Execution Differ


Description

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.

Generates Expected Code and Produces Unexpected Results


Description

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

Do one of the following:

• Lower the compiler optimization level.

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.

1 Select Optimizations off (faster builds) for the Model Configuration


parameter Code Generation > Compiler optimization level.
2 Rebuild the model.

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.

LCC Compiler Does Not Support Ampersands in Source Folder


Paths
Description

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

LCC Compiler Might Not Support Line Lengths of Rapid


Accelerator Code
Description

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

Choose Build Approach and Configure Build Process


The code generator supports these approaches for building (compiling and linking) code
that you generate from Simulink models:

• 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:

• Supports model referencing, SIL, and PIL.


• Supports Simulink Coder and Embedded Coder.

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:

• ert.tlc, ert_shrlib.tlc, grt.tlc, or any toolchain-compliant system target file,


the build process uses the toolchain approach on page 43-14 by default.
• Any non-toolchain-compliant system target file, the build process uses the template
makefile approach on page 43-20.

You can switch from the toolchain approach to the template makefile approach with this
command:

set_param(model, 'MakeCommand', 'make_rtw TMF=1')

Toolchain Approach
Toolchain settings appear under Build process when you set System target file to:

• grt.tlc — Generic Real-Time Target


• ert.tlc — Embedded Coder (requires the Embedded Coder product)

43-14
Choose Build Approach and Configure Build Process

• ert_shrlib.tlc — Embedded Coder (host-based shared library target)


(requires Embedded Coder)
• Any toolchain-compliant system target file (If ERT-based, requires Embedded Coder)

For more information about toolchain-compliant system target files, see “Support
Toolchain Approach with Custom Target” (Simulink Coder).

The Toolchain settings include:

• The “Toolchain” (Simulink Coder) parameter specifies the collection of third-party


software tools that builds the generated code. A toolchain can include a compiler,

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.

The default value of Toolchain is Automatically locate an installed


toolchain. The Toolchain parameter displays name of the located toolchain just
below Automatically locate an installed toolchain.

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:

• ert.tlc — Create Visual C/C++ Solution File for Embedded Coder


• grt.tlc — Create Visual C/C++ Solution File for Simulink Coder

To avoid confusion, click Browse to select the system target file and look at the
description of each file.

Upgrade Model to Use Toolchain Approach


When you open a model created before R2013b that uses the following system target
files, the software tries to upgrade the model. The upgrade changes the configuration
from using template makefile settings to using the toolchain settings:

• ert.tlc — Embedded Coder


• ert_shrlib.tlc — Embedded Coder (host-based shared library target)
• grt.tlc — Generic Real-Time Target

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:

• ert.tlc — Create Visual C/C++ Solution File for Embedded Coder


• grt.tlc — Create Visual C/C++ Solution File for Simulink Coder

To see if a model was upgraded:

1 Open the model configuration parameters by pressing Ctrl+E.


2 Select Configuration Parameters > Code Generation.
3 If the Build process subpane contains the Toolchain and Build configuration
parameters, the model has already been upgraded.

43-17
43 Program Building, Interaction, and Debugging in Simulink Coder

If the Build process area displays Makefile configuration parameters, such as


Generate makefile, Make command, and Template makefile, the software has
not upgraded the model.

Start by creating a working copy of the model using File > Save As. This action
preserves the original model and configuration parameters for reference.

Try to upgrade the model using Upgrade Advisor:


1 In your model, select Analysis > Model Advisor > Upgrade Advisor.
2 In Upgrade Advisor, select Check and update model to use toolchain approach
to build generated code and click Run This Check.

43-18
Choose Build Approach and Configure Build Process

3 Perform the suggested actions and/or click Update Model.

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:

• Compiler optimization level — Optimizations off (faster builds)


• Generate makefile — Enabled
• Template makefile — System target file-specific template makefile
• Make command — make_rtw without arguments

Sometimes, a model cannot be upgraded. Try the following procedure:

• 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.

Template Makefile Approach


When the System target file is set to a tlc file that uses the template makefile
approach, the software displays Compiler optimization level, Generate makefile,
Make command, and Template makefile parameters.

43-20
Choose Build Approach and Configure Build Process

Specify Whether to Generate a Makefile

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:

• The Make command and Template makefile options are unavailable.


• Set up post code generation build processing using a user-defined command, as
explained in “Customize Post-Code-Generation Build Processing” (Simulink Coder).

43-21
43 Program Building, Interaction, and Debugging in Simulink Coder

Specify a Make Command

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.

Specify the Template Makefile

The Template makefile field has these functions:

• 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

Associate the Template Makefile with a Toolchain

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.

Use this code for the toolchain definition file.


function tc = minimalToolchainForTMF
% Create a toolchain object
tc = coder.make.ToolchainInfo('Name', 'Minimal Toolchain for TMF Build');

% Specify that the linker requires a response file instead of


% including all object file modules on the linker command line
tc.addAttribute('RequiresCommandFile', true);

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);

Use a copy of ert_unix.tmf or ert_vcx64.tmf as the template makefile.


copyfile(fullfile(matlabroot,'rtw','c','ert','ert_vcx64.tmf'), 'ert_copy.tmf')

In the template makefile, i.e. ert_copy.tmf, edit the TOOLCHAIN_NAME macro.


TOOLCHAIN_NAME = "Minimal Toolchain for TMF Build"

Associate the toolchain with the template make file.

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.

a Place this code in an rtwTargetInfo.m file.

function rtwTargetInfo(tr)
tr.registerTargetInfo(@loc_createToolchain);
end

function config = loc_createToolchain


config(1) = coder.make.ToolchainInfoRegistry;
config(1).Name = 'Minimal Toolchain for TMF Build';
config(1).FileName = fullfile(fileparts(mfilename('fullpath')),...
'tcMinimal.mat');
config(1).TargetHWDeviceType = {'*'};
config(1).Platform = {computer('arch')};
end
b Save the file in the current working folder or in a folder that is on theMATLAB
search path.
c Reset the TargetRegistry.

RTW.TargetRegistry.getInstance('reset');

Associate the template makefile with your model and build the model.

set_param(model, 'TemplateMakefile', 'ert_copy.tmf');


rtwbuild(model);

Specify TLC for Code Generation


Target Language Compiler (TLC) is an integral part of the code generator. It enables you
to customize generated code. Through customization, you can produce platform-specific
code, or you can incorporate your own algorithmic changes for performance, code size, or
compatibility with existing methods that you prefer to maintain. For additional
information, see “Target Language Compiler Overview” (Simulink Coder).

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')

Some common uses of TLC options include the following:

• -aVarName=1 to declare a TLC variable and/or assign a value to it


• -IC:\Work to specify an include path
• -v to obtain verbose output from TLC processing (for example, when debugging)

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

Template Makefiles and Make Options


The code generator includes a set of built-in template makefiles that build programs for
specific system target files.

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

Types of Template Makefiles


There are two types of template makefiles:

• Compiler-specific template makefiles are for a particular compiler or development


system.

By convention, compiler-specific template makefiles names correspond to the system


target file and compiler (or development system). For example, grt_vcx64.tmf is the
template makefile for building a generic real-time program under the Visual C++
compiler; ert_lcc.tmf is the template makefile for building an Embedded Coder
program under the lcc compiler.
• Default template makefiles make your model designs more portable, by choosing the
compiler-specific makefile and compiler for your installation. “Select and Configure C
or C++ Compiler or IDE” on page 43-3 describes the operation of default template
makefiles in detail.

Default template makefiles have names that follow the pattern


target_default_tmf. They are MATLAB language files that, when run, select the
TMF for the specified system target file configuration. For example,
grt_default_tmf is the default template makefile for building a generic real-time
program; ert_default_tmf is the default template makefile for building an
Embedded Coder program.

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.

Specify Template Makefile Options


You can specify template makefile options by using the Make command box in
Configuration Parameters > Code Generation. Append the options after make_rtw
(or other make command), as in the following example:

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

• System target file-independent values Optimizations on (faster runs) and


Optimizations off (faster builds), which easily allow you to toggle compiler
optimizations on and off during code development
• The value Custom for entering custom compiler optimization flags at Simulink GUI
level (rather than at other levels of the build process)

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.

Template Makefiles for UNIX Platforms


The template makefiles for UNIX platforms are for the Free Software Foundation's GNU
Make. These makefiles conform to the guidelines specified in the IEEE®8 Std 1003.2-1992
(POSIX) standard.

• 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 — User-specific options, for example,

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.

Template Makefiles for the Microsoft Visual C++ Compiler


• “Visual C++ Executable Build” on page 43-28
• “Visual C++ Code Generation Only” on page 43-29

Visual C++ Executable Build

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:

• OPT_OPTS — Optimization option. Default is -O2. To enable debugging, specify the


option as OPT_OPTS=-Zi.
• OPTS — User-specific options.
• 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.

Visual C++ Code Generation Only

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 — User-specific options, for example,

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.

Template Makefiles for the LCC Compiler


The code generator provides template makefiles to create an executable for the Windows
platform using Lcc compiler Version 2.4 and GNU Make (gmake).

• 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 — User-specific options, for example,

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 — Additional include paths. For example:

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

Build Process Workflow for Real-Time Systems


The building process includes generating code in C or C++ from a model and building an
executable program from the generated code. This example can use a generic real-time
(GRT) or an embedded real-time (ERT) system target file (STF) for code generation. The
resulting standalone program runs on your development computer, independent of
external timing and events.

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

The model appears in the Simulink Editor model window.


5 In the model window, choose File > Save As. Navigate to your working folder,
aircraftexample. Save a copy of the slexAircraftExample model as
myAircraftExample.

Build Folder and Code Generation Folders


While producing code, the code generator creates a build folder within your working
folder. The build folder name is model_target_rtw, derived from the name of the
source model and the chosen system target file. The build folder stores generated source
code and other files created during the build process. Examine the build folder contents
at the end of this example.

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.

Set Model Parameters for Code Generation


To generate code from your model, you must change some of the model configuration
parameters. In particular, the generic real-time (GRT) system target file and most other
system target files require that the model specifies a fixed-step solver.

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:

1 Open the myAircraftExample model if it is not already open.


2 From the model window, open the Configuration Parameters dialog box by selecting
Simulation > Model Configuration Parameters.
3 Select Configuration Parameters > Solver. Enter the following parameter values
(some could already be set):

• Start time: 0.0


• Stop time: 60
• Type: Fixed-step
• Solver: ode5 (Dormand-Prince)
• Fixed step size (fundamental sample time): 0.1
• Treat each discrete rate as a separate task: Off
4 Click Apply.
5 Save the model. Simulation parameters persist with the model for use in future
sessions.

43-33
43 Program Building, Interaction, and Debugging in Simulink Coder

Configure Build Process


To configure the build process for your model, choose a system target file, a toolchain or
template makefile, and a make command.

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:

1 With the myAircraftExample model open, select Simulation > Model


Configuration Parameters to open the Configuration Parameters dialog box.
2 Select Configuration Parameters > Code Generation.
3 For System target file, enter grt.tlc, and click Apply.

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.

Set Code Generation Parameters


With the myAircraftExample model open, select Simulation > Model Configuration
Parameters:

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:

• Verbose build (RTWVerbose parameter)


• Retain .rtw file (RetainRTWFile parameter)
• Profile TLC (ProfileTLC parameter)
• Start TLC debugger when generating code (TLCDebug parameter)
• Start TLC coverage when generating code (TLCCoverage parameter)
• Enable TLC assertion (TLCAssert parameter)

Use the default settings.


5 Select Code Generation > Interface.

• 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.

Build and Run a Program


The build process generates C code from the model. It then compiles and links the
generated program to create an executable image. To build and run the program:

1 With the myAircraftExample model open, initiate code generation and the build
process for the model by using any of the following options:

• Click the Build Model button.


• Press Ctrl+B.
• Select Code > C/C++ Code > Build Model.

43-36
Build Process Workflow for Real-Time Systems

• Invoke the rtwbuild command from the MATLAB command line.


• Invoke the slbuild command from the MATLAB command line.

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

The code generation folder now contains an executable, myAircraftExample.exe


(Microsoft Windows platforms) or myAircraftExample (UNIX platforms). In
addition, the build process has created an slprj folder and a
myAircraftExample_grt_rtw folder in your “Code generation folder” (Simulink).

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

** starting the model **


** created myAircraftExample.mat **
4 To see the files created in the build folder, use the dir or ls command again. The
exact list of files produced varies among MATLAB platforms and versions. Here is a
sample list from a Windows platform:
>> dir myAircraftExample_grt_rtw

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

Contents of the Build Folder


The build process creates a build folder and names it model_target_rtw, where model
is the name of the source model and target is the system target file selected for the
model. In this example, the build folder is named myAircraftExample_grt_rtw.

The build folder includes the following generated files.

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:

• myAircraftExample.mk — Makefile for building executable using the specified


Toolchain.
• Object (.obj) files
• myAircraftExample.bat — Batch control file

43-38
See Also

• rtw_proj.tmw — Marker file


• buildInfo.mat — Build information for relocating generated code to another
development environment
• defines.txt — Preprocessor definitions required for compiling the generated code
• myAircraftExample_ref.rsp — Data to include as command-line arguments to
mex (Windows systems only)

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).

Customized Makefile Generation


After producing code, the code generator produces a customized makefile, model.mk.
The generated makefile instructs the make system utility to compile and link source code
generated from the model, any required harness program, libraries, or user-provided
modules. The code generator produces the file model.mk regardless of the approach that
you use for build process control:

• 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

• “Reports for Code Generation” (Simulink Coder)


• “Select and Configure C or C++ Compiler or IDE” on page 43-3

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

Control Regeneration of Top Model Code


When you rebuild a model, by default, the build process performs checks to determine
whether changes to the model or relevant settings require regeneration of the top model
code. The model build regenerates top model code if any of the following conditions is
true:

• The structural checksum of the model has changed.


• The top-model-only checksum has changed. The top-model-only checksum provides
information about top model parameters, such as application lifespan, maximum stack
size, make command, verbose and .rtw file debug settings, and TLCOptions.
• Any of the following TLC debugging model options, on the Configuration
Parameters > Code Generation > Advanced parameters tab, is on:

• Start TLC debugger when generating code (TLCDebug)


• Start TLC coverage when generating code (TLCCoverage)
• Enable TLC assertion (TLCAssert)
• Profile TLC (ProfileTLC)

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.

Regeneration of Top Model Code


If the checks determine that top model code generation is required, the build process
fully regenerates and compiles the model code. An example check is whether previously
generated code is not current due to a model update.

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

• The top model generated code is current for the model.


• No model settings require full regeneration,

This omission can significantly reduce model build times.

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.

Force Regeneration of Top Model Code


If you want to control or override the default top model build behavior, use one of the
following command-line options:

• 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

Reduce Build Time for Referenced Models


In a parallel computing environment, you can increase the speed of code generation and
compilation for models containing large model reference hierarchies. Achieve the speed
by building referenced models in parallel whenever conditions allow. For example, if you
have Parallel Computing Toolbox software, code generation and compilation for each
referenced model can be distributed across the cores of a multicore host computer. If you
also 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.

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

Parallel Building for Large Model Reference Hierarchies


The performance gain realized by using parallel builds for referenced models depends on
several factors. These factors include how many models can be built in parallel for a given
model referencing hierarchy, the size of the referenced models, and parallel computing
resources. The resources include the number of local and/or remote workers available
and the hardware attributes of the local and remote machines. Examples of hardware
attributes are the amount of RAM and number of cores.

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

Note In a MATLAB Distributed Computing Server parallel computing configuration,


parallel building is designed to work interactively with the software. You can initiate
builds from the Simulink user interface or from the MATLAB Command Window using
commands such as slbuild. You cannot initiate builds using batch or other batch mode
workflows.

Parallel Building Configuration Requirements


The following requirements apply to configuring your parallel computing environment for
building model reference hierarchies in parallel whenever conditions allow:

• 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.

Build Models in a Parallel Computing Environment


To take advantage of parallel building for a model reference hierarchy:
1 Set up a pool of local and/or remote MATLAB workers in your parallel computing
environment.
a Make sure that Parallel Computing Toolbox software is licensed and installed.
b To use remote workers, make sure that MATLAB Distributed Computing Server
software is licensed and installed.
c Issue MATLAB commands to set up the parallel pool, for example, parpool(4).
2 From the top model of the model reference hierarchy, open the Configuration
Parameters dialog box. Go to the Model Referencing pane and select the Enable

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.

• To turn on verbose messages in model builds for simulation, go to Configuration


Parameters > Optimization > Advanced parameters and select Verbose
accelerator builds.
• To turn on verbose messages in model builds for code generation, go to
Configuration Parameters > Code Generation > Advanced parameters and
select Verbose build.

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.

Locate Parallel Build Logs


If verbose builds are turned on when you build a model for which referenced models are
built in parallel, messages in the MATLAB Command Window record when each parallel
or serial build starts and finishes. For example,
### Initializing parallel workers for parallel model reference build.
### Parallel worker initialization complete.
### Starting parallel model reference SIM build for 'bot_model001'
### Starting parallel model reference SIM build for 'bot_model002'

43-48
Reduce Build Time for Referenced Models

### Starting parallel model reference SIM build for 'bot_model003'


### Starting parallel model reference SIM build for 'bot_model004'
### Finished parallel model reference SIM build for 'bot_model001'
### Finished parallel model reference SIM build for 'bot_model002'
### Finished parallel model reference SIM build for 'bot_model003'
### Finished parallel model reference SIM build for 'bot_model004'
### Starting parallel model reference RTW build for 'bot_model001'
### Starting parallel model reference RTW build for 'bot_model002'
### Starting parallel model reference RTW build for 'bot_model003'
### Starting parallel model reference RTW build for 'bot_model004'
### Finished parallel model reference RTW build for 'bot_model001'
### Finished parallel model reference RTW build for 'bot_model002'
### Finished parallel model reference RTW build for 'bot_model003'
### Finished parallel model reference RTW build for 'bot_model004'

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':

Error(s) encountered while building model "bot_model001"

### Cleaning up parallel workers.

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

subfolder such as build_folder/par_mdl_ref/bot_model001/slprj/grt/


bot_model001, build_folder/par_mdl_ref/bot_model001/slprj/ert/
bot_model001, or build_folder/par_mdl_ref/bot_model001/slprj/sim/
bot_model001.

View Build Process Status


The Build Process Status window lets you view in-progress build status or cancel in-
progress parallel builds of models. After completing a model build, you can view the
completion status by using the Build Process Status window. For more information, see
“Apply Build Process Status to Improve Parallel Builds” on page 43-51.

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

Apply Build Process Status to Improve Parallel Builds


The Build Process Status window lets you view in-progress build status or cancel in-
progress parallel builds of models. For more information, see “View Build Process Status”
on page 43-50.

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.

1 Open a parallel pool for the build process.

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

The table describes the types of build status.

Build Process Description


Status
Blocked The code generator cannot schedule the model build because the
build is blocked by dependencies. For example, another model
build must complete before the blocked build can be scheduled.
Scheduled For parallel build processes, the code generator schedules the
model build when it is not blocked by dependencies. The model
build waits at the scheduled status until a parallel core is available
to process the model build.
Building The code generator is executing the build process for the model.
Completed or Error When the build process exits successfully, the status is Completed.
When the build process is not success, the status is Error.
Up To Date When the build process detects that no code generation is needed
(for example, generated code is current with the model), the
status is Up to Date.

43-54
See Also

Build Process Description


Status
Canceling or When you use the Cancel Build button, the build process
Canceled changes the status of all incomplete builds (for example, all except
Completed or Error status) to Canceling. After processing the
Canceling operation, the build process changes the status of these
builds to Canceled.

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

Relocate Code to Another Development Environment


If you require relocating the static and generated code files for a model to another
development environment, use the pack-and-go utility. This condition occurs when your
system or integrated development environment (IDE) does not include MATLAB and
Simulink products.

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.

To package model code files, you can do either of the following:

• 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.

Package Code Using the User Interface


To package and relocate code for your model using the user interface:

1 Open Configuration Parameters > Code Generation.

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.

Package Code Using the Command-Line Interface


To package and relocate code for your model using the command-line interface:

1 Select a structure for the zip file. on page 43-58


2 Select a name for the zip file. on page 43-59
3 Package the model code files in the zip file. on page 43-59
4 Inspect the generated zip file. on page 43-60
5 Relocate and unpack the zip file. on page 43-60

Select a Structure for the Zip 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... Then Use a...


You are relocating files to an IDE that does Single, flat folder structure
not use the generated makefile, or the code
is not dependent on the relative location of
required static files
The destination development environment Hierarchical structure
must maintain the folder structure of the
source environment because it uses the
generated makefile, or the code depends on
the relative location of files

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:

• mlrFiles.zip — files in your matlabroot folder tree

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.

Select a Name for the Zip File

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.

Package Model Code in a Zip File

Package model code files by using the PostCodeGenCommand configuration parameter,


packNGo function, and build information object for the model. You can set up the
packaging operation to use:

• A system generated build information object.

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.

Inspect a Generated Zip File

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 and Unpack a Zip File

Relocate the generated zip file to the destination development environment and unpack
the file.

43-60
Relocate Code to Another Development Environment

Code Packaging Example

This example shows how to package code files generated for the example model
rtwdemo_rtwintro using the command-line interface:

1 Set your working folder to a writable folder.


2 Open the model rtwdemo_rtwintro and save a copy to your working folder.
3 Enter the following MATLAB command:
set_param('rtwdemo_rtwintro', 'PostCodeGenCommand',...
'packNGo(buildInfo, {''packType'' ''hierarchical''})');

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.

Build Integrated Code Outside the Simulink Environment


Identify required files and interfaces for calling generated code in an external build
process.

Learn how to:

• Collect files required for building integrated code outside of Simulink®.


• Interface with external variables and functions.

For information about the example model and related examples, see “Generate C Code
from a Control Algorithm for an Embedded System”.

Collect and Build Required Data and Files

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.

Open the example model, rtwdemo_PCG_Eval_P5.

This model is configured to run packNGo after code generation.

Generate code from the entire model.

To generate the zip file manually:

1 Load the file buildInfo.mat (located in the rtwdemo_PCG_Eval_P5_ert_rtw


subfolder).
2 At the command prompt, enter the command packNGo(buildInfo).

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.

Integrating the Generated Code into an Existing System

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.

Overview of Integration Environment

A full embedded controls system consists of multiple hardware and software components.
Control algorithms are just one type of component. Other components can be:

• An operating system (OS)


• A scheduling layer
• Physical hardware I/O
• Low-level hardware device drivers

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:

• Defines function interfaces (function prototypes).


• Includes files that declare external data.
• Defines extern data.
• Initializes data.
• Calls simulated hardware.

43-63
43 Program Building, Interaction, and Debugging in Simulink Coder

• Calls algorithmic functions.

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.

Match System Interfaces

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.

Connect Input Data

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.

Connect Output Data

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.

Access Additional Data

The generated code contains several structures that store commonly used data including:

• Block state values (integrator, transfer functions)


• Local parameters
• Time

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.

Data Type Data Name Data Purpose

Constants |model_cP| Constant parameters


Constants |model_cB| Constant block I/O
Output |model_U| Root and atomic subsystem input
Output |model_Y| Root and atomic subsystem output
Internal data |model_B| Value of block output
Internal data |model_D| State information vectors
Internal data |model_M| Time and other system level data
Internal data |model_Zero| Zero-crossings
Parameters |model_P| Parameters

Match Function Call Interfaces

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.

Calls to the function PI_Cntrl_Reusable use a mixture of separate, unstructured global


variables and Simulink® Coder™ data structures. The handwritten code defines these
variables. The structure types are defined in rtwdemo_PCG_Eval_P5.h.

Build Project in Eclipse™ Environment

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

• Eclipse™ SDK 3.2


• Eclipse™ CDT 3.3
• Cygwin™/GCC 3.4.4-1
• Cygwin™/GDB 20060706-2

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:

Set up the build folder.

Alternatively, to install the files manually:

1 Create a build folder (Eclipse_Build_P5).


2 Unzip the file rtwdemo_PCG_Eval_P5.zip into the build folder.
3 Delete the files rtwdemo_PCG_Eval_P5.c, ert_main.c and rt_logging.c, which
are replaced by example_main.c.

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

packNGo Function Limitations


The following limitations apply to the packNGo function:

• 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

Executable Program Generation


The following figure shows how the process for program building.

Click Build
Button

Simulink Generate model.c


Model Code model.h
model_private.h

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

Profile Code Performance


By profiling the performance of generated code, you can help verify that the code meets
performance requirements.

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

Use the Profile Hook Function Interface


You can profile code generated with code generation technology by using a Target
Language Compiler (TLC) hook function interface.

To use the profile hook function interface:

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.

Function Input Arguments Output Type Description


ProfilerHeaders void Array of header file Return an array of the
names header file names to
be included in the
generated code.

43-72
Profile Code Performance

Function Input Arguments Output Type Description


ProfilerTypedefs void typedefs Generate code
statements for profiler
type definitions.
ProfilerGlobal‐ system Global data for the Generate code
Data specified system statements that
declare global data.
ProfilerExtern‐ system extern declarations Generate code
DataDecls for the specified statements that create
system global extern
declarations.
ProfilerSystem‐ system, Declarations for the Generate code for
Decls functionType specified system for required variable
the specified declarations within the
functionType scope of an atomic
subsystem Output,
Update,
OutputUpdate, or
Derivatives
function.
ProfilerSystem‐ system, Profiler start Generate code that
Start functionType commands for the starts the profiler
specified system and within the scope of an
functionType atomic subsystem
Output, Update,
OutputUpdate, or
Derivatives
function.
ProfilerSystem‐ system, Profiler end commands Generate code that
Finish functionType for the specified stops the profiler
system and within the scope of the
functionType Output, Update,
OutputUpdate, or
Derivatives
functions of an atomic
subsystem.

43-73
43 Program Building, Interaction, and Debugging in Simulink Coder

Function Input Arguments Output Type Description


ProfilerSystem‐ system Profiler termination Generate code that
Terminate code for the specified terminates profiling
system (and possibly reports
results) for an atomic
subsystem.

For an example TLC file, see matlabroot/toolbox/rtw/rtwdemos/


rtwdemo_profile_hook.tlc.
2 In your target.tlc file, define the following global variables.

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

Profile Hook Function Interface Limitation


The TLC hook function interface for profiling code performance does not support the S-
function system target file (rtwsfcn.tlc).

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

• “Host-Target Communication with External Mode Simulation” on page 44-2


• “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 Host/Target Communication in Simulink Coder

Host-Target Communication with External Mode


Simulation
You can use external mode simulations for rapid prototyping. An external mode simulation
establishes a communication channel between Simulink on your development computer
(host) and the target hardware that runs the executable file created by the code
generation and build process.

Through the communication channel, you can:

• 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

Communication Supported By Why Select


Mechanism
XCP, the Universal ERT and GRT system target XCP external mode:
Measurement and files.
Calibration Protocol • Uses a standard
These Simulink support communication protocol.
packages: • Requires only a lightweight
communication software
• Xilinx® Zynq® ZC7000
stack on the target
development kits:
hardware.
• ZedBoard • Supports signal logging and
• ZC702 Evaluation Kit streaming for Dashboard
blocks and the Simulation
• ZC706 Evaluation Kit Data Inspector. You can
• Intel SoC FPGA stream signals from within
evaluation boards: a referenced model
hierarchy.
• Cyclone® V SoC
Development Kit • Provides documented
ext_mode.h API for
• Arrow® SoCkit external mode target
• Arria® 10 SoC connectivity.
Development Kit • Supports streaming of
• ARM® Cortex®-A9 execution-time metrics to
processors the Simulation Data
• STMicroelectronics® Inspector for host-based
Discovery boards: and support package
external mode simulations.
• STM32F746NG
For information about running
• STM32F769NI XCP external mode
simulations, see:

• “External Mode Simulation


with XCP Communication”
on page 44-8
• “Customize XCP Slave
Software” on page 44-22

44-4
Host-Target Communication with External Mode Simulation

Communication Supported By Why Select


Mechanism
TCP/IP and serial ERT, GRT, and RSim system You do not want to use the
(RS-232) target files. Simulation Data Inspector for
visualizing, exporting, and
Simulink support packages. saving data.

You want to use signal


triggering.

For information about running


TCP/IP and serial external
mode simulations, see:

• “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

This table summarises feature support for both forms of external mode simulations.

Feature XCP Support TCP/IP and Serial


Support
With Dashboard blocks Yes Yes
Parameter tuning Of tunable (Simulink) block Yes Yes
parameters
Yes. Includes signals No
Simulation Data Inspector within referenced
models.
Yes. Includes signals No
Logic Analyzer within referenced
models.

44-5
44 Host/Target Communication in Simulink Coder

Feature XCP Support TCP/IP and Serial


Support
Dashboard Yes, provided signal No
logging is enabled
for block input.
Floating Scope, Scope Yes, provided signal Yes
logging is enabled
for block input.
Spectrum Analyzer, Time Yes, provided signal Yes
Scope (DSP System logging is enabled
Toolbox) for block input.
Display Yes, provided signal Yes
logging is enabled
for block input.
Blocks that
To Workspace Yes, provided signal Yes
receive and
logging is enabled
display signals
for block input.
from target
application User-written S-Function. Yes, provided signal Yes
logging is enabled
An external mode method for block input.
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 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

External Mode Simulation with XCP Communication


Set up and run external mode simulations (Simulink Coder) that use an XCP
communication channel.

Run XCP External Mode Simulation From Simulink Editor


Configure and run an external mode simulation (Simulink Coder) that uses the XCP
communication protocol. During the simulation:

• 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

1 Create a folder for this example.

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:

a Right-click Test Signal.


b From the context menu, select Log Selected Signals. If you do not enable
signal logging, you cannot view the signal with the Scope block or stream signal
data to the Simulation Data Inspector.
6 Configure the Half Gauge block to monitor the value of Test Signal:

44-8
External Mode Simulation with XCP Communication

a Double-click the Half Gauge block.


b In the Simulink Editor, select Test Signal.
c In the Block Parameters dialog box:

• Connect the block to Test Signal.


• In the Maximum field, enter a value, for example, 1.
d Click OK.
7 Configure the Knob block to tune the Amplitude parameter of the Sine Wave block:

a Double-click the Knob block.


b In the Simulink Editor, select the Sine Wave block.
c In the Block Parameters dialog box:

• 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

Build Target Application for XCP External Mode

1 Select Simulation > Model Configuration Parameters.


2 On the Solver pane:

• In the Type field, specify Fixed-step.


• Under Solver details, in the Fixed-step size field, specify a value, for example,
0.1.
3 On the Code Generation pane, set System target file to grt.tlc or ert.tlc
(requires Embedded Coder license).
4 On the Code Generation > Optimization pane, set Default parameter behavior
to Tunable.
5 On the Code Generation > Interface pane, select the External mode check box.
6 Set Transport layer to XCP on TCP/IP, which specifies ext_xcp for MEX-file
name.
7 In the Mex-file arguments field, enter 'localhost' 1 5555. These arguments
specify that the:

• Target hardware is your development computer.


• Verbosity level is 1
• Port number of the TCP/IP server is 5555.
8 Leave the Static memory allocation check unselected. The platform abstraction
layer of the XCP slave software provides a configurable memory allocator.
9 If System target file is ert.tlc, on the Code Generation > Templates pane:

• 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.

In Windows, in addition to the executable file, xcpExample.exe, the build process


creates xcpExample.pdb, which is a debugging symbols file for signals and parameters.

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.

Run Target Application

1 Open a command window for your operating system and navigate to the
ext_mode_xcp_example folder.
2 In the command window, enter:

xcpExample -w -tf inf -port 5555

The target application runs as a separate process on your development computer:

• -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:

a Select Simulation > Mode > External.


b
On the Simulink Editor toolbar, click the Connect to Target button . Simulink
downloads current parameter values from the model to the target application.
4 To run the generated model code, click the Run button.

Monitor Signal and Tune Parameter

You can monitor Test Signal through the:

• Scope block – Double-click the block.


• Simulation Data Inspector – Click the Simulation Data Inspector button. When the
Simulation Data Inspector opens, select the Test Signal check box, which displays
streamed data.
• Half-Gauge block.

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:

• If a block parameter is a variable in the MATLAB workspace, from the Command


Window, assign a new value to the variable. Then, in the Simulink Editor, select
Simulation > Update Diagram. Simulink downloads the new value to the target
application.
• Open the Block Parameter dialog box. In the parameter field, specify the required
value. When you click Apply or OK, Simulink downloads the new parameter value to
the target application.

For more information about parameter tuning with generated code, see:

• “External Mode Simulation with TCP/IP or Serial Communication” on page 44-36

• “Create Tunable Calibration Parameter in the Generated Code” on page 22-121

Stop Target Application

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

execution, click the Disconnect from Target button .

Target Application Arguments


You can run your target application with optional arguments.

Argument Description
-w Specify that the target application enters and stays in a
wait state until it receives a message from Simulink.

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.

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.

For XCP on Serial transport layer,


specify serial port ID. For example:

• On Windows, 'COM1' or 1 for COM1,


'COM2' or 2 for COM2, etc.

• On Linux, '/dev/ttyS0', etc.


-baud value For XCP on Serial transport layer,
specify baud value. 1200, 2400, 4800, 9600,
14400, 19200, 38400, 57600 (default), or
115200.

Graphical Controls for XCP External Mode Simulations


You can control an XCP external mode simulation through:

• The Simulink Editor toolbar.


• A Simulink Editor menu.
• The External Mode Control Panel. To open this dialog box, in Simulink Editor, select
Code > External Mode Control Panel.

44-13
44 Host/Target Communication in Simulink Coder

This table gives the controls that you can use for an XCP external mode simulation.

External Mode Toolbar Menu External Mode Control


Action Panel
Set simulation mode of From the simulation Simulation > Connect
model to external mode drop-down list, Mode > External
mode. select External. If the model simulation mode
is not already set, clicking
the button sets the
simulation mode to external.
Connect Simulink to a Connect to Target Simulation > Connect
waiting or running Connect to Target
target application. button When the Simulink is
connected to the target
application, the button
changes to Disconnect.

44-14
External Mode Simulation with XCP Communication

External Mode Toolbar Menu External Mode Control


Action Panel
Start real-time Run button Simulation > Run Start Real-Time Code
execution of generated (keyboard shortcut
code in the target Ctrl+T) When the generated code
environment. starts executing, the button
changes to Stop Real-Time
Code.
Disconnect Simulink Disconnect from Simulation > Disconnect
from the target Disconnect from
environment, but do Target button Target
not stop real-time
execution of code.
Stop target application Stop button Simulation > Stop Stop Real-Time Code
execution and (keyboard shortcut
disconnect Simulink Ctrl+Shift+T)
from the target
environment.

44-15
44 Host/Target Communication in Simulink Coder

External Mode Toolbar Menu External Mode Control


Action Panel
Tune batch of block N/A N/A Batch download
parameters.
To tune a batch of block
parameters:

1 In the External Mode


Control Panel, select
Batch download.
2 In Simulink Editor,
modify the required
block parameters.
3 When you modify
parameters, the
External Mode Control
Panel displays this
message next to
Download:

Parameter changes pending...

Simulink stores the


modified parameters
locally.
4 Click Download.
Simulink downloads the
batch of modified
parameters to the target
application.

Run XCP External Mode Simulation From Command Line


You can use commands or scripts to run XCP external mode simulations. Use get_param
and set_param commands to retrieve and set the values of model parameters.

These commands assume that a Simulink model is open and a target application is
running:

44-16
External Mode Simulation with XCP Communication

1 Set simulation mode of the model to external mode.

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');

To disconnect Simulink from the target application without stopping execution of


generated code, use this command:

set_param(gcs,'SimulationCommand','disconnect');

XCP External Mode Limitations


This table describes limitations that apply to external mode simulations that use XCP
communication.

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

If you make these changes to the block diagram,


then you must rebuild the target application.

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.

If the Simulink block diagram does not match the


target application, Simulink produces an error
stating that the checksums do not match. The
checksums take into account the top models, but not

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

Customize XCP Slave Software


The XCP communication protocol for Simulink external mode simulations is a master-
slave communication protocol. By default, the software supports XCP external mode
simulations:

• 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.

The external mode target connectivity software comprises:

• External mode abstraction layer


• XCP slave protocol layer
• XCP slave transport layer
• XCP platform abstraction layer

44-22
Customize XCP Slave Software

External Mode Abstraction Layer


To communicate with Simulink during an external mode simulation, your target
application must invoke functions from the external mode abstraction layer.

The parent folder for source files is:

matlabroot\toolbox\coder\xcp\src\target\ext_mode

The layer APIs are declared in include\ext_mode.h and implemented in src


\xcp_ext_mode.c.

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

Stage Function Purpose


INITIALIZE extmodeParseArgs Extract external mode command
line arguments.
modelName_initialize Initialize generated Simulink
model code.
extmodeInit Initialize external mode target
connectivity.
HOST START extmodeWaitForHostReque Wait for a start request from
REQUEST st development computer, which is
created when you click Run
button.
RUN modelName_step Run single step of generated
Simulink model code.
extmodeEvent For sample time ID of the model,
sample signals generated by model
step function and pass packet
content to transport layer of
communication protocol for
transmission to development
computer.
extmodeBackgroundRun Transmit and receive packet from
physical communication interface
and process packet content in
accordance with selected
communication protocol.
HOST STOP extmodeStopRequested Check whether request to stop
REQUEST OR external mode simulation is
SIMULATION received from model on
COMPLETE development computer. The
request is created when you click
the Stop button.
extmodeSimulationComple Check whether execution of
te generated model code is complete.
RESET modelName_terminate Terminate generated Simulink
model code.

44-25
44 Host/Target Communication in Simulink Coder

Stage Function Purpose


extmodeReset Reset external mode target
connectivity to initial state.

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.

The pseudo-code simulates multithreading by running periodicThread and


extmodeBackgroundRun sequentially within the same while() loop.
/*------------- Pseudo-Code Example -------------*/
/* Define periodic thread */
void periodicThread(void)
{
/* Run model step function */
modelName_step();
/* Notify external mode abstraction layer about periodic event */
extmodeEvent(PERIODIC_EVENT_ID, currentSimulationTime);
}

/* Main function for target application */


main(int argc, char *argv[])
{
/*------------- INITIALIZE -------------*/
/* Parse external mode command line arguments */
extmodeParseArgs(argc, argv);

/* Initialize model */
modelName_initialize();

/* Initialize external mode target connectivity */


extmodeInit(extModeInfo, finalSimulationTime);

/*------------- HOST START REQUEST -------------*/


/* Wait until a start request is received from development computer */
extmodeWaitForHostRequest(EXTMODE_WAIT_FOREVER);

/*------- HOST STOP REQUEST OR SIMULATION COMPLETE -------*/


/* While simulation is not complete and stop request is not received */
while (!extmodeSimulationComplete() && !extmodeStopRequested()) {

/*------------- RUN -------------*/


periodicThread();
extmodeBackgroundRun();
}

/*------------- RESET -------------*/


/* Terminate model */

44-26
Customize XCP Slave Software

modelName_terminate();

/* Reset external mode target connectivity */


extmodeReset();
return 0;
}

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.

XCP Slave Protocol Layer


The XCP slave protocol layer interprets XCP commands and data according to the
Association for Standardisation of Automation and Measuring Systems (ASAM) standard,
ASAM MCD-1 XCP.

The source folder is:

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).

XCP Slave Transport Layer


The XCP slave transport layer transmits and receives messages from the communication
medium according to ASAM specifications.

The source folder is:

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).

XCP Platform Abstraction Layer


The XCP platform abstraction layer provides:

• 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

• The implementation of a static memory allocator on page 44-28.


• Other target hardware-specific functionality (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:

• Store XCP messages that are received and transmitted.


• Hold internal data structures.

In an external mode simulation, the build process automatically adds memory allocator
files to the build information object.

The xcpMemBlockSizes and xcpMemBlockCounts preprocessor macros define memory


allocation.

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:

• The block size through the XCP_MEM_BLOCK_N_SIZE preprocessor macro.


• The number of blocks in each set through the XCP_MEM_BLOCK_N_NUMBER
preprocessor macro.

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

Configure the block sizes of the different sets in ascending order:

XCP_MEM_BLOCK_N_SIZE < XCP_MEM_BLOCK_N+1_SIZE

The smallest block size, XCP_MEM_BLOCK_1_SIZE, must be large enough to hold a


pointer.

Configure alignment for the memory allocator through the XCP_MEM_ALIGNMENT


preprocessor macro. For example:

#define XCP_MEM_ALIGNMENT 8

Other Platform Abstraction Layer Functionality

This file defines the platform abstraction layer interface:


matlabroot\toolbox\coder\xcp\src\target\slave\platform\include\xcp_platform.h

To implement custom platform abstraction layer functionality, add the


XCP_CUSTOM_PLATFORM preprocessor macro to the build information object. You must
provide the implementation of the custom functionality in a file named
xcp_platform_custom.h. If you do not define XCP_CUSTOM_PLATFORM, the build
process uses default files that support Linux and Windows systems.

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.

To support mutual exclusion for your target hardware, provide


a custom implementation.

The default implementation for Linux and Windows supports


mutual exclusion.

#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)


...
#define XCP_MUTEX_DEFINE(lock) HANDLE lock
#define XCP_MUTEX_INIT(lock) lock = CreateMutex(0, FALSE, 0)
#define XCP_MUTEX_LOCK(lock) WaitForSingleObject((lock), INFINITE
#define XCP_MUTEX_UNLOCK(lock) ReleaseMutex(lock)

#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:

#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)


...
#define XCP_SLEEP(seconds,microseconds) Sleep((seconds) * 1000 \
+ (((microseconds) + 1000 - 1) / 1000))

#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.

The XCP Master extracts the addresses of signals and


parameters of the model by parsing the debug information that
is created by the build process. The debug information is in
DWARF or PDB format.

The XCP Master requests access to parameters and signals by


sending an XCP command that contains the arguments
addressExtension and address.

When addressExtension and address information is


received by the target hardware, the XCP Slave must convert
the address to the location of the variable in the target
hardware memory. The variable location is assigned by the
loader and is target-specific.

Use the XCP_ADDRESS_GET() macro to specify the conversion


logic. The default implementation for Linux and Windows
systems is:
#if defined(__MINGW32__) || defined(__MINGW64__)
#define XCP_ADDRESS_GET(addressExtension, address) \
(uint8_T*) ((uintptr_t) address)
#else
#define XCP_ADDRESS_GET(addressExtension, address) \
(uint8_T*) ((address) + (uint8_T*)&__ImageBase)
#endif

Currently, only 32-bit hardware architectures are supported, so


addressExtension is 0.

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.

If you do not define the XCP_MEMCPY and XCP_MEMSET


preprocessor macros, the default implementation specifies the
standard C functions, memcpy and memset.

#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.

To replace the -w option, you can use this command to specify


that the target application enters and stays in a wait state until
it receives a Connect message from Simulink:

set_param(modelName, 'OnTargetWaitForStart', 'on');

The build process provides the required option (-


DON_TARGET_WAIT_FOR_START=1) to the compiler.

Create Custom Abstraction Layer

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

/* _POSIX_C_SOURCE >= 199309L */


#if _POSIX_C_SOURCE >= 199309L
#define XCP_SLEEP(seconds,microseconds) do {struct timespec t;\
t.tv_sec = seconds; t.tv_nsec = microseconds * 1000; nanosleep(&t, NULL);} while(0)
#else
/* nanosleep is not available. Use select instead. */
#define XCP_SLEEP(seconds,microseconds) do {struct timeval t; t.tv_sec = seconds;\
t.tv_usec = microseconds; select(0, NULL, NULL, NULL, &t);} while(0)
#endif /* _POSIX_C_SOURCE >= 199309L */
#endif
2 Define the post-code generation command.

function myXCPTargetPostCodeGenCommand(buildInfo)

buildInfo.addDefines('-DXCP_CUSTOM_PLATFORM', 'OPTS');

% Configure the default memory allocator


buildInfo.addDefines('-DXCP_MEM_BLOCK_1_SIZE=64', 'OPTS');
buildInfo.addDefines('-DXCP_MEM_BLOCK_1_NUMBER=46', 'OPTS');
buildInfo.addDefines('-DXCP_MEM_BLOCK_2_SIZE=256', 'OPTS');
buildInfo.addDefines('-DXCP_MEM_BLOCK_2_NUMBER=10', 'OPTS');

% Add my rtiostream
buildInfo.addSourceFiles(customRtIOStreamFileName, customRtIOStreamSrcPath);

% If the target hardware does not support parsing of command


% line arguments
buildInfo.addDefines('-DEXTMODE_DISABLE_ARGS_PROCESSING', 'OPTS');

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

External Mode Simulation with TCP/IP or Serial


Communication
Set up and run an external mode simulation that uses a TCP/IP or serial (RS-232)
communication channel.

1 Create and configure a simple model.


2 Build the target executable file.
3 Run the target program.
4 Tune parameters.

The example, which uses the GRT target, does not require external hardware. The
generated executable file runs:

• On the development computer that hosts Simulink and Simulink Coder.


• As a separate process from MATLAB and Simulink.

Create and Configure Model


In this part of the example, you create a simple model, ex_extModeExample. You also
create a folder called ext_mode_example to store the model and the generated
executable.

To create the folder and the model:

1 From the MATLAB command line, type:

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

4 Define and assign two MATLAB workspace variables, A and B:

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.

8 Save the model as ex_extModeExample.

Build Target Executable


Set up the model and code generation parameters required for an external mode
compatible target program. Then, generate code and build the target executable.

1 Open the Configuration Parameters dialog box by selecting Simulation > Model
Configuration Parameters.
2 Select the Solver pane.
3 In the Solver selection subpane:

a In the Type field, select Fixed-step.


b In the Solver field, select discrete (no continuous states).

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.)

Leave Start time set to the default value of 0.0.

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.

Run Target Program


You now run the ex_extModeExample target executable and use Simulink as an
interactive front end to the running target program. The executable file is in your working
folder. Run the target program and establish communication between Simulink and the
target.

Note An external mode program like ex_extModeExample is a host-based executable.


Its execution is not tied to a real-time operating system (RTOS) or a periodic timer
interrupt, and it does not run in real time. The program just runs as fast as possible, and
the time units it counts off are simulated time units that do not correspond to time in the
world outside the program.

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.

Enter this command:

ex_extModeExample -tf inf -w

Note Alternatively, you can run the target program from the MATLAB Command
Window, using the following syntax.

!ex_extModeExample -tf inf -w &

The target program begins execution, and enters a wait state.

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

4 To simultaneously disconnect host/target communication and end execution of the


target program, from the Simulation menu, select Stop. Alternatively, in the
External Mode Control Panel, click Stop Real-Time Code.

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:

/* Parameters (auto storage) */


struct P_ex_extModeExample_T_ {
real_T A; /* Variable: A
*/
real_T B; /* Variable: B
*/
real_T SineWave_Amp; /* Expression: 1
*/
real_T SineWave_Bias; /* Expression: 0
*/
real_T SineWave_Freq; /* Expression: 1
*/
real_T SineWave_Phase; /* Expression: 0
*/
};

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_:

ex_extModeExample_B.GainA = ex_extModeExample_P.A * rtb_SineWave;

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.

Control Memory Allocation for Communication Buffers in


Target
If you select the Code Generation > Interface > Static memory allocation check box
(for GRT and ERT targets), the code generator produces code for external mode that uses
only static memory allocation (“malloc-free” code). Selecting Static memory allocation
enables the Static memory buffer size parameter. Use this parameter to specify the size
of the external mode static memory buffer. The default value is 1,000,000 bytes. If you
enter too small a value for your program, external mode issues an out-of-memory error
when it tries to allocate more memory than you allowed. In such cases, increase the value
in the Static memory buffer size field and regenerate the code.

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.

Pure Integer Code with External Mode


For an ERT target, if you clear the Code Generation > Interface > Support: floating-
point numberscheck box, you can generate pure integer code that is free of doubles and
floats. For more information, see “Model Configuration Parameters: Code Generation
Interface” (Simulink Coder).

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

stop time in seconds / base rate step size in seconds

Control External Mode Simulation Through Editor Toolbar


This table gives Simulink Editor features that you can use to control an external mode
simulation.

External Mode Action Toolbar Control Menu Control External Mode


Control Panel Button
Set the simulation From the simulation Simulation > Connect (if the model
mode of your model to mode drop-down list, Mode > External simulation mode is not
external mode select External already set, sets the
simulation mode to
external mode)
Connect your model to Connect to Target Simulation > Connect
a waiting or running Connect to Target
target program button
Start running real-time Run button Simulation > Run Start Real-Time Code
code in the target (keyboard shortcut Ctrl
environment +T)
Disconnect your model Disconnect from Simulation > Disconnect
from the target Disconnect from
environment (does not Target button Target
halt running real-time
code)

44-47
44 Host/Target Communication in Simulink Coder

External Mode Action Toolbar Control Menu Control External Mode


Control Panel Button
Stop target program Stop button Simulation > Stop Stop Real-Time Code
execution and (keyboard shortcut Ctrl
disconnect your model +Shift+T)
from the target
environment

Control External Mode Simulation Through External Mode


Control Panel
The External Mode Control Panel provides centralized control of external mode
operations, including:

• “Connect, Start, and Stop” on page 44-49


• “Upload Target Program Signal Data to Host” on page 44-50
• “Download Parameters to Target Program” on page 44-51
• “Configure Host Monitoring of Target Program Signal Data” on page 44-52
• “Configure Host Archiving of Target Program Signal Data” on page 44-60

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

Connect, Start, and Stop

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.

Connect sets the model simulation mode to external mode.

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.

Upload Target Program Signal Data to Host

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:

• Do not appear in the External Signal & Triggering dialog box.


• Do not log data to external mode archiving.
• Support manual triggering only.

The Floating scope section contains the following parameters:

• 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

• To trigger data uploading to floating scopes, select Enable data uploading.


• To cancel data uploading to floating scopes, clear Enable data uploading.
• Duration edit field, which specifies the number of base-rate steps for which external
mode logs floating scopes data after a trigger event. By default, it is set to auto,
which causes the duration value set in the External Signal & Triggering dialog box to
be used. The default duration value is 1000 base rate steps.

Download Parameters to Target Program

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

Configure Host Monitoring of Target Program Signal Data


• “Role of Trigger in Signal Data Uploading” on page 44-53
• “Configure Signal Data Uploading” on page 44-53
• “Default Trigger Options” on page 44-54
• “Select Signals to Upload” on page 44-55
• “Configure Trigger Options” on page 44-55
• “Select Trigger Signal” on page 44-57
• “Set Trigger Conditions” on page 44-58
• “Modify Signal and Triggering Options While Connected” on page 44-59

44-52
External Mode Simulation with TCP/IP or Serial Communication

Role of Trigger in Signal Data Uploading

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.

Configure Signal Data Uploading

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.

Default Trigger Options

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.

The default configuration of trigger options is:

• Select all: on
• Source: manual
• Mode: normal
• Duration: 1000
• Delay: 0
• Arm when connecting to target: on

Select Signals to Upload

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.

The Clear all button clears all signals.

Configure Trigger Options

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

• Source: manual or signal. Controls whether a button or a signal triggers data


uploading.

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 the trigger Source is manual, data uploading begins immediately.


• If the trigger Source is signal, monitoring of the trigger signal begins
immediately. Data uploading begins when the trigger signal satisfies trigger
conditions (as defined in the Trigger signal section).

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.

Select Trigger Signal

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.

Set Trigger Conditions

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.

Modify Signal and Triggering Options While Connected

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:

1 Open the External Mode Control Panel.


2 Click Cancel Trigger. Triggering and display of uploaded data stops.
3 Open the External Signal & Triggering dialog box and modify signal and trigger
options as required. For example, in the Signal selection section, you can enable or
disable a scope, and in the Trigger options section, change the trigger Mode, for
example, from normal to one-shot.
4 Click Arm Trigger. Triggering and display of uploaded data resumes, with your
modifications.

44-59
44 Host/Target Communication in Simulink Coder

Configure Host Archiving of Target Program Signal Data


In external mode, you can use the Simulink Scope and To Workspace blocks to archive
data to disk.

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.

The Enable Data Archiving dialog box supports:

• 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

Automated Data Archiving

To configure automatic writing of logging results to disk, optionally including


intermediate results, use the Enable archiving option and the controls it enables . The
dialog box provides the following related controls:

• 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.

Blocks and Subsystems Compatible with External Mode


• “Compatible Blocks” on page 44-63
• “Signal Viewing Subsystems” on page 44-64
• “Supported Blocks for Data Archiving” on page 44-66

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

• Floating Scope and Scope blocks


• Spectrum Analyzer and Time Scope blocks from the DSP System Toolbox product
• Display blocks
• To Workspace blocks
• User-written S-Function blocks

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.

Signal Viewing Subsystems

A Signal Viewing Subsystem is an atomic subsystem that encapsulates processing and


viewing of signals received from the target system. A Signal Viewing Subsystem runs only
on the host, and does not generate code in the target system. Signal Viewing Subsystems
run in normal, accelerator, rapid accelerator, and external simulation modes.

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

To declare a subsystem to be a Signal Viewing Subsystem:

1 In the Block Parameters dialog box, select the Treat as atomic unit option.

For more information on atomic subsystems, see “Control Generation of Subsystem


Functions” (Simulink Coder).
2 To turn the SimViewingDevice property on, use the set_param command:

set_param('blockname', 'SimViewingDevice','on')

'blockname' is the name of the subsystem.


3 Make sure the subsystem meets the following requirements:

• 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 following model, sink_examp, contains an atomic subsystem, theSink.

The subsystem theSink applies a gain and an offset to its input signal and displays it on
a Scope block.

If theSink is declared as a Signal Viewing Subsystem, the generated target program


includes only the code for the Sine Wave block. If theSink is selected and armed in the

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.

Supported Blocks for Data Archiving

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.

External Mode Mechanism for Downloading Tunable


Parameters
• “Download Mechanism” on page 44-66
• “Inlined and Tunable Parameters” on page 44-68

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 Process


mexFunction

External Program

Client Server
IPC Code IPC Code
External Interface
ext_svr.
MEX-file (e.g., ext_comm)

Interprocess Communication Channel Transport Layer

External Mode Architecture

Inlined and Tunable Parameters

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.

Automatic Parameter Uploading on Host/Target Connection

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.

Choose Communication Protocol for Client and Server


• “Introduction” on page 44-70
• “Using the TCP/IP Implementation” on page 44-70
• “Using the Serial Implementation” on page 44-73
• “Run the External Program” on page 44-75
• “Implement an External Mode Protocol Layer” on page 44-77

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.

Using the TCP/IP Implementation

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).

To use Simulink external mode over TCP/IP:

• 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')

You can specify multiple targets and/or transports with additional


cm.ExtModeTransports.add lines, for example:
function sl_customization(cm)
cm.ExtModeTransports.add('mytarget.tlc', 'tcpip', 'ext_comm', 'Level1');
cm.ExtModeTransports.add('mytarget.tlc', 'serial', ...
'ext_serial_win32_comm', 'Level1');
%end function

• 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.

The next figure shows the structure of the TCP/IP-based implementation.

44-71
44 Host/Target Communication in Simulink Coder

UNIX or PC Host Target

Simulink in External Mode Target Code

Process block
parameter changes
ext_svr.c
Update block parameters

ext_comm

TCP/IP on Ethernet

External Mode Message Format

header data in target format

TCP/IP-Based Client/Server Implementation for External Mode


MEX-File Optional Arguments for TCP/IP Transport

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:

<TargetNetworkName> <VerbosityLevel> <ServerPortNumber>

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.

Using the Serial Implementation

Controlling host/target communication on a serial channel is similar to controlling host/


target communication on a TCP/IP channel.

To use Simulink external mode over a serial channel, you must:

• 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')

You can specify multiple targets and/or transports with additional


cm.ExtModeTransports.add lines, for example:
function sl_customization(cm)
cm.ExtModeTransports.add('mytarget.tlc', 'tcpip', 'ext_comm', 'Level1');
cm.ExtModeTransports.add('mytarget.tlc', 'serial', ...
'ext_serial_win32_comm', 'Level1');
%end function

• 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

• Baud rate: Specify an integer value. The default value is 57600.

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.

Run the External Program

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).

To run the external program, you type a command of the form:


model -opt1 ... -optN

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

!ext_example -tf inf -w &

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.

Running the External Program in the UNIX Environment

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:

./ext_example -tf inf -w


• Alternatively, you can launch the target executable from the MATLAB Command
Window. You must run it in the background so that you can still access the Simulink
environment. The command must be preceded by an exclamation point (!), dot slash
(./ indicating the current directory), and followed by an ampersand (&), as in the
following example:

!./ext_example -tf inf -w &

The ampersand (&) causes the operating system to spawn another process to run the
target executable.

Command-Line Options for the External Program

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.

The following example sets the stop time to 10 seconds.

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

Specified as an integer, this option is only available for serial transport.

Implement an External Mode Protocol Layer

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).

Use External Mode Programmatically


You can run external mode simulations from the MATLAB command line or
programmatically in scripts. Use the get_param and set_param commands to retrieve
and set the values of model simulation command-line parameters, such as

44-77
44 Host/Target Communication in Simulink Coder

SimulationMode and SimulationCommand, and external mode command-line


parameters, such as ExtModeCommand and ExtModeTrigType.

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.

1 Change the Simulink model to 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')

To trigger or cancel data uploading to scopes, use the ExtModeCommand values


armFloating and cancelFloating, or armWired and cancelWired. For example, to
trigger and then cancel data uploading to wired (nonfloating) scopes:

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

External Mode Command-Line Parameters

Parameter and Values Dialog Box Equivalent Description


ExtModeAddSuffixToVar Enable Data Archiving: Increment variable names
off, on Append file suffix to for each incremented
variable names check box filename.
ExtModeArchiveDirName Enable Data Archiving: Save data in specified folder.
character vector Directory text field
ExtModeArchiveFileName Enable Data Archiving: File Save data in specified file.
character vector text field
ExtModeArchiveMode Enable Data Archiving: Activate automated data
character vector - off, on Enable archiving check box archiving features.
ExtModeArmWhenConnect External Signal & Triggering: Arm the trigger as soon as
off, on Arm when connecting to the Simulink Coder software
target check box connects to the target.
ExtModeAutoIncOneShot Enable Data Archiving: Save new data buffers in
off, on Increment file after one- incremental files.
shot check box
ExtModeAutoUpdateStatusClock Not available Continuously upload and
(Microsoft Windows platforms only) display target time on the
off, on model window status bar.
ExtModeBatchMode External Mode Control Panel: Enable or disable
off, on Batch download check box downloading of parameters
in batch mode.
ExtModeChangesPending Not available When ExtModeBatchMode
off, on is enabled, indicates
whether parameters remain
in the queue of parameters
to be downloaded to the
target.

44-80
External Mode Simulation with TCP/IP or Serial Communication

Parameter and Values Dialog Box Equivalent Description


ExtModeCommand • armFloating and Issue an external mode
character vector - armFloating, cancelFloating are command to the target
armWired, cancelFloating, equivalent to selecting and program.
cancelWired clearing External Mode
Control Panel check box
Floating scope > Enable
data uploading
• armWired and
cancelWired are
equivalent to External
Mode Control Panel
buttons Arm Trigger and
Cancel Trigger
ExtModeConnected External Mode Control Panel: Indicate the state of the
off, on Connect/Disconnect button connection with the target
program.
ExtModeEnableFloating External Mode Control Panel: Enable or disable the arming
off, on Enable data uploading and canceling of triggers
check box when a connection is
established with floating
scopes.
ExtModeIncDirWhenArm Enable Data Archiving: Write log files to incremental
off, on Increment directory when folders each time the trigger
trigger armed check box is armed.
ExtModeLogAll External Signal & Triggering: Upload available signals
off, on Select all check box from the target to the host.

44-81
44 Host/Target Communication in Simulink Coder

Parameter and Values Dialog Box Equivalent Description


ExtModeParamChangesPending Not available When the Simulink Coder
off, on software is connected to the
target and
ExtModeBatchMode is
enabled, indicates whether
parameters remain in the
queue of parameters to be
downloaded to the target.
More efficient than
ExtModeChangesPending,
because it checks for a
connection to the target.
ExtModeSkipDownloadWhenConnec Not available Connect to the target
t program without
off, on downloading parameters.
ExtModeTrigDelay External Signal & Triggering: Specify the amount of time
integer (0) Delay text field (expressed in base rate
steps) that elapses between
a trigger occurrence and the
start of data collection.
ExtModeTrigDirection External Signal & Triggering: Specify the direction in
character vector - rising, Direction menu which the signal must be
falling, either traveling when it crosses the
threshold value.
ExtModeTrigDuration External Signal & Triggering: Specify the number of base
integer (1000) Duration text field rate steps for which external
mode is to log data after a
trigger event.
ExtModeTrigDurationFloating External Mode Control Panel: Specify the duration for
character vector - integer Duration text field floating scopes. If auto is
(auto) specified, the value of
ExtModeTrigDuration is
used.

44-82
External Mode Simulation with TCP/IP or Serial Communication

Parameter and Values Dialog Box Equivalent Description


ExtModeTrigElement External Signal & Triggering: Specify the elements of the
character vector - integer, any, Element text field input port of the specified
last trigger block that can cause
the trigger to fire.
ExtModeTrigHoldOff External Signal & Triggering: Specify the base rate steps
integer (0) Hold-off text field between when a trigger
event terminates and the
trigger is rearmed.
ExtModeTrigLevel External Signal & Triggering: Specify the threshold value
integer (0) Level text field the trigger signal must cross
to fire the trigger.
ExtModeTrigMode External Signal & Triggering: Specify whether the trigger
character vector - normal, Mode menu is to rearm automatically
oneshot after each trigger event or
whether only one buffer of
data is to be collected each
time the trigger is armed.
ExtModeTrigPort External Signal & Triggering: Specify the input port of the
character vector - integer (1), Port text field specified trigger block for
last which elements can cause
the trigger to fire.
ExtModeTrigType External Signal & Triggering: Specify whether to start
character vector - manual, Source menu logging data when the
signal trigger is armed or when a
specified trigger signal
satisfies trigger conditions.
ExtModeUploadStatus Not available Return the status of the
character vector - inactive, external mode upload
armed, uploading mechanism — inactive,
armed, or uploading.
ExtModeWriteAllDataToWs Enable Data Archiving: Write Write intermediate results to
off, on intermediate results to the workspace.
workspace check box

44-83
44 Host/Target Communication in Simulink Coder

Animate Stateflow Charts in External Mode


If you have Stateflow, you can animate a chart in external mode. In external mode, you
can animate states in a chart, and view test point signals in a floating scope or signal
viewer.

• “Animate States During Simulation in External Mode” on page 44-84


• “View Test Point Data in Floating Scopes and Signal Viewers” on page 44-85

Animate States During Simulation in External Mode

To animate states in a chart in external mode:


1 Load the chart you want to animate to the target machine.
2 Open the Model Configuration Parameters dialog box.
3 In the left Select pane, select Code Generation > Interface.
4 In the Data exchange interface section, select External mode and click OK.
5 In the Simulink Editor, select Code > External Mode Control Panel.
6 In the External Mode Control Panel dialog box, click Signal & Triggering.
7 In the External Signal & Triggering dialog box, set these parameters.

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

11 Start simulation. The chart highlights states as they execute.

View Test Point Data in Floating Scopes and Signal Viewers

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.

To view test point data during simulation in external mode:

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 Signal Selector dialog box opens.


3 In the Signal Selector Model hierarchy pane, select the chart.
4 In the Signal Selector List contents menu, select Testpointed/Logged signals only
and then select the signals you want to view.
5 Simulate the model in external mode as described in “Animate States During
Simulation in External Mode” on page 44-84.

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).

TCP/IP and Serial External Mode Limitations


• “Changing Parameters” on page 44-86
• “Mixing 32-Bit and 64-Bit Architectures” on page 44-87
• “Uploading Data” on page 44-87
• “Uploading Variable-Size Signals” on page 44-87

44-85
44 Host/Target Communication in Simulink Coder

• “Signal Value Display in Simulation” on page 44-87


• “Tunable Structure Parameters” on page 44-87
• “Archiving Data” on page 44-87
• “Scopes in Referenced Models” on page 44-88
• “Simulation Start Time” on page 44-88
• “File-Scoped Data” on page 44-88
• “Use of printf Statements” on page 44-88
• “Command-Line Arguments” on page 44-88
• “Row-Major Code Generation” on page 44-89

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

• 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

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.

Mixing 32-Bit and 64-Bit Architectures

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.

Uploading Variable-Size Signals

External mode does not support uploading variable-size signals for the following targets:

• Simulink Real-Time
• Texas Instruments™ C2000™

Signal Value Display in Simulation

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.

Tunable Structure Parameters

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.

Scopes in Referenced Models

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.

Simulation Start Time

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.

Use of printf Statements

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:

• Parsing of the command-line arguments requires the sscanf function, which


increases the program size for some target hardware.
• Some target programs do not accept command-line arguments.

44-88
See Also

To disable the processing of command-line arguments, specify the preprocessor macro


definition EXTMODE_DISABLE_ARGS_PROCESSING=1 for your target program compiler.

Row-Major Code Generation

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

Create a Transport Layer for TCP/IP or Serial External


Mode Communication

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:

• An overview of the design and operation of external mode


• A description of external mode source files
• Guidelines for modifying the external mode source files and building an executable to
handle the tasks of the default ext_comm MEX-file

This section assumes that you are familiar with the execution of Simulink Coder
programs, and with the basic operation of external mode.

Design of External Mode


External mode communication between the Simulink engine and a target system is based
on a client/server architecture. The client (the Simulink engine) transmits messages
requesting the server (target) to accept parameter changes or to upload signal data. The
server responds by executing the request.

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.

Built-In Transport Layer Implementations

Protocol Client or Source Files


Server?
TCP/IP Client • matlabroot/toolbox/coder/simulinkcoder_core/ext_mode/
(host) host/common/rtiostream_interface.c
• matlabroot/rtw/c/src/rtiostream/rtiostreamtcpip/
rtiostream_tcpip.c
Server • matlabroot/rtw/c/src/ext_mode/common/
(target) rtiostream_interface.c
• matlabroot/rtw/c/src/rtiostream/rtiostreamtcpip/
rtiostream_tcpip.c
Serial Client • matlabroot/toolbox/coder/simulinkcoder_core/ext_mode/
(host) host/serial/ext_serial_transport.c
• matlabroot/rtw/c/src/rtiostream/rtiostreamserial/
rtiostream_serial.c
Server • matlabroot/rtw/c/src/ext_mode/serial/
(target) ext_svr_serial_transport.c
• matlabroot/rtw/c/src/rtiostream/rtiostreamserial/
rtiostream_serial.c

For serial communication, the modules ext_serial_transport.c and


rtiostream_serial.c implement the client-side transport functions and the modules
ext_svr_serial_transport.c and rtiostream_serial.c implement the
corresponding server-side functions. For TCP/IP communication, the modules
rtiostream_interface.c and rtiostream_tcpip.c implement both client-side and
server-side functions. You can edit copies of these files (but do not modify the originals).
You can support external mode using your own low-level communications layer by
creating similar files using the following templates:

44-91
44 Host/Target Communication in Simulink Coder

• Client (host) side: matlabroot/rtw/c/src/rtiostream/rtiostreamtcpip/


rtiostream_tcpip.c (TCP/IP) or matlabroot/rtw/c/src/rtiostream/
rtiostreamserial/rtiostream_serial.c (serial)
• Server (target) side: matlabroot/rtw/c/src/rtiostream/rtiostreamtcpip/
rtiostream_tcpip.c (TCP/IP) or matlabroot/rtw/c/src/rtiostream/
rtiostreamserial/rtiostream_serial.c (serial)

The file rtiostream_interface.c 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 make changes to the file rtiostream_interface.c or
other external mode related files.

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.

External Mode Communications Overview


This section gives a high-level overview of how a Simulink Coder generated program
communicates with Simulink external mode. This description is based on the TCP/IP
version of external mode that ships with the Simulink Coder product.

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:

• Connection message / connection response


• Start target simulation / start response
• Parameter download / parameter download response
• Arm trigger for data uploading / arm trigger response
• Terminate target simulation / target shutdown response

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.

External Mode Source Files


• “Client (Host) MEX-file Interface Source Files” on page 44-94
• “Server (Target) Source Files” on page 44-96
• “Other Files in the Server Folder” on page 44-98

Client (Host) MEX-file Interface Source Files

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.

Tasks carried out by ext_comm.c include establishment of a connection with the


target, downloading of parameters, and termination of the connection with the target.
• common/rtiostream_interface.c

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 implements required serial transport layer functions.


ext_serial_transport.c includes ext_serial_utils.c, which is located in
matlabroot/rtw/c/src/ext_mode/serial (open) and contains functions common
to client and server sides.
• common/ext_main.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

information.) ext_main.c contains a function dispatcher, esGetAction, that sends


requests from the Simulink engine to ext_comm.c.
• common/ext_convert.c and ext_convert.h

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).

Note You do not need to customize ext_convert to implement a custom transport


layer. However, you might want to customize ext_convert for the intended target.
For example, if the target represents the float data type in Texas Instruments
format, ext_convert must be modified to perform a Texas Instruments to IEEE
conversion.
• common/extsim.h

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.

Server (Target) Source Files

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

ext_svr.c is analogous to ext_comm.c on the host, but generally is responsible for


more tasks. It acts as a relay station between the host and the generated code. Like
ext_comm.c, ext_svr.c carries out tasks such as establishing and terminating
connection with the host. ext_svr.c also contains the background task functions that
either write downloaded parameters to the target model, or extract data from the
target data buffers and send it back to the host.
• common/rtiostream_interface.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

This file defines the rtIOStream* functions implemented in rtiostream_tcpip.c.


• serial/ext_svr_serial_transport.c

This file implements required serial transport layer functions.


ext_svr_serial_transport.c includes serial/ext_serial_utils.c, which
contains functions common to client and server sides.
• common/updown.c

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.

Other Files in the Server Folder

• 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

• serial/ext_serial_pkt.c and ext_serial_pkt.h


• serial/ext_serial_port.h

Implement a Custom Transport Layer


• “Requirements for Custom Transport Layers” on page 44-99
• “Create a Custom Client (Host) Transport Protocol” on page 44-99
• “MATLAB Commands to Rebuild ext_comm and ext_serial_win32 MEX-Files”
on page 44-100
• “Register a Custom Client (Host) Transport Protocol” on page 44-101
• “Create a Custom Server (Target) Transport Protocol” on page 44-102
• “Serial Receive Buffer Smaller than 64 Bytes” on page 44-104

44-98
Create a Transport Layer for TCP/IP or Serial External Mode Communication

Requirements for Custom Transport Layers

• By default, ext_svr.c and updown.c use malloc to allocate buffers in target


memory for messages, data collection, and other purposes, although there is also an
option to preallocate static memory. If your target uses another memory allocation
scheme, you must modify these modules.
• The target is assumed to support both int32_T and uint32_T data types.

Create a Custom Client (Host) Transport Protocol

To implement the client (host) side of your low-level transport protocol,

1 Edit the template file matlabroot/rtw/c/src/rtiostream/rtiostreamtcpip/


rtiostream_tcpip.c to replace low-level communication calls with your own
communication calls.

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.

MATLAB Commands to Rebuild ext_comm and ext_serial_win32 MEX-Files

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

Note The rtiostream_interface.c function defines


RTIOSTREAM_SHARED_LIB as libmwrtiostreamtcpip and dynamically
loads the MathWorks TCP/IP rtiostream shared library. Modify this file if you
need to load a different rtiostream shared library.
Linux, TCP/IP Use the Windows commands, with these changes:

• Change -DSL_EXT_DLL to -DSL_EXT_SO.


• Change -lsl_services to -lmwsl_services.
• Replace back slashes with forward slashes.
Mac, TCP/IP Use the Windows commands, with these changes:

• Change -DSL_EXT_DLL to -DSL_EXT_DYLIB.


• Change -lsl_services to -lmwsl_services.
• Replace back slashes with forward slashes.

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 The rtiostream_interface.c function defines


RTIOSTREAM_SHARED_LIB as libmwrtiostreamserial and dynamically
loads the MathWorks serial rtiostream shared library. Modify this file if you
need to load a different rtiostream shared library.
Linux, serial Use the Windows commands, with these changes:

• Change -DSL_EXT_DLL to -DSL_EXT_SO.


• Change -lsl_services to -lmwsl_services.
• Replace back slashes with forward slashes.
Mac, serial Use the Windows commands, with these changes:

• Change -DSL_EXT_DLL to -DSL_EXT_DYLIB.


• Change -lsl_services to -lmwsl_services.
• Replace back slashes with forward slashes.

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.

Register a Custom Client (Host) Transport Protocol

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')

You can specify multiple targets and/or transports with additional


cm.ExtModeTransports.add lines, for example:
function sl_customization(cm)
cm.ExtModeTransports.add('grt.tlc', 'mytcpip', 'ext_mytcpip_comm', 'Level1');
cm.ExtModeTransports.add('ert.tlc', 'mytcpip', 'ext_mytcpip_comm', 'Level1');
% -- end of sl_customization

If you place the sl_customization.m file containing the transport registration


information on the MATLAB path, your custom client transport protocol will be registered
with each subsequent Simulink session. The name of the transport will appear in the
Transport layer menu on the Interface pane of the Configuration Parameters dialog
box. When you select the transport for your model, the name of the associated external
interface MEX-file will appear in the noneditable MEX-file name field, as shown in the
following figure.

Create a Custom Server (Target) Transport Protocol

The rtIOStream* function prototypes in matlabroot/rtw/c/src/rtiostream.h


define the calling interface for both the server (target) and client (host) side transport
layer functions.

44-102
Create a Transport Layer for TCP/IP or Serial External Mode Communication

• The TCP/IP implementations are in matlabroot/rtw/c/src/rtiostream/


rtiostreamtcpip/rtiostream_tcpip.c.
• The serial implementations are in matlabroot/rtw/c/src/rtiostream/
rtiostreamserial/rtiostream_serial.c.

Note The Ext* function prototypes in matlabroot/rtw/c/src/ext_mode/common/


ext_svr_transport.h are implemented in matlabroot/rtw/c/src/ext_mode/
common/rtiostream_interface.c or matlabroot/rtw/c/src/ext_mode/serial/
rtiostream_serial_interface.c. In most cases you will not need to modify
rtiostream_interface.c or rtiostream_serial_interface.c for your custom
TCP/IP or serial transport layer.

To implement the server (target) side of your low-level TCP/IP or serial transport protocol:

1 Edit the template matlabroot/rtw/c/src/rtiostream/rtiostreamtcpip/


rtiostream_tcpip.c or matlabroot/rtw/c/src/rtiostream/
rtiostreamserial/rtiostream_serial.c to replace low-level communication
calls with your own communication calls.

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.

You must implement the functions defined in rtiostream.h, and your


implementations must conform to the prototypes defined in that file. Refer to the
original rtiostream_tcpip.c or rtiostream_serial.c for guidance.
2 Incorporate the external mode source files for your transport layer into the model
build process. Use a build process mechanism such as a post code generation
command or a before_make hook function to make the transport files available to
the build process. For more information on the build process mechanisms, see
“Customize Post-Code-Generation Build Processing” (Simulink Coder), “Customize
Build Process with STF_make_rtw_hook File” (Simulink Coder), and “Customize Build
Process with sl_customization.m” (Simulink Coder).

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

• For TCP/IP, add the following file to the build information:


matlabroot/rtw/c/src/ext_mode/common/rtiostream_interface.c

• For serial, add the following files to the build information:


matlabroot/rtw/c/src/ext_mode/serial/ext_serial_pkt.c
matlabroot/rtw/c/src/ext_mode/serial/rtiostream_serial_interface.c
matlabroot/rtw/c/src/ext_mode/serial/ext_svr_serial_transport.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.

Serial Receive Buffer Smaller than 64 Bytes

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

Implement the change in the following files:


matlabroot/rtw/c/src/ext_mode/serial/ext_serial_utils.c
matlabroot/toolbox/coder/simulinkcoder_core/ext_mode/host/serial/ext_serial_utils.c
2 Run the command to rebuild the ext_serial_win32 MEX-file. See “MATLAB
Commands to Rebuild ext_comm and ext_serial_win32 MEX-Files” on page 44-100.

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

• “Host-Target Communication with External Mode Simulation” on page 44-2


• “Customize XCP Slave Software” on page 44-22

44-105
45

Logging in Simulink Coder


45 Logging in Simulink Coder

Log Program Execution Results


Multiple techniques are available by which a program generated by the Simulink Coder
software can save data to a MAT-file for analysis. A generated executable can save system
states, outputs, and simulation time at each model execution time step. The data is
written to a MAT-file, named (by default) model.mat, where model is the name of your
model. See “Log Data for Analysis” on page 45-2 for a data logging tutorial.

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

Log Data for Analysis


• “Set Up and Configure Model” on page 45-2
• “Data Logging During Simulation” on page 45-4
• “Data Logging from Generated Code” on page 45-7

Set Up and Configure Model

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 &#x30A2;. 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.

Data Logging During Simulation

To use the data logging feature:

1 Open the myAircraftExample model if it is not already open.


2 Open the Configuration Parameters dialog box by selecting Simulation > Model
Configuration Parameters from the model window.
3 Select the Data Import/Export pane. The Data Import/Export pane lets you
specify which outport data is to be saved to the workspace and what variable names
to use for it.
4 Set Format to Structure with time. When you select this format, Simulink saves
the model states and outputs in structures that have their names specified in the
Save to workspace or file area. By default, the structures are xout for states and
yout for output. The structure used to save output has two top-level fields: time and
signals. The time field contains a vector of simulation times and signals contains
an array of substructures, each of which corresponds to a model output port.
5 Select the Output option. This tells Simulink to save output signal data during
simulation as a variable named yout. Selecting Output enables the code generator
to create code that logs the root Output block (alpha, rad) to a MAT-file.
6 Set Decimation to 1.
7 If other options are enabled, clear them. The figure below shows how the dialog box
should appear.

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

yout 1x1 10756 struct

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)

The resulting plot is shown below.

45-6
Log Program Execution Results

Data Logging from Generated Code

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

** starting the model **


** created myAircraftExample.mat **
7 Load the MAT-file data created by the executable and look at the workspace variables
from simulation and the generated program by typing:

load myAircraftExample.mat
whos yout*

Simulink displays:

Name Size Bytes Class Attributes

yout 1x1 10756 struct


yout_rt 1x1 10756 struct

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).

Configure State, Time, and Output Logging


The Data Import/Export pane enables a generated program to save system states,
outputs, and simulation time at each model execution time step. The data is written to a
MAT-file, named (by default) model.mat.

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:

• Root Outport blocks

The default MAT-file variable name for system outputs is rt_yout.

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

The default MAT-file variable name for system states is rt_xout.


• Simulation time

The default MAT-file variable name for simulation time is rt_tout.

• “Override Default MAT-File Variable Names” on page 45-9


• “Override Default MAT-File Name or Buffer Size” on page 45-10

Override Default MAT-File Variable Names

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.

Override Default MAT-File Name or Buffer Size

You can specify compiler options to override the following MAT-file attributes in generated
code:

MAT-File Attribute Default Compiler Option


Name model.mat -DSAVEFILE=filename
Size of data logging buffer 1024 bytes -DDEFAULT_BUFFER_SIZE=n

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

cCompilerOpts = '$(cflags) $(CVARSFLAG) $(CFLAGS_ADDITIONAL)';


cppCompilerOpts = '$(cflags) $(CVARSFLAG) $(CPPFLAGS_ADDITIONAL)';
myCompilerOpts = {' -DSAVEFILE=myCodeLog.mat '};
...

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.

Log Data with Scope and To Workspace Blocks


The code generated by the code generator also logs data from these sources:

• 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.

Log Data with To File Blocks


You can also log data to a To File block. The generated program creates a separate MAT-
file (distinct from model.mat) for each To File block in the model. The file contains the
block time and input variable(s). You must specify the filename, variable names,
decimation, and sample time in the To File block dialog box.

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

Data Logging Differences Between Single- and Multitasking


When logging data in single-tasking and multitasking systems, you will notice differences
in the logging of

• Noncontinuous root Outport blocks


• Discrete states

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

Data Interchange Using the C API in


Simulink Coder

• “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

Exchange Data Between Generated and External Code


Using C API
Some Simulink Coder applications must interact with signals, states, root-level inputs/
outputs, or parameters in the generated code for a model. For example, calibration
applications monitor and modify parameters. Signal monitoring or data logging
applications interface with signal, state, and root-level input/output data. Using the
Simulink Coder C API, you can build target applications that log signals, states, and root-
level inputs/outputs, monitor signals, states, and root-level inputs/outputs, and tune
parameters, while the generated code executes.

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

Generated C API Files


When you configure a model to use the C API, the Simulink Coder code generator
generates two additional files, model_capi.c (or .cpp) and model_capi.h, where
model is the name of the model. The code generator places the two C API files in the
build folder, based on settings in the Configuration Parameters dialog box. The C API
source code file contains information about global block output signals, states, root-level
inputs/outputs, and global parameters defined in the generated code model source code.
The C API header file is an interface header file between the model source code and the
generated C API. You can use the information in these C API files to create your
application. Among the files generated are those shown in the next figure.

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

Generated Files with C API Selected

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 &#x30A2;. For more information, see “Internationalization and Code
Generation” (Simulink Coder).

Generate C API Files


To generate C API files for your model:

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.

• “Select C API with Configuration Parameters Dialog” on page 46-4


• “Select C API from the Command Line” on page 46-4
2 Generate code for your model.

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

Select C API with Configuration Parameters Dialog


1 Open your model, and open the Configuration Parameters dialog box.
2 In the Code Generation > Interface pane, in the Data exchange interface
subgroup, select one or more C API options. Based on the options you select,
support for accessing signals, parameters, states, and root-level I/O will appear in the
C API generated code.

• 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.

Select C API from the Command Line

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.

To select Generate C API for: signals, enter:


set_param('modelname','RTWCAPISignals','on')

To clear Generate C API for: signals, enter:


set_param('modelname','RTWCAPISignals','off')

To select Generate C API for: parameters, enter:


set_param('modelname','RTWCAPIParams','on')

To clear Generate C API for: parameters, enter:


set_param('modelname','RTWCAPIParams','off')

To select Generate C API for: states, enter:


set_param('modelname','RTWCAPIStates','on')

46-4
Exchange Data Between Generated and External Code Using C API

To clear Generate C API for: states, enter:

set_param('modelname','RTWCAPIStates','off')

To select Generate C API for: root-level I/O, enter:

set_param('modelname','RTWCAPIRootIO','on')

To clear Generate C API for: root-level I/O, enter:

set_param('modelname','RTWCAPIRootIO','off')

Description of C API Files


• “About C API Files” on page 46-5
• “Structure Arrays Generated in C API Files” on page 46-8
• “Generate Example C API Files” on page 46-9
• “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
• “C API Parameters” on page 46-16
• “Map C API Data Structures to rtModel” on page 46-18

About C API Files

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

• Port number (for signals and root-level inputs/outputs only)


• Address
• Data type information: native data type, data size, complexity, and other attributes
• Dimensions information: number of rows, number of columns, and data orientation
(scalar, vector, matrix, or n-dimensional)
• Fixed-point information: slope, bias, scale type, word length, exponent, and other
attributes
• Sample-time information (for signals, states, and root-level inputs/outputs only):
sample time, task identifier, frames

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

Array of Signal Structures


rtwCapi_Signals rtBlockSignals[]
{
Array of Data Type Structures
{
rtwCAPI_DataTypeMap rtDataTypeMap[]
...
{
blockPath sys/blk1
{
signalName signal1
cName "double"
portNumber 0
mwName "real_T"
dataTypeIndex 0
These indices of numElements 0
... 0 point to the first
element in the elemMapIndex 0
},
rtDataTypeMap dataSize sizeof(real_T)
{ array. slDataId SS_DOUBLE
...
isComplex 0
blockPath sys/blk2
isPointer 0
signalName signal2
};
portNumber 1
{
dataTypeIndex 0
cName "int"
...
mwName "int32_T"
},
numElements 0
{
elemMapIndex 0
...
dataSize sizeof(int32_T)
blockPath sys/blk3
slDataId SS_INT32
signalName signal3
...
portNumber 0 }
dataTypeIndex 1 };
... The index of 1 points
} to the second element
in the rtDataTypeMap
}; array.

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.

Structure Arrays Generated in C API Files

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):

• rtBlockSignals is an array of structures that contains information about global


block output signals in the model. Each element in the array is of type struct
rtwCAPI_Signals. The members of this structure provide the signal name, block
path, block port number, address, and indices to the data type, dimension, fixed-point,
and sample-time structure arrays.
• rtBlockParameters is an array of structures that contains information about the
tunable block parameters in the model by block name and parameter name. Each
element in the array is of type struct rtwCAPI_BlockParameters. The members
of this structure provide the parameter name, block path, address, and indices to data
type, dimension, and fixed-point structure arrays.
• rtBlockStates is an array of structures that contains information about discrete and
continuous states in the model. Each element in the array is of type struct
rtwCAPI_States. The members of this structure provide the state name, block path,
type (continuous or discrete), and indices to the address, data type, dimension, fixed-
point, and sample-time structure arrays.
• rtRootInputs is an array of structures that contains information about root-level
inputs in the model. Each element in the array is of type struct rtwCAPI_Signals.
The members of this structure provide the root-level input name, block path, block
port number, address, and indices to the data type, dimension, fixed-point, and sample-
time structure arrays.
• rtRootOutputs is an array of structures that contains information about root-level
outputs in the model. Each element in the array is of type struct
rtwCAPI_Signals. The members of this structure provide the root-level output
name, block path, block port number, address, and indices to the data type, dimension,
fixed-point, and sample-time structure arrays.

46-8
Exchange Data Between Generated and External Code Using C API

• rtModelParameters is an array of structures that contains information about


workplace variables that one or more blocks or Stateflow charts in the model
reference as block parameters. Each element in the array is of data type
rtwCAPI_ModelParameters. The members of this structure provide the variable
name, address, and indices to data type, dimension, and fixed-point structure arrays.
• rtDataAddrMap is an array of base addresses of signals, states, root-level inputs/
outputs, and parameters that appear in the rtBlockSignals, rtBlockParameters,
rtBlockStates, and rtModelParameters arrays. Each element of the
rtDataAddrMap array is a pointer to void (void*).
• rtDataTypeMap is an array of structures that contains information about the various
data types in the model. Each element of this array is of type struct
rtwCAPI_DataTypeMap. The members of this structure provide the data type name,
size of the data type, and information on whether or not the data is complex.
• rtDimensionMap is an array of structures that contains information about the various
data dimensions in the model. Each element of this array is of type struct
rtwCAPI_DimensionMap. The members of this structure provide information on the
number of dimensions in the data, the orientation of the data (whether it is scalar,
vector, or a matrix), and the actual dimensions of the data.
• rtFixPtMap is an array of structures that contains fixed-point information about the
signals, states, root-level inputs/outputs, and parameters. Each element of this array is
of type struct rtwCAPI_FixPtMap. The members of this structure provide
information about the data scaling, bias, exponent, and whether or not the fixed-point
data is signed. If the model does not have fixed-point data (signal, state, root-level
input/output, or parameter), the Simulink Coder software assigns NULL or zero values
to the elements of the rtFixPtMap array.
• rtSampleTimeMap is an array of structures that contains sampling information about
the global signals, states, and root-level inputs/outputs in the model. (This array does
not contain information about parameters.) Each element of this array is of type
struct rtwCAPI_SampleTimeMap. The members of this structure provide
information about the sample period, offset, and whether or not the data is frame-
based or sample-based.

Generate Example C API Files

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

1 Open the model by clicking the rtwdemo_capi link above or by typing


rtwdemo_capi on the MATLAB command line.
2 If you want to generate C API structures for root-level inputs/outputs in
rtwdemo_capi, open the Configuration Parameters dialog box, go to the Code
Generation > Interface pane, and select Generate C API for: root-level I/O.

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:

• Four root-level inputs, In1 through In4


• Six root-level outputs, Out1 through Out6

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.

Here is the section of code in rtwdemo_capi_capi.c that provides information on C API


signals for the top model in rtwdemo_capi:
/* Block output signal information */
static const rtwCAPI_Signals rtBlockSignals[] = {
/* addrMapIndex, sysNum, blockPath,
* signalName, portNumber, dataTypeIndex, dimIndex, fxpIndex, sTimeIndex
*/
{ 0, 0, "rtwdemo_capi/Gain1",
"top_sig1", 0, 0, 0, 0, 0 },

{ 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.

Here is the section of code in rtwdemo_capi_capi.c that provides information on C API


states for the top model in rtwdemo_capi:
/* Block states information */
static const rtwCAPI_States rtBlockStates[] = {
/* addrMapIndex, contStateStartIndex, blockPath,
* stateName, pathAlias, dWorkIndex, dataTypeIndex, dimIndex,
* fixPtIdx, sTimeIndex, isContinuous
*/
{ 2, -1, "rtwdemo_capi/Delay1",
"top_state", "", 0, 0, 0, 0, 0, 0 },

{
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.

C API Root-Level Inputs and Outputs

The rtwCAPI_Signals structure captures root-level input/output information including


the input/output name, address, block path, port number, data type information,
dimensions information, fixed-point information, and sample-time information. (This
structure also is used for block output signals, as previously described in “C API Signals”
on page 46-11.)

Here is the section of code in rtwdemo_capi_capi.c that provides information on C API


root-level inputs/outputs for the top model in rtwdemo_capi:
/* Root Inputs information */
static const rtwCAPI_Signals rtRootInputs[] = {
/* addrMapIndex, sysNum, blockPath,
* signalName, portNumber, dataTypeIndex, dimIndex, fxpIndex, sTimeIndex
*/
{ 3, 0, "rtwdemo_capi/In1",
"", 1, 0, 0, 0, 0 },

{ 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
}
};

/* Root Outputs information */


static const rtwCAPI_Signals rtRootOutputs[] = {
/* addrMapIndex, sysNum, blockPath,
* signalName, portNumber, dataTypeIndex, dimIndex, fxpIndex, sTimeIndex
*/
{ 7, 0, "rtwdemo_capi/Out1",
"", 1, 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 rtwCAPI_BlockParameters and rtwCAPI_ModelParameters structures capture


parameter information including the parameter name, block path (for block parameters),
address, data type information, dimensions information, and fixed-point information.

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).

• If you set Default parameter behavior to Tunable, the rtBlockParameters array


contains an entry for every modifiable parameter of every block in the model.
However, if you use a MATLAB variable or a tunable parameter to specify a block
parameter, the block parameter does not appear in rtBlockParameters. Instead, the
variable or tunable parameter appears in rtModelParameters.
• If you set Default parameter behavior to Inlined, the rtBlockParameters array
is empty. The Simulink Coder software assigns its elements only NULL or zero values.

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.

Here is the rtBlockParameters array that is generated by default in


rtwdemo_capi_capi.c:
/* Individual block tuning is not valid when inline parameters is *
* selected. An empty map is produced to provide a consistent *
* interface independent of inlining parameters. *
*/
static const rtwCAPI_BlockParameters rtBlockParameters[] = {
/* addrMapIndex, blockPath,
* paramName, dataTypeIndex, dimIndex, fixPtIdx
*/
{
0, (NULL), (NULL), 0, 0, 0
}
};

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.

Here is the rtModelParameters array that is generated by default in


rtwdemo_capi_capi.c:
/* Tunable variable parameters */
static const rtwCAPI_ModelParameters rtModelParameters[] = {
/* addrMapIndex, varName, dataTypeIndex, dimIndex, fixPtIndex */
{ 2, TARGET_STRING("Ki"), 0, 0, 0 },

{ 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:

• The address of the fourth parameter is given by addrMapIndex, which, in this


example, is 5. This is an index into the rtDataAddrMap array, found later in
rtwdemo_capi_capi.c. Because the index is zero based, 5 corresponds to the sixth
element in rtDataAddrMap, which is rtP_p2.
• 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.
• The dimIndex (dimensions index) provides an index into the rtDimensionMap array,
found later in rtwdemo_capi_capi.c. The value 3 corresponds to the fourth entry,
which is { rtwCAPI_MATRIX_COL_MAJOR, 6, 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.

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.

Map C API Data Structures to rtModel

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

rtwCAPI_Signals const *signals; rtBlockSignals


rtwCAPI_Signals const *rootInputs; rtRootInputs
model.h rtwCAPI_Signals const *rootOutputs; rtRootOutputs
. .
struct rtModel_model {
rtwCAPI_BlockParameters const *blockParameters; rtBlockParameters
.
. .
. rtwCAPI_ModelParameters const *modelParameters; rtModelParameters
. . .
struct { rtwCAPI_States const *states; rtBlockStates
rtwCAPI_ModelMappingInfo mmi; . .
} DataMapInfo: rtwCAPI_DataTypeMap const *dataTypeMap; rtDataTypeMap
. .
.
rtwCAPI_DimensionMap const *dimensionMap; rtDimensionMap
.
. .
.
rtwCAPI_FixPtMap const *fixPtMap; rtFixPtMap
}
. .
rtwCAPI_SampleTimeMap const *sampleTimeMap; rtSampleTimeMap
. .
void** dataAddrMap; rtDataAddrMap
. .

Map Model to C API Arrays of Structures

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.

Generate C API Data Definition File for Exchanging Data with


a Target System
This model illustrates the target-based C API for interfacing signals, parameters, and
states in the generated code.

46-20
Exchange Data Between Generated and External Code Using C API

Open Example Model

Open the example model rtwdemo_capi.

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:

• Objects without the package csc_registration file


• Grouped custom storage classes
• Objects defined by using macros
• BitField objects
• FileScope objects
• Customized data placement is disabled when you are using the C API. The interface
looks for global data declaration in model.h and model_private.h. Declarations
placed in any other file by customized data placement result in code that does not
compile.

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

Use C API to Access Model Signals and States


This example helps you get started writing application code to interact with model signals
and states. To get started writing application code to interact with model parameters, see
“Use C API to Access Model Parameters” on page 46-30.

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.

This example uses the following macro and function interfaces:

• 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)

• Custom functions capi_StartLogging, capi_UpdateLogging, and


capi_TerminateLogging, provided via the files rtwdemo_capi_datalog.h and
rtwdemo_capi_datalog.c. These files are located in matlabroot/toolbox/rtw/
rtwdemos (open).

46-24
Use C API to Access Model Signals and States

• capi_StartLogging initializes signal and state logging.


• capi_UpdateLogging logs a signal and state value at each time step.
• capi_TerminateLogging terminates signal and state logging and writes the
logged values to a text file.

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:

• capi_StartLogging is called in the model_initialize function.


• capi_UpdateLogging is called in the model_step function.
• capi_TerminateLogging is called in the model_terminate function.

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

** starting the model **


** Started state/signal logging via C API **
** Logging 2 signal(s) and 1 state(s). In this demo, only scalar named
signals/states are logged **
** Finished state/signal logging. Created rtwdemo_capi_ModelLog.txt **

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

******** Signal Log File ********

Number of Signals Logged: 2


Number of points (time steps) logged: 51

Time bot_sig1 (Referenced Model) top_sig1


0 70 4
0.2 70 4
0.4 70 4
0.6 70 4
0.8 70 4
1 70 4
1.2 70 4
1.4 70 4
1.6 70 4
1.8 70 4
2 70 4
...

******** State Log File ********

Number of States Logged: 1


Number of points (time steps) logged: 51

Time bot_state (Referenced Model)


0 0
0.2 70
0.4 35
0.6 52.5
0.8 43.75
1 48.13
1.2 45.94
1.4 47.03
1.6 46.48
1.8 46.76
2 46.62
...

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

Use C API to Access Model Parameters


This example helps you get started writing application code to interact with model
parameters. To get started writing application code to interact with model signals and
states, see “Use C API to Access Model Signals and States” on page 46-24.

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

rtwCAPI_ModelMappingInfo* mmi = &(rtmGetDataMapInfo(rtM).mmi);

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:

uint_T nModelParams = rtwCAPI_GetNumModelParameters(mmi);


• Uses rtwCAPI_GetModelParameters to access the array of model parameter
structures mapped in C API:
rtwCAPI_ModelParameters* capiModelParams = \
rtwCAPI_GetModelParameters(mmi);
• Loops over the capiModelParams array to access individual parameter structures. A
call to the function capi_PrintModelParameter displays the value of the
parameter.

The example application code is provided below:

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);

/* Get number of Model Parameters from capiMap */


uint_T nModelParams = rtwCAPI_GetNumModelParameters(capiMap);
printf("Number of Model Parameters: %d\n", nModelParams);

/* If the model has Model Parameters, print them using the


application capi_PrintModelParameter */
if (nModelParams == 0) {
printf("No Tunable Model Parameters in the model \n");
}
else {
unsigned int idx;

for (idx=0; idx < nModelParams; idx++) {


/* call print utility function */
capi_PrintModelParameter(capiMap, idx);
}
}
}

The print utility function is located in matlabroot/rtw/c/src/


rtw_capi_examples.c. This file contains utility functions for accessing the C API
structures.

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

a Select 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.
5 Use the Custom Code pane to embed your custom application code in the generated
code. Select the Custom Code pane, and then click Initialize function. The
Initialize function input field is displayed.
6 In the Initialize function input field, type or copy and paste the example application
code shown above step 1. This embeds the application code in the
model_initialize function.

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

** starting the model **


Number of Model Parameters: 5
Ki =
7
Kp =
4
p1 =
0.15
0.36
0.81
p2 =
0.09 0.75 0.57

46-33
46 Data Interchange Using the C API in Simulink Coder

0.13 0.96 0.059


p3 =
ans(:,:,1) =
0.23 0.82 0.04 0.64
0.35 0.01 0.16 0.73

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

ASAP2 Data Measurement and


Calibration in Simulink Coder
47 ASAP2 Data Measurement and Calibration in Simulink Coder

Export ASAP2 File for Data Measurement and


Calibration
The ASAM MCD-2 MC standard, also known as ASAP2, is a data definition standard
proposed by the Association for Standardization of Automation and Measuring Systems
(ASAM). ASAP2 is a non-object-oriented description of the data used for measurement,
calibration, and diagnostic systems. For more information on ASAM and the ASAM MCD-2
MC (ASAP2) standard, see the ASAM Web site at http://www.asam.net.

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

What You Should Know


To make use of ASAP2 file generation, you should become familiar with the following
topics:

• 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”.

Targets Supporting ASAP2


ASAP2 file generation is available to all code generator system target file configurations.
For example,

• 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.

Define ASAP2 Information


• “Define ASAP2 Information for Parameters and Signals” on page 47-4
• “Memory Address Attribute” on page 47-5
• “Automatic ECU Address Replacement for ASAP2 Files (Embedded Coder)”
on page 47-6
• “Define ASAP2 Information for Lookup Tables” on page 47-7

47-3
47 ASAP2 Data Measurement and Calibration in Simulink Coder

Define ASAP2 Information for Parameters and Signals

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.

Data Attribute Defined In Property Name


Name (symbol) Model and data object Inherited from the handle of
the data object to which
parameter or signal name
resolves
Description Data object Description
Data type Model or data object DataType
Scaling Model or data object DataType
(if fixed-point data type)
Minimum allowable value Model or data object Min
Maximum allowable value Model or data object Max
Unit Model or data object Unit
Memory address (optional) Model or data object MemoryAddress_ASAP2
(optional; see “Memory
Address Attribute” on page
47-5.)

47-4
Export ASAP2 File for Data Measurement and Calibration

Memory Address Attribute

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

Differences Between ASAP2 and Simulink Parameter and Signal Object


Properties

ASAP2 Object Properties (Previous) Simulink Object Properties (Current)


LONGIG_ASAP2 Description
PhysicalMin_ASAP2 Min
PhysicalMax_ASAP2 Max
Units_ASAP2 Unit

Automatic ECU Address Replacement for ASAP2 Files (Embedded 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

Define ASAP2 Information for Lookup Tables

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:

• Direct Lookup Table (n-D) — 1 and 2 dimensions


• Interpolation Using Prelookup — 1 and 2 dimensions
• 1–D Lookup Table
• 2–D Lookup Table
• n-D Lookup Table — 1 and 2 dimensions

The software supports the following types of lookup table breakpoints (axis points):

Breakpoint Type Generates


Tunable and shared among COM_AXIS
multiple table axes (common
axis)
Fixed and nontunable (fixed One of these variants of FIX_AXIS:
axis)
• FIX_AXIS_PAR if breakpoints are integers with
equidistant spacing and the equidistant spacing is a
power of two
• FIX_AXIS_PAR_DIST if breakpoints are integers with
equidistant spacing
• FIX_AXIS_PAR_LIST if breakpoints are integers with
non-equidistant spacing
Tunable but not shared STD_AXIS
among multiple tables
(standard axis)

When you configure the blocks for ASAP2 code generation:

• 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

/begin RECORD_LAYOUT Lookup1D_X_WORD_Y_FLOAT32_IEEE


AXIS_PTS_X 1 WORD INDEX_INCR DIRECT
FNC_VALUES 2 FLOAT32_IEEE COLUMN_DIR DIRECT
/end RECORD_LAYOUT

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.

Generate an ASAP2 File


• “About Generating ASAP2 Files” on page 47-9
• “Use GRT or ERT System Target File” on page 47-9
• “Use the ASAM-ASAP2 Data Definition Target” on page 47-10
• “Generate ASAP2 Files for Referenced Models” on page 47-11
• “Merge ASAP2 Files for Top and Referenced Models” on page 47-11

About Generating ASAP2 Files

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.

Use GRT or ERT System Target File

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.

Use the ASAM-ASAP2 Data Definition Target

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.

Generate ASAP2 Files for Referenced Models

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.

Merge ASAP2 Files for Top and Referenced Models

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.

Consider the following example.

[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.

The example model rtwdemo_asap2 includes an example of merging ASAP2 files.

Structure of the ASAP2 File


The following table outlines the basic structure of the ASAP2 file and describes the Target
Language Compiler (TLC) functions and files used to create each part of the file:

• Static parts of the ASAP2 file are shown in bold.


• Function calls are indicated by %<FunctionName()>.

File Section Contents of asap2main.tlc TLC File Containing


Function Definition
File header %<ASAP2UserFcnWriteFileHead()> asap2userlib.tlc
/begin PROJECT "" /begin PROJECT "%<ASAP2ProjectName>" asap2setup.tlc
/begin HEADER "" /begin HEADER"%<ASAP2HeaderName>" asap2setup.tlc
HEADER contents %<ASAP2UserFcnWriteHeader()> asap2userlib.tlc
/end HEADER /end HEADER
/begin MODULE "" /begin MODULE "%<ASAP2ModuleName>"} asap2setup.tlc
MODULE contents: asap2userlib.tlc
- A2ML %<ASAP2UserFcnWriteHardwareInterface(
- MOD_PAR )>
- MOD_COMMON
...

47-12
Export ASAP2 File for Data Measurement and Calibration

File Section Contents of asap2main.tlc TLC File Containing


Function Definition
Model-dependent %<SLibASAP2WriteDynamicContents()> asap2lib.tlc
MODULE contents: Calls user-defined functions:
- RECORD_LAYOUT ...WriteRecordLayout_TemplateName() user/templates/...
- CHARACTERISTIC ...WriteCharacteristic_TemplateName(
- ParameterGroups )
- ModelParameters ...WriteCharacteristic_Scalar()
- MEASUREMENT ...WriteMeasurement() asap2userlib.tlc
- ExternalInputs
- BlockOutputs
- COMPU_METHOD ...WriteCompuMethod() asap2userlib.tlc
/end MODULE /end MODULE
File footer/tail %<ASAP2UserFcnWriteFileTail()> asap2userlib.tlc

Create a Host-Based ASAM-ASAP2 Data Definition File for


Data Measurement and Calibration
This model shows ASAP2 data export. ASAP2 is a data definition standard proposed by
the Association for Standardization of Automation and Measuring Systems (ASAM).

Open Example Model

Open the example model rtwdemo_asap2.

open_system('rtwdemo_asap2');

47-13
47 ASAP2 Data Measurement and Calibration in Simulink Coder

ASAP2 is a non-object-oriented description of the data used for measurement, calibration,


and diagnostics systems. For more information on ASAM and the ASAP2 standard, see the
ASAM Web site: http://www.asam.de.

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

Direct Memory Access to Generated


Code for Simulink Coder
48 Direct Memory Access to Generated Code for Simulink Coder

Access Memory in Generated Code Using Global Data


Map
Simulink Coder provides a Target Language Compiler (TLC) function library that lets you
create a global data map record. The global data map record, when generated, is added
to the CompiledModel structure in the model.rtw file. The global data map record is a
database containing information required for accessing memory in the generated code,
including

• Signals (Block I/O)


• Parameters
• Data type work vectors (DWork)
• External inputs
• External outputs

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

Desktops in Simulink Coder

• “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

Accelerate, Refine, and Test Hybrid Dynamic System on


Host Computer by Using RSim System Target File
After you create a model, you can use the rapid simulation (RSim) system target file to
characterize model behavior. The executable program that results from the build process
is for non-real-time execution on your development computer. The executable program is
highly optimized for simulating models of hybrid dynamic systems, including models that
use variable-step solvers and zero-crossing detection. The speed of the generated code
makes the RSim system target file ideal for building programs for batch or Monte Carlo
simulations.

About Rapid Simulation


Use the RSim target to generate an executable that runs fast, standalone simulations. You
can repeat simulations with varying data sets, interactively or programmatically with
scripts, without rebuilding the model. This can accelerate the characterization and tuning
of model behavior and code generation testing.

Using command-line options:

• 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)."

Rapid Simulation Advantage


The advantage that you gain from rapid simulation varies. Larger simulations achieve
speed improvements of up to 10 times faster than standard Simulink simulations. Some
models might not show noticeable improvement in simulation speed. To determine the

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.

General Rapid Simulation Workflow


Like other stages of Model-Based Design, characterization and tuning of model behavior
is an iterative process, as shown in the general workflow diagram in the figure. Tasks in
the workflow are:

1 Identify your rapid simulation requirements. on page 49-4


2 Configure Inport blocks on page 49-6 that provide input source data for rapid
simulations.
3 Configure the model on page 49-6 for rapid simulation.
4 Set up simulation input data. on page 49-8
5 Run the rapid simulations. on page 49-19

49-3
49 Desktops in Simulink Coder

Identify rapid simulation


requirements

Model includes Yes Configure


Inport blocks? Inport blocks

No
Configure and
build model

Set up input data

Batch
or Monte Carlo Yes
Program script
simulations?

No
Run simulation

Analyze simulation
results

Yes Change input Done


data?

Identify Rapid Simulation Requirements


The first step to setting up a rapid simulation is to identify your simulation requirements.

Question... For More Information, See...


How long do you want simulations to run? “Configure and Build Model for Rapid Simulation” on
page 49-6
Are there solver requirements? Do you “Configure and Build Model for Rapid Simulation” on
expect to use the same solver for which page 49-6
the model is configured for your rapid
simulations?

49-4
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File

Question... For More Information, See...


Do your rapid simulations need to “Configure and Build Model for Rapid Simulation” on
accommodate flexible custom code page 49-6
interfacing? Or, do your simulations need
to retain storage class settings?
Will you be running simulations with “Set Up Rapid Simulation Input Data” on page 49-8
multiple data sets?
Will the input data consist of global “Set Up Rapid Simulation Input Data” on page 49-8
parameters, signals, or both?
What type of source blocks provide input “Set Up Rapid Simulation Input Data” on page 49-8
data to the model — From File, Inport,
From Workspace?
Will the model's parameter vector “Create a MAT-File That Includes a Model Parameter
(model_P) be used as input data? Structure” on page 49-9
What is the data type of the input “Set Up Rapid Simulation Input Data” on page 49-8
parameters and signals?
Will the source data consist of one variable “Set Up Rapid Simulation Input Data” on page 49-8
or multiple variables?
Does the input data include tunable “Create a MAT-File That Includes a Model Parameter
parameters? Structure” on page 49-9
Do you need to gain access to tunable “Create a MAT-File That Includes a Model Parameter
parameter information — model checksum Structure” on page 49-9
and parameter data types, identifiers, and
complexity?
Will you have a need to vary the simulation “Configure and Build Model for Rapid Simulation” on
stop time for simulation runs? page 49-6 and“Override a Model Simulation Stop
Time” on page 49-22
Do you want to set a time limit for the “Set a Clock Time Limit for a Rapid Simulation” on
simulation? Consider setting a time limit if page 49-22
your model experiences frequent zero
crossings and has a small minor step size.
Do you need to preserve the output of each “Specify a New Output File Name for a Simulation” on
simulation run? page 49-29 and “Specify New Output File Names for
To File Blocks” on page 49-30

49-5
49 Desktops in Simulink Coder

Question... For More Information, See...


Do you expect to run the simulations “Scripts for Batch and Monte Carlo Simulations” on
interactively or in batch mode? page 49-19

Configure Inports to Provide Simulation Source Data


You can use Inport blocks as a source of input data for rapid simulations. To do so,
configure the blocks so that they can import data from external MAT-files. By default, the
Inport block inherits parameter settings from downstream blocks. In most cases, to
import data from an external MAT-file, you must explicitly set the following parameters to
match the source data in the MAT-file.

• Main > Interpolate data


• Signal Attributes > Port dimensions
• Signal Attributes > Data type
• Signal Attributes > Signal type

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.

Configure and Build Model for Rapid Simulation


After you identify your rapid simulation requirements, configure the model for rapid
simulation.

1 Open the Configuration Parameters dialog box.


2 Go to the Code Generation pane.
3 On the Code Generation pane, click Browse. The System Target File Browser
opens.
4 Select rsim.tlc (Rapid Simulation Target) and click OK.

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.

If You Want to... Then...


Generate code that allows the RSim Select Enable RSim executable to load
executable to load parameters from a MAT- parameters from a MAT-file (default).
file
Let the target choose a solver based on the Set Solver selection to auto (default). The code
solver already configured for the model generator uses a built-in solver if a fixed-step
solver is specified on the Solver pane or calls the
Simulink solver module (a shared library) if a
variable-step solver is specified.
Explicitly instruct the target to use a fixed- Set Solver selection to Use fixed-step
step solver solvers. In the Configuration Parameters dialog
box, on the Solver pane, specify a fixed-step
solver.
Explicitly instruct the target to use a Set Solver selection to Use Simulink solver
variable-step solver module. In the Configuration Parameters dialog
box, on the Solver pane, specify a variable-step
solver.
Force storage classes to Auto for flexible Select Force storage classes to AUTO (default).
custom code interfacing

49-7
49 Desktops in Simulink Coder

If You Want to... Then...


Retain storage class settings, such as Clear Force storage classes to AUTO.
ExportedGlobal or ImportedExtern,
due to application requirements
7 Set up data import and export options. On the Data Import/Export pane, in the
Save to Workspace section, select the Time, States, Outputs, and Final States
options, as they apply. By default, the code generator saves simulation logging results
to a file named model.mat. For more information, see “Export Simulation Data”
(Simulink).
8 If you are using external mode communication, set up the interface, using the Code
Generation > Interface pane. See “Host-Target Communication with External Mode
Simulation” (Simulink Coder) for details.
9 Press Ctrl+B. The code generator builds a highly optimized executable program that
you can run on your development computer with varying data, without rebuilding.

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 .

Set Up Rapid Simulation Input Data


• “About Rapid Simulation Data Setup” on page 49-8
• “Create a MAT-File That Includes a Model Parameter Structure” on page 49-9
• “Create a MAT-File for a From File Block” on page 49-13
• “Create a MAT-File for an Inport Block” on page 49-14

About Rapid Simulation Data Setup

The format and setup of input data for a rapid simulation depends on your requirements.

If the Input Data Source Is... Then...


The model's global parameter vector Use the rsimgetrtp function to get the vector
(model_P) content and then save it to a MAT-file.
The model's global parameter vector Call the rsimgetrtp function to get the global
and you want a mapping between the parameter structure and then save it to a MAT-
vector and tunable parameters file.

49-8
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File

If the Input Data Source Is... Then...


Provided by a From File block Create a MAT-file that a From File block can
read.
Provided by an Inport block Create a MAT-file that adheres to one of the three
data file formats that the Inport block can read.
Provided by a From Workspace block Create structure variables in the MATLAB
workspace.

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.

Create a MAT-File That Includes a Model Parameter Structure

To create a MAT-file that includes a model global parameter structure (model_P),

1 Get the structure by calling the function rsimgetrtp.


2 Save the parameter structure to a MAT-file.

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.

The parameter structure contains the following information.

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 =

modelChecksum: [1.7165e+009 3.0726e+009 2.6061e+009 2.3064e+009]


parameters: [1x1 struct]

49-10
Accelerate, Refine, and Test Hybrid Dynamic System on Host Computer by Using RSim System Target File

Save the Parameter Structure to a MAT-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.

save myrsimdemo.mat param_struct;

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.

To convert the structure to a cell array:

1 Use the function rsimgetrtp to get a structure containing parameter information


for the example model rtwdemo_rsimtf. Store the structure in a variable
param_struct.

param_struct = rsimgetrtp('rtwdemo_rsimtf');

The parameters field of the structure is a substructure that contains parameter


information. The values field of the parameters substructure contains the numeric
values of the parameters that you can tune during execution of the simulation code.
2 Use the function rsimsetrtpparam to expand the structure so that it contains more
parameter sets. In this case, create two more parameter sets (for a total of three
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 Specify new values for the parameters in the second and third parameter sets.

49-11
49 Desktops in Simulink Coder

param_struct.parameters{2}.values = [-150 -5000 0 4950];


param_struct.parameters{3}.values = [-170 -5500 0 5100];
4 Save the structure containing the parameter set information to a MAT-file.
save rtwdemo_rsimtf.mat param_struct;

Alternatively, you can modify the block parameters in the model, and use rsimgetrtp to
create multiple parameter sets:

1 Use the function rsimgetrtp to get a structure containing parameter information


for the example model rtwdemo_rsimtf. Store the structure in a variable
param_struct.
param_struct = rsimgetrtp('rtwdemo_rsimtf');
2 Use the function rsimsetrtpparam to expand the structure so that it contains more
parameter sets. In this case, create two more parameter sets (for a total of three
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.

Create a MAT-File for a From File Block

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.

To create a MAT-file for a From File block:

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.

The following example saves the matrix var_matrix to the MAT-file


myrsimdemo.mat in Version 7.3 format.
save '-v7.3' myrsimdemo.mat var_matrix;

49-13
49 Desktops in Simulink Coder

Using a command-line option, you can then specify that MAT-file as input for rapid
simulations.

Create a MAT-File for an Inport Block

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.

For an example, see Single time/data matrix in the following procedure,


step 4. For more information, see “Loading Data Arrays to Root-Level
Inputs” (Simulink).

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.

For an example, see Signal-and-time structure in the following


procedure, step 4. For more information on this format, see “Loading Data
Structures to Root-Level Inputs” (Simulink).

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.

For an example, see Per-port structure in the following procedure, step 4.


For more information, see “Loading Data Structures to Root-Level Inputs”
(Simulink).

The supported formats and the following procedure are illustrated in rtwdemo_rsim_i.

To create a MAT-file for an Inport block:

1 Choose one of the preceding data file formats.


2 Update Inport block parameter settings and specifications to match specifications of
the data to be supplied by the MAT-file.

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.

• Main > Interpolate data


• Signal Attributes > Port dimensions
• Signal Attributes > Data type
• Signal Attributes > Signal type

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.

An example of each format follows:

Single time/data matrix

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.

Single time/data matrix

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

The following example saves the workspace structure variable var_single_struct


to the MAT-file rsim_i_single_struct.mat.
save rsim_i_single_struct.mat var_single_struct;

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

Scripts for Batch and Monte Carlo Simulations


The RSim target is for batch simulations in which parameters and input signals vary for
multiple simulations. New output file names allow you to run new simulations without
overwriting prior simulation results. You can set up a series of simulations to run by
creating a .bat file for use on a Microsoft Windows platform.

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).

Run Rapid Simulations


• “Rapid Simulations” on page 49-20
• “Requirements for Running Rapid Simulations” on page 49-21
• “Set a Clock Time Limit for a Rapid Simulation” on page 49-22
• “Override a Model Simulation Stop Time” on page 49-22
• “Read the Parameter Vector into a Rapid Simulation” on page 49-23

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.

From the operating system command line, use

rtwdemo_rsimtf

From the MATLAB command line, use

!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:

• Created or changed to a working folder.


• Opened the example model.
• Copied the data file matlabroot/toolbox/rtw/rtwdemos/rsimdemos/
rsim_tfdata.mat to your working folder. You can perform this operation using the
command:

copyfile(fullfile(matlabroot,'toolbox','rtw','rtwdemos',...
'rsimdemos','rsim_tfdata.mat'),pwd);

Requirements for Running Rapid Simulations

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.

Set a Clock Time Limit for a Rapid Simulation

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:

• On a Microsoft Windows platform,

Exiting program, time limit exceeded


Logging available data ...
• On The Open Group UNIX platform,

** Received SIGALRM (Alarm) signal @ Fri Jul 25 15:43:23 2003


** Exiting model 'vdp' @ Fri Jul 25 15:43:23 2003

You do not need to do anything to your model or to its configuration to use this option.

Override a Model Simulation Stop Time

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.

!rtwdemo_rsimtf -tf 6.0

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.

Read the Parameter Vector into a Rapid Simulation

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:

1 Build an RSim executable for the example model rtwdemo_rsimtf.


2 Modify parameters in your model and save the parameter structure.

param_struct = rsimgetrtp('rtwdemo_rsimtf');
save myrsimdata.mat param_struct
3 Run the executable with the new parameter set.

!rtwdemo_rsimtf -p myrsimdata.mat

** Starting model 'rtwdemo_rsimtf' @ Tue Dec 27 12:30:16 2005


** created rtwdemo_rsimtf.mat **
4 Load workspace variables and plot the simulation results by entering the following
commands:

load myrsimdata.mat
plot(rt_yout)

Specify New Signal Data File for a From File Block

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.

1 Set some parameters in the MATLAB workspace. For 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)

The next figure shows the resulting plot.

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.

Workspace data must be in the format:

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

Specify Signal Data File for an Inport Block

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:

1 Open the model rtwdemo_rsim_i.


2 Check the Inport block parameter settings. The following Inport block data
parameter settings and specifications that you specify for the workspace variables
must match settings in the MAT-file, as indicated in “Configure Inports to Provide
Simulation Source Data” on page 49-6:

• Main > Interpolate data


• Signal Attributes > Port dimensions
• Signal Attributes > Data type
• Signal Attributes > Signal type
3 Build the model.
4 Set up the input signals. 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

** Starting model 'rtwdemo_rsim_i' @ Tue Aug 19 10:26:53 2014


*** rsim_i_single_struct.mat is successfully loaded! ***
** created rtwdemo_rsim_i.mat **

** Execution time = 0.02024185130718954s


8 Load and plot the results.
load rtwdemo_rsim_i.mat
plot(rt_tout, rt_yout);

Change Block Parameters for an RSim Simulation

As described in “Create a MAT-File That Includes a Model Parameter Structure” on page


49-9, after you alter one or more parameters in a Simulink block diagram, you can extract
the parameter vector, model_P, for the entire model. You can then save the parameter
vector, along with a model checksum, to a MAT-file. This MAT-file can be read directly by
the standalone RSim executable, allowing you to replace the entire parameter vector or
individual parameter values, for running studies of variations of parameter values
representing coefficients, new data for input signals, and so on.

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.

The following example converts param_struct to a cell array, changes parameter


values, saves the changes to MAT-file mymatfile.mat, and then runs the executable
using the parameter values in the second element of the cell array as input.
param_struct = rsimgetrtp('rtwdemo_rsimtf');
param_struct = rsimsetrtpparam(param_struct,2);
param_struct.parameters{1}

ans =

dataTypeName: 'double'
dataTypeId: 0
complex: 0
dtTransIdx: 0
values: [-140 -4900 0 4900]
map: []
structParamInfo: []

param_struct.parameters{2}.values=[-150 -5000 0 4950];


save mymatfile.mat param_struct;
!rtwdemo_rsimtf -p mymatfile.mat@2 -o rsim2.mat

Specify a New Output File Name for a Simulation

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.

Specify New Output File Names for To File Blocks

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.

Tune Parameters Interactively During Rapid Simulation


The RSim target was designed to let you run batch simulations at the fastest possible
speed. Using variable-step or fixed-step solvers with RSim combined with the use of a
tunable parameter data structure, whether you set Default parameter behavior to
Tunable or to Inlined, you can create multiple parameter sets to run with the RSim
target's standalone executable file (.exe on Windows) generated using Simulink Coder.
Each invocation of the executable allows specification of the file name to use for results.

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).

Open Example Model

Open the example model rtwdemo_rsim_param_tuning.

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.

Rapid Simulation Target Limitations


The RSim target has the following limitations:

• Does not support algebraic loops.


• Does not support Interpreted MATLAB Function blocks.
• Does not support noninlined MATLAB language or Fortran S-functions.
• If an RSim build includes referenced models (by using Model blocks), set up these
models to use fixed-step solvers to generate code for them. The top model, however,
can use a variable-step solver as long as the blocks in the referenced models are
discrete.
• In certain cases, changing block parameters can result in structural changes to your
model that change the model checksum. An example of such a change is changing the
number of delays in a DSP simulation. In such cases, you must regenerate the code for
the model.

See Also

More About
• “Acceleration” (Simulink)

49-33
49 Desktops in Simulink Coder

• “Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-


Function Target” (Simulink Coder)

49-34
Run Rapid Simulations Over Range of Parameter Values

Run Rapid Simulations Over Range of Parameter Values


This example shows how to use the RSim target to run simulations over a range of
parameter values. The example uses the Van der Pol oscillator and performs a parameter
sweep over a range of initial state values to obtain the phase diagram of a nonlinear
system.

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.

[stat, fa] = fileattrib(pwd);


if ~fa.UserWrite
disp('This script must be run in a writable directory');
return
end

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.

prmFileName = [mdlName, '_prm_sets.mat'];


logFileName = [mdlName, '_run_scr.log'];
batFileName = [mdlName, '_run_scr'];
exeFileName = mdlName;
if ispc
exeFileName = [exeFileName, '.exe'];
batFileName = [batFileName, '.bat'];
end

49-36
Run Rapid Simulations Over Range of Parameter Values

aggDataFile = [mdlName, '_results'];


startTime = cputime;

Step 2. Build the Model

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);

### Starting build procedure for model: rtwdemo_rsim_vdp


### Successful completion of build procedure for model: rtwdemo_rsim_vdp

Step 3. Get the Default Parameter Set for the Model

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 =

struct with fields:

modelChecksum: [1.5936e+09 1.0250e+09 283187421 2.0458e+09]


parameters: [1x1 struct]
globalParameterInfo: [1x1 struct]

Step 4. Create Parameter Sets

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 =

struct with fields:

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

Step 5. Create a Batch File

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.

For example, the command (on Windows®)


model.exe -p prm.mat@3 -o run3.mat -L 3600 2>&1>> run.log

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.

Step 6. Execute Batch File to Run Simulations

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®.

Step 7. Load Output MAT-files and Collate the Results

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).

Step 8. Analyze Simulation Results

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.

colors = {'b','g','r','c','m','y','k'}; nColors = length(colors);


for idx = 1:nPrmSets
col = colors{idx - nColors*floor(idx/nColors) + 1};
plot(aggData(idx).prms.INIT_X1, aggData(idx).prms.INIT_X2, [col,'x'], ...
aggData(idx).yout(:,1), aggData(idx).yout(:,2),col);
hold on
end
grid on
xlabel('X1');
ylabel('X2');
axis('square');
title('Phase diagram for Van der Pol equation');

49-41
49 Desktops in Simulink Coder

49-42
Run Batch Simulations Without Recompiling Generated Code

Run Batch Simulations Without Recompiling Generated


Code
This example shows how to run batch simulations without recompiling the generated
code. The example modifies input signal data and model parameters by reading data from
a MAT-file. In the first part (steps 1-5), ten parameter sets are created from the
Simulink® model by changing the transfer function damping factor. The ten parameter
sets are saved to a MAT-file, and the RSim executable reads the specified parameter set
from the file. In the second part (step 6-7) of this example, five sets of signal data chirps
are created with increasingly high frequencies. In both parts, the RSim executable runs
the set of simulations and creates output MAT-files containing the specific simulation
result. Finally, a composite of runs appears in a MATLAB® figure.

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.

[stat, fa] = fileattrib(pwd);


if ~fa.UserWrite
disp('This script must be run in a writable directory');
return;
end

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

The MAT-file rsim_tfdata.mat is required in the local directory.

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);

Step 2. Build the Model

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);

Building compiled RSim simulation.


### Starting build procedure for model: rtwdemo_rsimtf
### Successful completion of build procedure for model: rtwdemo_rsimtf

Step 3. Get the Default Parameter Set and Create 10 Parameters Sets

disp('Creating rtP data files')


for i=1:10
% Extract current rtP structure using new damping factor.
[rtpstruct]=evalin('base','rsimgetrtp(''rtwdemo_rsimtf'');');
savestr = strcat('save params',num2str(i),'.mat rtpstruct');

49-44
Run Batch Simulations Without Recompiling Generated Code

eval(savestr);
evalin('base','theta = theta - .1;');
end
disp('Finished creating parameter data files.')

Creating rtP data files


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 plot shows 10 simulations, each using a different damping factor.

Step 5. Set Up a Time Vector and an Initial Frequency Vector

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

Step 6. Create 5 Sets of Signal Data in MAT Files

Creating .mat files with chirp data.

disp('This part of the example illustrates a sequence of 5 plots. Each')


disp('plot shows an input chirp signal of certain frequency range.')
for i = 1:5
wlo = whi; whi = 3*whi; % keep increasing frequencies
omega = [wlo:((whi-wlo)/n):whi - (whi-wlo)/n];
% In a real application we recommend shaping the chirp using
% a windowing function (hamming or hanning window, etc.)
% This example does not use a windowing function.
u = sin(omega.*t);
tudata = [t;u];
% At each pass, save one more set of tudata to the next
% .mat file.
savestr = strcat('save sweep',num2str(i),'.mat tudata');
eval(savestr);
% Display each chirp. Note that this is only input data.
% Simulations have not been run yet.
plotstr = strcat('subplot(5,1,',num2str(i),');');
eval(plotstr);
plot(t,u)
pause(0.3)
end

This part of the example illustrates a sequence of 5 plots. Each


plot shows an input chirp signal of certain frequency range.

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.

disp('Starting batch simulations.')


for i = 1:5
% Bang out and run the next set of data with RSim
runstr = ['.', filesep, 'rtwdemo_rsimtf -f rsim_tfdata.mat=sweep', ...
num2str(i),'.mat -v -tf 4.096'];
[status, result] = system(runstr);
if status ~= 0, error(result); end
% Load the data to MATLAB and plot the results.
load rtwdemo_rsimtf.mat

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);

Starting batch simulations.


This part of the example illustrates a sequence of 5 plots. Each plot
shows the simulation results for the next frequency range. Using the
mouse, zoom in on each signal to observe signal amplitudes.

49-49
49 Desktops in Simulink Coder

49-50
Use MAT-Files to Feed Data to Inport Blocks for Rapid Simulations

Use MAT-Files to Feed Data to Inport Blocks for Rapid


Simulations
This example shows how the RSim -i option in Simulink® Coder™ lets you use a MAT-file
as the input data source for Inport blocks for rapid simulations. The data in such a MAT-
file can be presented in any of the following formats:

1 One variable that defines a time/input data matrix of double values.


2 One variable that defines a structure that uses a combination of Simulink® data
types.
3 Multiple variables, each defining a structure that uses a combination of Simulink®
data types.

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

Step 2. Configure the Inport Blocks

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

Step 3. Build the Model

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

Step 4. The Input Signals

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.');

The following figure displays the input signals.

49-54
Use MAT-Files to Feed Data to Inport Blocks for Rapid Simulations

Step 5. Prepare the MAT-File

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.');

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

rsim_i_single_struct.mat contains one variable var_single_struct in


struct format.

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.');

rsim_i_multi_struct.mat contains three variables Inb1\Inb2\Inb3


in struct format. Note that command save -append option must be
used to generate the MAT-file to preserve the order of the
variables in the MAT-file generated. The command:
save rsim_i_multi_struct.mat Inb1 Inb2 Inb3 might not preserve
the order of the variables in the MAT-file and you should not use it
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

disp('This part of the example illustrates a sequence of 3 plots. Each plot');


disp('shows the simulation results by using input MAT-file with different');
disp('variable format. Notice that the model is compiled only once.');
close_system(mdlName, 0);

This part of the example illustrates a sequence of 3 plots. Each plot


shows the simulation results by using input MAT-file with different
variable format. Notice that the model is compiled only once.

49-57
49 Desktops in Simulink Coder

49-58
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target

Accelerate Simulation, Reuse Code, or Protect


Intellectual Property by Using S-Function Target
S-functions are an important class of system target file for which the code generator can
produce code. The ability to encapsulate a subsystem into an S-function allows you to
increase its execution efficiency and facilitate code reuse.

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

About the S-Function Target


Using the S-function target, you can build an S-function component and use it as an S-
Function block in another model. The following sections describe deployment
considerations for the S-function target.

• “Required Files for S-Function Deployment” on page 49-60


• “Sample Time Propagation in Generated S-Functions” on page 49-61
• “Choose a Solver Type” on page 49-61
• “Solver Type Overrides” on page 49-62

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

• Conversion of a model to a component. You can generate an S-Function block for a


model, m1. Then, you can place the generated S-Function block in another model, m2.
Regenerating code for m2 does not require regenerating code for m1.
• Conversion of a subsystem to a component. By extracting a subsystem to a separate
model and generating an S-Function block from that model, you can create a reusable
component from the subsystem. See “Create S-Function Blocks from a Subsystem” on
page 49-63 for an example of this procedure.
• Speeding up simulation. Often, an S-function generated from a model performs more
efficiently than the original model.
• Code reuse. You can incorporate multiple instances of one model inside another
without replicating the code for each instance. Each instance continues to maintain its
own unique data.

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.

Required Files for S-Function Deployment

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

where subsys is the subsystem name and mexext is a platform-dependent MEX-file


extension (see mexext). For example, SourceSubsys_sf.mexw64.

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:

• subsys_sf.c or .cpp, where subsys is the subsystem name (for example,


SourceSubsys_sf.c)
• subsys_sf.h
• subsys_sf.mexext, where mexext is a platform-dependent MEX-file extension (see
mexext)
• Subfolder subsys_sfcn_rtw and its contents

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.

Sample Time Propagation in Generated S-Functions

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).

Choose a Solver Type

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

Top-level Model Solver Options and Subsystem Build Types

Model Configuration Parameters: top-level model


configuration
Subsystem Build Type Solver options, Type: Solver options, Type:
Variable-step Fixed-step
Build This Subsystem Generated S-function does Generated S-function does
NOT require variable-step NOT require variable-step
solver solver
Generate S-Function Generated S-function Generated S-function does
requires variable-step solver NOT require variable-step
solver

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.

Solver Type Overrides

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

Model Configuration Parameters: top-level model


configuration
Subsystem Build Type Solver options, Type: Solver options, Type:
Variable-step Fixed-step
Build This Subsystem Subsystem uses fixed-step Subsystem uses fixed-step
solver type solver type
Generate S-Function Subsystem uses variable- Subsystem uses fixed-step
step solver type solver type

49-62
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target

Create S-Function Blocks from a Subsystem


This section illustrates how to extract a subsystem from a model and generate a reusable
S-function component from it.

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:

• A Step block with sample time 1


• A Sine Wave block with sample time 0.5
• A Constant block whose value is the vector [-2 3]

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).

To build SourceSubsys as an S-function component,

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.

Optionally you can save the generated model, for example as


SourceSubsys_Sfunction.
12 You can now copy the S-Function block generated from the new model and use it in
other models or in a library.

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.

Generated S-Function Configured Like SourceModel

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

Tunable Parameters in Generated S-Functions


You can use tunable parameters in generated S-functions in two ways:

• 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.

System Target File


The rtwsfcn.tlc system target file is provided for use with the S-function target.

Checksums and the S-Function Target


The code generator creates a checksum for a model and uses the checksum during the
build process for code reuse, model reference, and external mode features.

The code generator calculates a model checksum by

49-68
Accelerate Simulation, Reuse Code, or Protect Intellectual Property by Using S-Function Target

1 Calculating a checksum for each subsystem in the model. A subsystem's checksum is


the combination of properties (data type, complexity, sample time, port dimensions,
and so forth) of the subsystem's blocks.
2 Combining the subsystem checksums and other model-level information.

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.

Generated S-Function Compatibility


When you build a MEX S-function from your model, the code generator builds a level 2
noninlined S-function. Cross-release usage limitations on the generated code and binary
MEX file (for example, *.mexw64) include:

• 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

S-Function Target Limitations


• “Limitations on Using Tunable Variables in Expressions” on page 49-70
• “Parameter Tuning” on page 49-70
• “Run-Time Parameters and S-Function Compatibility Diagnostics” on page 49-71
• “Limitations on Using Goto and From Block” on page 49-71
• “Limitations on Building and Updating S-Functions” on page 49-72
• “Unsupported Blocks” on page 49-73
• “SimState Not Supported for Code Generation” on page 49-73
• “Profiling Code Performance with TLC Hook Function Not Supported” on page 49-74
• “Limitations on Nesting S-Functions” on page 49-74
• “Limitations on User-Defined Data Types” on page 49-74
• “Limitation on Right-Click Generation of an S-Function Target” on page 49-74
• “Limitation on S-Functions with Bus I/O Signals” on page 49-75
• “Limitation on Subsystems with Function-Call I/O Signals” on page 49-75
• “Data Store Access” on page 49-75
• “Cannot Specify Inport or Outport Block Parameters Through Subsystem Mask”
on page 49-75

Limitations on Using Tunable Variables in Expressions

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):

• The software produces warnings during the build process.


• The generated S-Function block mask does not display these parameters.

Run-Time Parameters and S-Function Compatibility Diagnostics

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.

Limitations on Using Goto and From Block

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.

Example Before Work Around

• Root model with a From block and subsystem, Subsystem1

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

• Subsystem1 replaced with an S-function generated with the S-Function target — a


warning results when you run the model because the generated S-function does not
implement the Goto block

Example After Work Around

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.

Limitations on Building and Updating S-Functions

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:

• Interpreted MATLAB Function block


• S-Function blocks containing any of the following:

• 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.

SimState Not Supported for Code Generation

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 Code Performance with TLC Hook Function Not Supported

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.

Limitations on Nesting S-Functions

The following limitations apply to nesting a generated S-Function block in a model or


subsystem from which you generate another S-function:

• 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.

Limitations on User-Defined Data Types

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.

Limitation on Right-Click Generation of an S-Function Target

If you generate an S-function target by right-clicking a Function-Call Subsystem block,


the original subsystem and the generated S-function might not be consistent. An
inconsistency occurs when the States when enabling parameter of the Trigger Port

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.

Limitation on S-Functions with Bus I/O Signals

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.

Limitation on Subsystems with Function-Call I/O Signals

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.

Data Store Access

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:

• Global data stores


• Data stores placed outside the subsystem, but accessed by Data Store Read or Data
Store Write blocks.

Cannot Specify Inport or Outport Block Parameters Through Subsystem Mask

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

Invalid setting in 'testSystem/Subsystem/__OutputSSForSFun__/Out2'


for parameter 'PortDimensions'
...

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

Desktops in Embedded Coder


50 Desktops in Embedded Coder

Package Generated Code as Shared Libraries


If you have an Embedded Coder license, you can package generated source code from a
model component for easy distribution and shared use by building the code as a shared
library—Windows dynamic link library (.dll), UNIX shared object (.so), or Macintosh
OS X dynamic library (.dylib). You or others can integrate the shared library into an
application that runs on a Windows, UNIX, or Macintosh OS X development computer.
The generated .dll, .so, or .dylib file is shareable among different applications and
upgradeable without having to recompile the applications that use it.

About Generated Shared Libraries


You build a shared library by configuring the code generator to use the system target file
ert_shrlib.tlc. Code generation for that system target file exports:

• Variables and signals of type ExportedGlobal as data


• Real-time model structure (model_M) as data
• Functions essential to executing your model code

To view a list of symbols contained in a generated shared library:

• On Windows, use the Dependency Walker utility, downloadable from http://


www.dependencywalker.com
• On UNIX, use nm -D model.so
• On Macintosh OS X , use nm -g model.dylib

To generate and use a shared library:

1 Generate a shared library version of your model code


2 Create application code to load and use your shared library file

Generate Shared Library Version of Model Code


To generate a shared library version of your model code:

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.

Create Application Code to Use Shared Library


To illustrate how application code can load a shared library file and access its functions
and data, MathWorks provides the model rtwdemo_shrlib.

Note Change directory to a writable working folder before running the


rtwdemo_shrlib script.

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.

Example Application Header File

The example application header file rtwdemo_shrlib_app.h contains type declarations


for the model's external input and output.
#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_*/

50-4
Package Generated Code as Shared Libraries

Example Application C Code

The example application rtwdemo_shrlib_app.c includes the following code for


dynamically loading the shared library file. Notice that, depending on platform, the code
invokes Windows or UNIX library commands.
#if (defined(_WIN32)||defined(_WIN64)) /* WINDOWS */
#include <windows.h>
#define GETSYMBOLADDR GetProcAddress
#define LOADLIB LoadLibrary
#define CLOSELIB FreeLibrary

#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

/* 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 ,
"_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++){
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);
}

50-6
Package Generated Code as Shared Libraries

Example Application Script

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.

Note To run the run_rtwdemo_shrlib_app script without first opening the


rtwdemo_shrlib model, change directory to a writable working folder and issue the
following MATLAB command:

addpath(fullfile(matlabroot,'toolbox','rtw','rtwdemos','shrlib_demo'))

Shared Library Limitations


The following limitations apply to building shared libraries:

• Code generation for the ert_shrlib.tlc system target file exports the following as
data:

• Variables and signals of type ExportedGlobal


• Real-time model structure (model_M)
• Code generation for the ert_shrlib.tlc system target file supports the C language
only (not C++). When you select ert_shrlib.tlc, language selection is greyed out
on the Code Generation pane of the Configuration Parameters dialog box.
• To reconstruct a model simulation using a generated shared library, the application
author must maintain the timing between system and shared library function calls in
the original application. The timing needs to be consistent so that you can compare
the simulation and integration results. Additional simulation considerations apply if
generating a shared library from a model that enables parameters Support:
continuous time and Single output/update function. For more information, see
“Single output/update function” (Simulink Coder) dependencies.

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

Real-Time Systems in Simulink


Coder

• “Deploy Algorithm Model for Real-Time Rapid Prototyping” on page 51-2


• “Deploy Environment Model for Real-Time Hardware-In-the-Loop (HIL) Simulation”
on page 51-5
51 Real-Time Systems in Simulink Coder

Deploy Algorithm Model for Real-Time Rapid Prototyping


Use the code generator to deploy algorithm models for real-time rapid prototyping.
In this section...
“About Real-Time Rapid Prototyping” on page 51-2
“Goals of Real-Time Rapid Prototyping” on page 51-2
“Refine Code With Real-Time Rapid Prototyping” on page 51-3

About Real-Time Rapid Prototyping


Real-time rapid prototyping requires the use of a real-time simulator, potentially
connected to system hardware (for example, physical plant or vehicle) being controlled.
You generate, deploy, and tune code as it runs on the real-time simulator or embedded
microprocessor. This design step is crucial for verifying whether a component can
adequately control the system, and allows you to assess, interact with, and optimize code.

The following figure shows a typical approach for real-time rapid prototyping.

System model

Algorithm model Environment model

Host
generation

Tuning and
Code

logging

Real-time Harness
simulator

Actual environment (plants)

Goals of Real-Time Rapid Prototyping


Assuming that you have documented functional requirements, refined concept models,
system hardware for the physical plant or vehicle being controlled, and access to target

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:

• Refine component and environment model designs by rapidly iterating between


algorithm design and prototyping
• Validate whether a component can adequately control the physical system in real time
• Evaluate system performance before laying out hardware, coding production software,
or committing to a fixed design
• Test hardware

Refine Code With Real-Time Rapid Prototyping


To perform real-time rapid prototyping:

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.

Engineering Tasks Related Product Examples


Information
Generate code for real-time “Compare System Target File rtwdemo_counter
rapid prototyping Support” (Simulink Coder) rtwdemo_counter_msvc

“Event-Based Scheduling”
(Simulink Coder)

Embedded Coder

“Support for Standards and


Guidelines” on page 12-2

51-3
51 Real-Time Systems in Simulink Coder

Engineering Tasks Related Product Examples


Information
Generate code for rapid Simulink Real-Time help xpcdemos
prototyping in hard real time,
using PCs “Simulink Real-Time Options
Pane” (Simulink Real-Time)
Generate code for rapid Simulink Desktop Real-Time sldrtex_vdp (and others)
prototyping in soft real time,
using PCs “Simulink Desktop Real-Time
Pane” (Simulink Desktop Real-
Time)
3 Monitor signals, tune parameters, and log data.

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

Deploy Environment Model for Real-Time Hardware-In-


the-Loop (HIL) Simulation
In this section...
“About Hardware-In-the-Loop Simulation” on page 51-5
“Set Up and Run HIL Simulations” on page 51-6

About Hardware-In-the-Loop Simulation


Hardware-in-the-loop (HIL) simulation tests and verifies an embedded system or control
unit in the context of a software test platform. Examples of test platforms include real-
time target systems and instruction set simulators (IISs). You use Simulink software to
develop and verify a model that represents the test environment. Using the code
generator, you produce, build, and download an executable program for the model to the
HIL simulation platform. After you set up the environment, you can run the executable to
validate the embedded system or control unit in real time.

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).

The following figure shows a typical HIL setup.

Simulink

Algorithm model Environment model


generation

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.

Set Up and Run HIL Simulations


To set up and run HIL simulations iterate through the following steps:

1 Develop a model that represents the environment or system under development.

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

Real-Time and Embedded Systems


in Embedded Coder

• “Deploy Generated Standalone Executable Programs To Target Hardware”


on page 52-2
• “Deploy Generated Component Software to Application Target Platforms”
on page 52-31
52 Real-Time and Embedded Systems in Embedded Coder

Deploy Generated Standalone Executable Programs To


Target Hardware
By default, the Embedded Coder software generates standalone executable programs that
do not require an external real-time executive or operating system. A standalone program
requires minimal modification to be adapted to the target hardware. The standalone
program architecture supports execution of models with either single or multiple sample
rates.

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

Generate a Standalone Program


To generate a standalone program:

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:

• Whether the model executes in single-tasking or multitasking mode.


• Whether or not reusable code is being generated.

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.

Standalone Program Components


The core of a standalone program is the main loop. On each iteration, the main loop
executes a background or null task and checks for a termination condition.

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

The following pseudocode shows the execution of a main program.

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.

Guidelines for Modifying the Main Program

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):

• Disable timer interrupts.


• Perform target-specific cleanup such as zeroing DACs.
• Detect and handle errors. Note that even if your program is designed to run
indefinitely, you may need to handle severe error conditions, such as timer
interrupt overruns.

You can use the macros rtmGetErrorStatus and rtmSetErrorStatus to


detect and signal errors.

rt_OneStep and Scheduling Considerations


• “Overview of Operation” on page 52-5
• “Single-Rate Single-Tasking Operation” on page 52-5
• “Multirate Multitasking Operation” on page 52-6
• “Multirate Single-Tasking Operation” on page 52-9
• “Guidelines for Modifying rt_OneStep” on page 52-9

52-4
Deploy Generated Standalone Executable Programs To Target Hardware

Overview of Operation

The operation of rt_OneStep depends upon

• Whether your model is single-rate or multirate. In a single-rate model, the sample


times of all blocks in the model, and the model's fixed step size, are the same. A model
in which the sample times and step size do not meet these conditions is termed
multirate.
• Your model's solver mode (SingleTasking versus MultiTasking)

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.

Permitted Solver Modes for Embedded Real-Time System Target Files

Mode Single-Rate Multirate


SingleTasking Allowed Allowed
MultiTasking Disallowed Allowed
Auto Allowed Allowed

(defaults to (defaults to MultiTasking)


SingleTasking)

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.

Single-Rate Single-Tasking Operation

The only valid solver mode for a single-rate model is SingleTasking. Such models run
in “single-rate” operation.

The following pseudocode shows the design of rt_OneStep in a single-rate program.

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

For the single-rate case, the generated model_step function is

void model_step(void)

Single-rate rt_OneStep is designed to execute model_step within a single clock period.


To enforce this timing constraint, rt_OneStep maintains and checks a timer overrun
flag. On entry, timer interrupts are disabled until the overrun flag and other error
conditions have been checked. If the overrun flag is clear, rt_OneStep sets the flag, and
proceeds with timer interrupts enabled.

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.

Reinterruption of rt_OneStep by the timer is an error condition. If this condition is


detected rt_OneStep signals an error and returns immediately. (Note that you can
change this behavior if you want to handle the condition differently.)

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.

Multirate Multitasking Operation

In a multirate multitasking system, code generation uses a prioritized, preemptive


multitasking scheme to execute the different sample rates in your model.

The following pseudocode shows the design of rt_OneStep in a multirate multitasking


program.

rt_OneStep()
{
Check for base-rate interrupt overrun
Enable "rt_OneStep" interrupt
Determine which rates need to run this time step

Model_Step0() -- run base-rate time step code

For N=1:NumTasks-1 -- iterate over sub-rate tasks


If (sub-rate task N is scheduled)
Check for sub-rate interrupt overrun
Model_StepN() -- run sub-rate time step code
EndIf

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

Multirate rt_OneStep also maintains an array of timer overrun flags. rt_OneStep


detects timer overrun, per task, by the same logic as single-rate rt_OneStep.

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

Multirate Single-Tasking Operation

In a multirate single-tasking program, by definition, sample times in the model must be an


integer multiple of the model's fixed-step size.

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.

Guidelines for Modifying rt_OneStep

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

Comments in rt_OneStep indicate the place to add your code.

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.

Also observe the following cautionary guidelines:

• 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:

/* Set model inputs here */


/* Step the model */

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

Static Main Program Module


• “Overview” on page 52-11
• “Rate Grouping and the Static Main Program” on page 52-12
• “Modify the Static Main Program” on page 52-13
• “Modify Static Main to Allocate and Access Model Instance Data” on page 52-14

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:

• matlabroot/rtw/c/src/common/rt_main.c — Supports Nonreusable


function code interface packaging.
• matlabroot/rtw/c/src/common/rt_malloc_main.c — Supports Reusable
function code interface packaging. The model option Use dynamic memory
allocation for model initialization must be on and model parameter Pass root-
level I/O as must be set to Part of model data structure.
• matlabroot/rtw/c/src/common/rt_cppclass_main.cpp — Supports C++
class code interface packaging.

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.

The static main module contains

52-11
52 Real-Time and Embedded Systems in Embedded Coder

• rt_OneStep, a timer interrupt service routine (ISR). rt_OneStep calls model_step


to execute processing for one clock period of the model.
• A skeletal main function. As provided, main is useful in simulation only. You must
modify main for real-time interrupt-driven execution.

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.

Rate Grouping and the Static Main Program

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:

void model_step(int_T tid);

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:

void mymodel_step(int_T tid) /* Sample time: */


{

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

ModelStep(tid=0) --base-rate time step

For N=1:NumTasks-1 -- iterate over sub-rate tasks


Check for sub-rate interrupt overflow
If (sub-rate task N is scheduled)
ModelStep(tid=N) --sub-rate time step
EndIf
EndFor
}

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.

You should set RateBasedStepFcn prior to the %include "codegenentry.tlc"


statement in your system target file. Alternatively, you can set RateBasedStepFcn in
your target_settings.tlc file.

Modify the Static Main Program

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

Other modifications you may need to make are

• If applicable, follow comments in the code regarding where to add code for reading/
writing model I/O and saving/restoring FPU context.

Note If you modify rt_main.c, rt_malloc_main.c, or rt_cppclass_main.cpp to


read a value from a continuous output port after each base-rate model step, see the
relevant cautionary guideline in “Guidelines for Modifying rt_OneStep” on page 52-9.
• When the Generate an example main program option is off, rtmodel.h is
generated to provide an interface between the main module and generated model
code. If you create your own static main program module, you would normally include
rtmodel.h.

Alternatively, you can suppress generation of rtmodel.h, and include model.h


directly in your main module. To suppress generation of rtmodel.h, use the following
statement in your system target file:
%assign AutoBuildProcedure = 0
• If you have cleared the Terminate function required option, remove or comment out
the following in your production version of rt_main.c, rt_malloc_main.c, or
rt_cppclass_main.cpp:

• The #if TERMFCN... compile-time error check


• The call to MODEL_TERMINATE
• For rt_main.c (not applicable to rt_cppclass_main.cpp): If you do not want to
combine output and update functions, clear the Single output/update function
option and make the following changes in your production version of rt_main.c:

• Replace calls to MODEL_STEP with calls to MODEL_OUTPUT and MODEL_UPDATE.


• Remove the #if ONESTEPFCN... error check.
• The static rt_main.c module does not support Reusable function code interface
packaging. The following error check raises a compile-time error if Reusable
function code interface packaging is used illegally.
#if MULTI_INSTANCE_CODE==1

Modify Static Main to Allocate and Access Model Instance Data

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.

RTM Macro Syntax Description


rtmGetBlockIO(rtm) Get the block I/O data structure
rtmSetBlockIO(rtm,val) Set the block I/O data structure
rtmGetContStates(rtm) Get the continuous states data structure
rtmSetContStates(rtm,val) Set the continuous states data structure
rtmGetDefaultParam(rtm) Get the default parameters data structure
rtmSetDefaultParam(rtm,val) Set the default parameters data structure
rtmGetPrevZCSigState(rtm) Get the previous zero-crossing signal state data
structure
rtmSetPrevZCSigState(rtm,val) Set the previous zero-crossing signal state data
structure
rtmGetRootDWork(rtm) Get the DWork data structure
rtmSetRootDWork(rtm,val) Set the DWork data structure
rtmGetU(rtm) Get the root inputs data structure (when root inputs
are passed as part of the model data structure)
rtmSetU(rtm,val) Set the root inputs data structure (when root inputs
are passed as part of the model data structure)
rtmGetY(rtm) Get the root outputs data structure (when root
outputs are passed as part of the model data
structure)
rtmSetY(rtm,val) Set the root outputs data structure (when root
outputs are passed as part of the model data
structure)

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;

/* Parameters (auto storage) */


struct Parameters_ {
real_T k1; /* Variable: k1
* Referenced by: '<Root>/Gain'
*/
};

/* Model entry point functions */


extern void rtwdemo_reusable_initialize(RT_MODEL *const rtM, real_T *rtU_In1,
real_T *rtU_In2, real_T *rtY_Out1);
extern void rtwdemo_reusable_step(RT_MODEL *const rtM, real_T rtU_In1, real_T
rtU_In2, real_T *rtY_Out1);

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

/* Example parameter data definition with initial values */


static Parameters rtP = {
2.0 /* Variable: k1
* Referenced by: '<Root>/Gain'
*/
}; /* Modifiable parameters */

#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 */

static D_Work rtDWork; /* Observable states */

/* '<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.

Rate Grouping Compliance and Compatibility Issues


• “Main Program Compatibility” on page 52-17
• “Make Your S-Functions Rate Grouping Compliant” on page 52-17

Main Program Compatibility

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.

Make Your S-Functions Rate Grouping Compliant

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.

Use of noncompliant multirate blocks to generate rate-grouping code generates dead


code. This can cause two problems:

• Reduced code efficiency.


• Warning messages issued at compile time. Such warnings are caused when dead code
references temporary variables before initialization. Since the dead code does not run,
this problem does not affect the run-time behavior of the generated code.

To make your S-functions rate grouping compliant, you can use the following TLC
functions to generate ModelOutputs and ModelUpdate code, respectively:

OutputsForTID(block, system, tid)


UpdateForTID(block, system, tid)

The code listings below illustrate generation of output computations without rate
grouping (Listing 1) and with rate grouping (Listing 2). Note the following:

• The tid argument is a task identifier (0..NumTasks-1).


• Only code guarded by the tid passed in to OutputsForTID is generated. The if
(%<LibIsSFcnSampleHit(portName)>) test is not used in OutputsForTID.
• When generating rate grouping code, OutputsForTID and/or UpdateForTID is
called during code generation. When generating non-rate-grouping code, Outputs
and/or Update is called.
• In rate grouping compliant code, the top-level Outputs and/or Update functions call
OutputsForTID and/or UpdateForTID functions for each rate (tid) involved in the
block. The code returned by OutputsForTID and/or UpdateForTID must be guarded
by the corresponding tid guard:

if (%<LibIsSFcnSampleHit(portName)>)

as in Listing 2.

Listing 1: Outputs Code Generation Without Rate Grouping


%% multirate_blk.tlc

52-18
Deploy Generated Standalone Executable Programs To Target Hardware

%implements "multirate_blk" "C"

%% Function: mdlOutputs =====================================================


%% Abstract:
%%
%% Compute the two outputs (input signal decimated by the
%% specified parameter). The decimation is handled by sample times.
%% The decimation is only performed if the block is enabled.
%% Each port has a different rate.
%%
%% Note, the usage of the enable should really be protected such that
%% each task has its own enable state. In this example, the enable
%% occurs immediately which may or may not be the expected behavior.
%%
%function Outputs(block, system) Output
/* %<Type> Block: %<Name> */
%assign enable = LibBlockInputSignal(0, "", "", 0)
{
int_T *enabled = &%<LibBlockIWork(0, "", "", 0)>;

%if LibGetSFcnTIDType("InputPortIdx0") == "continuous"


%% Only check the enable signal on a major time step.
if (%<LibIsMajorTimeStep()> && ...
%<LibIsSFcnSampleHit("InputPortIdx0")>) {
*enabled = (%<enable> > 0.0);
}
%else
if (%<LibIsSFcnSampleHit("InputPortIdx0")>) {
*enabled = (%<enable> > 0.0);
}
%endif

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

Listing 2: Outputs Code Generation With Rate Grouping


%% example_multirateblk.tlc

%implements "example_multirateblk" "C"

52-19
52 Real-Time and Embedded Systems in Embedded Coder

%% Function: mdlOutputs =====================================================


%% Abstract:
%%
%% Compute the two outputs (the input signal decimated by the
%% specified parameter). The decimation is handled by sample times.
%% The decimation is only performed if the block is enabled.
%% All ports have different sample rate.
%%
%% Note: the usage of the enable should really be protected such that
%% each task has its own enable state. In this example, the enable
%% occurs immediately which may or may not be the expected behavior.
%%
%function Outputs(block, system) Output

%assign portIdxName = ["InputPortIdx0","OutputPortIdx0","OutputPortIdx1"]


%assign portTID = [%<LibGetGlobalTIDFromLocalSFcnTID("InputPortIdx0")>, ...
%<LibGetGlobalTIDFromLocalSFcnTID("OutputPortIdx0")>, ...
%<LibGetGlobalTIDFromLocalSFcnTID("OutputPortIdx1")>]
%foreach i = 3
%assign portName = portIdxName[i]
%assign tid = portTID[i]
if (%<LibIsSFcnSampleHit(portName)>) {
%<OutputsForTID(block,system,tid)>
}
%endforeach

%endfunction

%function OutputsForTID(block, system, tid) Output


/* %<Type> Block: %<Name> */
%assign enable = LibBlockInputSignal(0, "", "", 0)
%assign enabled = LibBlockIWork(0, "", "", 0)
%assign signal = LibBlockInputSignal(1, "", "", 0)

%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

%assign y = LibBlockOutputSignal(1, "", "", 0)


%<y> = %<signal>;
}
%break
%default
%% error it out
%endswitch

%endfunction

%% [EOF] sfun_multirate.tlc

Generate Code That Dereferences Data from a Literal Memory


Address
This example shows how to generate code that reads the value of a signal by
dereferencing a memory address that you specify. With this technique, you can generate a
control algorithm that interacts with memory that your hardware populates (for example,
memory that stores the output of an analog-to-digital converter in a microcontroller).

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:

#define A2D_INPUT ((*(volatile const uint16_T *)0x8675309)&0x03FF)

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

Derivation of Macro Syntax

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.

(volatile const uint16_T *)0x8675309

Dereference the address.

*(volatile const uint16_T *)0x8675309

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.

(*(volatile const uint16_T *)0x8675309)&0x03FF

As a safe coding practice, wrap the entire construct in another layer of parentheses.

((*(volatile const uint16_T *)0x8675309)&0x03FF)

Create Example Model

Create the example model ex_memmap_simple.

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.

Create Custom Storage Class

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.

Rename the new custom storage class MemoryMappedAddress.

For MemoryMappedAddress, on the General tab, set:

• 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

Definition file to Specify instead of Instance specific prevents users of the


custom storage class from unnecessarily specifying a definition file.
• Header file to Instance specific. To control the file placement of the macro
definition, the user of the custom storage class must specify a header file for each data
item that uses this custom storage class.
• Owner to Specify (leave the text box empty). Owner applies only to data items that
consume memory.

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 Class to Store Custom Attributes for 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.

In the MemoryMap package (the +MemoryMap folder), create a folder named


@MemoryMapAttribs.

In the @MemoryMapAttribs folder, create a file named MemoryMapAttribs. The file


defines a class that derives from the built-in class
Simulink.CustomStorageClassAttributes.

classdef MemoryMapAttribs < Simulink.CustomStorageClassAttributes


properties( PropertyType = 'char' )
MemoryAddress = '';
end
end

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 Emits Correct C Code

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.

In the +MemoryMap folder, create a folder named tlc.

Navigate to the new folder.

Inspect the built-in template TLC file, TEMPLATE_v1.tlc.

edit(fullfile(matlabroot,...
'toolbox','rtw','targets','ecoder','csc_templates','TEMPLATE_v1.tlc'))

Save a copy of TEMPLATE_v1.tlc in the tlc folder. Rename the copy


memory_map_csc.tlc.

In memory_map_csc.tlc, find the portion that controls the generation of C-code data
declarations.

%case "declare"

%% LibDefaultCustomStorageDeclare is the default declare function to


%% declares a global variable whose identifier is the name of the data.
%return "extern %<LibDefaultCustomStorageDeclare(record)>"
%%break

%% ==========================================================================

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"

%% In TLC code, a 'record' is a data item (for example, a signal line).


%% 'LibGetRecordIdentifier' returns the name of the data item.
%assign id = LibGetRecordIdentifier(record)

52-25
52 Real-Time and Embedded Systems in Embedded Coder

%assign dt = LibGetRecordCompositeDataTypeName(record)

%% The 'CoderInfo' property of a data item stores a


%% 'Simulink.CoderInfo' object, which stores code generation settings
%% such as the storage class or custom storage class that you specify
%% for the item.
%assign ci = record.Object.ObjectProperties.CoderInfo
%% The 'ci' variable now stores the 'Simulink.CoderInfo' object.

%% By default, the 'CustomAttributes' property of a 'Simulink.CoderInfo'


%% object stores a 'Simulink.CustomStorageClassAttributes' object.
%% This nested object stores specialized code generation settings
%% such as the header file and definition file that you specify for
%% the data item.
%%
%% The 'MemoryMap' package derives a new class,
%% 'MemoryMapAttribs', from 'Simulink.CustomStorageClassAttributes'.
%% The new class adds a property named 'MemoryAddress'.
%% This TLC code determines the memory address of the data item by
%% acquiring the value of the 'MemoryAddress' property.
%assign ca = ci.Object.ObjectProperties.CustomAttributes
%assign address = ca.Object.ObjectProperties.MemoryAddress

%assign width = LibGetDataWidth(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"

%% LibDefaultCustomStorageDefine is the default define function to define


%% a global variable whose identifier is the name of the data. If the
%% data is a parameter, the definition is also statically initialized to
%% its nominal value (as set in MATLAB).
%return "%<LibDefaultCustomStorageDefine(record)>"
%%break

%% ==========================================================================

The define case derives a return value that the code generator emits into a .c file,
which defines data items that consume memory.

Replace the existing %case content with this new content:

%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"

%% LibDefaultCustomStorageInitialize is the default initialization


%% function that initializes a scalar element of a global variable to 0.
%return LibDefaultCustomStorageInitialize(record, idx, reim)
%%break

%% ==========================================================================

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).

Replace the existing %case content with this new content:

%case "initialize"
%return ""
%%break

%% ==========================================================================

MemoryMappedAddress yields a macro, so the generated code must not attempt to


initialize the value of the macro. The new TLC code returns an empty string.

Complete the Definition of the Custom Storage Class

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.

Navigate to the folder that contains the +MemoryMap folder.

Open the Custom Storage Class Designer again.


cscdesigner('MemoryMap','-advanced');

For MemoryMappedAddress, on the Other Attributes tab, set:

• TLC file name to memory_map_csc.tlc.


• CSC attributes class to MemoryMap.MemoryMapAttribs.

Click Apply and Save.

Define Signal Data Class

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.

In the MemoryMap package, create a folder named @Signal.

52-28
Deploy Generated Standalone Executable Programs To Target Hardware

In the @Signal folder, create a file named Signal.m.

classdef Signal < Simulink.Signal


methods
function setupCoderInfo( this )
useLocalCustomStorageClasses( this, 'MemoryMap' );
return;
end
end
end

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.

Apply Custom Storage Class to Signal Line

Navigate to the folder that contains the example model and open the model.

In the model, select View > Property Inspector.

Click the signal named A2D_INPUT.

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.

In the Property Inspector, set Storage class to MemoryMappedAddress.

Set Header file to memory_mapped_addresses.h.

Set MemoryAddress to 0x8675309.

Generate and Inspect Code

Generate code from the model.

52-29
52 Real-Time and Embedded Systems in Embedded Coder

### Starting build procedure for model: ex_memmap_simple


### Successful completion of build procedure for model: ex_memmap_simple

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.

/* Declaration of data with custom storage class MemoryMappedAddress */


#define A2D_INPUT ((*(volatile const uint16_T*)0x8675309) & 0x03FF

Inspect the generated file ex_memmap_simple.c. The generated algorithmic code


(which corresponds to the Gain block) calculates the model output, rtY.Out1, by
operating on A2D_INPUT.

/* Model step function */


void ex_memmap_simple_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Gain: '<Root>/Gain'
* Inport: '<Root>/In1'
*/
rtY.Out1 = 42.0 * (real_T)A2D_INPUT;
}

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

Deploy Generated Component Software to Application


Target Platforms
The code generator supports integration of generated code with operating systems and
processors. For details, see “Embedded Coder Supported Hardware” on page 71-2.

Interface to an Example Real-Time Operating System


(VxWorks®)
This example shows how to simulate and generate code for asynchronous events on an
example RTOS (VxWorks).

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

Open the rtwdemo_vxworks 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)

Multirate Modeling in Multitasking Mode (VxWorks® OS)


This example generates code for a multirate discrete-time model configured for a
multitasking operating system target (VxWorks®). 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 solver
configuration parameter setting. 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. Simulink® and the code generator enforce
proper rate transitions. This model specifies an explicit Rate Transition block.
Alternatively, you can instruct Simulink® to insert this block for you by setting 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 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

Export Code Generated from Model


to External Application in
Embedded Coder

• “Control Generation of Function Interfaces” on page 53-2


• “Control Generation of C++ Class Interfaces” on page 53-4
53 Export Code Generated from Model to External Application in Embedded Coder

Control Generation of Function Interfaces


The Embedded Coder software provides a Configure Model Functions button, located
on the Code Generation > Interface pane of the Configuration Parameters dialog box,
that allows you to control the model function interfaces that are generated for ERT-based
models.

By default, the function prototype of an ERT-based model's generated model_step


function resembles the following:
void model_step(void);

The function prototype of an ERT-based model's generated model_initialize function


resembles the following:
void model_initialize(void);

(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

Control Generation of C++ Class Interfaces


Using the Code interface packaging (Simulink Coder) option C++ class, on the Code
Generation > Interface pane of the Configuration Parameters dialog box, you can
generate a C++ class interface to model code. The generated interface encapsulates
required model data into C++ class attributes and model entry point functions into C++
class methods. The benefits of C++ class encapsulation include:

• Greater control over access to model data


• Ability to multiply instantiate model classes
• Easier integration of model code into C++ programming environments

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

Code Replacement Customization


for Simulink Models in Embedded
Coder

• “What Is Code Replacement Customization?” on page 54-3


• “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
• “Identify Code Replacement Requirements” on page 54-39
• “Prepare for Code Replacement Library Development” on page 54-42
• “Define Code Replacement Mappings” on page 54-43
• “Specify Build Information for Replacement Code” on page 54-61
• “Register Code Replacement Mappings” on page 54-70
• “Troubleshoot Code Replacement Library Registration” on page 54-78
• “Verify Code Replacements” on page 54-79
• “Troubleshoot Code Replacement Misses” on page 54-89
• “Deploy Code Replacement Library” on page 54-96
• “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 coder.ceval Calls to External Functions” on page 54-147
54 Code Replacement Customization for Simulink Models in Embedded Coder

• “Replace MATLAB Functions Specified in MATLAB Function Blocks” on page 54-153


• “Reserved Identifiers and Code Replacement” on page 54-157
• “Customize Match and Replacement Process” on page 54-159
• “Scalar Operator Code Replacement” on page 54-174
• “Addition and Subtraction Operator Code Replacement” on page 54-177
• “Small Matrix Operation to Processor Code Replacement” on page 54-182
• “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
• “Remap Operator Output to Function Input” on page 54-201
• “Fixed-Point Operator Code Replacement” on page 54-204
• “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-2
What Is Code Replacement Customization?

What Is Code Replacement Customization?


Customize how and when the code generator replaces C/C++ code that it generates by
default for functions and operators by developing a custom code replacement library. You
can develop libraries interactively with the Code Replacement Tool or
programmatically.

• Develop libraries tailored to specific application requirements


• Add identifiers to the list of reserved keywords the code generator considers during
code replacement
• Customize the code generator’s match and replacement process for functions

To get started, “Quick Start Code Replacement Library Development - Simulink®” on


page 54-28.

Code Replacement Match and Replacement Process


When the code generator encounters a call site for a function or operator, it:

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:

• Conceptual name or key


• Arguments, including quantity, type, type qualifiers, and complexity
• Algorithm (computation method)
• Fixed-point saturation and rounding modes
• Priority
3 When a match exists, the code generator returns a code replacement object, fully
populated with the conceptual representation, implementation representation, and
priority. If the code generator finds multiple matches within a table, the entry priority
determines the match. The priority can range from 0 to 100. The highest priority is 0.
The code generator uses a higher-priority entry over a similar entry with a lower
priority.

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.

Code Replacement Customization Limitations


• Code replacement verification — It is possible that code replacement behaves
differently than you expect. For example, data types that you observe in code
generator input might not match what the code generator uses as intermediate data
types during an operation. Verify code replacements by examining generated code.
See “Verify Code Replacements” on page 54-79.
• Tokens in file paths—You can include tokens in file paths when specifying build
information for a code replacement entry by using the programming interface only.
The ability to include tokens is not available from the Code Replacement Tool. See
“Specify Build Information for Replacement Code” on page 54-61.
• Addition and subtraction operation replacements—See“Addition and Subtraction
Operator Code Replacement” on page 54-177 for relevant limitations.
• Data alignment—

• Not supported for

• 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:

• Compiler supports global variable alignment


• Generate an example main program (select Configuration Parameters >
Generate an example main program)

54-4
What Is Code Replacement Customization?

• Generate a reusable function interface for the model (set Configuration


Parameters > Code Generation > Interface > Code interface packaging
to Reusable function)
• Function uses root-level I/O variables that are passed in as individual arguments
(set Configuration Parameters > Code Generation > Interface > Pass
root-level I/O asto Individual arguments)
• Replaced function uses a root-level I/O variable
• Replaced function imposes alignment requirements

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:

• If user registered alignment specifications do not support structure field


alignment, aligning Simulink.Bus objects is not supported unless the
Simulink.Bus is imported.
• When aligning a Simulink.Bus data object, the elements in the bus object are
aligned on the same boundary. The boundary is the lowest common multiple of
the alignment requirements for each individual bus element.
• When you specify alignment for functions that occur in a model reference
hierarchy, and multiple models in the hierarchy operate on the same function data,
the bottommost model dictates alignment for the rest of the hierarchy. If the
alignment requirement for a function in a model higher in the hierarchy cannot be
honored due to the alignment set by a model lower in the hierarchy, the
replacement in the higher model does not occur. In some cases, an error message
is generated. To work around this issue, if the shared data is represented by a bus
or signal object, manually set the alignment property on the shared data by setting
the alignment property of the Simulink.Bus or Simulink.Signal object.
• It is your responsibility to honor the Alignment property setting for custom
storage classes that you create.

54-5
54 Code Replacement Customization for Simulink Models in Embedded Coder

See “Data Alignment for Code Replacement” on page 54-136.


• coder.replace function — See coder.replace for relevant limitations.

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

Code You Can Replace From Simulink Models


Code that the code generator replaces depends on the code replacement library (CRL)
that you use. By default, the code generator does not apply a code replacement library.
Your choice of libraries is dependent on product licensing and whether you have access to
custom libraries.

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

Math Functions – Simulink Support


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 math functions with application-specific
implementations.

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
abs1 Integer Scalar Real
Floating point Vector
Fixed point Matrix
acos Floating point Scalar Real
Complex input/complex
output
Real input/complex output

54-7
54 Code Replacement Customization for Simulink Models in Embedded Coder

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
acosd2 Floating point Scalar Real
Vector Complex
Matrix
acosh Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output
acot2 Floating point Scalar Real
Vector Complex
Matrix
acotd2 Floating point Scalar Real
Vector Complex
Matrix
acoth2 Floating point Scalar Real
Vector Complex
Matrix
acsc2 Floating point Scalar Real
Vector Complex
Matrix
acscd2 Floating point Scalar Real
Vector Complex
Matrix
acsch2 Floating point Scalar Real
Vector Complex
Matrix
asec2 Floating point Scalar Real
Vector Complex
Matrix
asecd2 Floating point Scalar Real
Vector Complex
Matrix

54-8
Code You Can Replace From Simulink Models

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
asech2 Floating point Scalar Real
Vector Complex
Matrix
asin Floating point Scalar Real
Complex input/complex
output
Real input/complex output
asind2 Floating point Scalar Real
Vector Complex
Matrix
asinh Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output
atan Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output
atan2 Floating point Scalar Real
Vector
Matrix
atan2d2 Floating point Scalar Real
Vector
Matrix
atand2 Floating point Scalar Real
Vector Complex
Matrix
atanh Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output
ceil • Floating-point • Floating-point • Floating-point
• Scalar • Scalar • Scalar

54-9
54 Code Replacement Customization for Simulink Models in Embedded Coder

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
cos3 Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output
cosd2 Floating point Scalar Real
Vector Complex
Matrix
cosh Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output
cot2 Floating point Scalar Real
Vector Complex
Matrix
cotd2 Floating point Scalar Real
Vector Complex
Matrix
coth2 Floating point Scalar Real
Vector Complex
Matrix
csc2 Floating point Scalar Real
Vector Complex
Matrix
cscd2 Floating point Scalar Real
Vector Complex
Matrix
csch2 Floating point Scalar Real
Vector Complex
Matrix
exactrSqrt Integer Scalar Real
Floating point

54-10
Code You Can Replace From Simulink Models

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
exp Floating point Scalar Real
Vector
Matrix
fix Floating point Scalar Real
floor • Floating-point • Floating-point • Floating-point
• Scalar • Scalar • Scalar
4
fmod Floating point Scalar Real
frexp Floating point Scalar Real
hypot Floating point Scalar Real
Vector
Matrix
ldexp Floating point Scalar Real
ln Floating point Scalar Real
log Floating point Scalar Real
Vector
Matrix
log10 Floating point Scalar Real
Vector
Matrix
log22 Floating point Scalar Real
Vector Complex
Matrix
max Integer Scalar Real
Floating point
Fixed point
min Integer Scalar Real
Floating point
Fixed point
mod Integer Scalar Real
Floating point Vector
Matrix

54-11
54 Code Replacement Customization for Simulink Models in Embedded Coder

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
pow Floating point Scalar Real
Vector
Matrix
rem Floating point Scalar Real
Vector
Matrix
round Floating point Scalar Real
rSqrt Integer Scalar Real
Floating point Vector
Matrix
saturate Integer Scalar Real
Floating point Vector
Fixed point Matrix
sec2 Floating point Scalar Real
Vector Complex
Matrix
secd2 Floating point Scalar Real
Vector Complex
Matrix
sech2 Floating point Scalar Real
Vector Complex
Matrix
sign Integer Scalar Real
Floating point Vector
Fixed point Matrix
signPow Floating point Scalar Real
Vector
Matrix
sin3 Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output

54-12
Code You Can Replace From Simulink Models

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
sincos3 Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output
sind2 Floating point Scalar Real
Vector Complex
Matrix
sinh Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output
sqrt Integer Scalar Real
Floating point Vector
Fixed point Matrix
tan Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output
tand2 Floating point Scalar Real
Vector Complex
Matrix
tanh Floating point Scalar Real
Vector Complex input/complex
Matrix output
Real input/complex output
1
Wrap on integer overflow only. Clear block parameter Saturate on integer overflow.
2
Only when used with the MATLAB Function block.
3
Supports the CORDIC approximation method.
4
Stateflow support only.

54-13
54 Code Replacement Customization for Simulink Models in Embedded Coder

Math Functions – Stateflow Support


When generating C/C++ code from Stateflow charts, 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.

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.

Function Data Type Support Scalar, Vector, Real, Complex


Matrix Support Support
memcmp Void pointer (void*) Scalar Real
Vector Complex
Matrix
memcpy Void pointer (void*) Scalar Real
Vector Complex
Matrix
memset Void pointer (void*) Scalar Real
Vector Complex
Matrix
memset2zero Void pointer (void*) Scalar Real
Vector Complex
Matrix

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.

Function Data Type Support Scalar, Vector, Real, Complex


Matrix Support Support
getInf Floating point Scalar Real
getMinusInf Floating point Scalar Real
getNaN Floating point Scalar Real
rtIsInf Floating point Scalar Real
Complex
rtIsNaN Floating point Scalar Real
Complex

Mutex and Semaphore Functions


Mutex and semaphore functions control access to resources shared by multiple processes
in multicore target environments. MathWorks provides code replacement libraries that
support mutex and semaphore replacement for Rate Transition and Task Transition blocks
on Windows, Linux, Mac, and VxWorks platforms.

Generated mutex and semaphore code typically consists of:

• In model initialization code, an initialization function call to create a mutex or


semaphore to control entry to a critical section of code.
• In model step code:

• 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.

Depending on code replacement libraries available in your development environment, you


can configure the code generator to replace instances of the following mutex and
semaphore functions with application-specific implementations.

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.

Operator Key Data Type Scalar, Real,


Support Vector, Complex
Matrix Support
Support
Addition (+)1 RTW_OP_ADD Integer Scalar Real
Floating point Vector Complex
Fixed-point Matrix
Mixed

54-21
54 Code Replacement Customization for Simulink Models in Embedded Coder

Operator Key Data Type Scalar, Real,


Support Vector, Complex
Matrix Support
Support
Subtraction (-)1 RTW_OP_MINUS Integer Scalar Real
Floating point Vector Complex
Fixed-point Matrix
Mixed
Multiplication RTW_OP_MUL Integer Scalar Real
(*)2 Floating point Vector Complex
Fixed-point Matrix
Mixed
Division (/) RTW_OP_DIV Integer Scalar Real
Floating point Complex
Fixed-point
Mixed
Data type RTW_OP_CAST Integer Scalar Real
conversion (cast) Floating point3 Vector Complex
Fixed-point Matrix
Mixed
Shift left (<<) RTW_OP_SL Integer Scalar Real
Fixed-point Vector
Mixed Matrix4
Shift right RTW_OP_SRA Integer Scalar Real
arithmetic (>>)5 Fixed-point Vector
Mixed Matrix4
Shift right RTW_OP_SRL Integer Scalar Real
logical (>>) Fixed-point Vector
Mixed Matrix4
Element-wise RTW_OP_ELEM_MUL Integer Vector Real
matrix Floating point Matrix Complex
multiplication Fixed-point
(.*)6 Mixed

54-22
Code You Can Replace From Simulink Models

Operator Key Data Type Scalar, Real,


Support Vector, Complex
Matrix Support
Support
Matrix right RTW_OP_RDIV Integer Vector Real
division (/) Floating point Matrix Complex
Fixed-point
Mixed
Matrix left RTW_OP_LDIV Integer Vector Real
division (\) Floating point Matrix Complex
Fixed-point
Mixed
Matrix inversion RTW_OP_INV Integer Vector Real
(inv) Floating point Matrix Complex
Fixed-point
Mixed
Complex RTW_OP_CONJUGATE Integer Scalar Real
conjugation Floating point Vector Complex
Fixed-point Matrix
Mixed
Transposition RTW_OP_TRANS Integer Vector Real
(.') Floating point Matrix Complex
Fixed-point
Mixed
Hermitian RTW_OP_HERMITIAN Integer Vector Real
(complex Floating point Matrix Complex
conjugate) Fixed-point
transposition (') Mixed
Multiplication RTW_OP_TRMUL Integer Vector Real
with Floating point Matrix Complex
transposition2 Fixed-point
Mixed
Multiplication RTW_OP_HMMUL Integer Vector Real
with Hermitian Floating point Matrix Complex
transposition2 Fixed-point
Mixed

54-23
54 Code Replacement Customization for Simulink Models in Embedded Coder

Operator Key Data Type Scalar, Real,


Support Vector, Complex
Matrix Support
Support
Multiplication RTW_OP_MUL_SRA Integer Scalar Real
followed by shift Fixed-point
right arithmetic
(u1*u2>>u3)7
Multiplication RTW_OP_MULDIV Integer Scalar Real
followed by Fixed-point
division
(u1*u2/u3)8
Greater than (>) RTW_OP_GREATER_ Integer Scalar Real
THAN Floating point Vector Complex
Fixed-point Matrix
Mixed
Greater than or RTW_OP_GREATER_ Integer Scalar Real
equal (>=) THAN_OR_EQUAL Floating point Vector Complex
Fixed-point Matrix
Mixed
Less than (<) RTW_OP_LESS_THAN Integer Scalar Real
Floating point Vector Complex
Fixed-point Matrix
Mixed
Less than or RTW_OP_LESS_THAN_ Integer Scalar Real
equal (<=) OR_EQUAL Floating point Vector Complex
Fixed-point Matrix
Mixed
Equal (==) RTW_OP_EQUAL Integer Scalar Real
Floating point Vector Complex
Fixed-point Matrix
Mixed
Not equal (!=) RTW_OP_NOT_EQUAL Integer Scalar Real
Floating point Vector Complex
Fixed-point Matrix
Mixed

54-24
See Also

Operator Key Data Type Scalar, Real,


Support Vector, Complex
Matrix Support
Support
1
See “Addition and Subtraction Operator Code Replacement” on page 54-177 for details
to consider when defining mappings for addition and subtraction code replacements.
2
Can map to Basic Linear Algebra Subroutine (BLAS) multiplication functions.
3
Scaled floating point is not supported.
4
Shift operator replacement with matrix data is supported for shift values that you
specify with an input port. Replacement is not supported for shift values that you specify
in a block parameter dialog.
5
The code generator converts some arithmetic shift rights to logical shift rights. To
avoid unexpected results, when creating a code replacement library that includes a table
entry for an arithmetic shift right implementation, also include an entry for a logical shift
right implementation.
6
Use the multiplication (*) operator (RTW_OP_MUL) for scalar multiplication.
7
Requires scalar, real, or fixed-point data types with zero bias; output type of the
multiplication operation to accommodate all possible output values; shift operand is an
unsigned integer; and net slope is equal to 1 (U1_slope * U2_slope ==
Mul_output_slope and Mul_output_slope ==
output_slope_of_shift_operation).
8
Requires scalar, real, or fixed-point data types with zero bias; output type of the
multiplication operation to accommodate all possible output values; and net slope is
equal to 1 (U1_slope * U2_slope == Mul_output_slope == U3_slope *
Div_output_slope).

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

• “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-26
Develop a Code Replacement Library

Develop a Code Replacement Library


Iterate through the following steps, as necessary, to develop a code replacement library:

1 “Identify Code Replacement Requirements” on page 54-39


2 “Prepare for Code Replacement Library Development” on page 54-42
3 “Define Code Replacement Mappings” on page 54-43
4 “Specify Build Information for Replacement Code” on page 54-61
5 “Register Code Replacement Mappings” on page 54-70
6 “Verify Code Replacements” on page 54-79
7 “Deploy Code Replacement Library” on page 54-96

To get started, see “Identify Code Replacement Requirements” on page 54-39.

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

Quick Start Code Replacement Library Development -


Simulink®
This example shows how to develop a code replacement library that includes an entry for
generating replacement code for the math function sin. You use the Code Replacement
Tool.

Prerequisites

To complete this example, install the following software:

• MATLAB®
• MATLAB Coder™
• Simulink®
• Simulink Coder™
• Embedded Coder®
• Compiler

For instructions on installing MathWorks® products, see the MATLAB installation


documentation. If you have installed MATLAB and want to see what other MathWorks
products are installed, in the Command Window, enter ver.

For a list of supported compilers, see https://www.mathworks.com/support/


compilers/current_release/.

Open the Code Replacement Tool

1. Start a MATLAB session.

2. Create or navigate (cd) to an empty folder.

3. At the command prompt, enter the crtool command. The Code Replacement Tool
window opens.

Create Code Replacement Table

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 Table Entry

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.

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.

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.

The following figure shows the completed mapping information.

54-30
Quick Start Code Replacement Library Development - Simulink®

54-31
54 Code Replacement Customization for Simulink Models in Embedded Coder

Specify Build Information for Replacement 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 Another Table 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.

1. In the middle pane, select the sin_dbl entry.

2. Select Edit > Copy.

3. Select Edit > Paste.

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.

Validate the Code Replacement Table

1. Select Actions > Validate table.

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

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.

Review the Code Replacement Table Definition

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.

Generate a Registration File

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.

Register the Code Replacement Table

At the command prompt, enter:

RTW.TargetRegistry.getInstance('reset');

Review and Test Code Replacements

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 =

TflTable with properties:

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:

crviewer('Sin Function 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:

• Incorrect argument order.


• Conceptual argument names that do not match what the code generator expects.
• Incorrect priority settings.

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:

• Create code generation report


• Open report automatically
• Code-to-model
• Model-to-code
• Summarize which blocks triggered code replacements
• Include comments
• Simulink block comments
• Simulink block descriptions

7. Configure the model to generate code only. Before you build an executable program,
confirm that the code generator is replacing code as expected.

8. Generate code for the model.

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

• “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

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

Identify Code Replacement Requirements


The first step to developing a code replacement library is to consider the following types
of requirements for the library.

Mapping Information Requirements


• Are you defining a code replacement mapping for the first time?
• Are you updating code replacement entries in an existing library? Or, are you creating
a new library?
• Are you rapid prototyping code replacements?
• Can you base your mappings on existing mappings?
• What type of code do you want to replace? Options include:

• 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?

• What is the replacement function name?


• What are the input and output arguments?
• Are there return values?
• What is the data type, complexity, and dimensionality of each argument and return
value?

54-39
54 Code Replacement Customization for Simulink Models in Embedded Coder

Build Information Requirements


• Does your replacement function implementation require a header file? If yes, specify
the header file.
• If the replacement function implementation requires a header file, what is the path for
that file?
• Is the source file for the replacement function in your working folder? If not, you can
explicitly specify the source file name and extension. For example, if the file is
required in the generated makefile or specified in a build information object, specify
the source file.
• Does the replacement function use additional include files? If yes, what are they and
what are the paths for those files?
• Does the replacement function use additional source files? If yes, what are they and
what are the paths for those files?
• What compiler flags are required for compiling code that includes the replacement
code?
• What linker flags are required for building an executable that includes the
replacement code?
• Are the required header, source, and object files for building an executable that
includes your replacement code in the working folder for your project? If not, before
starting the build process, do you want the code generator to copy required files to the
build folder?

Registration Information Requirements


• What do you want to name your code replacement library?
• What code replacement tables do you want to include in the library? What are the file
names and paths for the tables?
• What is the purpose of the library? You can document the purpose as the library
description.
• Does the library apply to specific hardware devices? If yes, what devices?
• Are you developing a hierarchy of code replacement libraries? Is the library that you
are developing based (dependent) on another library? For example, you can specify a
general TI device library as the base library for a more specific TI C28x device
library.

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?

Next, prepare for developing a library by reviewing a code replacement library


development checklist.

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

Prepare for Code Replacement Library Development


After you identify your code replacement requirements, prepare for library development
by reviewing this checklist:

• Get familiar with the library development process.


• Decide whether to define code replacement mappings and produce a registration file
interactively with the Code Replacement Tool or programmatically.
• Identify or develop MATLAB code and Simulink models to test your code replacement
library.
• Consider the hierarchy and organization of your library. A library can consist of
multiple tables and each table can include multiple entries. How do you want to
organize the library to optimize reuse of tables and entries? For example, a
registration file can define code replacement tables organized in a hierarchy of code
replacement libraries based on entries that increase in specificity:

• 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

Define Code Replacement Mappings


After you prepare for library development, use your requirements to define code
replacement mappings. A code replacement mapping associates a conceptual
representation of a function or operator that is familiar to the code generator with a
custom implementation representation that specifies a C or C++ replacement function
prototype. You capture a mapping as an entry in a code replacement table:

• Interactively, by using the Code Replacement Tool.


• Programmatically, by using a MATLAB programming interface.

Choose an Approach for Defining Code Replacement Mappings


The following table lists situations to help you decide when to use the interactive or
programmatic approach.

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

Define Mappings Interactively with the Code Replacement


Tool
This example shows how to use the Code Replacement Tool to develop code replacement
mappings. The tool is ideal for getting started with developing mappings, rapid
prototyping, and developing a mapping to use as a starting point for defining similar
mappings.

Open the Code Replacement Tool

Do one of the following:

• In the Command Window, enter the command crtool.


• In the Configuration Parameters dialog box, navigate to Code Generation pane. In
the Advanced parameters section, scroll down and click Custom CRL... button.

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.)

Create a Code Replacement Table

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 Table Entries

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:

• Integer saturation mode


• Rounding modes
• Whether to allow inputs that include expressions
• Whether a function modifies internal or global state
9 Click Apply.

Validate Tables and Entries

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

When you save a table, the tool validates unvalidated content.


1 Select File > Save table.
2 In the Browse For Folder dialog box, specify a location and name for the file.
Typically, you select a location on the MATLAB path. By default, the tool names the
file using the name that you specify for the table with the extension .m.
3 Click Save.

Open and Modify Tables

After saving a code replacement table, to make changes in the table:


1 Select File > Open table.
2 In the Import file dialog box, browse to the MATLAB file that contains the table.

Repeat the sequence to open and work on multiple tables.

If you open multiple tables, you can manage the tables together. For example, use the tool
to:

• Create new table entries.


• Delete entries.
• Copy and paste or cut and paste information between tables.

Define Mappings Programmatically


This example shows how to define a code replacement mapping programmatically. The
programming interface for defining code replacement table mappings is ideal for

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.

Steps for defining a mapping programmatically are:

• “Create Code Replacement Table” on page 54-48


• “Create Table Entry” on page 54-48
• “Set Entry Parameters” on page 54-50
• “Create Conceptual Arguments” on page 54-52
• “Create Implementation Arguments” on page 54-54
• “Add Entry to Table” on page 54-58
• “Validate Entry” on page 54-58
• “Save Table” on page 54-59

Create Code Replacement Table

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;

Create Table Entry

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.

Entry Type Function


Math operation RTW.TflCOperationEntry
Function RTW.TflCFunctionEntry
BLAS operation RTW.TflBlasEntryGenerator

54-48
Define Code Replacement Mappings

Entry Type Function


CBLAS operation RTW.TflCBlasEntryGenerator
Fixed-point addition and RTW.TflCOperationEntryGenerator
subtraction operations
(support for
SlopesMustBeTheSame and
MustHaveZeroNetBias
parameters)
Net slope fixed-point RTW.TflCOperationEntryGenerator_NetSlo
operation pe
Semaphore or mutex entry RTW.TflCSemaphoreEntry
Custom function entry MyCustomFunctionEntry (where
MyCustomFunctionEntry is a class derived
from RTW.TflCFunctionEntryML)
Custom operation entry MyCustomOperationEntry (where
MyCustomOperationEntry is a class derived
from RTW.TflCOperationEntryML)

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:

• Return argument is y1.


• Input arguments are u1, u2, ..., un.

For example:

54-49
54 Code Replacement Customization for Simulink Models in Embedded Coder

registerCFunctionEntry(hTable, 100, 1, 'sin', 'double', ...


'sin_dbl', 'double', 'sin_dbl.h','','');

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:

hEnt = createCRLEntry(hTable, ...


'double y1 = sin(double u1)', ...
'mySin');

This approach does not support:

• 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

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.

Entry Type Function


Math operation setTflCOperationEntryParameters
Function setTflCFunctionEntryParameters
BLAS operation setTflCOperationEntryParameters
CBLAS operation setTflCOperationEntryParameters

54-50
Define Code Replacement Mappings

Entry Type Function


Fixed-point addition and subtraction setTflCOperationEntryParameters
operations where there is a many-to-one
mapping, such as a mapping for a range of
fixed-point types to the same replacement
function (support for
SlopesMustBeTheSame and
MustHaveZeroNetBias parameters)
Net slope fixed-point operation setTflCOperationEntryParameters
Semaphore or mutex entry setTflCSemaphoreEntryParameters
Custom function entry setTflCFunctionEntryParameters
Custom operation entry setTflCOperationEntryParameters

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 =

TflCFunctionEntry with properties:

Implementation: [1x1 RTW.CImplementation]


SlopesMustBeTheSame: 0
BiasMustBeTheSame: 0
AlgorithmParams: []
ImplType: 'FCN_IMPL_FUNCT'
AdditionalHeaderFiles: {0x1 cell}
AdditionalSourceFiles: {0x1 cell}
AdditionalIncludePaths: {0x1 cell}
AdditionalSourcePaths: {0x1 cell}
AdditionalLinkObjs: {0x1 cell}
AdditionalLinkObjsPaths: {0x1 cell}
AdditionalLinkFlags: {0x1 cell}
AdditionalCompileFlags: {0x1 cell}
SearchPaths: {0x1 cell}
Key: ''
Priority: 100
ArrayLayout: 'COLUMN_MAJOR'
ConceptualArgs: [0x1 handle]
EntryInfo: []

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]

To see the implementation parameters, enter:


hEnt.Implementation

ans =

CImplementation with properties:

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

Create conceptual arguments and add them to the entry’s array of conceptual arguments.

• Specify output arguments before input arguments.


• Specify argument names that comply with code generator argument naming
conventions:

54-52
Define Code Replacement Mappings

• y1 for a return argument


• u1, u2, ..., un for input arguments
• Specify data types that are familiar to the code generator.
• The function signature, including argument naming, order, and attributes, must fulfill
the signature match sought by function or operator callers.
• The code generator determines the size of the value for an argument with an unsized
type, such as integer, based on hardware implementation configuration settings.

For each argument:

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');

The second argument specifies whether the argument


is scalar (RTW.TflArgNumeric
orRTW.TflArgMatrix) .

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

arg = getTflArgFromString(hEnt, 'y1','double');


arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(hEnt, arg);

arg = getTflArgFromString(hEnt, 'u1','double');


addConceptualArg(hEnt, arg);

Create Implementation Arguments

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.

For each argument:

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);

The following call to getTflArgFromString passes


the constant 0 to argument u2:

arg = getTflArgFromString(hEnt,...
'u2', 'int16', 0)
hEnt.Implementation.addArgument(arg);

For semaphore and mutex entries, use the functions


getTflDWorkFromString and addDWorkArg to
create and add a DWork argument to the entry. Then
create implementation arguments as shown above with
getTflArgFromString and the convenience methods
setReturn and addArgument. For example:

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);

Add Entry to Table

Add an entry to a code replacement table by calling the function addEntry.


addEntry(hTable, hEnt);

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

??? RTW_CORE:tfl:TflTable: Unsupported data type, 'dooble'.

Error in ==> crl_table_sinfcn at 7


hTable.registerCFunctionEntry(100, 1, 'sin', 'dooble', 'sin_dbl', ...

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

• “Customize Match and Replacement Process” on page 54-159


• “Scalar Operator Code Replacement” on page 54-174
• “Addition and Subtraction Operator Code Replacement” on page 54-177
• “Small Matrix Operation to Processor Code Replacement” on page 54-182
• “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
• “Remap Operator Output to Function Input” on page 54-201
• “Customize Code Match and Replacement for Scalar Operations” on page 54-167
• “Fixed-Point Operator Code Replacement” on page 54-204
• “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
• “Optimize Generated Code By Developing and Using Code Replacement Libraries -
Simulink®”
• “Prepare for Code Replacement Library Development” on page 54-42
• “Specify Build Information for Replacement Code” on page 54-61
• “Develop a Code Replacement Library” on page 54-27
• “What Is Code Replacement Customization?” on page 54-3

54-60
Specify Build Information for Replacement Code

Specify Build Information for Replacement Code


After you define code replacement mappings, determine whether you need to specify
build information for your replacement code. A code replacement table entry can specify
build information for the code generator to use when replacing code for a match. For
example, specify files for implementation replacement code if you are using a generated
makefile and the code generation software compiles the code.

Add build information to an entry:

• 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:

• Paths and file names for header files


• Paths and file names for source files
• Paths and file names for object files
• Compile flags
• Link flags

Choose an Approach for Specifying Build Information


The following table lists situations to help you decide when to use an interactive or
programmatic approach to specifying build information:

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:

• In the call to packNGo, specify the property-value pair 'minimalHeaders' true


(the default). That setting instructs the function to include the minimal header files
required to build the code in the zip file.
• Do not collocate files that you copy with files that you do not copy. If the packNGo
function finds multiple instances of the same file, the function returns an error.
• If you use the programming interface, paths that you specify can include tokens. A
token is a variable defined as a character vector or cell array of character vectors in
the MATLAB workspace that you enclose with dollar signs ($variable$). The code
generator evaluates and replaces a token with the defined value. For example,
consider the path $myfolder$\folder1, where myfolder is a character vector
variable defined in the MATLAB workspace as 'd:\work\source\module1'. The
code generator generates the custom path as d:\work\source\module1\folder1.

Specify Build Information Interactively with the Code


Replacement Tool
The Code Replacement Tool provides a quick, easy way for you to specify build
information for code replacement table entries. It is ideal for getting started with defining
a table entry, rapid prototyping, and developing table entries to use as a starting point for
defining similar mappings.

54-62
Specify Build Information for Replacement Code

1 Determine the information that you must specify.


2 Open the Code Replacement Tool.
3 Select the code replacement table entry for which you want to specify the build
information. In the left pane, select the table that contains the entry. In the middle
pane, select the entry that you want to modify.
4 In the right pane, select the Build Information tab.
5 On the Build Information tab, specify your build information.

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.

Specify Build Information Programmatically


The programming interface for specifying build information for a code replacement entry
is ideal for:

• Modifying entries created with the Code Replacement Tool.


• Replicating and then modifying similar entries and tables.

The basic workflow for specifying build information programmatically is:

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:

libdir = fullfile('$(MATLAB_ROOT)','..', '..', 'lib');

hEnt = RTW.TflCFunctionEntry;

addAdditionalHeaderFile(hEnt, 'common.h');
addAdditionalIncludePath(hEnt, fullfile(libdir, 'include'));

These functions add -I to the compile line in the generated makefile.

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:

libdir = fullfile('$(MATLAB_ROOT)','..', '..', 'lib');

hEnt = RTW.TflCFunctionEntry;

addAdditionalSourceFile(hEnt, 'common.c');
addAdditionalSourcePath(hEnt, fullfile(libdir, 'src'));

These functions add -I to the compile line in the generated makefile.


Additional object For each file, specify the file name and path in calls to the functions
files/paths addAdditionalLinkObj and addAdditionalLinkObjPath. For
example:

libdir = fullfile('$(MATLAB_ROOT)','..', '..', 'lib');

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.AdditionalCompileFlags = {'-Zi -Wall', '-03'};


Link flags Set the entry property AdditionalLinkFlags to a cell array of
character vectors representing the required link flags. For example:

hEnt = RTW.TflCFunctionEntry;

hEnt.AdditionalCompileFlags = {'-MD -Gy', '-T'};

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'.

If a match occurs for a table entry, a call to the function


RTW.copyFileToBuildDir copies required files to the build folder.

If you specify 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.
4 Save the table that includes the entry that you added or modified.

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);

The following example uses the functions addAdditionalHeaderFile,


addAdditionalIncludePath, addAdditionalSourceFile,
addAdditionalSourcePath, addAdditionalLinkObj, and
addAdditionalLinkObjPath in addition to the code generation callback function
RTW.copyFileToBuildDir.
hTable = RTW.TflTable;

% Path to external source, header, and object files


libdir = fullfile('$(MATLAB_ROOT)','..', '..', 'lib');

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

Register Code Replacement Mappings


After you define code replacement entries and specify build information in a code
replacement table, you can include the table in a code replacement library that you
register with the code generator. When registered, a library appears in the list of
available code replacement libraries that you can choose from when configuring the code
generator.

Register a code replacement table as a code replacement library:

• Interactively, by using the Code Replacement Tool


• Programmatically, by using a MATLAB programming interface

Choose an Approach for Creating the Registration File


The following table lists situations to help you decide when to use an interactive or
programmatic approach to creating a registration file:

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

Create Registration File Interactively with the Code


Replacement Tool
The Code Replacement tool provides a quick, easy way for you to create a registration file
for a code replacement table. It is ideal for getting started, rapid prototyping, and
generating a registration file that you want to use as a starting point for similar
registrations.

1 After you validate and save a code replacement table, select File > Generate
registration file to open the Generate registration file dialog box.

2 Enter the registration information. Minimally, specify:

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:

• Name of a table file on the MATLAB search path


• Absolute path to a table file
• Path to a table file relative to $(MATLAB_ROOT)

You can specify multiple tables. If you do, separate the


table specifications with a comma. For example:

crl_table_sinfcn, c:/work_crl/
crl_table_muldiv

See “Registration Files That Define Multiple Code


Replacement Libraries” on page 55-62 for examples of
each type of table specification.

Optionally, you can specify:

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

Create Registration File Programmatically


The programming interface for creating a registration file for a code replacement table is
ideal for:

• Modifying registration files created with the Code Replacement Tool


• Replicating and modifying similar registration files
• Defining multiple code replacement libraries in one registration file

The basic workflow for creating a registration file programmatically consists of the
following steps:

1 Define an rtwTargetInfo function. The code generator recognizes this function as a


customization file. The function definition must include at least the following content:

function rtwTargetInfo(cm)

cm.registerTargetInfo(@loc_register_crl);

function this = 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:

• Name of a table file on the MATLAB


search path
• Absolute path to a table file
• Path to a table file relative to $
(MATLAB_ROOT)

You can specify multiple tables. If you do,


separate the table specifications with
commas.

Optionally, you can specify:

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.

See “Registration Files That Define Code


Replacement Library Hierarchies” on page
55-62 for an example.

For example:

function rtwTargetInfo(cm)

cm.registerTargetInfo(@loc_register_crl);

function this = 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.

Register a Code Replacement Library


Before you can use the code replacement tables defined in a registration file, refresh
Simulink customizations within the current MATLAB session. To initiate a refresh, enter
the following command:

sl_refresh_customizations

54-75
54 Code Replacement Customization for Simulink Models in Embedded Coder

Register a Library that Includes Multiple Code Replacement


Tables
Use the programming interface to create a registration file that defines a code
replacement library that includes multiple code replacement tables. The following
example defines a library that includes multiple tables. The TableList fields specify
tables that reside at different locations. The tables reside on the MATLAB search path or
at locations specified with a path.
function rtwTargetInfo(cm)

cm.registerTargetInfo(@locCrlRegFcn);

function thisCrl = locCrlRegFcn

% Register a code replacement library for use with model: rtwdemo_crladdsub


thisCrl(1) = RTW.TflRegistry;
thisCrl(1).Name = 'Addition & Subtraction Examples';
thisCrl(1).Description = 'Example of addition/subtraction op replacement';
thisCrl(1).TableList = {'crl_table_addsub'};
thisCrl(1).TargetHWDeviceType = {'*'};

% Register a code replacement library for use with model: rtwdemo_crlmuldiv


thisCrl(2) = RTW.TflRegistry;
thisCrl(2).Name = 'Multiplication & Division Examples';
thisCrl(2).Description = 'Example of mult/div op repl for built-in integers';
thisCrl(2).TableList = {'c:/work_crl/crl_table_muldiv'};
thisCrl(2).TargetHWDeviceType = {'*'};

% Register a code replacement library for use with model: rtwdemo_crlfixpt


thisCrl(3) = RTW.TflRegistry;
thisCrl(3).Name = 'Fixed-Point Examples';
thisCrl(3).Description = 'Example of fixed-point operator replacement';
thisCrl(3).TableList = {fullfile('$(MATLAB_ROOT)', ...
'toolbox','rtw','rtwdemos','crl_demo','crl_table_fixpt')};
thisCrl(3).TargetHWDeviceType = {'*'};

Registration Files That Define Code Replacement Library


Hierarchies
Using the programming interface, you can organize multiple code replacement libraries
in a hierarchy. The following example shows a registration file that defines four code
replacement tables organized in a hierarchy of four code replacement libraries. The
tables include entries that increase in specificity: common entries, entries for TI devices,
entries for TI C6xx devices, and entries specific to the TI C67x device.
function rtwTargetInfo(cm)

54-76
See Also

cm.registerTargetInfo(@locCrlRegFcn);

function thisCrl = locCrlRegFcn

% Register a code replacement library that includes common entries


thisCrl(1) = RTW.TflRegistry;
thisCrl(1).Name = 'Common Replacements';
thisCrl(1).Description = 'Common code replacement entries shared by other libraries';
thisCrl(1).TableList = {'crl_table_general'};
thisCrl(1).TargetHWDeviceType = {'*'};

% Register a code replacement library for TI devices


thisCrl(2) = RTW.TflRegistry;
thisCrl(2).Name = 'TI Device Replacements';
thisCrl(2).Description = 'Code replacement entries shared across TI devices';
thisCrl(2).TableList = {'crl_table_TI_devices'};
thisCrl(2).TargetHWDeviceType = {'TI C28x', 'TI C55x', 'TI C62x', 'TI C64x', 'TI 67x'};
thisCrl(1).BaseTfl = 'Common Replacements'

% Register a code replacement library for TI c6xx devices


thisCrl(3) = RTW.TflRegistry;
thisCrl(3).Name = 'TI c6xx Device Replacements';
thisCrl(3).Description = 'Code replacement entries shared across TI C6xx devices';
thisCrl(3).TableList = {'crl_table_TIC6xx_devices'};
thisCrl(3).TargetHWDeviceType = {'TI C62x', 'TI C64x', 'TI 67x'};

% Register a code replacement library for the TI c67x device


thisCrl(3) = RTW.TflRegistry;
thisCrl(3).Name = 'TI c67x Device Replacements';
thisCrl(3).Description = 'Code replacement entries for the TI C67x device';
thisCrl(3).TableList = {'crl_table_TIC67x_device'};
thisCrl(3).TargetHWDeviceType = {'TI 67x'};

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

Troubleshoot Code Replacement Library Registration


If a code replacement library is not listed as a configuration option or does not appear in
the Code Replacement Viewer:

• 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

Verify Code Replacements


After you create or modify and register a code replacement table, use the following
techniques to examine and verify the table and its entries.

• Invoke the table definition file at the command prompt.


• Use the Code Replacement Viewer to examine libraries, tables, and entries.
• Trace code replacements from the source where you applied the code replacement
library.
• Examine code replacement hits and misses logged during code generation.

Code Replacement Hits and Misses


The code generator logs code replacement table entries for which it finds and does not
find matches in the hit cache and miss cache, respectively. When a code replacement
entry match fails and code is not replaced, the code generator logs the call site object
(CSO) for the miss in the miss cache. When an entry match succeeds, the code generator
logs the matched entry in the hit cache.

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:

• Identifies the call site object.


• Provides a link to the relevant source location for the miss.
• Includes information about the reason for the miss.

54-79
54 Code Replacement Customization for Simulink Models in Embedded Coder

Validate Table Definition File


After you create or modify a code replacement table definition file, validate it. At the
command prompt, specify the name of the table in a call to the isvalid function. For
example:
isvalid(crl_table_sinfcn)

ans =

MATLAB displays errors that occur. In the following example, MATLAB detects a typo in a
data type name.
isvalid(crl_table_sinfcn)

??? RTW_CORE:tfl:TflTable: Unsupported data type, 'dooble'.

Error in ==> crl_table_sinfcn at 7


hTable.registerCFunctionEntry(100, 1, 'sin', 'dooble', 'sin_dbl', ...

Review Library Content


After you create or modify a code replacement library, use the Code Replacement
Viewer to review and verify the list of tables in the library and the entries in each table.

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

Review Table Content


After you create or modify a code replacement table, use the Code Replacement Viewer
to review and verify table entries.

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

• Argument order is correct.


• Conceptual argument names match code generator naming conventions.

54-84
Verify Code Replacements

• Implementation argument names are correct.


• Algorithm properties (for example, saturation and rounding mode) are set
correctly.
• Header or source file specification is not missing.
• I/O types are correct.
• Relative priority of entries is correct.

Review Code Replacements


After you review the content of your code replacement library and tables, generate code
and a code generation report. Verify that the code generator replaces code as you expect.

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.

The following example illustrates two complementary approaches to reviewing code


replacements:

• 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

In the Code Replacements Report, these options include Simulink block


information.
5 Configure the code generator to generate only code. Before you build an executable
file, review your code replacements in the generated code.
6 Generate code and a report.
7 Open the Code Replacements Report section of the code generation report.

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

Review the report:

• Check whether expected function and operator code replacements occurred.


• In the replacements sections, click each block link to see the source that triggered
the reported code replacement.
8 In the Simulink model window, use model-to-code highlighting to trace code
replacements. Identify and right-click a block where you expected code replacement
to occur. Select C/C++ Code > Navigate to C/C++ Code. The code generation
report appears with the corresponding replacement code highlighted. In the example
model rtwdemo_crladdsub, right-click the Add8 block and select C/C++ Code >
Navigate to C/C++ Code.

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.

Next, deploy your code replacement library for others to use.

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

Troubleshoot Code Replacement Misses


Use miss reason messages that appear in the Code Replacement Viewer to analyze and
correct code replacement misses.

Miss Reason Messages


The Code Replacement Viewer displays miss reason messages in trace information for
code replacement misses. A legend listing each message that appears in the miss report
precedes the report details. A message consists of:

• Numeric identifier, which identifies the message in the report details.


• Message text, which in some cases includes placeholders for names of arguments, call
site object values, table entry values, and property names.

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 message identifier, as listed in the legend.


• The placeholder values for that instance of the miss reason message.

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.

1. y1, int8, uint32


u1, int8, uint32
u2, int8, 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.

Analyze and Correct Code Replacement Misses


The following example shows how to use Code Replacement Viewer trace information to
troubleshoot code replacement misses. You must have already reviewed and tested code
replacements for your model.

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.

The model opens with the Sub32 block highlighted.

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

Deploy Code Replacement Library


After you verify code replacements and are ready to package and deploy a code
replacement library for others to use:

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

Math Function Code Replacement


This example shows how to define a code replacement mapping for a math function. The
example defines a mapping for the sin function 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_sinfcn2()
%CRL_TABLE_SINFCN2 - Define function entry for code replacement table.
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create an entry for the function mapping with a call to the
RTW.TflCFunctionEntry function.
% Create entry for sin function replacement
fcn_entry = RTW.TflCFunctionEntry;
4 Set function entry parameters with a call to the
setTflCFunctionEntryParameters function.
setTflCFunctionEntryParameters(fcn_entry, ...
'Key', 'sin', ...
'Priority', 30, ...
'ImplementationName', 'mySin', ...
'ImplementationHeaderFile', 'basicMath.h',...
'ImplementationSourceFile', 'basicMath.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.
createAndAddConceptualArg(fcn_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1',...
'IOType', 'RTW_IO_OUTPUT',...
'DataTypeMode', 'double');

createAndAddConceptualArg(fcn_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT',...
'DataTypeMode', 'double');
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.

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

Memory Function Code Replacement


This example shows how to define a code replacement mapping for a memory function.
The example defines a mapping for the memcpy function 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_memcpy()


2 Within the function body, create the table by calling the function RTW.TflTable.

hTable = RTW.TflTable;
3 Create an entry for the function mapping with a call to the
RTW.TflCFunctionEntry function.

% Create entry for void* memcpy(void*, void*, size_t)


fcn_entry = RTW.TflCFunctionEntry;
4 Set function entry parameters with a call to the
setTflCFunctionEntryParameters function.
% Set SideEffects to 'true' for function returning void to prevent it from
% being optimized away.
setTflCFunctionEntryParameters(fcn_entry, ...
'Key', 'memcpy', ...
'Priority', 90, ...
'ImplementationName', 'memcpy_int', ...
'ImplementationHeaderFile', 'memcpy_int.h',...
'SideEffects', true);
5 Create conceptual arguments y1, u1, u2, and u3. 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', 'void*');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(fcn_entry, arg);

arg = getTflArgFromString(hTable, 'u1', 'void*');


addConceptualArg(fcn_entry, arg);

arg = getTflArgFromString(hTable, 'u2', 'void*');


addConceptualArg(fcn_entry, arg);

arg = getTflArgFromString(hTable, 'u3', 'size_t');


addConceptualArg(fcn_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-99
54 Code Replacement Customization for Simulink Models in Embedded Coder

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.

To test this example:

1 Register the code replacement mapping.


2 Create a model that uses the memcpy function for vector assignments. For example,
use In, Out, and Mux blocks to create the following model. (Alternatively, open the
example model rtwdemo_crlmath and copy the contents of Subsystem1 to a new
model.)

3 Select the diagram and use Edit > Subsystem to make it a subsystem.

4 Configure the subsystem with the following settings:

• On the Solver pane, select a fixed-step solver.


• On the Optimization pane, select Use memcpy for vector assignment and set
Memcpy threshold (bytes) to 64.
• 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 memory function entry.

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

Nonfinite Function Code Replacement


This example shows how to define a code replacement mapping for nonfinite utility
functions.

1 Create a table definition file that contains a function definition. For example:

function hTable = crl_table_nonfinite()


2 Within the function body, create the table by calling the function RTW.TflTable.

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)

locAddFcnEnt(hTable, 'getNaN', 'getNaN', 'double', 'void', 'nonfin.h');


locAddFcnEnt(hTable, 'getNaN', 'getNaNF', 'single', 'void', 'nonfin.h');
locAddFcnEnt(hTable, 'getInf', 'getInf', 'double', 'void', 'nonfin.h');
locAddFcnEnt(hTable, 'getInf', 'getInfF', 'single', 'void', 'nonfin.h');
locAddFcnEnt(hTable, 'getMinusInf', 'getMinusInf', 'double', 'void', 'nonfin.h');
locAddFcnEnt(hTable, 'getMinusInf', 'getMinusInfF', 'single', 'void', 'nonfin.h');

%% Local Function
function locAddFcnEnt(hTable, key, implName, out, in1, hdr)
if isempty(hTable)
return;
end

fcn_entry = RTW.TflCFunctionEntry;

4 Set function entry parameters with a call to the


setTflCFunctionEntryParameters function.
setTflCFunctionEntryParameters(fcn_entry, ...
'Key', key, ...
'Priority', 90, ...
'ImplementationName', implName, ...
'ImplementationHeaderFile', hdr);

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

arg = getTflArgFromString(hTable, 'u1', in1);


addConceptualArg(fcn_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
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.

To test this example:

1 Register the code replacement mapping.


2 Create a model that uses a nonfinite function. For example, create a model that
includes a Math Function block that is set to the rem function. For example:

3 Configure the model with the following settings:

• On the Solver pane, select a fixed-step solver.


• 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 memory function entry and select Support: non-finite
numbers.
4 In the Model Explorer, configure the Signal Attributes for the In1 and Constant
source blocks. For each source block, set Data type to double. Apply the changes.
Save the model.
5 Generate code and a code generation report.
6 Review the code replacements.

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

Semaphore and Mutex Function Replacement


You can create a code replacement table for a custom target that supports concurrent
execution. Create table entries that specify custom implementations of semaphore or
mutex operations. The table must have four semaphore entries, four mutex entries, or
both, and include the table in a custom code replacement library. (The semaphore or
mutex entries are mutually dependent. Provide them in complete sets of four.)

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.

Generated mutex and semaphore code typically consists of these elements:

Code Generated Code


Model initialization Initialization function call that creates a mutex or
semaphore function to control entry to a critical section of
code.
Model step • Before code for a data transfer between tasks enters
the critical section, mutex lock or semaphore wait
function calls reserve the critical section of code.
• After code for a data transfer between tasks finishes
executing the critical section, mutex unlock or
semaphore post function calls release the critical
section of code.

54-105
54 Code Replacement Customization for Simulink Models in Embedded Coder

Code Generated Code


Model termination Optional destroy function call to delete the mutex or
semaphore explicitly.

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.

1 Open the Code Replacement Tool.


2 Create and open a new table.
3 Name the table crl_table_rt_mutex.
4 Create an entry for a mutex initialization function replacement.

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

On the DWork attributes pane, configure a DWork argument to the


replacement function. The DWork argument supports sharing of a semaphore or
mutex between:

• Code that creates the semaphore or mutex


• Code that requests and relinquishes access
• Code that deletes the semaphore or mutex

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**.

The C function signature preview is:

void myMutexCreate (void** d1);

54-107
54 Code Replacement Customization for Simulink Models in Embedded Coder

e In the Replacement function section, select Function modifies internal or


global state. This option instructs the code generator not to optimize away the
implementation function described by this entry because it accesses global
memory values. Click Apply. Optionally, you can click Validate entry to validate
the information entered in the Mapping Information tab.

To create a sample table entry, configure the replacement function signature


without the replacement function and its build information. If header and source
files for these functions are available, select the Build Information table to
specify them.
f The Mutex Init table entry is complete. Optionally, you can save the table to a
file, and inspect the MATLAB code created for the table definition so far.
5 Repeat the following sequence to create the table entries for the mutex lock, unlock,
and destroy function replacements. Each table entry references the DWork unique
tag entry, entry_25576, defined in the Mutex Init table entry.

a Select File > New entry > Semaphore entry.


b In the Mapping Information tab, use the Function parameter to select Mutex
Lock, Mutex Unlock, or Mutex Destroy. Initial default values for the table
entry appear. In the Conceptual function section, typically you can leave the
argument settings at their defaults.
c For a Rate Transition block mutex, the wait, post, and destroy functions operate
on the DWork allocated at system startup by the mutex initialization function. In
the DWork attributes section, verify that the Allocate DWork option is cleared.
From the DWork Allocator entry drop-down list, select the entry tag matching
the value in the Mutex Init table entry. In this example, the entry tag is
entry_25576.

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

e In the Implementation attributes section, select the option Function


modifies internal or global state. This option instructs the code generator not
to optimize away the implementation function described by this entry because it
accesses global memory values.
f Optionally, supply build information for the replacement function on the Build
Information tab.
g Click Apply. In the middle pane, right-click the table entry and select Validate
entry(s).
6 When you have added the table entries for Mutex Lock, Mutex Unlock, and Mutex
Destroy to the entry for Mutex Init, the rate transition mutex replacement table is
complete. In the left-most pane, right-click the table name and select Validate table.
Address errors and repeat the table validation.

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.

To test this example:

1 Register the code replacement mapping.


2 Create a model that contains a rate transition for which the build process generates
mutex function calls. For example:

3 Configure the model for a multicore target environment and the following settings:

• On the Solver pane, select a fixed-step solver.


• 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 mutex entry.

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

Algorithm-Based Code Replacement


For some math function blocks, you can control code replacement based on the
computation or approximation algorithm configured for that block. For example, you can
configure:

• The Reciprocal Sqrt block to use the Newton-Raphson or Exact computation


method.
• The Trigonometric Function block, with Function set to sin, cos, or sincos, to use
the approximation method CORDIC or None.

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:

function hTable = crl_rsqrt()


%CRL_TABLE_RSQRT - Define function entry for code replacement table.
2 Within the function body, create the table by calling the function RTW.TflTable.

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');

createAndAddConceptualArg(e, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'DataTypeMode', 'double');
6 Copy the conceptual arguments to 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.

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

/* Outport: '<Root>/Out1' incorporates:


* Inport: '<Root>/In1'
* Sqrt: '<Root>/rSqrtBlk'
*/
mrsqrt_Y.Out1 = rsqrt_newton(mrsqrt_U.In1);
}

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

Lookup Table Function Code Replacement


You can configure the algorithm for table lookup operations and index searches to better
meet your application code requirements. Use the Algorithm tab of lookup table blocks.
For example, you can specify the interpolation, extrapolation, and index search methods.

Lookup Table Algorithm Replacement


If the code generated for available algorithm options does not meet requirements for your
application, create custom code replacement table entries to replace generated algorithm
code. You can create the table entries programmatically or interactively by using the
Code Replacement Tool.

For more information about using lookup table blocks, see “Nonlinearity” (Simulink).

Lookup Table Function Signatures


To create code replacement table entries for a function corresponding to a lookup table
algorithm, you must have:

• Information about the conceptual function signature.


• Relevant algorithm parameters.

The following table provides the conceptual function signature information.

Conceptual Function Signature Argument Summary


y1 = interp1D(u1, u2, u3, u4) y1 – output
u1 – index
u2 – fraction
u3 – table data
u4 – table dimension length
y1 = interp2D(u1, u2, u3, u4, u5, u6, u7) y1 – output
u1, u3 – index
u2, u4 – fraction
u5 – table data
u6, u7 – table dimension lengths

54-115
54 Code Replacement Customization for Simulink Models in Embedded Coder

Conceptual Function Signature Argument Summary


y1 = interp3D(u1, u2, u3, u4, u5, u6, u7, u8, y1 – output
u9, u10) u1, u3, u5 – index
u2, u4, u6 – fraction
u7 – table data
u8, u9, u10 – table dimension
lengths
y1 = interp4D(u1, u2, u3, u4, u5, u6, u7, u8, y1 – output
u9, u10, u11, u12, u13) u1, u3, u5, u7 – index
u2, u4, u6, u8 – fraction
u9 – table data
u10, u11, u12, u13 – table
dimension lengths
y1 = interp5D(u1, u2, u3, u4, u5, u6, u7, u8, y1 – output
u9, u10, u11, u12, u13, u14, u15, u16) u1, u3, u5, u7, u9 – index
u2, u4, u6, u8, u10 – fraction
u11 – table data
u12, u13, u14, u15, u16 – table
dimension lengths
y1 = interpND({ui, uf,}... ut, un...) y1 – output
ui, uf is an index and fraction pair
per dimension
ut – table data
un – table dimension lengths
Explicit values y1 – output
y1 = lookup1D(u1, u2, u3, u4) u1 – input
u2 – breakpoint data
u3 – table data
u4 – table dimension length
Even spacing y1 – output
y1 = lookup1D(u1, u2, u3, u4, u5) u1 – input
u2 – first point of breakpoint data
u3 – spacing of breakpoints
u4 – table data
u5 – table dimension length

54-116
Lookup Table Function Code Replacement

Conceptual Function Signature Argument Summary


Explicit values y1 – output
y1 = lookup2D(u1, u2, u3, u4, u5, u6, u7) u1, u2 – input
u3, u4 – breakpoint data
u5 – table data
u6, u7 – table dimension lengths
Even spacing y1 – output
y1 = lookup2D(u1, u2, u3, u4, u5, u6, u7, u8, u1, u2 – input
u9) u3, u5 – first point of breakpoint
data
u4, u6 – spacing of breakpoints
u7 – table data
u8, u9 – table dimension lengths
Explicit spacing y1 – output
y1 = lookup3D(u1, u2, u3, u4, u5, u6, u7, u8, u1, u2, u3 – input
u9, u10) u4, u5, u6 – breakpoint data
u7 – table data
u8, u9, u10 – table dimension
lengths
Even spacing y1 – output
y1 = lookup3D(u1, u2, u3, u4, u5, u6, u7, u8, u1, u2, u3 – input
u9, u10, u11, u12, u13) u4, u6, u8 – first point of
breakpoint data
u5, u7, u9 – spacing of breakpoints
u10 – table data
u11, u12, u13 – table dimension
lengths
Explicit values y1 – output
y1 = lookup4D(u1, u2, u3, u4, u5, u6, u7, u8, u1, u2, u3, u4 – input
u9, u10, u11, u12, u13) u5, u6, u7, u8 – breakpoint data
u9 – table data
u10, u11, u12, u13 – table
dimension lengths

54-117
54 Code Replacement Customization for Simulink Models in Embedded Coder

Conceptual Function Signature Argument Summary


Even spacing y1 – output
y1 = lookup4D(u1, u2, u3, u4, u5, u6, u7, u8, u1, u2, u3, u4 – input
u9, u10, u11, u12, u13, u14, u15, u16, u17) u5, u7, u9, u11 – first point of
breakpoint data
u6, u8, u10, u12 – spacing of
breakpoints
u13 – table data
u14, u15, u16, u17 – table
dimension lengths
Explicit values y1 – output
y1 = lookup5D(u1, u2, u3, u4, u5, u6, u7, u8, u1, u2, u3, u4, u5 – input
u9, u10, u11, u12, u13, u14, u15, u16) u6, u7, u8, u9, u10 – breakpoint
data
u11 – table data
u12, u13, u14, u15, u16 – table
dimension lengths
Even spacing y1 – output
y1 = lookup5D(u1, u2, u3, u4, u5, u6, u7, u8, u1, u2, u3, u4, u5 – input
u9, u10, u11, u12, u13, u14, u15, u16, u17, u6, u8, u10, u12, u14 – first
u18, u19, u20, u21) point of breakpoint data
u7, u9, u11, u13, u15 – spacing
of breakpoints
u16 – table data
u17, u18, u19, u20, u21 – table
dimension lengths
Explicit values y1 – output
y1 = lookupND(un,..., ub,..., ut, un...) un, input per dimension
ub, breakpoint per dimension
ut – table data
un – table dimension lengths

54-118
Lookup Table Function Code Replacement

Conceptual Function Signature Argument Summary


Even spacing y1 – output
y1 = lookupND(un,..., {ufn, usn,}... ut, un – input per dimension
un...) ufn – first point of breakpoint data
per dimension
usn – spacing of breakpoint per
dimension
ut – table data
un – table dimension lengths
y1 = lookupND_Direct(u1, u2,...ui, ui+1) y1 – output
u1...ui – input
ui+1 – table data
Explicit values y1 – index
y1, y2 = prelookup(u1, u2, u3) y2 – fraction
u1 – input
u2 – breakpoint data
u3 – number of breakpoints
Evenly spaced y1 – index
y1, y2 = prelookup(u1, u2, u3, u4) y2 – fraction
u1 – input
u2 – first point of breakpoint data
u3 – spacing of breakpoints
u4 – number of breakpoints

When defining a table entry programmatically, you might also need to change the values
of required (primary) and optional algorithm parameters.

• Set values for required parameters to achieve code replacement.


• If you do not set a value for an optional parameter, the algorithm parameter software
applies don't care. The code replacement software ignores the parameter while
searching for matches.

To look up algorithm parameter information for a lookup table function:

1 Create a table entry for a function.

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 =

Prelookup with properties:

ExtrapMethod: [1x1 coder.algorithm.parameter.ExtrapMethod]


RndMeth: [1x1 coder.algorithm.parameter.RndMeth]
IndexSearchMethod: [1x1 coder.algorithm.parameter.IndexSearchMethod]
UseLastBreakpoint: [1x1 coder.algorithm.parameter.UseLastBreakpoint]
RemoveProtectionInput: [1x1 coder.algorithm.parameter.RemoveProtectionInput]

4 Examine information available for each parameter.


algParams.ExtrapMethod

ans =

ExtrapMethod with properties:

Name: 'ExtrapMethod'
Options: {'Linear' 'Clip'}
Primary: 1
Value: {'Linear'}

algParams.RndMeth

ans =

RndMeth with properties:

Name: 'RndMeth'
Options: {1x7 cell}
Primary: 0
Value: {1x7 cell}

algParams.RndMeth.Value

ans =

Columns 1 through 6

'Ceiling' 'Convergent' 'Floor' 'Nearest' 'Round' 'Simplest'

Column 7

'Zero'

algParams.IndexSearchMethod

54-120
Lookup Table Function Code Replacement

ans =

IndexSearchMethod with properties:

Name: 'IndexSearchMethod'
Options: {'Linear search' 'Binary search' 'Evenly spaced points'}
Primary: 0
Value: {'Binary search' 'Evenly spaced points' 'Linear search'}

algParams.UseLastBreakpoint

ans =

UseLastBreakpoint with properties:

Name: 'UseLastBreakpoint'
Options: {'off' 'on'}
Primary: 0
Value: {'off' 'on'}

algParams.RemoveProtectionInput

ans =

RemoveProtectionInput with properties:

Name: 'RemoveProtectionInput'
Options: {'off' 'on'}
Primary: 0
Value: {'off' 'on'}

Interactive Mapping with Code Replacement Tool


This example shows how to specify a code replacement table entry for a lookup table
algorithm by using the Code Replacement Tool.

Open and Examine Example Replacement Function

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

Place a copy of these files in your working folder.

Open and examine the code for myLookup1D.h.


#include "rtwtypes.h"
real_T my_Lookup1D_Repl(real_T u0, const real_T *bp0, const real_T *table, uint32_T tdl);

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;

if (u0 <= bp0[0U]) {


bpIdx = 0U;
frac = 0U;
} else if (u0 < bp0[maxIndex]) {
bpIdx = maxIndex >> 1U;
while ((u0 < bp0[bpIdx]) && (bpIdx > 0U)) {
bpIdx--;
}

while ((bpIdx < maxIndex - 1U) && (u0 >= bp0[bpIdx + 1U])) {
bpIdx++;
}

frac = (uint16_T)((u0 - bp0[bpIdx]) / (bp0[bpIdx + 1U] -


bp0[bpIdx]) * 32768.0);
} else {
bpIdx = maxIndex;
frac = 0U;
}

if (bpIdx == maxIndex) {
y = table[bpIdx];
} else {
y = (table[bpIdx + 1U] - table[bpIdx]) * ((real_T)frac * 3.0517578125E-5) +
table[bpIdx];
}

return y;
}

Open and Examine the Example Model

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

Create Code Replacement Table

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:

y1 = lookup1D(u1, u2, u3, u4)

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.

Signature Conceptual Data I/O type Argument Lower Upper


Argument Argument type type range range
Name Name
y y1 double OUTPUT Scalar Not Not
applicable applicable
u1 u1 double INPUT Scalar Not Not
applicable applicable
bp1 u2 double INPUT Matrix [0 0] [Inf Inf]
table u3 double INPUT Matrix [0 0] [Inf Inf]

54-124
Lookup Table Function Code Replacement

Signature Conceptual Data I/O type Argument Lower Upper


Argument Argument type type range range
Name Name
tdl u4 uint32 INPUT Scalar Not Not
applicable applicable
7 Enter information for the replacement function prototype. The prototype for the
example function is:
real_T my_Lookup1D_Repl(real_T u0, const real_T *bp0, const real_T *table, uint32_T tdl)

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.

The function signature preview should appear as follows:


double my_Lookup1D_Repl(double u1, const double* u2, const double* u3, uint32 u4)

9 Set relevant implementation attributes. Use the default settings.


10 Validate the entry. If the tool reports errors, fix them, and retry the validation. Repeat
the procedure until the tool does not report errors.
11 Save the code replacement table in your working folder as
my_lookup_replacement_table.m.

Specify Build Information

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.

Test the Entry

To test this example:

1 Register the code replacement mapping.


2 Use the example model rtwdemo_crllookup1D.
3 Configure the model with the following settings:

• On the Solver pane, select a fixed-step solver.


• 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 lookup table function entry.

Programmatic Specification
This example shows how to specify code replacement table entries for lookup table
functions programmatically.

Open and Examine Example Replacement Function

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

Place a copy of these files in your working folder.

Open and examine the code for myLookup1D.h.


#include "rtwtypes.h"
real_T my_Lookup1D_Repl(real_T u0, const real_T *bp0, const real_T *table, uint32_T tdl);

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;

if (u0 <= bp0[0U]) {


bpIdx = 0U;
frac = 0U;
} else if (u0 < bp0[maxIndex]) {
bpIdx = maxIndex >> 1U;
while ((u0 < bp0[bpIdx]) && (bpIdx > 0U)) {
bpIdx--;
}

while ((bpIdx < maxIndex - 1U) && (u0 >= bp0[bpIdx + 1U])) {
bpIdx++;
}

frac = (uint16_T)((u0 - bp0[bpIdx]) / (bp0[bpIdx + 1U] -


bp0[bpIdx]) * 32768.0);
} else {
bpIdx = maxIndex;
frac = 0U;
}

if (bpIdx == maxIndex) {
y = table[bpIdx];
} else {
y = (table[bpIdx + 1U] - table[bpIdx]) * ((real_T)frac * 3.0517578125E-5) +
table[bpIdx];
}

return y;
}

Review Lookup Function Signature

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:

y1 = lookup1D(u1, u2, u3, u4)

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 Code Replacement Entry

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.

Open crl_table_lookup1D.m and examine the definition.

1 Create a table definition file that contains a function definition. For example:

function hLib = my_lookup_replacement_table


2 Within the function body, create the table by calling the function RTW.TflTable.

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 = RTW.TflArgMatrix('u2', 'RTW_IO_INPUT', 'double');


arg.DimRange = [0 0; Inf Inf];
addConceptualArg(hEnt, arg);

arg = RTW.TflArgMatrix('u3', 'RTW_IO_INPUT', 'double');


arg.DimRange = [0 0; Inf Inf];
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 =

Lookup with properties:

InterpMethod: [1x1 coder.algorithm.parameter.InterpMethod]


ExtrapMethod: [1x1 coder.algorithm.parameter.ExtrapMethod]
RndMeth: [1x1 coder.algorithm.parameter.RndMeth]
IndexSearchMethod: [1x1 coder.algorithm.parameter.IndexSearchMethod]
UseLastTableValue: [1x1 coder.algorithm.parameter.UseLastTableValue]
RemoveProtectionInput: [1x1 coder.algorithm.parameter.RemoveProtectionInput]
SaturateOnIntegerOverflow: [1x1 coder.algorithm.parameter.SaturateOnIntegerOverflow]
SupportTunableTableSize: [1x1 coder.algorithm.parameter.SupportTunableTableSize]
BPPower2Spacing: [1x1 coder.algorithm.parameter.BPPower2Spacing]

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 =

InterpMethod with properties:

Name: 'InterpMethod'
Options: {'Linear' 'Flat' 'Nearest'}
Primary: 1
Value: {'Linear'}

algParams.RndMeth

ans =

RndMeth with properties:

Name: 'RndMeth'
Options: {1x7 cell}
Primary: 0
Value: {1x7 cell}

algParams.RndMeth.Options

ans =

Columns 1 through 5

'Ceiling' 'Convergent' 'Floor' 'Nearest' 'Round'

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 =

RndMeth with properties:

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.

Test the Entry

To test this example:

1 Register the code replacement mapping.


2 Use the example model rtwdemo_crllookup1D.
3 Configure the model with the following settings:

• On the Solver pane, select a fixed-step solver.


• On the Code Generation pane, select an ERT-based system target 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.

Sample Code Replacement Definition for the lookup2D


Function
The following code shows a replacement definition for the lookup2D function.

function hLib = my_2dlookup_replacement_table

hLib = RTW.TflTable;

hEnt = RTW.TflCFunctionEntry;
setTflCFunctionEntryParameters(hEnt, ...
'Key', 'lookup2D', ...
'Priority', 100, ...

'ImplementationName', 'custom_lookup2d', ...


'ImplementationHeaderFile', 'custom_lookup2d.h', ...
'ImplementationSourceFile', 'custom_lookup2d.c', ...
'GenCallback', 'RTW.copyFileToBuildDir');

% 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);

arg = RTW.TflArgMatrix('u3', 'RTW_IO_INPUT', 'double');


arg.DimRange = [1 1; 10 1];
addConceptualArg(hEnt, arg);

arg = RTW.TflArgMatrix('u4', 'RTW_IO_INPUT', 'double');


arg.DimRange = [1 1; 10 1];
addConceptualArg(hEnt, arg);

arg = RTW.TflArgMatrix('u5', 'RTW_IO_INPUT', 'double');

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

Data Alignment for Code Replacement


Code replacement libraries can align data objects passed into a replacement function to a
specified boundary.

Code Replacement Data Alignment


You can take advantage of function implementations that require aligned data to optimize
application performance. To configure data alignment for a function implementation:

1 Specify the data alignment requirements in a code replacement entry. Specify


alignment separately for each implementation function argument or collectively for
all function arguments. See “Specify Data Alignment Requirements for Function
Arguments” on page 54-136.
2 Specify the data alignment capabilities and syntax for one or more compilers. Include
the alignment specifications in a library registration entry in the rtwTargetInfo.m
file. See “Provide Data Alignment Specifications for Compilers” on page 54-138.
3 Register the library containing the table entry and alignment specification object.
4 Configure the code generator to use the code replacement library and generate code.
Observe the results.

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.

Specify Data Alignment Requirements for Function Arguments


To specify the data alignment requirement for an argument in a code replacement entry:

• If you are defining a replacement function in a code replacement table registration


file, create an argument descriptor object (RTW.ArgumentDescriptor). Use its
AlignmentBoundary property to specify the required alignment boundary and assign
the object to the argument Descriptor property.
• If you are defining a replacement function using the Code Replacement Tool, on the
Mapping Information tab, in the Argument properties section for the replacement
function, enter a value for the Alignment value parameter.

54-136
Data Alignment for Code Replacement

The AlignmentBoundary property (or Alignment value parameter) specifies the


alignment boundary for data passed to a function argument, in number of bytes. The
AlignmentBoundary property is valid only for addressable objects, including matrix and
pointer arguments. It is not applicable for value arguments. Valid values are:

• -1 (default) — If the data is a Simulink.Bus, Simulink.Signal, or


Simulink.Parameter object, specifies that the code generator determines an
optimal alignment based on usage. Otherwise, specifies that there is not an alignment
requirement for this argument.
• Positive integer that is a power of 2, not exceeding 128 — Specifies number of bytes in
the boundary. The starting memory address for the data allocated for the function
argument is a multiple of the specified value. If you specify an alignment boundary
that is less than the natural alignment of the argument data type, the alignment
directive is emitted in the generated code. However, the target compiler ignores the
directive.

The following code specifies the AlignmentBoundary for an argument as 16 bytes.

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.

Note If your model imports Simulink.Bus, Simulink.Parameter, or


Simulink.Signal objects, specify an alignment boundary in the object properties, using
the Alignment property. For more information, see Simulink.Bus,
Simulink.Parameter, and Simulink.Signal.

Provide Data Alignment Specifications for Compilers


To support data alignment in generated code, describe the data alignment capabilities
and syntax for your compilers in the code replacement library registration. Provide one or
more alignment specifications for each compiler in a library registry entry.

To describe the data alignment capabilities and syntax for a compiler:

• If you are defining a code replacement library registration entry in a


rtwTargetInfo.m customization file, add one or more AlignmentSpecification
objects to an RTW.DataAlignment object. Attach the RTW.DataAlignment object to
the TargetCharacteristics object of the registry entry.

The RTW.DataAlignment object also has the property DefaultMallocAlignment,


which specifies the default alignment boundary, in bytes, that the compiler uses for
dynamically allocated memory. If the code generator uses dynamic memory allocation
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.

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.

Click the plus (+) symbol to add additional compiler specifications.

For each data alignment specification, provide the following information.

54-139
54 Code Replacement Customization for Simulink Models in Embedded Coder

Alignment‐ Dialog Box Description


Specification Parameter
Property
AlignmentType Alignment Cell array of predefined enumerated strings, specifying
type which types of alignment this specification supports.

• DATA_ALIGNMENT_LOCAL_VAR — Local variables.


• DATA_ALIGNMENT_GLOBAL_VAR — Global variables.
• DATA_ALIGNMENT_STRUCT_FIELD — Individual
structure fields.
• DATA_ALIGNMENT_WHOLE_STRUCT — Whole structure,
with padding (individual structure field alignment, if
specified, is favored and takes precedence over whole
structure alignment).

Each alignment specification must specify at least


DATA_ALIGNMENT_GLOBAL_VAR and
DATA_ALIGNMENT_STRUCT_FIELD.

54-140
Data Alignment for Code Replacement

Alignment‐ Dialog Box Description


Specification Parameter
Property
AlignmentPositio Alignment Predefined enumerated string specifying the position in
n position which you must place the compiler alignment directive for
alignment type DATA_ALIGNMENT_WHOLE_STRUCT:

• DATA_ALIGNMENT_PREDIRECTIVE — The alignment


directive is emitted before struct st_tag{…}, as part
of the type definition statement (for example, MSVC).
• DATA_ALIGNMENT_POSTDIRECTIVE — The alignment
directive is emitted after struct st_tag{…}, as part
of the type definition statement (for example, gcc).
• DATA_ALIGNMENT_PRECEDING_STATEMENT — The
alignment directive is emitted as a standalone
statement immediately preceding the definition of the
structure type. A semicolon (;) must terminate the
registered alignment syntax.
• DATA_ALIGNMENT_FOLLOWING_STATEMENT — The
alignment directive is emitted as a standalone
statement immediately following the definition of the
structure type. A semicolon (;) must terminate the
registered alignment syntax.

For alignment types other than


DATA_ALIGNMENT_WHOLE_STRUCT, code generation uses
alignment position DATA_ALIGNMENT_PREDIRECTIVE.

54-141
54 Code Replacement Customization for Simulink Models in Embedded Coder

Alignment‐ Dialog Box Description


Specification Parameter
Property
AlignmentSyntax‐ Alignment Specifies the alignment directive string that the compiler
Template syntax supports. The string is registered as a syntax template that
has placeholders in it. These placeholders are supported:

• %n — Replaced by the alignment boundary for the


replacement function argument.
• %s — Replaced by the aligned symbol, usually the
identifier of a variable.

For example, for the gcc compiler, you can specify


__attribute__((aligned(%n))), or for the MSVC
compiler, __declspec(align(%n)).
SupportedLanguag Supported Cell array specifying the languages to which this alignment
es languages specification applies, among c and c++. Sometimes
alignment syntax and position differ between languages for
a compiler.

Here is a data alignment specification for the GCC compiler:


da = RTW.DataAlignment;

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

Basic Example of Code Replacement Data Alignment


A simple example of the complete workflow for data alignment specified for code
replacement is:

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);

arg = getTflArgFromString(hLib, 'y1','single*');


desc = RTW.ArgumentDescriptor;
desc.AlignmentBoundary = 16;
arg.Descriptor = desc;
entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hLib, 'u1','single*');


desc = RTW.ArgumentDescriptor;
desc.AlignmentBoundary = 16;
arg.Descriptor = desc;
entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hLib, 'u2','single*');


desc = RTW.ArgumentDescriptor;
desc.AlignmentBoundary = 16;
arg.Descriptor = desc;
entry.Implementation.addArgument(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

% Register the CRL defined in local function locCrlRegFcn


cm.registerTargetInfo(@locCrlRegFcn);

end % End of RTWTARGETINFO

% Local function to define a CRL containing crl_table_mmul_4x4_single_align


function thisCrl = locCrlRegFcn

% create an alignment specification object, assume gcc

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++'};

% add the alignment specification object


da = RTW.DataAlignment;
da.addAlignmentSpecification(as);

% add the data alignment object to target characteristics


tc = RTW.TargetCharacteristics;
tc.DataAlignment = da;

% Instantiate a CRL registry entry


thisCrl = RTW.TflRegistry;

% Define the CRL properties


thisCrl.Name = 'Data Alignment Example';
thisCrl.Description = 'Example of replacement with data alignment';
thisCrl.TableList = {'crl_table_mmul_4x4_single_align'};
thisCrl.TargetCharacteristics = tc;

end % End of LOCCRLREGFCN

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

Replace MATLAB Functions with Custom Code Using


coder.replace
The coder.replace function provides the ability to replace a specified MATLAB function
with a code replacement function in generated code. Use coder.replace in MATLAB
code from which you want to generate C code using:

• MATLAB Coder
• MATLAB code in a Simulink MATLAB Function block

You can replace MATLAB functions that have:

• Single or multiple inputs


• Single or multiple outputs
• Scalar and matrix inputs and outputs

Supported types include:

• single, double (complex and noncomplex)


• int8, uint8 (complex and noncomplex)
• int16, uint16 (complex and noncomplex)
• int32, uint32 (complex and noncomplex)
• Fixed-point integers
• Mixed types (different type on each input)

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

Replace coder.ceval Calls to External Functions


The coder.ceval function calls external C/C++ functions from code generated from
MATLAB code. The code replacement software supports replacement of the function that
you specify in a call to coder.ceval. An application of this code replacement scenario is
to write generic MATLAB code that you can customize for different platforms with code
replacements. A code replacement library can define hardware-specific code
replacements for the function call. Use coder.ceval in MATLAB code from which you
want to generate C code using:

• 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:

• Custom C function my_add.c.

/* my_add.c */

#include "my_add.h"

double my_add(double in1, double in2)


{
return in1 + in2;
}
• Custom C header file my_add.h.

/* my_add.h */

double my_add(double in1, double in2);


• MATLAB function call_my_add.m, which uses coder.ceval to invoke my_add.c.

function y = call_my_add(in1, in2) %#codegen

y=0.0;

if ~coder.target('Rtw')

54-147
54 Code Replacement Customization for Simulink Models in Embedded Coder

% Executing in MATLAB, call MATLAB equivalent of C function my_add


y= in1+in2;
else
% Executing in generated code, call C function my_add
y = coder.ceval('my_add', in1, in2);
end
• MATLAB test function call_my_add_test.m, which calls call_my_add.m.

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"

double my_add_replacement(double in1, double in2)


{
return in1 + in2;
}
• Replacement C header file my_add_replacement.h.

/* my_add_replacement.h */

double my_add_replacement(double in1, double in2);

Interactive External Function Call Replacement Specification


with Code Replacement Tool
This example shows how to define a code replacement table entry for a MATLAB function
that calls coder.ceval to invoke an external C function. The example shows how to
define the entry interactively with the Code Replacement Tool.

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:

double my_add_replacement(double u1, double u2);


9 On the Build Information tab, specify my_add_replacement.h for the
Implementation header file parameter and my_add_replacement.c for the
Implementation source file.
10 Click Validate entry.
11 Save the code replacement table in the same folder as my_add_replacement.c.
Name the file crl_table_my_add.m.

To test the example:

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

Programmatic External Function Call Replacement


Specification
This example shows how to define a code replacement table entry for a MATLAB function
that calls coder.ceval to invoke an external C function. The example shows how to
define the entry programmatically.

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:

function hLib = crl_table_my_add


3 Within the function body, create the table by calling the function 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.

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.

To test the example:

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

• “Develop a Code Replacement Library” on page 54-27

54-152
Replace MATLAB Functions Specified in MATLAB Function Blocks

Replace MATLAB Functions Specified in MATLAB


Function Blocks
This example shows how to use code replacement to replace a MATLAB function
specified in a MATLAB Function block.

1 Open the ex_replace model. At the command prompt, enter:

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.

function y = customFcn(u1, u2) %#codegen


% This block supports MATLAB for code generation.

% Replace this MATLAB function with CRL replacement function and if no


% CRL replacement is found, generate an error during code generation.
coder.replace('-errorifnoreplacement');

assert(isa(u1,'int32'));
assert(isa(u2,'int32'));

y = power(u1,u2);

The coder.replace('-errorifnoreplacement') statement instructs the code


generator to replace this MATLAB function with a code replacement library function.
The code generator produces an error if it does not find a match.
3 Create a table definition file that contains a function definition. For example:

function hTable = crl_table_coderreplace()


4 Within the function body, create the table by calling the function RTW.TflTable.

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);

arg = getTflArgFromString(hEnt, 'u1','int32');


addConceptualArg(hEnt, arg);

arg = getTflArgFromString(hEnt, 'u2','int32');


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.

arg = getTflArgFromString(hEnt, 'void','void');


arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);

arg = getTflArgFromString(hEnt, 'u1','int32');


hEnt.Implementation.addArgument(arg);

arg = getTflArgFromString(hEnt, 'u2','int32');


hEnt.Implementation.addArgument(arg);

arg = getTflArgFromString(hEnt, 'y1','int32*');


arg.IOType = 'RTW_IO_OUTPUT';
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-154
Replace MATLAB Functions Specified in MATLAB Function Blocks

To test the example:

1 Register the code replacement mapping.


2 Create files MyMath.c and MyMath.h that define the replacement function,
scalarFcnReplacement, which has two int32 inputs and one int32 output.

MyMath.c

#include "MyMath.h"

void scalarFcnReplacement(int32_T u1, int32_T u2, int32_T* y1 ) {


*y1 = u1^u2;
}

MyMath.h

#ifndef _ScalarMath_h
#define _ScalarMath_h

#include "rtwtypes.h"

#ifdef __cplusplus
extern "C" {
#endif

extern void scalarFcnReplacement(int32_T u1, int32_T u2, int32_T* y1);

#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

scalarFcnReplacement(ex_replace_U.In1, ex_replace_U.In2, &y);


ex_replace_Y.Out1 = y;
}

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

Reserved Identifiers and Code Replacement


The code generator and C programming language use, internally, reserved keywords for
code generation. Do not use reserved keywords as identifiers or function names. Reserved
keywords for code generation include many code replacement library identifiers, the
majority of which are function names, such as acos.

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.

To register additional code replacement reserved identifiers, use the


setReservedIdentifiers function. This function registers specified reserved
identifiers to be associated with a code replacement table.

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

• “Customize Match and Replacement Process” on page 54-159


• “Define Code Replacement Mappings” on page 54-43
• “Develop a Code Replacement Library” on page 54-27

54-158
Customize Match and Replacement Process

Customize Match and Replacement Process


During the build process, the code generator uses:

• 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:

• You want to replace an operator with a particular fixed-point implementation function


only when fraction lengths are within a particular range.
• When a match occurs, you want to modify your replacement function signature based
on compile-time information, such as passing fraction-length values into the function.

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.

To create a custom code replacement entry:

1 Create a custom code replacement entry class, derived from


RTW.TflCFunctionEntryML (for function replacement) or
RTW.TflCOperationEntryML (for operator replacement).
2 In your derived class, implement a do_match method with a fixed preset signature as
a MATLAB function. In your do_match method, provide either or both of the
following customizations that instantiate the class:

• 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

• Math modes, such as saturation and rounding


• Operator or function key
• Modify the implementation signature by adding additional arguments or setting
constant input argument values. You can inject a constant value, such as an input
scaling value, as an additional argument to the replacement function.
3 Create code replacement entries that instantiate the custom entry class.
4 Register a library containing the code replacement table that includes your entries.

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).

Customize Code Match and Replacement for Functions


This example shows how to use custom code replacement table entries to refine the
match and replacement logic for functions. The example shows how to:

• 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:

• Select a temporary target platform with a 32-bit integer size.


• Modify the code to match the integer size of your target platform.
2 Create a class, for example TflCustomFunctionEntry, that is derived from the
base class RTW.TflCFunctionEntryML. The derived class defines a do_match
method with the signature:

54-160
Customize Match and Replacement Process

function ent = do_match(hThis, ...


hCSO, ...
targetBitPerChar, ...
targetBitPerShort, ...
targetBitPerInt, ...
targetBitPerLong, ...
targetBitPerLongLong)

In the do_match signature:

• 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.

The do_match method:

• Adds required additional match criteria that the base class does not provide.
• Makes required modifications to the implementation signature.

In this case, the do_match method must match only targetBitPerInt,


representing the number of bits in the C int data type for the current target, to the
value 32. If the code generator finds a match, the method sets the return handle and
creates and adds an input argument. The input argument represents whether units
are expressed as degrees or radians, to the replacement function 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

targetBitPerLong, ... %#ok


targetBitPerLongLong) %#ok
% DO_MATCH - Create a custom match function. The base class
% checks the types of the arguments prior to calling this
% method. This will check additional data and perhaps modify
% the implementation function.

ent = []; % default the return to empty, indicating the match failed.

% Match sine function only if the target int size is 32 bits


if targetBitPerInt == 32
% Need to modify the default implementation, starting from a copy
% of the standard TflCFunctionEntry.
ent = RTW.TflCFunctionEntry(hThis);

% If the target int size is 32 bits, the implementation function


% takes an additional input flag argument indicating degress vs.
% radians. The additional argument can be created and added either
% in the CRL table definition file that instantiates this class, or
% here in the class definition, as follows:
createAndAddImplementationArg(ent, 'RTW.TflArgNumericConstant', ...
'Name', 'u2', ...
'IsSigned', true, ...
'WordLength', 32, ...
'FractionLength', 0, ...
'Value', 1);
end
end
end
end

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');

createAndAddConceptualArg(fcn_entry, 'RTW.TflArgNumeric', ...


'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...

54-162
Customize Match and Replacement Process

'DataTypeMode', 'double');

createAndAddConceptualArg(fcn_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'DataTypeMode', 'double');

% TflCustomFunctionEntry class do_match method will create and add


% an implementation function argument during code generation if
% the supported integer size on the current target is 32 bits.
copyConceptualArgsToImplementation(fcn_entry);

addEntry(hTable, fcn_entry);

4 Check the validity of the code replacement table entry.

• At the command prompt, invoke the table definition file.

tbl = crl_table_custom_sinfcn_double
• In the Code Replacement Viewer, view the table definition file.

crviewer(crl_table_custom_sinfcn_double)

Customize Code Match and Replacement for Nonscalar


Operations
This example shows how to create custom code replacement entries that add logic to the
code match and replacement process for a nonscalar operation. Custom entries specify
additional match criteria or modify the replacement function signature to meet
application needs.

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:

• do_match method — @MyElemMultEntry/MyElemMultEntry.m


• Replacement function source and header files — src/myMulImplLib.c and src/
myMulImplLib.h
• Model — myElemMul.slx

54-163
54 Code Replacement Customization for Simulink Models in Embedded Coder

• Code replacement table definition — myElemMultCrlTable.m


• Registration file — rtwTargetInfo.m

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:

function ent = do_match(hThis, ...


hCSO, ...
targetBitPerChar, ...
targetBitPerShort, ...
targetBitPerInt, ...
targetBitPerLong, ...
targetBitPerLongLong)

In the do_match 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.

The do_match method:

• 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:

• Sets the return handle.


• Uses the conceptual arguments to compute the number of elements in the array.
In the replacement entry returned, sets the value of the constant implementation
argument as the number of elements of the array.

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

function ent = do_match(hThis, ...


hCSO, ... %#ok
targetBitPerChar, ... %#ok
targetBitPerShort, ... %#ok
targetBitPerInt, ... %#ok
targetBitPerLong, ... %#ok
targetBitPerLongLong ) %#ok

% Fourth implementation arg represents number of elements for producing matches.


assert(strcmp(hThis.Implementation.Arguments(4).Name,'numElements'));

ent = RTW.TflCOperationEntry(hThis);

% Calculate number of elements and set value of injected constant.


ent.Implementation.Arguments(4).Value = prod(hCSO.ConceptualArgs(1).DimRange(1,:));

% Since implementation has been modified for specific DimRange, update


% returned entry to match similar CSOs only.
for idx =1:3
ent.ConceptualArgs(idx).DimRange = hCSO.ConceptualArgs(idx).DimRange;
end
end
end
end
2 Create and save the following code replacement table definition file,
myElemMultCrlTable.m. This file defines a code replacement table that contains an
operator entry generator for element-wise multiplication. The table entry:

• Instantiates the derived class myElemMultEntry from the previous step.


• Sets operator entry parameters with the call to
the setTflCOperationEntryParameters function.
• Creates conceptual arguments y1, u1, and u2. The argument class
RTW.TflArgMatrix specifies matrix arguments to match. The three arguments
are set up to match 2-dimensional matrices with at least two elements in each
dimension.
• Calls the getTflArgFromString function to create a return value and four
implementation arguments. Arguments u1 and u2 are the operands, y1 is the
product, and the fourth argument is the number of elements.

54-165
54 Code Replacement Customization for Simulink Models in Embedded Coder

Alternatively, the do_match method of the derived class myElemMultEntry can


create and add the implementation arguments. When the number of additional
implementation arguments required can vary based on compile-time information,
use the alternative approach.
• Calls addEntry to add the entry to a code replacement table.
function hLib = myElemMultCrlTable

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

arg = RTW.TflArgMatrix('y1', 'RTW_IO_OUTPUT', 'int32');


arg.DimRange = [2 2; Inf Inf];
hEnt.addConceptualArg(arg);

arg = RTW.TflArgMatrix('u1', 'RTW_IO_INPUT', 'int32');


arg.DimRange = [2 2; Inf Inf];
hEnt.addConceptualArg(arg);

arg = RTW.TflArgMatrix('u2', 'RTW_IO_INPUT', 'int32');


arg.DimRange = [2 2; Inf Inf];
hEnt.addConceptualArg(arg);

% 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.

• At the command prompt, invoke the table definition file.

tbl = myElemMultCrlTable
• In the Code Replacement Viewer, view the table definition file.

crviewer(myElemMultCrlTable)

Customize Code Match and Replacement for Scalar Operations


This example shows how to create custom code replacement entries that add logic to the
code match and replacement process for a scalar operation. Custom entries specify
additional match criteria or modify the replacement function signature to meet
application needs.

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)

In the do_match 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 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:

• Sets the return handle.


• Removes slope and bias wild cards from the conceptual arguments (the match is
for specific slope and bias values).
• Writes fraction-length values for the inputs and output into replacement function
arguments 3, 4, and 5.

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

% DO_MATCH - Create a custom match function. The base class


% checks the types of the arguments prior to calling this
% method. This class will check additional data and can
% modify the implementation function.

% 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

if length(hCSO.ConceptualArgs) == 3 && ...


hCSO.ConceptualArgs(1).Type.Bias == 0 && ...
hCSO.ConceptualArgs(2).Type.Bias == 0 && ...
hCSO.ConceptualArgs(3).Type.Bias == 0

% Modify the default implementation. Since this is a


% generator entry, a concrete entry is created using this entry
% as a template. The type of entry being created is a standard
% TflCOperationEntry. Using the standard operation entry
% provides required information, and you do not need
% a custom match function.
ent = RTW.TflCOperationEntry(hThis);

% Since this entry is modifying the implementation for specific


% fraction-length values (arguments 3, 4, and 5), the conceptual argument
% wild cards must be removed (the wildcards were inherited from the
% generator when it was used as a template for the concrete entry).
% This concrete entry is now for a specific slope and bias.
% hCSO holds the slope and bias values (created by the code generator).
for idx=1:3
ent.ConceptualArgs(idx).CheckSlope = true;
ent.ConceptualArgs(idx).CheckBias = true;

% Set the specific Slope and Biases


ent.ConceptualArgs(idx).Type.Slope = hCSO.ConceptualArgs(idx).Type.Slope;
ent.ConceptualArgs(idx).Type.Bias = 0;
end

% Set the fraction-length values in the implementation function.


ent.Implementation.Arguments(3).Value = ...

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:

• Instantiates the derived class TflCustomOperationEntry from the previous


step. If you want to replace word sizes and signedness attributes, you can use the
same derived class, but not the same entry, because you cannot use a wild card
with the WordLength and IsSigned arguments. For example, to support uint8,
int8, uint16, int16, and int32, add five other distinct entries. To use different
implementation functions for saturation and rounding modes other than overflow
and round to floor, add entries for those match permutations.
• Sets operator entry parameters with the call to
the setTflCOperationEntryParameters function.
• Calls the createAndAddConceptualArg function to create conceptual
arguments y1, u1, and u2.
• Calls createAndSetCImplementationReturn and
createAndAddImplementationArg to define the signature for the replacement
function. Three of the calls to createAndAddImplementationArg create
implementation arguments to hold the fraction-length values for the inputs and
output. Alternatively, the entry can omit those argument definitions. Instead, the
do_match method of the derived class TflCustomOperationEntry can create
and add the three implementation arguments. When the number of additional
implementation arguments required can vary based on compile-time information,
use the alternative approach.
• Calls addEntry to add the entry to a code replacement table.

function hTable = crl_table_custom_add_ufix32

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');

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataType', 'Fixed', ...
'Scaling', 'BinaryPoint', ...
'IsSigned', false, ...
'WordLength', 32);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataType', 'Fixed', ...
'Scaling', 'BinaryPoint', ...
'IsSigned', false, ...
'WordLength', 32);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataType', 'Fixed', ...
'Scaling', 'BinaryPoint', ...
'IsSigned', false, ...
'WordLength', 32);

% Specify replacement function signature

54-171
54 Code Replacement Customization for Simulink Models in Embedded Coder

createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0);

% 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);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumericConstant', ...


'Name', 'fl_in2', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0, ...
'Value', 0);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumericConstant', ...


'Name', 'fl_out', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0, ...

54-172
See Also

'Value', 0);

addEntry(hTable, op_entry);
3 Check the validity of the operator entry.

• At the command prompt, invoke the table definition file.

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

Scalar Operator Code Replacement


This example shows how to define a code replacement mapping for a scalar operator. The
example defines a mapping for the + (addition) operator 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_add_uint8


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


op_entry = RTW.TflCOperationEntry;
4 Set function entry parameters with a call to the
setTflCOperationEntryParameters function.
% Define addition operation of built-in uint8 data type
% Saturation on, Rounding unspecified
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 90, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'}, ...
'ImplementationName', 'u8_add_u8_u8', ...
'ImplementationHeaderFile', 'u8_add_u8_u8.h', ...
'ImplementationSourceFile', 'u8_add_u8_u8.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 getTflArgFromString and
addConceptualArg functions to create and add the arguments.
arg = getTflArgFromString(hTable, 'y1', 'uint8');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(op_entry, arg);

arg = getTflArgFromString(hTable, 'u1', 'uint8');


addConceptualArg(op_entry, arg );

arg = getTflArgFromString(hTable, 'u2', 'uint8');


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

copyConceptualArgsToImplementation function to create and add


implementation arguments to the entry by copying matching conceptual arguments.
copyConceptualArgsToImplementation(op_entry);

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:

1 Register the code replacement mapping.


2 Create a model that includes an Add block, such as this model.

3 Configure the model with the following settings:

• On the Solver pane, select a fixed-step solver.


• 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 Generate code and a code generation report.
5 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
• “Remap Operator Output to Function Input” on page 54-201

54-175
54 Code Replacement Customization for Simulink Models in Embedded Coder

• “Customize Match and Replacement Process” on page 54-159


• “Develop a Code Replacement Library” on page 54-27
• “What Is Code Replacement Customization?” on page 54-3

54-176
Addition and Subtraction Operator Code Replacement

Addition and Subtraction Operator Code Replacement


Consider the following when defining mappings for addition and subtraction operator
code replacements.

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-before-operation (CBO), default — Prior to performing the addition or subtraction


operation, the algorithm type casts input values to the output type. If the output data
type cannot exactly represent the input values, losses can occur as a result of the cast
to the output type. Additional loss can occur when the result of the operation is cast to
the final output type.

• 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.

Interactive Specification with Code Replacement Tool


When you use the Code Replacement Tool to create a code replacement table entry for an
addition or subtraction operation, the tool displays an Algorithm menu. Use that menu to
specify the Cast before operation or Cast after operation algorithm for that
entry.

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:

• Key to RTW_OP_ADD or RTW_OP_MINUS


• ImplementationName to the name of your replacement function
• EntryInfoAlgorithm to RTW_CAST_BFORE_OP (cast-before-operation) or
RTW_CAST_AFTER_OP (cast-after-operation)

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');

For more information, see setTflCOperationEntryParameters.

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.

• Floating-point types only

Input 1 Data Input 2 Data Accumulator Output Data Classifica


Type Type Data Type Type tion
double double double double CBO, CAO
double double double single —
double double single double —
double double single single CBO
double single double double CBO, CAO

54-178
Addition and Subtraction Operator Code Replacement

Input 1 Data Input 2 Data Accumulator Output Data Classifica


Type Type Data Type Type tion
double single double single —
double single single double —
double single single single CBO
single single single single CBO, CAO
single single single double —
single single double single —
single single double double CBO, CAO
• Floating-point and fixed-point types on the immediate addition or subtraction
operation

Algorith Conditions
m
CBO One of the following is true:

• Operation type is double.


• Operation type is single and input types are single or fixed-
point.
CAO Operation type is a superset of input types—that is, output type can
represent values of input types without loss of data.
• Fixed-point types only

Algorith Conditions
m
CBO At least one of the following is true:

• Accumulator type equals output type (Tacc == Tout).


• Output type is a superset of input types (Tacc >= {Tin1,
Tin2}) and accumulator type is a superset of output type (Tacc
>= Tout).
• Operation does not incur range or precision loss.

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

• “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
• “Fixed-Point Operator Code Replacement” on page 54-204
• “Develop a Code Replacement Library” on page 54-27

54-181
54 Code Replacement Customization for Simulink Models in Embedded Coder

Small Matrix Operation to Processor Code Replacement


This example shows how to define code replacement mappings that replace nonscalar
small matrix operations with processor-specific intrinsic functions. The example defines a
table containing two matrix operator replacement entries for the + (addition) operator
and the double data type. 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_matrix_add_double
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create the entry for the first operator mapping with a call to the
RTW.TflCOperationEntry function.
% Create table entry for matrix_sum_2x2_double
op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The code generator ignores
saturation and rounding modes for floating-point nonscalar addition and subtraction.
For code replacement entries for nonscalar addition and subtraction operations that
do not involve fixed-point data, in the call to setTflCOperationEntryParameters,
specify 'RTW_SATURATE_UNSPECIFIED' for the SaturationMode property and
{'RTW_ROUND_UNSPECIFIED'} for RoundingModes.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 30, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW', ...
'ImplementationName', 'matrix_sum_2x2_double', ...
'ImplementationHeaderFile', 'MatrixMath.h', ...
'ImplementationSourceFile', 'MatrixMath.c', ...
'ImplementationHeaderPath', LibPath, ...
'ImplementationSourcePath', LibPath, ...
'AdditionalIncludePaths', {LibPath}, ...
'GenCallback', 'RTW.copyFileToBuildDir', ...
'SideEffects', true);
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. To specify a matrix argument in the function call, use the argument
class RTW.TflArgMatrix. Specify the base type and the dimensions for which the

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);

arg = getTflArgFromString(hTable, 'u1', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'y1', ['double' '*']);


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 Create the entry for the second operator mapping.

% Create table entry for matrix_sum_3x3_double


op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 30, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW', ...
'ImplementationName', 'matrix_sum_3x3_double', ...
'ImplementationHeaderFile', 'MatrixMath.h', ...

54-183
54 Code Replacement Customization for Simulink Models in Embedded Coder

'ImplementationSourceFile', 'MatrixMath.c', ...


'ImplementationHeaderPath', LibPath, ...
'ImplementationSourcePath', LibPath, ...
'AdditionalIncludePaths', {LibPath}, ...
'GenCallback', 'RTW.copyFileToBuildDir', ...
'SideEffects', true);

% Specify operands and result


createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [3 3]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [3 3]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [3 3]);

% Specify replacement function signature


arg = getTflArgFromString(hTable, 'y2', 'void');
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);
arg = getTflArgFromString(hTable, 'u1', ['double' '*']);
op_entry.Implementation.addArgument(arg);
arg = getTflArgFromString(hTable, 'u2', ['double' '*']);
op_entry.Implementation.addArgument(arg);
arg = getTflArgFromString(hTable, 'y1', ['double' '*']);
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.addArgument(arg);

addEntry(hTable, op_entry);
9 Save the table definition file. Use the name of the table definition function to name
the file.

To test this example:

1 Register the code replacement mapping.


2 Create a model that includes an Add block.

54-184
See Also

3 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.
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

Matrix Multiplication Operation to MathWorks BLAS


Code Replacement
This example shows how to define code replacement mappings that replace nonscalar
multiplication operations with Basic Linear Algebra Subroutine (BLAS) multiplication
functions xgemm and xgemv. The example defines code replacement entries that map
floating-point matrix/matrix and matrix/vector multiplication operations to MathWorks
BLAS library multiplication functions dgemm and dgemv. The example defines the function
mappings programmatically. Alternatively, you can use the Code Replacement Tool to
define the same mappings.

BLAS libraries support matrix/matrix multiplication in the form of


C = a(op(A) * op(B)) + bC . op(X) means X, transposition of X, or Hermitian transposition
of X. However, code replacement libraries support only the limited case of
C = op(A) * op(B) (a = 1.0, b = 0.0) . Correspondingly, although BLAS libraries support
matrix/vector multiplication in the form of y = a(op(A) * x) + by , code replacement
libraries support only the limited case of y = op(A) * x (a = 1.0, b = 0.0) .

1 Create a table definition file that contains a function definition. For example:

function hTable = crl_table_tmwblas_mmult_double


2 Within the function body, create the table by calling the function RTW.TflTable.

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

LibPath = fullfile('$(MATLAB_ROOT)', 'extern', 'lib', arch, compilerName);


end
4 Create an entry for the first mapping with a call to the
RTW.TflBlasEntryGenerator function.

% Create table entry for dgemm32


op_entry = RTW.TflBlasEntryGenerator;
5 Set operator entry parameters with a call to the
setTflCFunctionEntryParameters function. The function call sets matrix
multiplication operator entry properties. The code generator ignores saturation and
rounding modes for floating-point nonscalar addition and subtraction. For code
replacement entries for nonscalar addition and subtraction operations that do not
involve fixed-point data, in the call to setTflCFunctionEntryParameters, specify
'RTW_SATURATE_UNSPECIFIED' for the SaturationMode property and
{'RTW_ROUND_UNSPECIFIED'} for RoundingModes.
if ispc
libExt = 'lib';
elseif ismac
libExt = 'dylib';
else
libExt = 'so';
end
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 100, ...
'ImplementationName', 'dgemm32', ...
'ImplementationHeaderFile', 'blascompat32_crl.h', ...
'ImplementationHeaderPath', fullfile('$(MATLAB_ROOT)','extern','include'), ...
'AdditionalLinkObjs', {['libmwblascompat32.' libExt]}, ...
'AdditionalLinkObjsPaths', {LibPath}, ...
'SideEffects', true);
6 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. To specify a matrix argument in the function call, use the argument
class RTW.TflArgMatrix and specify the base type and the dimensions for which
the argument is valid. This type of table entry supports a range of dimensions
specified in the format [Dim1Min Dim2Min ... DimNMin; Dim1Max
Dim2Max ... DimNMax]. For example, [2 2; inf inf] means a two-dimensional
matrix of size 2x2 or larger. The conceptual output argument for the dgemm32 entry
for matrix/matrix multiplication replacement specifies dimensions [2 2; inf inf],
while the conceptual output argument for the dgemv32 entry for matrix/vector
multiplication replacement specifies dimensions [2 1; inf 1].

54-187
54 Code Replacement Customization for Simulink Models in Embedded Coder

% Specify operands and result


createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [1 1; inf inf]);
7 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the getTflArgFromString
and RTW.TflArgCharConstant functions to create the arguments. The example
code configures special implementation arguments that are required for dgemm and
dgemv function replacements. 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.
% Using RTW.TflBlasEntryGenerator for xgemm requires the following
% implementation signature:
%
% void f(char* TRANSA, char* TRANSB, int* M, int* N, int* K,
% type* ALPHA, type* u1, int* LDA, type* u2, int* LDB,
% type* BETA, type* y, int* LDC)
%
% When a match occurs, the code generator computes the
% values for M, N, K, LDA, LDB, and LDC and inserts them into the
% generated code. TRANSA and TRANSB are set to 'N'.

% Specify replacement function signature

arg = getTflArgFromString(hTable, 'y2', 'void');


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);

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);

arg = getTflArgFromString(hTable, 'M', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;

54-188
Matrix Multiplication Operation to MathWorks BLAS Code Replacement

op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'N', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'K', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'ALPHA', 'double', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u1', ['double' '*']);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2', ['double' '*']);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDB', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'BETA', 'double', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'y1', ['double' '*']);


arg.IOType = 'RTW_IO_OUTPUT';
arg.PassByType = 'RTW_PASSBY_POINTER';
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDC', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
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);

54-189
54 Code Replacement Customization for Simulink Models in Embedded Coder

9 Create the entry for the second mapping.


% Create table entry for dgemv32
op_entry = RTW.TflBlasEntryGenerator;
if ispc
libExt = 'lib';
elseif ismac
libExt = 'dylib';
else
libExt = 'so';
end
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 100, ...
'ImplementationName', 'dgemv32', ...
'ImplementationHeaderFile', 'blascompat32_crl.h', ...
'ImplementationHeaderPath', fullfile('$(MATLAB_ROOT)','extern','include'), ...
'AdditionalLinkObjs', {['libmwblascompat32.' libExt]}, ...
'AdditionalLinkObjsPaths', {LibPath},...
'SideEffects', true);

% Specify operands and result


createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [2 1; inf 1]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [1 1; inf 1]);

% Using RTW.TflBlasEntryGenerator for xgemv requires the following


% implementation signature:
%
% void f(char* TRANS, int* M, int* N,
% type* ALPHA, type* u1, int* LDA, type* u2, int* INCX,
% type* BETA, type* y, int* INCY)
%
% Upon a match, the CRL entry will compute the
% values for M, N, LDA, INCX, and INCY, and insert them into the
% generated code. TRANS will be set to 'N'.

% Specify replacement function signature

arg = getTflArgFromString(hTable, 'y2', 'void');


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);

arg = RTW.TflArgCharConstant('TRANS');
arg.PassByType = 'RTW_PASSBY_POINTER';

54-190
Matrix Multiplication Operation to MathWorks BLAS Code Replacement

op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'M', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'N', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'ALPHA', 'double', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u1', ['double' '*']);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2', ['double' '*']);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'INCX','integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'BETA', 'double', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'y1', ['double' '*']);


arg.IOType = 'RTW_IO_OUTPUT';
arg.PassByType = 'RTW_PASSBY_POINTER';
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'INCY', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
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.

To test this example:

1 Register the code replacement mapping.


2 Create a model that includes two Product blocks.

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

• “Define Code Replacement Mappings” on page 54-43


• “Small Matrix Operation to Processor Code Replacement” on page 54-182
• “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-193
54 Code Replacement Customization for Simulink Models in Embedded Coder

Matrix Multiplication Operation to ANSI/ISO C BLAS Code


Replacement
This example shows how to define code replacement mappings that replace nonscalar
multiplication operations with ANSI/ISO C BLAS multiplication functions xgemm and
xgemv. The example defines code replacement entries that map floating-point matrix/
matrix and matrix/vector multiplication operations to ANSI/ISO C BLAS library
multiplication functions dgemm and dgemv. The example defines the function mappings
programmatically. Alternatively, you can use the Code Replacement Tool to define the
same mappings.

BLAS libraries support matrix/matrix multiplication in the form of


C = a(op(A) * op(B)) + bC . op(X) means X, transposition of X, or Hermitian transposition
of X. However, code replacement libraries support only the limited case of
C = op(A) * op(B) (a = 1.0, b = 0.0) . Correspondingly, although BLAS libraries support
matrix/vector multiplication in the form of y = a(op(A) * x) + by , code replacement
libraries support only the limited case of y = op(A) * x (a = 1.0, b = 0.0) .
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_cblas_mmult_double
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Define the path for the CBLAS function library. For example:
LibPath = fullfile(matlabroot, 'toolbox', 'rtw', 'rtwdemos', 'crl_demo');
4 Create an entry for the first mapping with a call to the
RTW.TflBlasEntryGenerator function.
% Create table entry for cblas_dgemm
op_entry = RTW.TflCBlasEntryGenerator;
5 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The function call sets matrix
multiplication operator entry properties. The code generator ignores saturation and
rounding modes for floating-point nonscalar addition and subtraction.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...

54-194
Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement

'Priority', 100, ...


'ImplementationName', 'cblas_dgemm', ...
'ImplementationHeaderFile', 'cblas.h', ...
'ImplementationHeaderPath', LibPath, ...
'AdditionalIncludePaths', {LibPath}, ...
'GenCallback', 'RTW.copyFileToBuildDir', ...
'SideEffects', true);
6 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. To specify a matrix argument in the function call, use the argument
class RTW.TflArgMatrix and specify the base type and the dimensions for which
the argument is valid. This type of table entry supports a range of dimensions
specified in the format [Dim1Min Dim2Min ... DimNMin; Dim1Max
Dim2Max ... DimNMax]. For example, [2 2; inf inf] means a two-dimensional
matrix of size 2x2 or larger. The conceptual output argument for the dgemm32 entry
for matrix/matrix multiplication replacement specifies dimensions [2 2; inf inf].
The conceptual output argument for the dgemv32 entry for matrix/vector
multiplication replacement specifies dimensions [2 1; inf 1].
% Specify operands and result
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [1 1; inf inf]);
7 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. The example code configures special
implementation arguments that are required for dgemm and dgemv function
replacements. 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.
% Using RTW.TflCBlasEntryGenerator for xgemm requires the following
% implementation signature:
%
% void f(enum ORDER, enum TRANSA, enum TRANSB, int M, int N, int K,
% type ALPHA, type* u1, int LDA, type* u2, int LDB,
% type BETA, type* y, int LDC)

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.

% Specify replacement function signature

arg = getTflArgFromString(hTable, 'y2', 'void');


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);

arg = getTflArgFromString(hTable, 'ORDER', 'integer', 102);


% arg.Type.ReadOnly=true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'TRANSA', 'integer', 111);


% arg.Type.ReadOnly=true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'TRANSB', 'integer', 111);


% arg.Type.ReadOnly=true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'M', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'N', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'K', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'ALPHA', 'double', 1);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u1', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDB', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'BETA', 'double', 0);


op_entry.Implementation.addArgument(arg);

54-196
Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement

arg = getTflArgFromString(hTable, 'y1', ['double' '*']);


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDC', 'integer', 0);


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 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);

% Specify operands and result


createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [2 1; inf 1]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [1 1; inf 1]);

% Using RTW.TflCBlasEntryGenerator for xgemv requires the following


% implementation signature:
%
% void f(enum ORDER, enum TRANSA, int M, int N,
% type ALPHA, type* u1, int LDA, type* u2, int INCX,
% type BETA, type* y, int INCY)
%
% 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.)
%
% Upon a match, the CRL entry will compute the
% values for M, N, LDA, INCX, and INCY and insert them into the
% generated code.

54-197
54 Code Replacement Customization for Simulink Models in Embedded Coder

% Specify replacement function signature

arg = getTflArgFromString(hTable, 'y2', 'void');


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);

arg = getTflArgFromString(hTable, 'ORDER', 'integer', 102);


% arg.Type.ReadOnly=true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'TRANSA', 'integer', 111);


% arg.Type.ReadOnly=true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'M','integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'N', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'ALPHA', 'double', 1);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u1', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'INCX', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'BETA', 'double', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'y1', ['double' '*']);


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'INCY', 'integer', 0);


op_entry.Implementation.addArgument(arg);

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:

1 Register the code replacement mapping.

54-198
See Also

2 Create a model that includes two Product blocks.

3 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.
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

• “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-200
Remap Operator Output to Function Input

Remap Operator Output to Function Input


If your generated code must meet a specific coding pattern or you want more flexibility,
for example, to further improve performance, you can remap operator outputs to input
positions in an implementation function argument list.

Note Remapping outputs to implementation function inputs is supported only for


operator replacement.

For example, for a sum operation, the code generator produces code similar to:

add8_Y.Out1 = u8_add_u8_u8(add8_U.In1, add8_U.In2);

If you remap the output to the first input, the code generator produces code similar to:

u8_add_u8_u8(&add8_Y.Out1;, add8_U.In1, add8_U.In2);

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:

function hTable = crl_table_add_uint8


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


op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. In the function call, set the
property SideEffects to true.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 90, ...
'ImplementationName', 'u8_add_u8_u8', ...
'ImplementationHeaderFile', 'u8_add_u8_u8.h', ...
'ImplementationSourceFile', 'u8_add_u8_u8.c', ...
'SideEffects', true );

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);

arg = getTflArgFromString(hTable, 'u1', 'uint8');


addConceptualArg(op_entry, arg );

arg = getTflArgFromString(hTable, 'u2', 'uint8');


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);

arg=getTflArgFromString(hTable, 'u1', 'uint8');


op_entry.Implementation.addArgument(arg);

arg=getTflArgFromString(hTable, 'u2', 'uint8');


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:

1 Register the code replacement mapping.

54-202
See Also

2 Create a model that includes an Add block.

3 Configure the model with the following settings:

• On the Solver pane, select a fixed-step solver.


• 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.
• Set the Optimize global data access parameter to Use global to hold
temporary results to reduce data copies in the generated code.
4 Generate code and a code generation report.
5 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
• “Develop a Code Replacement Library” on page 54-27

54-203
54 Code Replacement Customization for Simulink Models in Embedded Coder

Fixed-Point Operator Code Replacement


If you have a Fixed-Point Designer license, you can define fixed-point operator code
replacement entries to match:

• A binary-point-only scaling combination on the operator inputs and output.


• A slope bias scaling combination on the operator inputs and output.
• Relative scaling or net slope between multiplication or division operator inputs and
output. Use one of these methods to map a range of slope and bias values to a
replacement function for multiplication or division.
• Equal slope and zero net bias across addition or subtraction operator inputs and
output. Use this method to disregard specific slope and bias values and map relative
slope and bias values to a replacement function for addition or subtraction.

Common Ways to Match Fixed-Point Operator Entries


The following table maps common ways to match fixed-point operator code replacement
entries with the associated fixed-point parameters that you specify in a code replacement
table definition file.

Match Create entry Minimally specify parameters


A specific binary-point-only RTW.TflCOperationEntry createAndAddConceptualArg
scaling combination on the function:
operator inputs and
output. • CheckSlope: Specify the value
true.
• CheckBias: Specify the value true.
• DataTypeMode (or DataType/
Scaling equivalent): Specify fixed-
point binary-point-only scaling.
• FractionLength: Specify a
fraction length (for example, 3).

54-204
Fixed-Point Operator Code Replacement

Match Create entry Minimally specify parameters


A specific slope bias RTW.TflCOperationEntry createAndAddConceptualArg
scaling combination on the function:
operator inputs and
output. • CheckSlope: Specify the value
true.
• CheckBias: Specify the value true.
• DataTypeMode (or DataType/
Scaling equivalent): Specify fixed-
point [slope bias] scaling.
• Slope (or
SlopeAdjustmentFactor/
FixedExponent equivalent):
Specify a slope value (for example,
15).
• Bias: Specify a bias value (for
example, 2).
Net slope between RTW.TflCOperationEntry‐ setTflCOperationEntryParameter
operator inputs and output Generator_NetSlope s function:
(multiplication and
division). • NetSlopeAdjustmentFactor:
Specify the slope adjustment factor
(F) part of the net slope, F2E (for
example, 1.0).
• NetFixedExponent: Specify the
fixed exponent (E) part of the net
slope, F2E (for example, -3.0).

createAndAddConceptualArg
function:

• CheckSlope: Specify the value


false.
• CheckBias: Specify the value
false.
• DataType: Specify the value
'Fixed'.

54-205
54 Code Replacement Customization for Simulink Models in Embedded Coder

Match Create entry Minimally specify parameters


Relative scaling between RTW.TflCOperationEntry‐ setTflCOperationEntryParameter
operator inputs and output Generator s function:
(multiplication and
division). • RelativeScalingFactorF:
Specify the slope adjustment factor
(F) part of the relative scaling factor,
F2E (for example, 1.0).
• RelativeScalingFactorE:
Specify the fixed exponent (E) part
of the relative scaling factor, F2E (for
example, -3.0).

createAndAddConceptualArg
function:

• CheckSlope: Specify the value


false.
• CheckBias: Specify the value
false.
• DataType: Specify the value
'Fixed'.
Equal slope and zero net RTW.TflCOperationEntry‐ setTflCOperationEntryParameter
bias across operator inputs Generator s function:
and output (addition and
subtraction). • SlopesMustBeTheSame: Specify
the value true.
• MustHaveZeroNetBias: Specify
the value true.

createAndAddConceptualArg
function:

• CheckSlope: Specify the value


false.
• CheckBias: Specify the value
false.

54-206
Fixed-Point Operator Code Replacement

Fixed-Point Numbers and Arithmetic


Fixed-point numbers use integers and integer arithmetic to represent real numbers and
arithmetic with the following encoding scheme:

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:

( SOQO + BO ) = ( S1Q1 + B1 ) < op > ( S2Q2 + B2 )


The objective of fixed-point operator replacement is to replace an operator that accepts
and returns fixed-point or integer inputs and output with a function that accepts and
returns built-in C numeric data types. The following sections provide additional
programming information for each supported operator.

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.

The operation V0 = V1 * V2 implies, for binary-point-only scaling, that

S0Q0 = ( S1Q1 )( S 2Q2 )


ÊSS ˆ
Q0 = Á 1 2 ˜ Q1Q2
Ë S0 ¯
Q0 = SnQ1Q2

where Sn is the net slope.

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.)

Note When an operator entry specifies NetSlopeAdjustmentFactor and


NetFixedExponent, matching entries must have arguments with zero bias.

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

The operation V0 = (V1 / V2) implies, for binary-point-only scaling, that

ÊSQ ˆ
S0Q0 = Á 1 1 ˜
Ë S2Q2 ¯
ÊQ ˆ
Q0 = S n Á 1 ˜
Ë Q2 ¯

where Sn is the net slope.

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.)

Note When an operator entry specifies NetSlopeAdjustmentFactor and


NetFixedExponent, matching entries must have arguments with zero bias.

Data Type Conversion (Cast)


The data type conversion operation V0 = V1 implies, for binary-point-only scaling, that

Ê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

• “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-212
Binary-Point-Only Scaling Code Replacement

Binary-Point-Only Scaling Code Replacement


You can define code replacement entries for operations on fixed-point data types such that
they match a binary-point-only scaling combination on operator inputs and output. These
binary-point-only scaling entries can map the specified binary-point-scaling combination
to a replacement function for addition, subtraction, multiplication, or division.

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:

function hTable = crl_table_fixed_binptscale


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 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);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 15);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 13);

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.

To test this example:

1 Register the code replacement mapping.


2 Create a model.

3 For this model:

• Set the Inport 1 Data type to fixdt(1,16,15).


• Set the Inport 2 Data type to fixdt(1,16,13).
• In the Product block:

• Set Output data type to fixdt(1,32,28).


• Select the option Saturate on integer overflow.
4 Configure the model with the following settings:

• On the Solver pane, select a fixed-step, discrete solver.


• 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 Generate code and a code generation report.

54-215
54 Code Replacement Customization for Simulink Models in Embedded Coder

6 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
• “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

Slope Bias Scaling Code Replacement


You can define code replacement for operations on fixed-point data types as matching a
slope bias scaling combination on the operator inputs and output. The slope bias scaling
entries can map the specified slope bias combination to a replacement function for
addition, subtraction, multiplication, or division.

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

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: slope and bias scaling', ...
'IsSigned', true, ...
'WordLength', 16, ...
'Slope', 15, ...
'Bias', 2);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: slope and bias scaling', ...
'IsSigned', true, ...
'WordLength', 16, ...
'Slope', 15, ...
'Bias', 2);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: slope and bias scaling', ...
'IsSigned', true, ...
'WordLength', 16, ...
'Slope', 13, ...
'Bias', 5);
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);

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.

To test this example:

1 Register the code replacement mapping.


2 Create a model.

3 For this model:

• Set the Inport 1 Data type to fixdt(1,16,15,2).


• Set the Inport 2 Data type to fixdt(1,16,13,5).
• In the Divide block:

• Set Output data type to Inherit: Inherit via back propagation.


• Set Integer rounding mode to Ceiling.
• Select the option Saturate on integer overflow.
4 Configure the model with the following settings:

• On the Solver pane, select a fixed-step, discrete solver.


• 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.

54-219
54 Code Replacement Customization for Simulink Models in Embedded Coder

5 Generate code and a code generation report.


6 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
• “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

Net Slope Scaling Code Replacement

Multiplication and Division with Saturation


You can define code replacement entries for operations on fixed-point data types as
matching net slope between operator inputs and output. The net slope entries can map a
range of slope and bias values to a replacement function for multiplication or division.

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:

function hTable = crl_table_fixed_netslopesaturate


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.
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);

arg = getTflArgFromString(hTable, 'u1', typeStrBase(dtnum));


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2',typeStrBase(dtden));


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 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.

Multiplication and Division with Rounding Mode and


Additional Implementation Arguments
You can define code replacement entries for multiplication and division operations on
fixed-point data types such that they match the net slope between operator inputs and
output. The net slope entries can map a range of slope and bias values to a replacement
function for multiplication or division.

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:

function hTable = crl_table_fixed_netsloperound


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;
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

'ImplementationName', 's16_div_s16_s16', ...


'ImplementationHeaderFile', 's16_div_s16_s16.h', ...
'ImplementationSourceFile', 's16_div_s16_s16.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, 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);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataType', 'Fixed', ...
'IsSigned', true, ...
'WordLength', 16);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'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.

To test this example:

1 Register the code replacement mapping.


2 Create a model.

3 For this model:

• Set the Inport 1 Data type to int16.


• Set the Inport 2 Data type to fixdt(1,16,-5).
• In the Divide block:

• Set Output data type to fixdt(1,16,-13).


• Set Integer rounding mode to Ceiling.
4 Configure the model with the following settings:

• On the Solver pane, select a fixed-step, discrete solver.

54-226
See Also

• 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 Generate code and a code generation report.
6 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
• “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

Equal Slope and Zero Net Bias Code Replacement


You can define code replacement entries for addition or subtraction of fixed-point data
types such that they match relative slope and bias values (equal slope and zero net bias)
across operator inputs and output. These entries allow you to disregard slope and bias
values. Map relative slope and bias values to a replacement function for addition or
subtraction.

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

createAndAddConceptualArg function to create and add an argument with one


function call. Each argument is specified as 16 bits and unsigned. 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, ...
'IsSigned', false, ...
'WordLength', 16);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'IsSigned', false, ...
'WordLength', 16);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'IsSigned', false, ...
'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 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

'Name', 'u2', ...


'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'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.

To test this example:

1 Register the code replacement mapping.


2 Create a model.

3 For this model:

• Set the Inport 1 Data type to fixdt(0,16,13).


• Set the Inport 2 Data type to fixdt(0,16,13).
• In the Add block:

• 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:

• On the Solver pane, select a fixed-step, discrete solver.


• 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 Generate code and a code generation report.
6 Review the code replacements.

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

Data Type Conversions (Casts) and Operator Code


Replacement
You can use code replacement entries to replace code that the code generator produces
for data type conversion (cast) operations.

Casts from int32 To int16


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:

function hTable = crl_table_cast_int32_to_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 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');

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

54-232
Data Type Conversions (Casts) and Operator Code Replacement

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 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.

Casts Using Net Slope


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:
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

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_fxp_cast. 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_CAST', ...
'Priority', 50, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_FLOOR'}, ...
'NetSlopeAdjustmentFactor', 1.0, ...
'NetFixedExponent', (OutFL - InFL), ...
'ImplementationName', 'my_fxp_cast', ...
'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);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', InSgn, ...
'WordLength', InWL, ...
'FractionLength',InFL);

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

Shift Left Operations and Code Replacement


You can use code replacement entries to replace code that the code generator produces
for shift (<<) operations.

Shift Lefts for int16 Data


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);

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);

• The function getTflArgFromString is called to create an int8 input argument. This


argument is added to the operator entry both as the third conceptual argument and
the second implementation input argument.
• Add the entry to a code replacement table with a call to the addEntry function.

addEntry(hTable, op_entry);
• Save the table definition file. Use the name of the table definition function to name the
file.

Shift Lefts Using Net Slope


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:

function hTable = crl_table_shift_left_fixpt_net_slope

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

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', InSgn, ...
'WordLength', InWL, ...
'FractionLength',InFL);

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 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

Code Replacement Customization


for MATLAB Code

• “What Is Code Replacement Customization?” on page 55-3


• “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
• “Identify Code Replacement Requirements” on page 55-25
• “Prepare for Code Replacement Library Development” on page 55-28
• “Define Code Replacement Mappings” on page 55-29
• “Specify Build Information for Replacement Code” on page 55-47
• “Register Code Replacement Mappings” on page 55-56
• “Troubleshoot Code Replacement Library Registration” on page 55-64
• “Verify Code Replacements” on page 55-65
• “Troubleshoot Code Replacement Misses” on page 55-74
• “Deploy Code Replacement Library” on page 55-78
• “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
• “Data Alignment for Code Replacement” on page 55-88
• “Array Layout and Code Replacement” on page 55-102
• “Replace MATLAB Functions with Custom Code Using coder.replace” on page 55-105
• “Replace coder.ceval Calls to External Functions” on page 55-106
• “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
55 Code Replacement Customization for MATLAB Code

• “Small Matrix Operation to Processor Code Replacement” on page 55-128


• “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
• “Fixed-Point Operator Code Replacement” on page 55-149
• “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-2
What Is Code Replacement Customization?

What Is Code Replacement Customization?


Customize how and when the code generator replaces C/C++ code that it generates by
default for functions and operators by developing a custom code replacement library. You
can develop libraries interactively with the Code Replacement Tool or
programmatically.

• Develop libraries tailored to specific application requirements


• Add identifiers to the list of reserved keywords the code generator considers during
code replacement
• Customize the code generator’s match and replacement process for functions

To get started, “Quick Start Code Replacement Library Development - Simulink®” on


page 54-28.

Code Replacement Match and Replacement Process


When the code generator encounters a call site for a function or operator, it:

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:

• Conceptual name or key


• Arguments, including quantity, type, type qualifiers, and complexity
• Algorithm (computation method)
• Fixed-point saturation and rounding modes
• Priority
3 When a match exists, the code generator returns a code replacement object, fully
populated with the conceptual representation, implementation representation, and
priority. If the code generator finds multiple matches within a table, the entry priority
determines the match. The priority can range from 0 to 100. The highest priority is 0.
The code generator uses a higher-priority entry over a similar entry with a lower
priority.

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.

Code Replacement Customization Limitations


• Code replacement verification — It is possible that code replacement behaves
differently than you expect. For example, data types that you observe in code
generator input might not match what the code generator uses as intermediate data
types during an operation. Verify code replacements by examining generated code.
See “Verify Code Replacements” on page 55-65.
• Tokens in file paths—You can include tokens in file paths when specifying build
information for a code replacement entry by using the programming interface only.
The ability to include tokens is not available from the Code Replacement Tool. See
“Specify Build Information for Replacement Code” on page 55-47.
• Addition and subtraction operation replacements—See “Addition and Subtraction
Operator Code Replacement” on page 55-123for relevant limitations.
• coder.replace function — See coder.replace for relevant limitations.
• coder.dataAlignment function — See coder.dataAlignment for relevant
limitations.

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

Code You Can Replace from MATLAB Code


Code that the code generator replaces depends on the code replacement library (CRL)
that you use. By default, the code generator does not apply a code replacement library.
Your choice of libraries is dependent on product licensing and whether you have access to
custom libraries.

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.

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
abs1 Floating point Scalar Real
acos Floating point Scalar Real
Vector Complex
Matrix Complex input/complex output
Real input/complex output
acosd Floating point Scalar Real
Vector Complex
Matrix
acot Floating point Scalar Real
Vector Complex
Matrix
acotd Floating point Scalar Real
Vector Complex
Matrix

55-5
55 Code Replacement Customization for MATLAB Code

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
acoth Floating point Scalar Real
Vector Complex
Matrix
acsc Floating point Scalar Real
Vector Complex
Matrix
acscd Floating point Scalar Real
Vector Complex
Matrix
acsch Floating point Scalar Real
Vector Complex
Matrix
asec Floating point Scalar Real
Vector Complex
Matrix
asecd Floating point Scalar Real
Vector Complex
Matrix
asech Floating point Scalar Real
Vector Complex
Matrix
asin Floating point Scalar Real
Vector Complex
Matrix Complex input/complex output
Real input/complex output
asind Floating point Scalar Real
Vector Complex
Matrix
atan Floating point Scalar Real
Vector Complex
Matrix Complex input/complex output
Real input/complex output

55-6
Code You Can Replace from MATLAB Code

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
atan2 Floating point Scalar Real
Vector
Matrix
atan2d Floating point Scalar Real
Vector
Matrix
atand Floating point Scalar Real
Vector Complex
Matrix
cos Floating point Scalar Real
Vector Complex
Matrix Complex input/complex output
Real input/complex output
ceil • Floating-point • Floating-point • Floating-point
• Scalar • Scalar • Scalar
cosd Floating point Scalar Real
Vector Complex
Matrix
cosh Floating point Scalar Real
Vector Complex
Matrix Complex input/complex output
Real input/complex output
cot Floating point Scalar Real
Vector Complex
Matrix
cotd Floating point Scalar Real
Vector Complex
Matrix
coth Floating point Scalar Real
Vector Complex
Matrix

55-7
55 Code Replacement Customization for MATLAB Code

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
csc Floating point Scalar Real
Vector Complex
Matrix
cscd Floating point Scalar Real
Vector Complex
Matrix
csch Floating point Scalar Real
Vector Complex
Matrix
exp Floating point Scalar Real
fix Floating point Scalar Real
floor • Floating-point • Floating-point • Floating-point
• Scalar • Scalar • Scalar
hypot Floating point Scalar Real
Vector
Matrix
ldexp Floating point Scalar Real
log Floating point Scalar Real
Vector Complex
Matrix
log10 Floating point Scalar Real
Vector Complex
Matrix
log2 Floating point Scalar Real
Vector Complex
Matrix
max Integer Scalar Real
Floating point
min Integer Scalar Real
Floating point
pow Floating point Scalar Real

55-8
Code You Can Replace from MATLAB Code

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
rem Floating point Scalar Real
round Floating point Scalar Real
sec Floating point Scalar Real
Vector Complex
Matrix
secd Floating point Scalar Real
Vector Complex
Matrix
sech Floating point Scalar Real
Vector Complex
Matrix
sign Floating point Scalar Real
sin Floating point Scalar Real
Vector Complex
Matrix Complex input/complex output
Real input/complex output
sind Floating point Scalar Real
Vector Complex
Matrix
sinh Floating point Scalar Real
Vector Complex
Matrix Complex input/complex output
Real input/complex output
sqrt Floating point Scalar Real
tan Floating point Scalar Real
Vector Complex
Matrix Complex input/complex output
Real input/complex output
tand Floating point Scalar Real
Vector Complex
Matrix

55-9
55 Code Replacement Customization for MATLAB Code

Function Data Type Support Scalar, Vector, Real, Complex Support


Matrix Support
tanh Floating point Scalar Real
Vector Complex
Matrix Complex input/complex output
Real input/complex output
1
Wrap on integer overflow only

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.

Function Data Type Support Scalar, Vector, Real, Complex


Matrix Support Support
memcmp Void pointer (void*) Scalar Real
Vector Complex
Matrix
memcpy Void pointer (void*) Scalar Real
Vector Complex
Matrix
memset Void pointer (void*) Scalar Real
Vector Complex
Matrix
memset2zero Void pointer (void*) Scalar Real
Vector Complex
Matrix

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

generator to replace instances of the following operators with application-specific


implementations.

Mixed data type support indicates you can specify different data types of different inputs.

Operator Key Data Type Scalar, Real,


Support Vector, Complex
Matrix Support
Support
Addition (+)1 RTW_OP_ADD Integer Scalar Real
Floating point Vector Complex
Fixed-point Matrix
Mixed
Subtraction (-)1 RTW_OP_MINUS Integer Scalar Real
Floating point Vector Complex
Fixed-point Matrix
Mixed
Multiplication RTW_OP_MUL Integer Scalar Real
(*)2 Floating point Vector Complex
Fixed-point Matrix
Mixed
Division (/) RTW_OP_DIV Integer Scalar Real
Floating point Complex
Fixed-point
Mixed
Data type RTW_OP_CAST Integer Scalar Real
conversion (cast) Floating point3 Vector Complex
Fixed-point Matrix
Mixed
Shift left (<<) RTW_OP_SL Integer Scalar Real
Fixed-point Vector
Mixed Matrix
Shift right RTW_OP_SRA Integer Scalar Real
arithmetic (>>)4 Fixed-point Vector
Mixed Matrix

55-11
55 Code Replacement Customization for MATLAB Code

Operator Key Data Type Scalar, Real,


Support Vector, Complex
Matrix Support
Support
Shift right logical RTW_OP_SRL Integer Scalar Real
(>>) Fixed-point Vector
Mixed Matrix
Element-wise RTW_OP_ELEM_MUL Integer Vector Real
matrix Floating point Matrix Complex
multiplication Fixed-point
(.*)5 Mixed
Complex RTW_OP_CONJUGATE Integer Scalar Real
conjugation Floating point Vector Complex
Fixed-point Matrix
Mixed
Transposition RTW_OP_TRANS Integer Vector Real
(.') Floating point Matrix Complex
Fixed-point
Mixed
Hermitian RTW_OP_HERMITIAN Integer Vector Real
(complex Floating point Matrix Complex
conjugate) Fixed-point
transposition (') Mixed
Multiplication RTW_OP_TRMUL Integer Vector Real
with Floating point Matrix Complex
transposition2 Fixed-point
Mixed
Multiplication RTW_OP_HMMUL Integer Vector Real
with Hermitian Floating point Matrix Complex
transposition2 Fixed-point
Mixed
Multiplication RTW_OP_MUL_SRA Integer Scalar Real
followed by shift Fixed-point
right arithmetic
(u1*u2>>u3)6

55-12
Code You Can Replace from MATLAB Code

Operator Key Data Type Scalar, Real,


Support Vector, Complex
Matrix Support
Support
Multiplication RTW_OP_MULDIV Integer Scalar Real
followed by Fixed-point
division
(u1*u2/u3)7
Greater than (>) RTW_OP_GREATER_ Integer Scalar Real
THAN Floating point Vector Complex
Fixed-point Matrix
Mixed
Greater than or RTW_OP_GREATER_ Integer Scalar Real
equal (>=) THAN_OR_EQUAL Floating point Vector Complex
Fixed-point Matrix
Mixed
Less than (<) RTW_OP_LESS_THAN Integer Scalar Real
Floating point Vector Complex
Fixed-point Matrix
Mixed
Less than or RTW_OP_LESS_THAN_ Integer Scalar Real
equal (<=) OR_EUQAL Floating point Vector Complex
Fixed-point Matrix
Mixed
Equal (==) RTW_OP_EUQAL Integer Scalar Real
Floating point Vector Complex
Fixed-point Matrix
Mixed
Not equal (!=) RTW_OP_NOT_EUQAL Integer Scalar Real
Floating point Vector Complex
Fixed-point Matrix
Mixed

55-13
55 Code Replacement Customization for MATLAB Code

Operator Key Data Type Scalar, Real,


Support Vector, Complex
Matrix Support
Support
1
See “Addition and Subtraction Operator Code Replacement” on page 55-123 for details
to consider when defining mappings for addition and subtraction code replacements.
2
Can map to Basic Linear Algebra Subroutine (BLAS) multiplication functions.
3
Scaled floating point is not supported.
4
Code replacement libraries that provide arithmetic shift right implementations should
also provide logical shift right implementations, because some arithmetic shift rights are
converted to logical shift rights during code generation.
5
Use the multiplication (*) operator (RTW_OP_MUL) for scalar multiplication.
6
Requires scalar, real, or fixed-point data types with zero bias; output type of the
multiplication operation to accommodate all possible output values; shift operand is an
unsigned integer; and net slope is equal to 1 (U1_slope * U2_slope ==
Mul_output_slope and Mul_output_slope ==
output_slope_of_shift_operation).
7
Requires scalar, real, or fixed-point data types with zero bias; output type of the
multiplication operation to accommodate all possible output values; and net slope is
equal to 1 (U1_slope * U2_slope == Mul_output_slope == U3_slope *
Div_output_slope).

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

Develop a Code Replacement Library


Iterate through the following steps, as necessary, to develop a code replacement library:

1 “Identify Code Replacement Requirements” on page 55-25


2 “Prepare for Code Replacement Library Development” on page 55-28
3 “Define Code Replacement Mappings” on page 55-29
4 “Specify Build Information for Replacement Code” on page 55-47
5 “Register Code Replacement Mappings” on page 55-56
6 “Verify Code Replacements” on page 55-65
7 “Deploy Code Replacement Library” on page 55-78

To get started, see “Identify Code Replacement Requirements” on page 55-25.

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

Quick Start Library Development


This example shows how to develop a code replacement library that includes an entry for
generating replacement code for the math function sin. You use the Code Replacement
Tool.

Prerequisites

To complete this example, install the following software:

• MATLAB
• MATLAB Coder
• Embedded Coder
• C compiler

For instructions on installing MathWorks products, see “Installation and Activation”


(Installation, Licensing, and Activation). If you have installed MATLAB and want to see
what other MathWorks products are installed, in the Command Window, enter ver.

For a list of supported compilers, see https://www.mathworks.com/support/


compilers/current_release/.

Open the Code Replacement Tool

1 Start a new MATLAB session.


2 Create or navigate (cd) to an empty folder.
3 At the command prompt, enter the crtool command. The Code Replacement Tool
window opens.

Create Code Replacement Table

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 Table Entry

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.

The following figure shows the completed mapping information.

55-18
Quick Start Library Development

55-19
55 Code Replacement Customization for MATLAB Code

Specify Build Information for Replacement 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 Another Table 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.

1 In the middle pane, select the sin_dbl entry.


2 Select Edit > Copy
3 Select Edit > Paste
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.
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.

Validate the Code Replacement Table

1 Select Actions > Validate table.

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

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.

Review the Code Replacement Table Definition

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.

Generate a Registration File

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.

Register the Code Replacement Table

At the command prompt, enter:

RTW.TargetRegistry.getInstance('reset');

Review and Test Code Replacements

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 =

TflTable with properties:

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:

crviewer('Sin Function 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:

• Incorrect argument order.


• Conceptual argument names that do not match what is expected by the code
generator.

55-22
Quick Start Library Development

• Incorrect priority settings.


3 Identify existing or create new MATLAB code that calls the sin function. For
example:

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

Identify Code Replacement Requirements


The first step to developing a code replacement library is to consider the following types
of requirements for your code replacement library.

Mapping Information Requirements


• Are you defining a code replacement mapping for the first time?
• Are you updating code replacement entries in an existing library? Or, are you creating
a new library?
• Are you rapid prototyping code replacements?
• Can you base your mappings on existing mappings?
• What type of code do you want to replace? Options include:

• 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?

• What is the replacement function name?


• What are the input and output arguments?
• Are there return values?
• What is the data type, complexity, and dimensionality of each argument and return
value?

55-25
55 Code Replacement Customization for MATLAB Code

Build Information Requirements


• Does your replacement function implementation require a header file? If yes, specify
the header file.
• If the replacement function implementation requires a header file, what is the path for
that file?
• Is the source file for the replacement function in your working folder? If not, you can
explicitly specify the source file name and extension. For example, if the file is
required in the generated makefile or specified in a build information object, specify
the source file.
• Does the replacement function use additional include files? If yes, what are they and
what are the paths for those files?
• Does the replacement function use additional source files? If yes, what are they and
what are the paths for those files?
• What compiler flags are required for compiling code that includes the replacement
code?
• What linker flags are required for building an executable that includes the
replacement code?
• Are the required header, source, and object files for building an executable that
includes your replacement code in the working folder for your project? If not, before
starting the build process, do you want the code generator to copy required files to the
build folder?

Registration Information Requirements


• What do you want to name your code replacement library?
• What code replacement tables do you want to include in the library? What are the file
names and paths for the tables?
• What is the purpose of the library? You can document the purpose as the library
description.
• Does the library apply to specific hardware devices? If yes, what devices?
• Are you developing a hierarchy of code replacement libraries? Is the library that you
are developing based (dependent) on another library? For example, you can specify a
general TI device library as the base library for a more specific TI C28x device
library.

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?

Next, prepare for developing a library by reviewing a code replacement library


development checklist.

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

Prepare for Code Replacement Library Development


After you identify your code replacement requirements, prepare for library development
by reviewing this checklist:

• Get familiar with the library development process.


• Decide whether to define code replacement mappings and produce a registration file
interactively with the Code Replacement Tool or programmatically.
• Identify or develop MATLAB code and Simulink models to test your code replacement
library.
• Consider the hierarchy and organization of your library. A library can consist of
multiple tables and each table can include multiple entries. How do you want to
organize the library to optimize reuse of tables and entries? For example, a
registration file can define code replacement tables organized in a hierarchy of code
replacement libraries based on entries that increase in specificity:

• 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

Define Code Replacement Mappings


After you prepare for library development, use your requirements to define code
replacement mappings. A code replacement mapping associates a conceptual
representation of a function or operator that is familiar to the code generator with a
custom implementation representation that specifies a C or C++ replacement function
prototype. You capture a mapping as an entry in a code replacement table:

• Interactively, by using the Code Replacement Tool.


• Programmatically, by using a MATLAB programming interface.

Choose an Approach for Defining Code Replacement Mappings


The following table lists situations to help you decide when to use the interactive or
programmatic approach.

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

Define Mappings Interactively with the Code Replacement


Tool
This example shows how to use the Code Replacement Tool to develop code replacement
mappings. The tool is ideal for getting started with developing mappings, rapid
prototyping, and developing a mapping to use as a starting point for defining similar
mappings.

Open the Code Replacement Tool

Do one of the following:

• In the Command Window, enter the command crtool.


• In the Configuration Parameters dialog box, navigate to Code Generation pane. In
the Advanced parameters section, scroll down and click Custom CRL... button.

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.)

Create a Code Replacement Table

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 Table Entries

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:

• Integer saturation mode


• Rounding modes
• Whether to allow inputs that include expressions
• Whether a function modifies internal or global state
9 Click Apply.

Validate Tables and Entries

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

When you save a table, the tool validates unvalidated content.


1 Select File > Save table.
2 In the Browse For Folder dialog box, specify a location and name for the file.
Typically, you select a location on the MATLAB path. By default, the tool names the
file using the name that you specify for the table with the extension .m.
3 Click Save.

Open and Modify Tables

After saving a code replacement table, to make changes in the table:


1 Select File > Open table.
2 In the Import file dialog box, browse to the MATLAB file that contains the table.

Repeat the sequence to open and work on multiple tables.

If you open multiple tables, you can manage the tables together. For example, use the tool
to:

• Create new table entries.


• Delete entries.
• Copy and paste or cut and paste information between tables.

Define Mappings Programmatically


This example shows how to define a code replacement mapping programmatically. The
programming interface for defining code replacement table mappings is ideal for

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.

Steps for defining a mapping programmatically are:

• “Create Code Replacement Table” on page 55-34


• “Create Table Entry” on page 55-34
• “Set Entry Parameters” on page 55-36
• “Create Conceptual Arguments” on page 55-38
• “Create Implementation Arguments” on page 55-40
• “Add Entry to Table” on page 55-44
• “Validate Entry” on page 55-44
• “Save Table” on page 55-45

Create Code Replacement Table

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;

Create Table Entry

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.

Entry Type Function


Math operation RTW.TflCOperationEntry
Function RTW.TflCFunctionEntry
BLAS operation RTW.TflBlasEntryGenerator

55-34
Define Code Replacement Mappings

Entry Type Function


CBLAS operation RTW.TflCBlasEntryGenerator
Fixed-point addition and RTW.TflCOperationEntryGenerator
subtraction operations
(support for
SlopesMustBeTheSame and
MustHaveZeroNetBias
parameters)
Net slope fixed-point RTW.TflCOperationEntryGenerator_NetSlo
operation pe
Semaphore or mutex entry RTW.TflCSemaphoreEntry
Custom function entry MyCustomFunctionEntry (where
MyCustomFunctionEntry is a class derived
from RTW.TflCFunctionEntryML)
Custom operation entry MyCustomOperationEntry (where
MyCustomOperationEntry is a class derived
from RTW.TflCOperationEntryML)

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:

• Return argument is y1.


• Input arguments are u1, u2, ..., un.

For example:

55-35
55 Code Replacement Customization for MATLAB Code

registerCFunctionEntry(hTable, 100, 1, 'sin', 'double', ...


'sin_dbl', 'double', 'sin_dbl.h','','');

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:

hEnt = createCRLEntry(hTable, ...


'double y1 = sin(double u1)', ...
'mySin');

This approach does not support:

• 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

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.

Entry Type Function


Math operation setTflCOperationEntryParameters
Function setTflCFunctionEntryParameters
BLAS operation setTflCOperationEntryParameters
CBLAS operation setTflCOperationEntryParameters

55-36
Define Code Replacement Mappings

Entry Type Function


Fixed-point addition and subtraction setTflCOperationEntryParameters
operations where there is a many-to-one
mapping, such as a mapping for a range of
fixed-point types to the same replacement
function (support for
SlopesMustBeTheSame and
MustHaveZeroNetBias parameters)
Net slope fixed-point operation setTflCOperationEntryParameters
Semaphore or mutex entry setTflCSemaphoreEntryParameters
Custom function entry setTflCFunctionEntryParameters
Custom operation entry setTflCOperationEntryParameters

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 =

TflCFunctionEntry with properties:

Implementation: [1x1 RTW.CImplementation]


SlopesMustBeTheSame: 0
BiasMustBeTheSame: 0
AlgorithmParams: []
ImplType: 'FCN_IMPL_FUNCT'
AdditionalHeaderFiles: {0x1 cell}
AdditionalSourceFiles: {0x1 cell}
AdditionalIncludePaths: {0x1 cell}
AdditionalSourcePaths: {0x1 cell}
AdditionalLinkObjs: {0x1 cell}
AdditionalLinkObjsPaths: {0x1 cell}
AdditionalLinkFlags: {0x1 cell}
AdditionalCompileFlags: {0x1 cell}
SearchPaths: {0x1 cell}
Key: ''
Priority: 100
ArrayLayout: 'COLUMN_MAJOR'
ConceptualArgs: [0x1 handle]
EntryInfo: []

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]

To see the implementation parameters, enter:


hEnt.Implementation

ans =

CImplementation with properties:

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

Create conceptual arguments and add them to the entry’s array of conceptual arguments.

• Specify output arguments before input arguments.


• Specify argument names that comply with code generator argument naming
conventions:

55-38
Define Code Replacement Mappings

• y1 for a return argument


• u1, u2, ..., un for input arguments
• Specify data types that are familiar to the code generator.
• The function signature, including argument naming, order, and attributes, must fulfill
the signature match sought by function or operator callers.
• The code generator determines the size of the value for an argument with an unsized
type, such as integer, based on hardware implementation configuration settings.

For each argument:

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');

The second argument specifies whether the argument


is scalar (RTW.TflArgNumeric
orRTW.TflArgMatrix) .

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

arg = getTflArgFromString(hEnt, 'y1','double');


arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(hEnt, arg);

arg = getTflArgFromString(hEnt, 'u1','double');


addConceptualArg(hEnt, arg);

Create Implementation Arguments

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.

For each argument:

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);

The following call to getTflArgFromString passes


the constant 0 to argument u2:

arg = getTflArgFromString(hEnt,...
'u2', 'int16', 0)
hEnt.Implementation.addArgument(arg);

For semaphore and mutex entries, use the functions


getTflDWorkFromString and addDWorkArg to
create and add a DWork argument to the entry. Then
create implementation arguments as shown above with
getTflArgFromString and the convenience methods
setReturn and addArgument. For example:

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);

Add Entry to Table

Add an entry to a code replacement table by calling the function addEntry.


addEntry(hTable, hEnt);

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

??? RTW_CORE:tfl:TflTable: Unsupported data type, 'dooble'.

Error in ==> crl_table_sinfcn at 7


hTable.registerCFunctionEntry(100, 1, 'sin', 'dooble', 'sin_dbl', ...

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

• “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 for Operators” on page 55-114
• “Fixed-Point Operator Code Replacement” on page 55-149
• “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
• Replacing Math Functions and Operators
• “Prepare for Code Replacement Library Development” on page 55-28
• “Specify Build Information for Replacement Code” on page 55-47
• “Develop a Code Replacement Library” on page 55-15
• “What Is Code Replacement Customization?” on page 55-3

55-46
Specify Build Information for Replacement Code

Specify Build Information for Replacement Code


After you define code replacement mappings, determine whether you need to specify
build information for your replacement code. A code replacement table entry can specify
build information for the code generator to use when replacing code for a match. For
example, specify files for implementation replacement code if you are using a generated
makefile and the code generation software compiles the code.

Add build information to an entry:

• 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:

• Paths and file names for header files


• Paths and file names for source files
• Paths and file names for object files
• Compile flags
• Link flags

Choose an Approach for Specifying Build Information


The following table lists situations to help you decide when to use an interactive or
programmatic approach to specifying build information:

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:

• In the call to packNGo, specify the property-value pair 'minimalHeaders' true


(the default). That setting instructs the function to include the minimal header files
required to build the code in the zip file.
• Do not collocate files that you copy with files that you do not copy. If the packNGo
function finds multiple instances of the same file, the function returns an error.
• If you use the programming interface, paths that you specify can include tokens. A
token is a variable defined as a character vector or cell array of character vectors in
the MATLAB workspace that you enclose with dollar signs ($variable$). The code
generator evaluates and replaces a token with the defined value. For example,
consider the path $myfolder$\folder1, where myfolder is a character vector
variable defined in the MATLAB workspace as 'd:\work\source\module1'. The
code generator generates the custom path as d:\work\source\module1\folder1.

Specify Build Information Interactively with the Code


Replacement Tool
The Code Replacement Tool provides a quick, easy way for you to specify build
information for code replacement table entries. It is ideal for getting started with defining
a table entry, rapid prototyping, and developing table entries to use as a starting point for
defining similar mappings.

55-48
Specify Build Information for Replacement Code

1 Determine the information that you must specify.


2 Open the Code Replacement Tool.
3 Select the code replacement table entry for which you want to specify the build
information. In the left pane, select the table that contains the entry. In the middle
pane, select the entry that you want to modify.
4 In the right pane, select the Build Information tab.
5 On the Build Information tab, specify your build information.

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.

Specify Build Information Programmatically


The programming interface for specifying build information for a code replacement entry
is ideal for:

• Modifying entries created with the Code Replacement Tool.


• Replicating and then modifying similar entries and tables.

The basic workflow for specifying build information programmatically is:

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:

libdir = fullfile('$(MATLAB_ROOT)','..', '..', 'lib');

hEnt = RTW.TflCFunctionEntry;

addAdditionalHeaderFile(hEnt, 'common.h');
addAdditionalIncludePath(hEnt, fullfile(libdir, 'include'));

These functions add -I to the compile line in the generated makefile.

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:

libdir = fullfile('$(MATLAB_ROOT)','..', '..', 'lib');

hEnt = RTW.TflCFunctionEntry;

addAdditionalSourceFile(hEnt, 'common.c');
addAdditionalSourcePath(hEnt, fullfile(libdir, 'src'));

These functions add -I to the compile line in the generated makefile.


Additional object For each file, specify the file name and path in calls to the functions
files/paths addAdditionalLinkObj and addAdditionalLinkObjPath. For
example:

libdir = fullfile('$(MATLAB_ROOT)','..', '..', 'lib');

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.AdditionalCompileFlags = {'-Zi -Wall', '-03'};


Link flags Set the entry property AdditionalLinkFlags to a cell array of
character vectors representing the required link flags. For example:

hEnt = RTW.TflCFunctionEntry;

hEnt.AdditionalCompileFlags = {'-MD -Gy', '-T'};

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'.

If a match occurs for a table entry, a call to the function


RTW.copyFileToBuildDir copies required files to the build folder.

If you specify 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.
4 Save the table that includes the entry that you added or modified.

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);

The following example uses the functions addAdditionalHeaderFile,


addAdditionalIncludePath, addAdditionalSourceFile,
addAdditionalSourcePath, addAdditionalLinkObj, and
addAdditionalLinkObjPath in addition to the code generation callback function
RTW.copyFileToBuildDir.
hTable = RTW.TflTable;

% Path to external source, header, and object files


libdir = fullfile('$(MATLAB_ROOT)','..', '..', 'lib');

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

Register Code Replacement Mappings


After you define code replacement entries in a code replacement table, you can include
the table in a code replacement library that you register with the code generator. When
registered, a library appears in the list of available code replacement libraries that you
can choose from when configuring the code generator.

Register a code replacement table as a code replacement library:

• Interactively, by using the Code Replacement Tool


• Programmatically, by using a MATLAB programming interface

Choose an Approach for Creating the Registration File


The following table lists situations to help you decide when to use an interactive or
programmatic approach to creating a registration file:

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

Create Registration File Interactively with the Code


Replacement Tool
The Code Replacement tool provides a quick, easy way for you to create a registration file
for a code replacement table. It is ideal for getting started, rapid prototyping, and
generating a registration file that you want to use as a starting point for similar
registrations.

1 After you validate and save a code replacement table, select File > Generate
registration file to open the Generate registration file dialog box.

2 Enter the registration information. Minimally, specify:

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:

• Name of a table file on the MATLAB search path


• Absolute path to a table file
• Path to a table file relative to $(MATLAB_ROOT)

You can specify multiple tables. If you do, separate the


table specifications with a comma. For example:

crl_table_sinfcn, c:/work_crl/
crl_table_muldiv

See “Registration Files That Define Multiple Code


Replacement Libraries” on page 55-62 for examples of
each type of table specification.

Optionally, you can specify:

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

Create Registration File Programmatically


The programming interface for creating a registration file for a code replacement table is
ideal for:

• Modifying registration files created with the Code Replacement Tool


• Replicating and modifying similar registration files
• Defining multiple code replacement libraries in one registration file

The basic workflow for creating a registration file programmatically consists of the
following steps:

1 Define an rtwTargetInfo function. The code generator recognizes this function as a


customization file. The function definition must include at least the following content:

function rtwTargetInfo(cm)

cm.registerTargetInfo(@loc_register_crl);

function this = 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:

• Name of a table file on the MATLAB


search path
• Absolute path to a table file
• Path to a table file relative to $
(MATLAB_ROOT)

You can specify multiple tables. If you do,


separate the table specifications with
commas.

Optionally, you can specify:

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.

See “Registration Files That Define Code


Replacement Library Hierarchies” on page
55-62 for an example.

For example:

function rtwTargetInfo(cm)

cm.registerTargetInfo(@loc_register_crl);

function this = 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.

Register a Code Replacement Library


Before you can use the code replacement tables defined in a registration file, you must
refresh Simulink customizations within the current MATLAB session. To initiate a refresh,
enter the following command:

RTW.TargetRegistry.getInstance('reset');

55-61
55 Code Replacement Customization for MATLAB Code

Registration Files That Define Multiple Code Replacement


Libraries
Use the programming interface to create a registration file that defines a code
replacement library that includes multiple code replacement tables. The following
example defines a library that includes multiple tables. The TableList fields specify
tables that reside at different locations. The tables reside on the MATLAB search path or
at locations specified with a path.
function rtwTargetInfo(cm)

cm.registerTargetInfo(@locCrlRegFcn);

function thisCrl = locCrlRegFcn

% Register a code replacement library for use with model: rtwdemo_crladdsub


thisCrl(1) = RTW.TflRegistry;
thisCrl(1).Name = 'Addition & Subtraction Examples';
thisCrl(1).Description = 'Example of addition/subtraction op replacement';
thisCrl(1).TableList = {'crl_table_addsub'};
thisCrl(1).TargetHWDeviceType = {'*'};

% Register a code replacement library for use with model: rtwdemo_crlmuldiv


thisCrl(2) = RTW.TflRegistry;
thisCrl(2).Name = 'Multiplication & Division Examples';
thisCrl(2).Description = 'Example of mult/div op repl for built-in integers';
thisCrl(2).TableList = {'c:/work_crl/crl_table_muldiv'};
thisCrl(2).TargetHWDeviceType = {'*'};

% Register a code replacement library for use with model: rtwdemo_crlfixpt


thisCrl(3) = RTW.TflRegistry;
thisCrl(3).Name = 'Fixed-Point Examples';
thisCrl(3).Description = 'Example of fixed-point operator replacement';
thisCrl(3).TableList = {fullfile('$(MATLAB_ROOT)', ...
'toolbox','rtw','rtwdemos','crl_demo','crl_table_fixpt')};
thisCrl(3).TargetHWDeviceType = {'*'};

Registration Files That Define Code Replacement Library


Hierarchies
Using the programming interface, you can organize multiple code replacement libraries
in a hierarchy. The following example shows a registration file that defines four code
replacement tables organized in a hierarchy of four code replacement libraries. The
tables include entries that increase in specificity: common entries, entries for TI devices,
entries for TI C6xx devices, and entries specific to the TI C67x device.
function rtwTargetInfo(cm)

55-62
See Also

cm.registerTargetInfo(@locCrlRegFcn);

function thisCrl = locCrlRegFcn

% Register a code replacement library that includes common entries


thisCrl(1) = RTW.TflRegistry;
thisCrl(1).Name = 'Common Replacements';
thisCrl(1).Description = 'Common code replacement entries shared by other libraries';
thisCrl(1).TableList = {'crl_table_general'};
thisCrl(1).TargetHWDeviceType = {'*'};

% Register a code replacement library for TI devices


thisCrl(2) = RTW.TflRegistry;
thisCrl(2).Name = 'TI Device Replacements';
thisCrl(2).Description = 'Code replacement entries shared across TI devices';
thisCrl(2).TableList = {'crl_table_TI_devices'};
thisCrl(2).TargetHWDeviceType = {'TI C28x', 'TI C55x', 'TI C62x', 'TI C64x', 'TI 67x'};
thisCrl(1).BaseTfl = 'Common Replacements'

% Register a code replacement library for TI c6xx devices


thisCrl(3) = RTW.TflRegistry;
thisCrl(3).Name = 'TI c6xx Device Replacements';
thisCrl(3).Description = 'Code replacement entries shared across TI C6xx devices';
thisCrl(3).TableList = {'crl_table_TIC6xx_devices'};
thisCrl(3).TargetHWDeviceType = {'TI C62x', 'TI C64x', 'TI 67x'};

% Register a code replacement library for the TI c67x device


thisCrl(3) = RTW.TflRegistry;
thisCrl(3).Name = 'TI c67x Device Replacements';
thisCrl(3).Description = 'Code replacement entries for the TI C67x device';
thisCrl(3).TableList = {'crl_table_TIC67x_device'};
thisCrl(3).TargetHWDeviceType = {'TI 67x'};

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

Troubleshoot Code Replacement Library Registration


If a code replacement library is not listed as a configuration option or does not appear in
the Code Replacement Viewer:

• 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

Verify Code Replacements


After you create or modify a code replacement table, use the following techniques to
examine and validate the table and its entries.

• Invoke the table definition file at the command prompt.


• Use the Code Replacement Viewer to examine libraries, tables, and entries.
• Trace code replacements from the source where you applied the code replacement
library.
• Examine code replacement hits and misses logged during code generation.

Code Replacement Hits and Misses


The code generator logs code replacement table entries for which it finds and does not
find matches in the hit cache and miss cache, respectively. When a code replacement
entry match fails and code is not replaced, the code generator logs the call site object
(CSO) for the miss in the miss cache. When an entry match succeeds, the code generator
logs the matched entry in the hit cache.

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:

• Identifies the call site object.


• Provides a link to the relevant source location for the miss.
• Includes information about the reason for the miss.

55-65
55 Code Replacement Customization for MATLAB Code

Validate a Table Definition File


After you create or modify a code replacement table definition file, validate it. At the
command prompt, specify the name of the table in a call to the isvalid function. For
example:
isvalid(crl_table_sinfcn)

ans =

MATLAB displays errors that occur. In the following example, MATLAB detects a typo in a
data type name.
isvalid(crl_table_sinfcn)

??? RTW_CORE:tfl:TflTable: Unsupported data type, 'dooble'.

Error in ==> crl_table_sinfcn at 7


hTable.registerCFunctionEntry(100, 1, 'sin', 'dooble', 'sin_dbl', ...

Review Library Content


After you create or modify a code replacement library, use the Code Replacement
Viewer to review and verify the list of tables in the library and the entries in each table.

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

Review Table Content


After you create or modify a code replacement table, use the Code Replacement Viewer
to review and verify table entries.

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

• Argument order is correct.


• Conceptual argument names match code generator naming conventions.

55-70
Verify Code Replacements

• Implementation argument names are correct.


• Algorithm properties (for example, saturation and rounding mode) are set
correctly.
• Header or source file specification is not missing.
• I/O types are correct.
• Relative priority of entries is correct.

Review Code Replacements


After you review the content of your code replacement library and tables, generate code
and a code generation report. Verify that the code generator replaces code as you expect.

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.

function [y1, y2] = addsub_two_int16(u1, u2)

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)

[y1, y2] = addsub_two_int16(u1, u2);

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:

• Always create a code generation report


• Code replacements
• Automatically launch a report if one is generated
12 To generate code and a report, set Build type to Source Code. Then, click
Generate.
13 Open the Code Replacements Report section of the code generation report.

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

Review the report:

• Check whether expected function and operator code replacements occurred.


• In the replacements sections, click each code link to see the source that triggered
the reported code replacement.

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

Troubleshoot Code Replacement Misses


Use miss reason messages that appear in the Code Replacement Viewer to analyze and
correct code replacement misses.

Miss Reason Messages


The Code Replacement Viewer displays miss reason messages in trace information for
code replacement misses. A legend listing each message that appears in the miss report
precedes the report details. A message consists of:

• Numeric identifier, which identifies the message in the report details.


• Message text, which in some cases includes placeholders for names of arguments, call
site object values, table entry values, and property names.

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 message identifier, as listed in the legend.


• The placeholder values for that instance of the miss reason message.

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.

1. y1, int8, uint32


u1, int8, uint32
u2, int8, 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.

Analyze and Correct Code Replacement Misses


The following example shows how to use Code Replacement Viewer trace information to
troubleshoot code replacement misses. You must have already reviewed and tested code
replacements for your MATLAB code.
1 Review the code generated for a specific code element, looking for expected code
replacement. Regenerate or reopen the code generation report for your MATLAB
code. If you already generated the code generation report that includes the Code
Replacements Report for matlabroot/toolbox/rtw/rtwdemos/crl_demo/
addsub_two_int16.m, open the file codegen/lib/addsub_two_int16/html/
mldatx.html. For information on how to regenerate the report, see “Verify Code
Replacements” on page 55-65.

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

2 Open the Code Replacements Report for the MATLAB code.


3 Click the link to open the Code Replacement Viewer.
4 In the viewer left pane, select your code replacement table. For this example, select
code replacement table crl_table_addsub.
5 In the middle pane, select table entry RTW_OP_ADD with implementation function
u16_add_u16_u16.
6 In the right pane, select the Trace Information tab.

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)

In the MATLAB Coder app:

• Open the project that contains the addsub_to_int16 function.


• Use the updated test file addsub_to_int16_test to automatically redefine the
input types.
• Change the addition and subtraction algorithm setting. Open the code
replacement library crl_table_addsub. Change the entry Algorithm
parameter setting from Cast before operation (RTW_CAST_BEFORE_OP) to
Cast after operation (RTW_CAST_AFTER_OP).
• Regenerate code and a report.
9 From the Code Replacements Report, open the Code Replacement Viewer. Use the
Code Replacement Viewer trace information to verify that your MATLAB code or code
replacement table entry corrects the code replacement issue. The trace information
shows a hit for function addsub_two_int16.

See Also

More About
• “Verify Code Replacements” on page 55-65

55-77
55 Code Replacement Customization for MATLAB Code

Deploy Code Replacement Library


After you verify code replacements and are ready to package and deploy a code
replacement library for others to use:

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

Math Function Code Replacement


This example shows how to define a code replacement mapping for a math function. The
example defines a mapping for the sin function 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_sinfcn2()
%CRL_TABLE_SINFCN2 - Define function entry for code replacement table.
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create an entry for the function mapping with a call to the
RTW.TflCFunctionEntry function.
% Create entry for sin function replacement
fcn_entry = RTW.TflCFunctionEntry;
4 Set function entry parameters with a call to the
setTflCFunctionEntryParameters function.
setTflCFunctionEntryParameters(fcn_entry, ...
'Key', 'sin', ...
'Priority', 30, ...
'ImplementationName', 'mySin', ...
'ImplementationHeaderFile', 'basicMath.h',...
'ImplementationSourceFile', 'basicMath.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.
createAndAddConceptualArg(fcn_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1',...
'IOType', 'RTW_IO_OUTPUT',...
'DataTypeMode', 'double');

createAndAddConceptualArg(fcn_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT',...
'DataTypeMode', 'double');
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.

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

Memory Function Code Replacement


This example shows how to define a code replacement mapping for a memory function.
The example defines a mapping for the memcpy function 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_memcpy()


2 Within the function body, create the table by calling the function RTW.TflTable.

hTable = RTW.TflTable;
3 Create an entry for the function mapping with a call to the
RTW.TflCFunctionEntry function.

% Create entry for void* memcpy(void*, void*, size_t)


fcn_entry = RTW.TflCFunctionEntry;
4 Set function entry parameters with a call to the
setTflCFunctionEntryParameters function.
% Set SideEffects to 'true' for function returning void to prevent it from
% being optimized away.
setTflCFunctionEntryParameters(fcn_entry, ...
'Key', 'memcpy', ...
'Priority', 90, ...
'ImplementationName', 'memcpy_int', ...
'ImplementationHeaderFile', 'memcpy_int.h',...
'SideEffects', true);
5 Create conceptual arguments y1, u1, u2, and u3. 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', 'void*');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(fcn_entry, arg);

arg = getTflArgFromString(hTable, 'u1', 'void*');


addConceptualArg(fcn_entry, arg);

arg = getTflArgFromString(hTable, 'u2', 'void*');


addConceptualArg(fcn_entry, arg);

arg = getTflArgFromString(hTable, 'u3', 'size_t');


addConceptualArg(fcn_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-81
55 Code Replacement Customization for MATLAB Code

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.

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

Specify In-Place Code Replacement


In-place code replacement is an optimization technique that uses a single buffer, that is,
the same memory, to store function input and output data, as in x=foo(x).

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.

Argument Specification Requirements


• The argument must be a pointer.
• An argument can be in-place with only one other argument.
• Specify an input argument as in-place (shares memory) with an output argument or an
output argument as in-place with an input argument.

Interactive Argument Replacement Specification with Code


Replacement Tool
This example shows how to specify in-place function argument replacement when
replacing code for a MATLAB function with the Code Replacement Tool. The tool enforces
in-place argument specification requirements as you add arguments and modify argument
properties.
1 Create the following MATLAB function, customFunction.m.
function x = customFunction(x)
% Function that updates the input and returns it as an output

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

void custom_function_inplace_impl(double* u1);


12 Click Validate entry.
13 Save the code replacement table in the same folder as customFunction.m. Name
the file htfl_inplace_table.m.

To test the example:

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

Programmatic Argument Replacement Specification


This example shows how to specify in-place function argument replacement when
replacing code for a MATLAB function programmatically. For the input implementation
argument that shares the memory buffer, the example:

• 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

arg = getTflArgFromString(hEnt, 'u1','double');


addConceptualArg(hEnt, arg);

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.

arg = getTflArgFromString(hEnt, 'y2','void');


arg.IOType = 'RTW_IO_OUTPUT';
hEnt.Implementation.setReturn(arg);

arg = getTflArgFromString(hEnt, 'u1','double*');


arg.ArgumentForInPlaceUse = 'y1';
hEnt.Implementation.addArgument(arg);
8 Add the entry to a code replacement table with a call to the addEntry function.

addEntry(hLib, hEnt);
9 Save the table definition file. Use the name of the table definition function to name
the file.

To test the example:

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

Data Alignment for Code Replacement


Code replacement libraries can align data objects passed into a replacement function to a
specified boundary.

Code Replacement Data Alignment


You can take advantage of function implementations that require aligned data to optimize
application performance when using MATLAB Coder. To configure data alignment for a
function implementation:

1 Specify the data alignment requirements in a code replacement entry. Specify


alignment separately for each implementation function argument or collectively for
all function arguments. See “Specify Data Alignment Requirements for Function
Arguments” on page 54-136.
2 Specify the data alignment capabilities and syntax for one or more compilers. Include
the alignment specifications in a library registration entry in the rtwTargetInfo.m
file. See “Provide Data Alignment Specifications for Compilers” on page 54-138.
3 Register the library containing the table entry and alignment specification object.
4 Configure the code generator to use the code replacement library and generate code.
Observe the results.

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.

Specify Data Alignment Requirements for Function Arguments


To specify the data alignment requirement for an argument in a code replacement entry:

55-88
Data Alignment for Code Replacement

• If you are defining a replacement function in a code replacement table registration


file, create an argument descriptor object (RTW.ArgumentDescriptor). Use its
AlignmentBoundary property to specify the required alignment boundary and assign
the object to the argument Descriptor property.
• If you are defining a replacement function using the Code Replacement Tool, on the
Mapping Information tab, in the Argument properties section for the replacement
function, enter a value for the Alignment value parameter.

The AlignmentBoundary property (or Alignment value parameter) specifies the


alignment boundary for data passed to a function argument, in number of bytes. The
AlignmentBoundary property is valid only for addressable objects, including matrix and
pointer arguments. It is not applicable for value arguments. Valid values are:

• -1 (default) — If the data is a Simulink.Bus, Simulink.Signal, or


Simulink.Parameter object, specifies that the code generator determines an
optimal alignment based on usage. Otherwise, specifies that there is not an alignment
requirement for this argument.
• Positive integer that is a power of 2, not exceeding 128 — Specifies number of bytes in
the boundary. The starting memory address for the data allocated for the function
argument is a multiple of the specified value. If you specify an alignment boundary
that is less than the natural alignment of the argument data type, the alignment
directive is emitted in the generated code. However, the target compiler ignores the
directive.

The following code specifies the AlignmentBoundary for an argument as 16 bytes.

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.

Note If your model imports Simulink.Bus, Simulink.Parameter, or


Simulink.Signal objects, specify an alignment boundary in the object properties, using
the Alignment property. For more information, see Simulink.Bus,
Simulink.Parameter, and Simulink.Signal.

Provide Data Alignment Specifications for Compilers


To support data alignment in generated code, describe the data alignment capabilities
and syntax for your compilers in the code replacement library registration. Provide one or
more alignment specifications for each compiler in a library registry entry.

To describe the data alignment capabilities and syntax for a compiler:

• If you are defining a code replacement library registration entry in a


rtwTargetInfo.m customization file, add one or more AlignmentSpecification
objects to an RTW.DataAlignment object. Attach the RTW.DataAlignment object to
the TargetCharacteristics object of the registry entry.

The RTW.DataAlignment object also has the property DefaultMallocAlignment,


which specifies the default alignment boundary, in bytes, that the compiler uses for
dynamically allocated memory. If the code generator uses dynamic memory allocation

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.

Click the plus (+) symbol to add additional compiler specifications.

For each data alignment specification, provide the following information.

55-91
55 Code Replacement Customization for MATLAB Code

Alignment‐ Dialog Box Description


Specification Parameter
Property
AlignmentType Alignment Cell array of predefined enumerated strings, specifying
type which types of alignment this specification supports.

• DATA_ALIGNMENT_LOCAL_VAR — Local variables.


• DATA_ALIGNMENT_GLOBAL_VAR — Global variables.
• DATA_ALIGNMENT_STRUCT_FIELD — Individual
structure fields.
• DATA_ALIGNMENT_WHOLE_STRUCT — Whole structure,
with padding (individual structure field alignment, if
specified, is favored and takes precedence over whole
structure alignment).

Each alignment specification must specify at least


DATA_ALIGNMENT_GLOBAL_VAR and
DATA_ALIGNMENT_STRUCT_FIELD.

55-92
Data Alignment for Code Replacement

Alignment‐ Dialog Box Description


Specification Parameter
Property
AlignmentPositio Alignment Predefined enumerated string specifying the position in
n position which you must place the compiler alignment directive for
alignment type DATA_ALIGNMENT_WHOLE_STRUCT:

• DATA_ALIGNMENT_PREDIRECTIVE — The alignment


directive is emitted before struct st_tag{…}, as part
of the type definition statement (for example, MSVC).
• DATA_ALIGNMENT_POSTDIRECTIVE — The alignment
directive is emitted after struct st_tag{…}, as part
of the type definition statement (for example, gcc).
• DATA_ALIGNMENT_PRECEDING_STATEMENT — The
alignment directive is emitted as a standalone
statement immediately preceding the definition of the
structure type. A semicolon (;) must terminate the
registered alignment syntax.
• DATA_ALIGNMENT_FOLLOWING_STATEMENT — The
alignment directive is emitted as a standalone
statement immediately following the definition of the
structure type. A semicolon (;) must terminate the
registered alignment syntax.

For alignment types other than


DATA_ALIGNMENT_WHOLE_STRUCT, code generation uses
alignment position DATA_ALIGNMENT_PREDIRECTIVE.

55-93
55 Code Replacement Customization for MATLAB Code

Alignment‐ Dialog Box Description


Specification Parameter
Property
AlignmentSyntax‐ Alignment Specifies the alignment directive string that the compiler
Template syntax supports. The string is registered as a syntax template that
has placeholders in it. These placeholders are supported:

• %n — Replaced by the alignment boundary for the


replacement function argument.
• %s — Replaced by the aligned symbol, usually the
identifier of a variable.

For example, for the gcc compiler, you can specify


__attribute__((aligned(%n))), or for the MSVC
compiler, __declspec(align(%n)).
SupportedLanguag Supported Cell array specifying the languages to which this alignment
es languages specification applies, among c and c++. Sometimes
alignment syntax and position differ between languages for
a compiler.
.

Here is a data alignment specification for the GCC compiler:


da = RTW.DataAlignment;

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

Specify Data Alignment in MATLAB Code for Imported Data


If MATLAB Coder code replacements that require data alignment use imported data, such
as an entry-point or exported function I/O, specify data alignment to external code with
coder.dataAlignment statements in the MATLAB code.

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)

coder.dataAlignment('x1',16); % Specifies information

55-95
55 Code Replacement Customization for MATLAB Code

coder.dataAlignment('x2',16); % Specifies information


coder.dataAlignment('y',16); % Specifies information

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.

Replacing Math Functions and Operators with


Implementations that require Data Alignment - MATLAB®
This example shows how to develop and use code replacement library entries for target-
specific function implementations that 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.
• 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.

Create a New Folder and Copy Relevant Files

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.

Run Command: Create a New Folder and Copy Relevant Files


coderdemo_setup('coderdemo_crlalign');
cleanupObj = {};
mlpath = addpath(fullfile(...
matlabroot,'toolbox','coder','codegendemos','coderdemo_crlalign'));
cleanupObj{end+1} = onCleanup(@()path(mlpath));

Check selected compiler

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 MATLAB Coder options

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]));

Generate code using the SIMD Examples Code Replacement Library

To see the code replacement table definition file, look here.

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});

Inspect the MATLAB Coder Generated Code

After compiling, explore the generated source code.

Performance Gain from Data Alignment

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});

% Run SIMD executable and collect execution profile information


coder.runTest('run_biased_ssd_da16',[mcode_da16,'_sil.',mexext])
pause(120);
clear([mcode_da16,'_sil']); % stop simulation
executionProfile_simd = getCoderExecutionProfile(mcode_da16);
idx_section = find(strcmp(mcode_da16,{executionProfile_simd.Sections.Name}),1);
avg_selftime_simd = executionProfile_simd.Sections(idx_section)...
.TotalSelfTimeInTicks/executionProfile_simd.Sections(idx_section).NumCalls;

% Run ANSI executable and collect execution profile information


coder.runTest('run_biased_ssd',[mcode_noda,'_sil.',mexext])
pause(120);
clear([mcode_noda,'_sil']); % stop simulation
executionProfile_ansi = getCoderExecutionProfile(mcode_noda);
idx_section = find(strcmp(mcode_noda,{executionProfile_ansi.Sections.Name}),1);
avg_selftime_ansi = executionProfile_ansi.Sections(idx_section)...
.TotalSelfTimeInTicks/executionProfile_ansi.Sections(idx_section).NumCalls;

% Compare execution profile results


barObj = bar([avg_selftime_ansi; ...
avg_selftime_simd]);
axesObj = barObj.Parent;
figObj = axesObj.Parent;
axesObj.XTickLabel = {'ANSI SSD', 'SIMD SSD'};
axesObj.YLabel.String = 'Average Execution Time (Timer Ticks)';

55-98
Data Alignment for Code Replacement

axesObj.YLim = [min([0,avg_selftime_ansi,avg_selftime_simd]), ...


max(avg_selftime_ansi,avg_selftime_simd)*1.3];

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');

### Starting SIL execution for 'biased_sum_of_square_differences_da16'


To terminate execution: clear biased_sum_of_square_differences_da16_sil
Execution profiling data is available for viewing. Go to <a href="matlab:Simulink.s
Execution profiling report available after termination.
### Stopping SIL execution for 'biased_sum_of_square_differences_da16'
Execution profiling report: report(getCoderExecutionProfile('biased_sum_of_square_d

### Starting SIL execution for 'biased_sum_of_square_differences'


To terminate execution: clear biased_sum_of_square_differences_sil
Execution profiling data is available for viewing. Go to <a href="matlab:Simulink.s
Execution profiling report available after termination.
### Stopping SIL execution for 'biased_sum_of_square_differences'
Execution profiling report: report(getCoderExecutionProfile('biased_sum_of_square_d

55-99
55 Code Replacement Customization for MATLAB Code

Cleanup

Remove files and return to original folder

55-100
See Also

Run Command: Cleanup

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

Array Layout and Code Replacement


To improve the performance of algorithms or simplify integration with external code or
data, you can define code replacement mappings that apply a specific layout for storing
array elements in memory. By default, the code generator stores array elements in a
column-major layout. To change the layout to row-major, change the value of the entry
parameter ArrayLayout to ROW_MAJOR.

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);

arg = RTW.TflArgMatrix('u1', 'RTW_IO_INPUT', 'double');


arg.DimRange = [2 3; 2 3];

55-102
Array Layout and Code Replacement

hEnt.addConceptualArg(arg);

arg = RTW.TflArgMatrix('u2', 'RTW_IO_INPUT', 'double');


arg.DimRange = [3 4; 3 4];
h_Entru.addConceptualArg(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 void output argument. 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.

% 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

Replace MATLAB Functions with Custom Code Using


coder.replace
The coder.replace function provides the ability to replace a specified MATLAB function
with a code replacement function in generated code. Use coder.replace in MATLAB
code from which you want to generate C code using:

• MATLAB Coder
• MATLAB code in a Simulink MATLAB Function block

You can replace MATLAB functions that have:

• Single or multiple inputs


• Single or multiple outputs
• Scalar and matrix inputs and outputs

Supported types include:

• single, double (complex and noncomplex)


• int8, uint8 (complex and noncomplex)
• int16, uint16 (complex and noncomplex)
• int32, uint32 (complex and noncomplex)
• Fixed-point integers
• Mixed types (different type on each input)

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

Replace coder.ceval Calls to External Functions


The coder.ceval function calls external C/C++ functions from code generated from
MATLAB code. The code replacement software supports replacement of the function that
you specify in a call to coder.ceval. An application of this code replacement scenario is
to write generic MATLAB code that you can customize for different platforms with code
replacements. A code replacement library can define hardware-specific code
replacements for the function call. Use coder.ceval in MATLAB code from which you
want to generate C code using:

• 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:

• Custom C function my_add.c.

/* my_add.c */

#include "my_add.h"

double my_add(double in1, double in2)


{
return in1 + in2;
}
• Custom C header file my_add.h.

/* my_add.h */

double my_add(double in1, double in2);


• MATLAB function call_my_add.m, which uses coder.ceval to invoke my_add.c.

function y = call_my_add(in1, in2) %#codegen

y=0.0;

if ~coder.target('Rtw')

55-106
Replace coder.ceval Calls to External Functions

% Executing in MATLAB, call MATLAB equivalent of C function my_add


y= in1+in2;
else
% Executing in generated code, call C function my_add
y = coder.ceval('my_add', in1, in2);
end
• MATLAB test function call_my_add_test.m, which calls call_my_add.m.

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"

double my_add_replacement(double in1, double in2)


{
return in1 + in2;
}
• Replacement C header file my_add_replacement.h.

/* my_add_replacement.h */

double my_add_replacement(double in1, double in2);

Interactive External Function Call Replacement Specification


with Code Replacement Tool
This example shows how to define a code replacement table entry for a MATLAB function
that calls coder.ceval to invoke an external C function. The example shows how to
define the entry interactively with the Code Replacement Tool.

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:

double my_add_replacement(double u1, double u2);


9 On the Build Information tab, specify my_add_replacement.h for the
Implementation header file parameter and my_add_replacement.c for the
Implementation source file.
10 Click Validate entry.
11 Save the code replacement table in the same folder as my_add_replacement.c.
Name the file crl_table_my_add.m.

To test the example:

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

Programmatic External Function Call Replacement


Specification
This example shows how to define a code replacement table entry for a MATLAB function
that calls coder.ceval to invoke an external C function. The example shows how to
define the entry programmatically.

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:

function hLib = crl_table_my_add


3 Within the function body, create the table by calling the function 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.

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.

To test the example:

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

Reserved Identifiers and Code Replacement


The code generator and C programming language use, internally, reserved keywords for
code generation. Do not use reserved keywords as identifiers or function names. Reserved
keywords for code generation include many code replacement library identifiers, the
majority of which are function names, such as acos.

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.

To register additional code replacement reserved identifiers, use the


setReservedIdentifiers function. This function registers specified reserved
identifiers to be associated with a code replacement table.

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

• “Customize Match and Replacement Process” on page 55-113


• “Define Code Replacement Mappings” on page 55-29
• “Develop a Code Replacement Library” on page 55-15

55-112
Customize Match and Replacement Process

Customize Match and Replacement Process


During the build process, the code generator uses:

• 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:

• You want to replace an operator with a particular fixed-point implementation function


only when fraction lengths are within a particular range.
• When a match occurs, you want to modify your replacement function signature based
on compile-time information, such as passing fraction-length values into the function.

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.

To create a custom code replacement entry:

1 Create a custom code replacement entry class, derived from


RTW.TflCFunctionEntryML (for function replacement) or
RTW.TflCOperationEntryML (for operator replacement).
2 In your derived class, implement a do_match method with a fixed preset signature as
a MATLAB function. In your do_match method, provide either or both of the
following customizations that instantiate the class:

• 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

• Math modes, such as saturation and rounding


• Operator or function key
• Modify the implementation signature by adding additional arguments or setting
constant input argument values. You can inject a constant value, such as an input
scaling value, as an additional argument to the replacement function.
3 Create code replacement entries that instantiate the custom entry class.
4 Register a library containing the code replacement table that includes your entries.

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).

Customize Match and Replacement Process for Operators


This example shows how to create custom code replacement entries that add logic to the
code match and replacement process for a scalar operation. Custom entries specify
additional match criteria or modify the replacement function signature to meet
application needs.

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:

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, ...

55-114
Customize Match and Replacement Process

targetBitPerShort, ...
targetBitPerInt, ...
targetBitPerLong, ...
targetBitPerLongLong)

In the do_match 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 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:

• Sets the return handle.


• Removes slope and bias wild cards from the conceptual arguments (the match is
for specific slope and bias values).
• Writes fraction-length values for the inputs and output into replacement function
arguments 3, 4, and 5.

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

% DO_MATCH - Create a custom match function. The base class


% checks the types of the arguments prior to calling this
% method. This class will check additional data and can
% modify the implementation function.

% 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

if length(hCSO.ConceptualArgs) == 3 && ...


hCSO.ConceptualArgs(1).Type.Bias == 0 && ...
hCSO.ConceptualArgs(2).Type.Bias == 0 && ...
hCSO.ConceptualArgs(3).Type.Bias == 0

% Modify the default implementation. Since this is a


% generator entry, a concrete entry is created using this entry
% as a template. The type of entry being created is a standard
% TflCOperationEntry. Using the standard operation entry
% provides required information, and you do not need
% a custom match function.
ent = RTW.TflCOperationEntry(hThis);

% Since this entry is modifying the implementation for specific


% fraction-length values (arguments 3, 4, and 5), the conceptual argument
% wild cards must be removed (the wildcards were inherited from the
% generator when it was used as a template for the concrete entry).
% This concrete entry is now for a specific slope and bias.
% hCSO holds the slope and bias values (created by the code generator).
for idx=1:3
ent.ConceptualArgs(idx).CheckSlope = true;
ent.ConceptualArgs(idx).CheckBias = true;

% Set the specific Slope and Biases


ent.ConceptualArgs(idx).Type.Slope = hCSO.ConceptualArgs(idx).Type.Slope;
ent.ConceptualArgs(idx).Type.Bias = 0;
end

% Set the fraction-length values in the implementation function.


ent.Implementation.Arguments(3).Value = ...
-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.

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:

• Instantiates the derived class TflCustomOperationEntry from the previous


step. If you want to replace word sizes and signedness attributes, you can use the
same derived class, but not the same entry, because you cannot use a wild card
with the WordLength and IsSigned arguments. For example, to support uint8,
int8, uint16, int16, and int32, add five other distinct entries. To use different
implementation functions for saturation and rounding modes other than overflow
and round to floor, add entries for those match permutations.
• Sets operator entry parameters with the call to
the setTflCOperationEntryParameters function.
• Calls the createAndAddConceptualArg function to create conceptual
arguments y1, u1, and u2.
• Calls createAndSetCImplementationReturn and
createAndAddImplementationArg to define the signature for the replacement
function. Three of the calls to createAndAddImplementationArg create
implementation arguments to hold the fraction-length values for the inputs and
output. Alternatively, the entry can omit those argument definitions. Instead, the
do_match method of the derived class TflCustomOperationEntry can create
and add the three implementation arguments. When the number of additional
implementation arguments required can vary based on compile-time information,
use the alternative approach.
• Calls addEntry to add the entry to a code replacement table.
function hTable = crl_table_custom_add_ufix32

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

'ImplementationHeaderFile', 'myFixptAdd.h', ...


'ImplementationSourceFile', 'myFixptAdd.c');

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataType', 'Fixed', ...
'Scaling', 'BinaryPoint', ...
'IsSigned', false, ...
'WordLength', 32);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataType', 'Fixed', ...
'Scaling', 'BinaryPoint', ...
'IsSigned', false, ...
'WordLength', 32);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataType', 'Fixed', ...
'Scaling', 'BinaryPoint', ...
'IsSigned', false, ...
'WordLength', 32);

% Specify replacement function signature


createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...

55-118
Customize Match and Replacement Process

'IsSigned', false, ...


'WordLength', 32, ...
'FractionLength', 0);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0);

% 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);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumericConstant', ...


'Name', 'fl_in2', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0, ...
'Value', 0);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumericConstant', ...


'Name', 'fl_out', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'WordLength', 32, ...
'FractionLength', 0, ...
'Value', 0);

addEntry(hTable, op_entry);
3 Check the validity of the operator entry.

• At the command prompt, invoke the table definition file.

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

Scalar Operator Code Replacement


This example shows how to define a code replacement mapping for a scalar operator. The
example defines a mapping for the + (addition) operator 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_add_uint8


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


op_entry = RTW.TflCOperationEntry;
4 Set function entry parameters with a call to the
setTflCOperationEntryParameters function.
% Define addition operation of built-in uint8 data type
% Saturation on, Rounding unspecified
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 90, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_UNSPECIFIED'}, ...
'ImplementationName', 'u8_add_u8_u8', ...
'ImplementationHeaderFile', 'u8_add_u8_u8.h', ...
'ImplementationSourceFile', 'u8_add_u8_u8.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 getTflArgFromString and
addConceptualArg functions to create and add the arguments.
arg = getTflArgFromString(hTable, 'y1', 'uint8');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(op_entry, arg);

arg = getTflArgFromString(hTable, 'u1', 'uint8');


addConceptualArg(op_entry, arg );

arg = getTflArgFromString(hTable, 'u2', 'uint8');


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

copyConceptualArgsToImplementation function to create and add


implementation arguments to the entry by copying matching conceptual arguments.
copyConceptualArgsToImplementation(op_entry);
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
• “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

Addition and Subtraction Operator Code Replacement


Consider the following when defining mappings for addition and subtraction operator
code replacements.

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-before-operation (CBO), default — Prior to performing the addition or subtraction


operation, the algorithm type casts input values to the output type. If the output data
type cannot exactly represent the input values, losses can occur as a result of the cast
to the output type. Additional loss can occur when the result of the operation is cast to
the final output type.

• 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.

Interactive Specification with Code Replacement Tool


When you use the Code Replacement Tool to create a code replacement table entry for an
addition or subtraction operation, the tool displays an Algorithm menu. Use that menu to
specify the Cast before operation or Cast after operation algorithm for that
entry.

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:

• Key to RTW_OP_ADD or RTW_OP_MINUS


• ImplementationName to the name of your replacement function
• EntryInfoAlgorithm to RTW_CAST_BFORE_OP (cast-before-operation) or
RTW_CAST_AFTER_OP (cast-after-operation)

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');

For more information, see setTflCOperationEntryParameters.

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.

• Floating-point types only

Input 1 Data Input 2 Data Accumulator Output Data Classifica


Type Type Data Type Type tion
double double double double CBO, CAO
double double double single —
double double single double —
double double single single CBO
double single double double CBO, CAO

55-124
Addition and Subtraction Operator Code Replacement

Input 1 Data Input 2 Data Accumulator Output Data Classifica


Type Type Data Type Type tion
double single double single —
double single single double —
double single single single CBO
single single single single CBO, CAO
single single single double —
single single double single —
single single double double CBO, CAO
• Floating-point and fixed-point types on the immediate addition or subtraction
operation

Algorith Conditions
m
CBO One of the following is true:

• Operation type is double.


• Operation type is single and input types are single or fixed-
point.
CAO Operation type is a superset of input types—that is, output type can
represent values of input types without loss of data.
• Fixed-point types only

Algorith Conditions
m
CBO At least one of the following is true:

• Accumulator type equals output type (Tacc == Tout).


• Output type is a superset of input types (Tacc >= {Tin1,
Tin2}) and accumulator type is a superset of output type (Tacc
>= Tout).
• Operation does not incur range or precision loss.

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

• “Remap Operator Output to Function Input” on page 55-146


• “Customize Match and Replacement Process” on page 55-113
• “Fixed-Point Operator Code Replacement” on page 55-149
• “Develop a Code Replacement Library” on page 55-15

55-127
55 Code Replacement Customization for MATLAB Code

Small Matrix Operation to Processor Code Replacement


This example shows how to define code replacement mappings that replace nonscalar
small matrix operations with processor-specific intrinsic functions. The example defines a
table containing two matrix operator replacement entries for the + (addition) operator
and the double data type. 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_matrix_add_double
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Create the entry for the first operator mapping with a call to the
RTW.TflCOperationEntry function.
% Create table entry for matrix_sum_2x2_double
op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The code generator ignores
saturation and rounding modes for floating-point nonscalar addition and subtraction.
For code replacement entries for nonscalar addition and subtraction operations that
do not involve fixed-point data, in the call to setTflCOperationEntryParameters,
specify 'RTW_SATURATE_UNSPECIFIED' for the SaturationMode property and
{'RTW_ROUND_UNSPECIFIED'} for RoundingModes.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 30, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW', ...
'ImplementationName', 'matrix_sum_2x2_double', ...
'ImplementationHeaderFile', 'MatrixMath.h', ...
'ImplementationSourceFile', 'MatrixMath.c', ...
'ImplementationHeaderPath', LibPath, ...
'ImplementationSourcePath', LibPath, ...
'AdditionalIncludePaths', {LibPath}, ...
'GenCallback', 'RTW.copyFileToBuildDir', ...
'SideEffects', true);
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. To specify a matrix argument in the function call, use the argument
class RTW.TflArgMatrix. Specify the base type and the dimensions for which the

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);

arg = getTflArgFromString(hTable, 'u1', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'y1', ['double' '*']);


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 Create the entry for the second operator mapping.

% Create table entry for matrix_sum_3x3_double


op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 30, ...
'SaturationMode', 'RTW_WRAP_ON_OVERFLOW', ...
'ImplementationName', 'matrix_sum_3x3_double', ...
'ImplementationHeaderFile', 'MatrixMath.h', ...

55-129
55 Code Replacement Customization for MATLAB Code

'ImplementationSourceFile', 'MatrixMath.c', ...


'ImplementationHeaderPath', LibPath, ...
'ImplementationSourcePath', LibPath, ...
'AdditionalIncludePaths', {LibPath}, ...
'GenCallback', 'RTW.copyFileToBuildDir', ...
'SideEffects', true);

% Specify operands and result


createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [3 3]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [3 3]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [3 3]);

% Specify replacement function signature


arg = getTflArgFromString(hTable, 'y2', 'void');
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);
arg = getTflArgFromString(hTable, 'u1', ['double' '*']);
op_entry.Implementation.addArgument(arg);
arg = getTflArgFromString(hTable, 'u2', ['double' '*']);
op_entry.Implementation.addArgument(arg);
arg = getTflArgFromString(hTable, 'y1', ['double' '*']);
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.addArgument(arg);

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

Matrix Multiplication Operation to MathWorks BLAS


Code Replacement
This example shows how to define code replacement mappings that replace nonscalar
multiplication operations with Basic Linear Algebra Subroutine (BLAS) multiplication
functions xgemm and xgemv. The example defines code replacement entries that map
floating-point matrix/matrix and matrix/vector multiplication operations to MathWorks
BLAS library multiplication functions dgemm and dgemv. The example defines the function
mappings programmatically. Alternatively, you can use the Code Replacement Tool to
define the same mappings.

BLAS libraries support matrix/matrix multiplication in the form of


C = a(op(A) * op(B)) + bC . op(X) means X, transposition of X, or Hermitian transposition
of X. However, code replacement libraries support only the limited case of
C = op(A) * op(B) (a = 1.0, b = 0.0) . Correspondingly, although BLAS libraries support
matrix/vector multiplication in the form of y = a(op(A) * x) + by , code replacement
libraries support only the limited case of y = op(A) * x (a = 1.0, b = 0.0) .

1 Create a table definition file that contains a function definition. For example:

function hTable = crl_table_tmwblas_mmult_double


2 Within the function body, create the table by calling the function RTW.TflTable.

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

LibPath = fullfile('$(MATLAB_ROOT)', 'extern', 'lib', arch, compilerName);


end
4 Create an entry for the first mapping with a call to the
RTW.TflBlasEntryGenerator function.

% Create table entry for dgemm32


op_entry = RTW.TflBlasEntryGenerator;
5 Set operator entry parameters with a call to the
setTflCFunctionEntryParameters function. The function call sets matrix
multiplication operator entry properties. The code generator ignores saturation and
rounding modes for floating-point nonscalar addition and subtraction. For code
replacement entries for nonscalar addition and subtraction operations that do not
involve fixed-point data, in the call to setTflCFunctionEntryParameters, specify
'RTW_SATURATE_UNSPECIFIED' for the SaturationMode property and
{'RTW_ROUND_UNSPECIFIED'} for RoundingModes.
if ispc
libExt = 'lib';
elseif ismac
libExt = 'dylib';
else
libExt = 'so';
end
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 100, ...
'ImplementationName', 'dgemm32', ...
'ImplementationHeaderFile', 'blascompat32_crl.h', ...
'ImplementationHeaderPath', fullfile('$(MATLAB_ROOT)','extern','include'), ...
'AdditionalLinkObjs', {['libmwblascompat32.' libExt]}, ...
'AdditionalLinkObjsPaths', {LibPath}, ...
'SideEffects', true);
6 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. To specify a matrix argument in the function call, use the argument
class RTW.TflArgMatrix and specify the base type and the dimensions for which
the argument is valid. This type of table entry supports a range of dimensions
specified in the format [Dim1Min Dim2Min ... DimNMin; Dim1Max
Dim2Max ... DimNMax]. For example, [2 2; inf inf] means a two-dimensional
matrix of size 2x2 or larger. The conceptual output argument for the dgemm32 entry
for matrix/matrix multiplication replacement specifies dimensions [2 2; inf inf],
while the conceptual output argument for the dgemv32 entry for matrix/vector
multiplication replacement specifies dimensions [2 1; inf 1].

55-133
55 Code Replacement Customization for MATLAB Code

% Specify operands and result


createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [1 1; inf inf]);
7 Create the implementation arguments. There are multiple ways to set up the
implementation arguments. This example uses calls to the getTflArgFromString
and RTW.TflArgCharConstant functions to create the arguments. The example
code configures special implementation arguments that are required for dgemm and
dgemv function replacements. 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.
% Using RTW.TflBlasEntryGenerator for xgemm requires the following
% implementation signature:
%
% void f(char* TRANSA, char* TRANSB, int* M, int* N, int* K,
% type* ALPHA, type* u1, int* LDA, type* u2, int* LDB,
% type* BETA, type* y, int* LDC)
%
% When a match occurs, the code generator computes the
% values for M, N, K, LDA, LDB, and LDC and inserts them into the
% generated code. TRANSA and TRANSB are set to 'N'.

% Specify replacement function signature

arg = getTflArgFromString(hTable, 'y2', 'void');


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);

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);

arg = getTflArgFromString(hTable, 'M', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;

55-134
Matrix Multiplication Operation to MathWorks BLAS Code Replacement

op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'N', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'K', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'ALPHA', 'double', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u1', ['double' '*']);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2', ['double' '*']);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDB', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'BETA', 'double', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'y1', ['double' '*']);


arg.IOType = 'RTW_IO_OUTPUT';
arg.PassByType = 'RTW_PASSBY_POINTER';
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDC', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
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);

55-135
55 Code Replacement Customization for MATLAB Code

9 Create the entry for the second mapping.


% Create table entry for dgemv32
op_entry = RTW.TflBlasEntryGenerator;
if ispc
libExt = 'lib';
elseif ismac
libExt = 'dylib';
else
libExt = 'so';
end
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...
'Priority', 100, ...
'ImplementationName', 'dgemv32', ...
'ImplementationHeaderFile', 'blascompat32_crl.h', ...
'ImplementationHeaderPath', fullfile('$(MATLAB_ROOT)','extern','include'), ...
'AdditionalLinkObjs', {['libmwblascompat32.' libExt]}, ...
'AdditionalLinkObjsPaths', {LibPath},...
'SideEffects', true);

% Specify operands and result


createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [2 1; inf 1]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [1 1; inf 1]);

% Using RTW.TflBlasEntryGenerator for xgemv requires the following


% implementation signature:
%
% void f(char* TRANS, int* M, int* N,
% type* ALPHA, type* u1, int* LDA, type* u2, int* INCX,
% type* BETA, type* y, int* INCY)
%
% Upon a match, the CRL entry will compute the
% values for M, N, LDA, INCX, and INCY, and insert them into the
% generated code. TRANS will be set to 'N'.

% Specify replacement function signature

arg = getTflArgFromString(hTable, 'y2', 'void');


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);

arg = RTW.TflArgCharConstant('TRANS');
arg.PassByType = 'RTW_PASSBY_POINTER';

55-136
Matrix Multiplication Operation to MathWorks BLAS Code Replacement

op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'M', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'N', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'ALPHA', 'double', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u1', ['double' '*']);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2', ['double' '*']);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'INCX','integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'BETA', 'double', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'y1', ['double' '*']);


arg.IOType = 'RTW_IO_OUTPUT';
arg.PassByType = 'RTW_PASSBY_POINTER';
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'INCY', 'integer', 0);


arg.PassByType = 'RTW_PASSBY_POINTER';
arg.Type.ReadOnly = true;
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

Matrix Multiplication Operation to ANSI/ISO C BLAS Code


Replacement
This example shows how to define code replacement mappings that replace nonscalar
multiplication operations with ANSI/ISO C BLAS multiplication functions xgemm and
xgemv. The example defines code replacement entries that map floating-point matrix/
matrix and matrix/vector multiplication operations to ANSI/ISO C BLAS library
multiplication functions dgemm and dgemv. The example defines the function mappings
programmatically. Alternatively, you can use the Code Replacement Tool to define the
same mappings.

BLAS libraries support matrix/matrix multiplication in the form of


C = a(op(A) * op(B)) + bC . op(X) means X, transposition of X, or Hermitian transposition
of X. However, code replacement libraries support only the limited case of
C = op(A) * op(B) (a = 1.0, b = 0.0) . Correspondingly, although BLAS libraries support
matrix/vector multiplication in the form of y = a(op(A) * x) + by , code replacement
libraries support only the limited case of y = op(A) * x (a = 1.0, b = 0.0) .
1 Create a table definition file that contains a function definition. For example:
function hTable = crl_table_cblas_mmult_double
2 Within the function body, create the table by calling the function RTW.TflTable.
hTable = RTW.TflTable;
3 Define the path for the CBLAS function library. For example:
LibPath = fullfile(matlabroot, 'toolbox', 'rtw', 'rtwdemos', 'crl_demo');
4 Create an entry for the first mapping with a call to the
RTW.TflBlasEntryGenerator function.
% Create table entry for cblas_dgemm
op_entry = RTW.TflCBlasEntryGenerator;
5 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. The function call sets matrix
multiplication operator entry properties. The code generator ignores saturation and
rounding modes for floating-point nonscalar addition and subtraction.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_MUL', ...

55-139
55 Code Replacement Customization for MATLAB Code

'Priority', 100, ...


'ImplementationName', 'cblas_dgemm', ...
'ImplementationHeaderFile', 'cblas.h', ...
'ImplementationHeaderPath', LibPath, ...
'AdditionalIncludePaths', {LibPath}, ...
'GenCallback', 'RTW.copyFileToBuildDir', ...
'SideEffects', true);
6 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. To specify a matrix argument in the function call, use the argument
class RTW.TflArgMatrix and specify the base type and the dimensions for which
the argument is valid. This type of table entry supports a range of dimensions
specified in the format [Dim1Min Dim2Min ... DimNMin; Dim1Max
Dim2Max ... DimNMax]. For example, [2 2; inf inf] means a two-dimensional
matrix of size 2x2 or larger. The conceptual output argument for the dgemm32 entry
for matrix/matrix multiplication replacement specifies dimensions [2 2; inf inf].
The conceptual output argument for the dgemv32 entry for matrix/vector
multiplication replacement specifies dimensions [2 1; inf 1].
% Specify operands and result
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [1 1; inf inf]);
7 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. The example code configures special
implementation arguments that are required for dgemm and dgemv function
replacements. 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.
% Using RTW.TflCBlasEntryGenerator for xgemm requires the following
% implementation signature:
%
% void f(enum ORDER, enum TRANSA, enum TRANSB, int M, int N, int K,
% type ALPHA, type* u1, int LDA, type* u2, int LDB,
% type BETA, type* y, int LDC)

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.

% Specify replacement function signature

arg = getTflArgFromString(hTable, 'y2', 'void');


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);

arg = getTflArgFromString(hTable, 'ORDER', 'integer', 102);


% arg.Type.ReadOnly=true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'TRANSA', 'integer', 111);


% arg.Type.ReadOnly=true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'TRANSB', 'integer', 111);


% arg.Type.ReadOnly=true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'M', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'N', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'K', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'ALPHA', 'double', 1);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u1', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDB', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'BETA', 'double', 0);


op_entry.Implementation.addArgument(arg);

55-141
55 Code Replacement Customization for MATLAB Code

arg = getTflArgFromString(hTable, 'y1', ['double' '*']);


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDC', 'integer', 0);


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 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);

% Specify operands and result


createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'BaseType', 'double', ...
'DimRange', [2 1; inf 1]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
'Name', 'u1', ...
'BaseType', 'double', ...
'DimRange', [2 2; inf inf]);
createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
'Name', 'u2', ...
'BaseType', 'double', ...
'DimRange', [1 1; inf 1]);

% Using RTW.TflCBlasEntryGenerator for xgemv requires the following


% implementation signature:
%
% void f(enum ORDER, enum TRANSA, int M, int N,
% type ALPHA, type* u1, int LDA, type* u2, int INCX,
% type BETA, type* y, int INCY)
%
% 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.)
%
% Upon a match, the CRL entry will compute the
% values for M, N, LDA, INCX, and INCY and insert them into the
% generated code.

55-142
Matrix Multiplication Operation to ANSI/ISO C BLAS Code Replacement

% Specify replacement function signature

arg = getTflArgFromString(hTable, 'y2', 'void');


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);

arg = getTflArgFromString(hTable, 'ORDER', 'integer', 102);


% arg.Type.ReadOnly=true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'TRANSA', 'integer', 111);


% arg.Type.ReadOnly=true;
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'M','integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'N', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'ALPHA', 'double', 1);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u1', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2', ['double' '*']);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'INCX', 'integer', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'BETA', 'double', 0);


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'y1', ['double' '*']);


arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'INCY', 'integer', 0);


op_entry.Implementation.addArgument(arg);

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

2 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.
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

• “Develop a Code Replacement Library” on page 55-15

55-145
55 Code Replacement Customization for MATLAB Code

Remap Operator Output to Function Input


If your generated code must meet a specific coding pattern or you want more flexibility,
for example, to further improve performance, you can remap operator outputs to input
positions in an implementation function argument list.

Note Remapping outputs to implementation function inputs is supported only for


operator replacement.

For example, for a sum operation, the code generator produces code similar to:

add8_Y.Out1 = u8_add_u8_u8(add8_U.In1, add8_U.In2);

If you remap the output to the first input, the code generator produces code similar to:

u8_add_u8_u8(&add8_Y.Out1;, add8_U.In1, add8_U.In2);

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:

function hTable = crl_table_add_uint8


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


op_entry = RTW.TflCOperationEntry;
4 Set operator entry parameters with a call to the
setTflCOperationEntryParameters function. In the function call, set the
property SideEffects to true.
setTflCOperationEntryParameters(op_entry, ...
'Key', 'RTW_OP_ADD', ...
'Priority', 90, ...
'ImplementationName', 'u8_add_u8_u8', ...
'ImplementationHeaderFile', 'u8_add_u8_u8.h', ...
'ImplementationSourceFile', 'u8_add_u8_u8.c', ...
'SideEffects', true );

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);

arg = getTflArgFromString(hTable, 'u1', 'uint8');


addConceptualArg(op_entry, arg );

arg = getTflArgFromString(hTable, 'u2', 'uint8');


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);

arg=getTflArgFromString(hTable, 'u1', 'uint8');


op_entry.Implementation.addArgument(arg);

arg=getTflArgFromString(hTable, 'u2', 'uint8');


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:

1 Create a model that includes an Add block, such as the following:

55-147
55 Code Replacement Customization for MATLAB Code

2 Configure the model with the following settings:

• On the Solver pane, select a fixed-step solver.


• 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.
• Set the Optimize global data access parameter to Use global to hold
temporary results. This reduces data copies in the generated code.
3 Generate 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-148
Fixed-Point Operator Code Replacement

Fixed-Point Operator Code Replacement


If you have a Fixed-Point Designer license, you can define fixed-point operator code
replacement entries to match:

• A binary-point-only scaling combination on the operator inputs and output.


• A slope bias scaling combination on the operator inputs and output.
• Relative scaling or net slope between multiplication or division operator inputs and
output. Use one of these methods to map a range of slope and bias values to a
replacement function for multiplication or division.
• Equal slope and zero net bias across addition or subtraction operator inputs and
output. Use this method to disregard specific slope and bias values and map relative
slope and bias values to a replacement function for addition or subtraction.

Common Ways to Match Fixed-Point Operator Entries


The following table maps common ways to match fixed-point operator code replacement
entries with the associated fixed-point parameters that you specify in a code replacement
table definition file.

Match Create entry Minimally specify parameters


A specific binary-point-only RTW.TflCOperationEntry createAndAddConceptualArg
scaling combination on the function:
operator inputs and
output. • CheckSlope: Specify the value
true.
• CheckBias: Specify the value true.
• DataTypeMode (or DataType/
Scaling equivalent): Specify fixed-
point binary-point-only scaling.
• FractionLength: Specify a
fraction length (for example, 3).

55-149
55 Code Replacement Customization for MATLAB Code

Match Create entry Minimally specify parameters


A specific slope bias RTW.TflCOperationEntry createAndAddConceptualArg
scaling combination on the function:
operator inputs and
output. • CheckSlope: Specify the value
true.
• CheckBias: Specify the value true.
• DataTypeMode (or DataType/
Scaling equivalent): Specify fixed-
point [slope bias] scaling.
• Slope (or
SlopeAdjustmentFactor/
FixedExponent equivalent):
Specify a slope value (for example,
15).
• Bias: Specify a bias value (for
example, 2).
Net slope between RTW.TflCOperationEntry‐ setTflCOperationEntryParameter
operator inputs and output Generator_NetSlope s function:
(multiplication and
division). • NetSlopeAdjustmentFactor:
Specify the slope adjustment factor
(F) part of the net slope, F2E (for
example, 1.0).
• NetFixedExponent: Specify the
fixed exponent (E) part of the net
slope, F2E (for example, -3.0).

createAndAddConceptualArg
function:

• CheckSlope: Specify the value


false.
• CheckBias: Specify the value
false.
• DataType: Specify the value
'Fixed'.

55-150
Fixed-Point Operator Code Replacement

Match Create entry Minimally specify parameters


Relative scaling between RTW.TflCOperationEntry‐ setTflCOperationEntryParameter
operator inputs and output Generator s function:
(multiplication and
division). • RelativeScalingFactorF:
Specify the slope adjustment factor
(F) part of the relative scaling factor,
F2E (for example, 1.0).
• RelativeScalingFactorE:
Specify the fixed exponent (E) part
of the relative scaling factor, F2E (for
example, -3.0).

createAndAddConceptualArg
function:

• CheckSlope: Specify the value


false.
• CheckBias: Specify the value
false.
• DataType: Specify the value
'Fixed'.
Equal slope and zero net RTW.TflCOperationEntry‐ setTflCOperationEntryParameter
bias across operator inputs Generator s function:
and output (addition and
subtraction). • SlopesMustBeTheSame: Specify
the value true.
• MustHaveZeroNetBias: Specify
the value true.

createAndAddConceptualArg
function:

• CheckSlope: Specify the value


false.
• CheckBias: Specify the value
false.

55-151
55 Code Replacement Customization for MATLAB Code

Fixed-Point Numbers and Arithmetic


Fixed-point numbers use integers and integer arithmetic to represent real numbers and
arithmetic with the following encoding scheme:

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:

( SOQO + BO ) = ( S1Q1 + B1 ) < op > ( S2Q2 + B2 )


The objective of fixed-point operator replacement is to replace an operator that accepts
and returns fixed-point or integer inputs and output with a function that accepts and
returns built-in C numeric data types. The following sections provide additional
programming information for each supported operator.

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.

The operation V0 = V1 * V2 implies, for binary-point-only scaling, that

S0Q0 = ( S1Q1 )( S 2Q2 )


ÊSS ˆ
Q0 = Á 1 2 ˜ Q1Q2
Ë S0 ¯
Q0 = SnQ1Q2

where Sn is the net slope.

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.)

Note When an operator entry specifies NetSlopeAdjustmentFactor and


NetFixedExponent, matching entries must have arguments with zero bias.

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

The operation V0 = (V1 / V2) implies, for binary-point-only scaling, that

ÊSQ ˆ
S0Q0 = Á 1 1 ˜
Ë S2Q2 ¯
ÊQ ˆ
Q0 = S n Á 1 ˜
Ë Q2 ¯

where Sn is the net slope.

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.)

Note When an operator entry specifies NetSlopeAdjustmentFactor and


NetFixedExponent, matching entries must have arguments with zero bias.

Data Type Conversion (Cast)


The data type conversion operation V0 = V1 implies, for binary-point-only scaling, that

Ê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

• “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-157
55 Code Replacement Customization for MATLAB Code

Binary-Point-Only Scaling Code Replacement


You can define code replacement entries for operations on fixed-point data types such that
they match a binary-point-only scaling combination on operator inputs and output. These
binary-point-only scaling entries can map the specified binary-point-scaling combination
to a replacement function for addition, subtraction, multiplication, or division.

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:

function hTable = crl_table_fixed_binptscale


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 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);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 15);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', true, ...
'WordLength', 16, ...
'FractionLength', 13);

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

Slope Bias Scaling Code Replacement


You can define code replacement for operations on fixed-point data types as matching a
slope bias scaling combination on the operator inputs and output. The slope bias scaling
entries can map the specified slope bias combination to a replacement function for
addition, subtraction, multiplication, or division.

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

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'y1', ...
'IOType', 'RTW_IO_OUTPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: slope and bias scaling', ...
'IsSigned', true, ...
'WordLength', 16, ...
'Slope', 15, ...
'Bias', 2);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: slope and bias scaling', ...
'IsSigned', true, ...
'WordLength', 16, ...
'Slope', 15, ...
'Bias', 2);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', true, ...
'CheckBias', true, ...
'DataTypeMode', 'Fixed-point: slope and bias scaling', ...
'IsSigned', true, ...
'WordLength', 16, ...
'Slope', 13, ...
'Bias', 5);
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);

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

Net Slope Scaling Code Replacement

Multiplication and Division with Saturation


You can define code replacement entries for operations on fixed-point data types as
matching net slope between operator inputs and output. The net slope entries can map a
range of slope and bias values to a replacement function for multiplication or division.

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:

function hTable = crl_table_fixed_netslopesaturate


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.
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);

arg = getTflArgFromString(hTable, 'u1', typeStrBase(dtnum));


op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2',typeStrBase(dtden));


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 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.

Multiplication and Division with Rounding Mode and


Additional Implementation Arguments
You can define code replacement entries for multiplication and division operations on
fixed-point data types such that they match the net slope between operator inputs and
output. The net slope entries can map a range of slope and bias values to a replacement
function for multiplication or division.

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:

function hTable = crl_table_fixed_netsloperound


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;
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

'ImplementationName', 's16_div_s16_s16', ...


'ImplementationHeaderFile', 's16_div_s16_s16.h', ...
'ImplementationSourceFile', 's16_div_s16_s16.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, 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);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataType', 'Fixed', ...
'IsSigned', true, ...
'WordLength', 16);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'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

Equal Slope and Zero Net Bias Code Replacement


You can define code replacement entries for addition or subtraction of fixed-point data
types such that they match relative slope and bias values (equal slope and zero net bias)
across operator inputs and output. These entries allow you to disregard slope and bias
values. Map relative slope and bias values to a replacement function for addition or
subtraction.

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

createAndAddConceptualArg function to create and add an argument with one


function call. Each argument is specified as 16 bits and unsigned. 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, ...
'IsSigned', false, ...
'WordLength', 16);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'IsSigned', false, ...
'WordLength', 16);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u2', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'IsSigned', false, ...
'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 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

'Name', 'u2', ...


'IOType', 'RTW_IO_INPUT', ...
'IsSigned', false, ...
'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-172
Data Type Conversions (Casts) and Operator Code Replacement

Data Type Conversions (Casts) and Operator Code


Replacement
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 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:

function hTable = crl_table_cast_int32_to_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 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');

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.

55-173
55 Code Replacement Customization for MATLAB Code

arg = getTflArgFromString(hTable, 'y1', 'int16');


arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(op_entry, arg);
op_entry.Implementation.setReturn(arg);

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:

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;
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

my_fxp_cast. 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_CAST', ...
'Priority', 50, ...
'SaturationMode', 'RTW_SATURATE_ON_OVERFLOW', ...
'RoundingModes', {'RTW_ROUND_FLOOR'}, ...
'NetSlopeAdjustmentFactor', 1.0, ...
'NetFixedExponent', (OutFL - InFL), ...
'ImplementationName', 'my_fxp_cast', ...
'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);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', InSgn, ...
'WordLength', InWL, ...
'FractionLength',InFL);
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

55-175
55 Code Replacement Customization for MATLAB Code

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 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

Shift Left Operations and Code Replacement


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 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

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);

• The function getTflArgFromString is called to create an int8 input argument. This


argument is added to the operator entry both as the third conceptual argument and
the second implementation input argument.
• Add the entry to a code replacement table with a call to the addEntry function.

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:

function hTable = crl_table_shift_left_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. 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);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'CheckSlope', false, ...
'CheckBias', false, ...
'DataTypeMode', 'Fixed-point: binary point scaling', ...
'IsSigned', InSgn, ...
'WordLength', InWL, ...
'FractionLength',InFL);

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);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric', ...


'Name', 'u1', ...
'IOType', 'RTW_IO_INPUT', ...
'IsSigned', InSgn, ...
'WordLength', InWL, ...
'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

• “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
• “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-181
Performance

183
56

Optimizations for Generated Code


in Simulink Coder

• “Increase Code Generation Speed” on page 56-3


• “Control Compiler Optimizations” on page 56-6
• “Optimization Tools and Techniques” on page 56-7
• “Control Memory Allocation for Time Counters” on page 56-11
• “Execution Profiling for Generated Code” on page 56-12
• “Optimize Generated Code by Combining Multiple for Constructs” on page 56-15
• “Subnormal Number Performance” on page 56-19
• “Remove Code From Floating-Point to Integer Conversions That Wraps Out-of-Range
Values” on page 56-24
• “Remove Code That Maps NaN to Integer Zero” on page 56-27
• “Disable Nonfinite Checks or Inlining for Math Functions” on page 56-31
• “Minimize Computations and Storage for Intermediate Results at Block Outputs”
on page 56-37
• “Inline Invariant Signals” on page 56-40
• “Inline Numeric Values of Block Parameters” on page 56-44
• “Configure Loop Unrolling Threshold” on page 56-50
• “Use memcpy Function to Optimize Generated Code for Vector Assignments”
on page 56-53
• “Generate Target Optimizations Within Algorithm Code” on page 56-57
• “Remove Code for Blocks That Have No Effect on Computational Results”
on page 56-59
• “Eliminate Dead Code Paths in Generated Code” on page 56-62
• “Floating-Point Multiplication to Handle a Net Slope Correction” on page 56-65
• “Use Conditional Input Branch Execution” on page 56-68
• “Optimize Generated Code for Complex Signals” on page 56-74
56 Optimizations for Generated Code in Simulink Coder

• “Speed Up Linear Algebra in Code Generated from a MATLAB Function Block”


on page 56-77
• “Speed Up Fast Fourier Transforms in Code Generated from a MATLAB Function
Block” on page 56-81
• “Synchronize Multithreaded FFTW Planning in Code Generated from a MATLAB
Function Block” on page 56-85
• “Control Memory Allocation for Variable-Size Arrays in a MATLAB Function Block”
on page 56-90
• “Optimize Memory Usage for Time Counters” on page 56-93
• “Optimize Generated Code Using Boolean Data for Logical Signals” on page 56-100
• “Reduce Memory Usage for Boolean and State Configuration Variables”
on page 56-103
• “Customize Stack Space Allocation” on page 56-104
• “Optimize Generated Code Using memset Function” on page 56-106
• “Vector Operation Optimization” on page 56-110
• “Enable and Reuse Local Block Outputs in Generated Code” on page 56-113

56-2
Increase Code Generation Speed

Increase Code Generation Speed


In this section...
“Build a Model in Increments” on page 56-3
“Build Large Model Reference Hierarchies in Parallel” on page 56-3
“Minimize Memory Requirements During Code Generation” on page 56-4
“Generate Only Code” on page 56-5
“No Creation of a Code Generation Report” on page 56-5

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:

• Build a model in increments


• Build large model reference hierarchies in parallel
• Minimize memory requirements during code generation
• Generate only code
• Disable the creation of a code generation report

Build a Model in Increments


You can use the rtwbuild command to build a model and generate code. By default,
when rebuilding a model, rtwbuild provides an incremental model build, which only
rebuilds a model or submodels that have changed since the most recent model build.
Incremental model build saves code generation time. Use the Rebuild parameter on the
Model Referencing pane to change the method that Simulink uses to determine when to
rebuild code for referenced models. For more information on the Rebuild parameter, see
“Rebuild” (Simulink).

Build Large Model Reference Hierarchies in Parallel


In a parallel computing environment, whenever conditions allow, you can increase the
speed of code generation and compilation by building models containing large model
reference hierarchies in parallel. For example, if you have Parallel Computing Toolbox
software, you can distribute code generation and compilation for each referenced model

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).

Minimize Memory Requirements During Code Generation


Models that have large amounts of parameter and constant data (such as lookup tables)
can tax memory resources and slow code generation. The code generator copies this data
to the model.rtw file. The model.rtw file is a partial representation of the model that
the Target Language Compiler parses to transform block computations, parameters,
signals, and constant data into a high-level language (for example, C). The Target
Language Compiler (TLC) is an integral part of the code generator. The code generator
copies parameters and data into model.rtw, whether they originate in the model or
come from variables or objects in a workspace.

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:

set_param(0, 'RTWDataReferencesMinSize', <size>)

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.

Generate Only Code


You can increase code generation speed by specifying that the build process generate
code and a makefile, but not invoke the make command. When the code generator
invokes the make command, the build process takes longer because the code generator
generates code, compiles code, and creates an executable file.

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.

No Creation of a Code Generation Report


You can speed up code generation by not generating a code generation report as a part of
the build process. To disable the creation of a code generation report, on the Code
Generation > Report pane, clear the Create code generation report parameter. After
the build process, you can generate a code generation report by doing this procedure,
“Generate Code Generation Report After Build Process” (Simulink Coder).

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

Control Compiler Optimizations


To control compiler optimizations for a makefile build at the GUI level, use the Compiler
optimization level parameter. The Compiler optimization level parameter provides

• Target-independent values Optimizations on (faster runs) and


Optimizations off (faster builds), which allow you to easily toggle compiler
optimizations on and off during code development
• The value Custom for entering custom compiler optimization flags at the Simulink GUI
level, rather than editing compiler flags into template makefiles (TMFs) or supplying
compiler flags to build process make commands

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

Optimization Tools and Techniques


Use the Model Advisor to Optimize a Model for Code
Generation
You can use the Model Advisor to analyze a model for code generation and identify
aspects of your model that impede production deployment or limit code efficiency. You can
select from a set of checks to run on a model's current configuration. The Model Advisor
analyzes the model and generates check results providing suggestions for improvements
in each area. Most Model Advisor diagnostics do not require the model to be in a
compiled state; those that do are noted.

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

Note Example models rtwdemo_advisor2 and rtwdemo_advisor3 require Stateflow


and Fixed-Point Designer software.

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).

Design Tips for Optimizing Generated Code for Stateflow


Objects
Do Not Access Machine-Parented Data In a Graphical Function

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

Be Explicit About the Inline Option of a Graphical Function

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).

Avoid Using Multiple Edge-Triggered Events in Stateflow Charts

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).

Combine Input Signals of a Chart Into a Single Bus Object

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).

Use Charts with Discrete Sample Times

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.

Additional Optimization Techniques


You can apply the following techniques to optimize a model for code generation:

• 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

Control Memory Allocation for Time Counters


The Application lifespan (days) parameter lets you control the allocation of memory for
absolute and elapsed time counters. Such counters exist in the code for blocks that use
absolute or elapsed time. For a list of such blocks, see “Absolute Time Limitations”
(Simulink Coder).

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

Execution Profiling for Generated Code


Use code execution profiling to:

• 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:

1 With the Simulink model, design and optimize your algorithm.


2 Configure the model for code execution profiling, and generate code.
3 Execute generated code on target. For example, you can:

• Run a software-in-the-loop (SIL) simulation on your development computer.


• Run a processor-in-the-loop (PIL) simulation using a target support package or
custom PIL target.
• Perform real-time execution with Simulink Real-Time or a target support package.
4 Analyze performance through code execution profiling plots and reports. For
example, check that the algorithm code satisfies execution time requirements for
real-time deployment:

• 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.

If your target is a multicore processor, distribute the execution of algorithm code


across available cores.
5 If required, refine the model and return to step 2.

To find information about code execution profiling with Simulink products, use the
following table.

56-12
Execution Profiling for Generated Code

Target Execution Type of Relevant See


Feature Profiling Products
Development Model Execution Simulink Coder • “Optimize and Deploy on a
computer configured for time Multicore Target” (Simulink)
concurrent • “Concurrent Execution
execution Models” (Simulink)
Development Software-in-the- Execution Embedded • “Code Execution Profiling
computer loop (SIL) time Coder with SIL and PIL” on page 61-
2
• “View and Compare Code
Execution Times” on page 61-
7
• “Analyze Code Execution
Data” on page 61-16
Embedded Processor-in-the- Execution Embedded • “Code Execution Profiling
hardware or loop (PIL) time Coder with SIL and PIL” on page 61-
instruction set 2
simulator • “View and Compare Code
Execution Times” on page 61-
7
• “Analyze Code Execution
Data” on page 61-16
Target support Real-time Execution Embedded • “Code Execution Profiling for
packages execution, PIL time Coder IDE and Toolchain Targets”
on page 76-13
• “Perform Execution-Time
Profiling for IDE and
Toolchain Targets” on page
76-16
Target support Real-time Stack Embedded • “Code Execution Profiling for
packages execution Coder IDE and Toolchain Targets”
on page 76-13
• “Perform Stack Profiling with
IDE and Toolchain Targets”
on page 76-22

56-13
56 Optimizations for Generated Code in Simulink Coder

Target Execution Type of Relevant See


Feature Profiling Products
Simulink Real- Real-time Execution Simulink Coder, • “Execution Profiling for Real-
Time execution time Simulink Real- Time Applications” (Simulink
Time Real-Time)

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

Optimize Generated Code by Combining Multiple for


Constructs
This example shows how the code generator combines for loops. The generated code
uses for constructs to represent a variety of modeling patterns, such as a matrix signal
or Iterator blocks. Using data dependency analysis, the code generator combines for
constructs to reduce static code size and runtime branching.

The benefits of optimizing for loops are:

• Reducing ROM and RAM consumption.


• Increasing execution speed.

for Loop Modeling Patterns

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.

/* Model step function */


void rtwdemo_forloop_step(void)
{
int32_T k;

/* MATLAB Function: '<Root>/Accum' */

56-16
See Also

/* MATLAB Function 'Accum': '<S1>:1' */


/* '<S1>:1:3' */
/* '<S1>:1:4' */
rtwdemo_forloop_Y.Out1 = 0.0;

/* '<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;
}

/* End of Switch: '<Root>/Switch' */

/* MATLAB Function: '<Root>/Accum' */


/* '<S1>:1:5' */
/* '<S1>:1:6' */
rtwdemo_forloop_Y.Out1 += (1.0 + (real_T)k) +
rtwdemo_forloop_DW.Delay_DSTATE[k];
}
}

Close the model.

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

• “For Loop” on page 14-37

56-18
Subnormal Number Performance

Subnormal Number Performance


Subnormal numbers, formerly known as denormal numbers in floating-point literature, fill
the underflow gap around zero in floating-point arithmetic. Subnormal values are a
special category of floating-point values that are too close to 0.0 to be represented as a
normalized value. The leading significand (mantissa) of a subnormal number is zero.
When adding and subtracting floating-point numbers, subnormal numbers prevent
underflow.

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.

However, in a real-time system, using subnormal numbers can dramatically increase


execution latency, resulting in excessive design margins and real-time overruns. If the
simulation or generated code performs calculations that produce or consume subnormal
numbers, the execution of these calculations can be up to 50 times slower than similar
calculations on normal numbers. The actual simulation or code execution time for
subnormal number calculations depends on your computer operating environment.
Typically, for desktop processors, the execution time for subnormal number calculations is
five times slower than similar calculations on normal numbers.

To minimize the possibility of execution slowdowns or overruns due to subnormal number


calculation latency, do one of the following:

• 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.

To detect a subnormal value for a single precision, 32-bit floating-point number:


1 Find the smallest normalized number on a MATLAB host. In the Command
Window, type:
>> SmallestNormalSingle = realmin('single')

In the C language, FLT_MIN , defined in float.h, is equivalent to


realmin('single').
2 Look for values in range:
0 < fabsf(x) < SmallestNormalSingle

56-19
56 Optimizations for Generated Code in Simulink Coder

To detect a subnormal value for a double precision, 64-bit floating-point number:


1 Find the smallest normalized number on a MATLAB host. In the Command
Window, type:
>> SmallestNormalDouble = realmin('double')

In the C language, DBL_MIN , defined in float.h, is equivalent to


realmin('double').
2 To detect a subnormal value, look for values in this range:
0 < fabs(x) < SmallestNormalDouble
• On your processor, set flush-to-zero mode or, with your compiler, specify an option to
disable subnormal numbers. Flush-to-zero modes treat a subnormal number as 0 when
it is an input to a floating-point operation. Underflow exceptions do not occur in flush-
to-zero mode.

For example, in Intel® processors, the flush-to-zero (FTZ) and denormals-are-zero


(DAZ) flags in the MXCSR register control floating-point calculations. For the gcc
compiler on Linux, -ffast-math sets abrupt underflow (FTZ), flush-to-zero, while –
O3 -ffast-math reverts to gradual underflow, using subnormal numbers.

For more information, see the IEEE Standard 754, IEEE Standard for Floating-Point
Arithmetic.

Simulation Time With and Without Subnormal Numbers


This model shows how using subnormal numbers increases simulation time by ~5 times.

Open the model ex_subnormal. The Gain is set to subnormal value


realmin('double')/2.

56-20
Subnormal Number Performance

To run a simulation, in the Command Window, type for k=1:5, tic;


sim('ex_subnormal'); toc,end. Observe the elapsed times for simulation using
subnormals, similar to the following:

>> for k=1:5, tic; sim('ex_subnormal'); toc,end


Elapsed time is 9.909326 seconds.
Elapsed time is 9.617966 seconds.
Elapsed time is 9.797183 seconds.
Elapsed time is 9.702397 seconds.
Elapsed time is 9.893946 seconds.

Set the Gain to a number, 2, that is not a subnormal value:

>> set_param('ex_subnormal/Gain', 'Gain', '2');

To run a simulation, in the Command Window, type for k=1:5, tic;


sim('ex_subnormal'); toc,end. Observe elapsed times for simulations that do not
use subnormal values, similar to the following:

>> for k=1:5, tic; sim('ex_subnormal'); toc,end


Elapsed time is 2.045123 seconds.
Elapsed time is 1.796598 seconds.
Elapsed time is 1.758458 seconds.
Elapsed time is 1.721721 seconds.
Elapsed time is 1.780569 seconds.

Flush Subnormal Numbers to Zero


This example shows how to flush single precision subnormal numbers to zero.

1 Open the model ex_flush_to_zero:

56-21
56 Optimizations for Generated Code in Simulink Coder

• Repeating Sequence Stair generates a sequence of numbers from two raised


to the power of 0 through two raised to the power of -165. The sequence
approaches zero.
• ConditionRealScalar flushes subnormal single precision values that are less
than realmin('single') to zero.

• 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:

• Select Enable stepping back.

56-22
See Also

• Select Pause simulation when time reaches and enter 121.


3 In the model window, run the simulation. The simulation pauses at T=121. The
displayed values:

• ConditionRealScalar output approaches zero.


• Repeating Sequence Stair output approaches zero.
4 Step the simulation forward to T=127. ConditionRealScalar flushes the
subnormal value output from Repeating Sequence Stair to zero.

5 Continue stepping the simulation forward. ConditionRealScalar flushes the


subnormal single precision values output from Repeating Sequence Stair to
zero. When T=150, the output of Repeating Squence Stair is itself zero.

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

Remove Code From Floating-Point to Integer


Conversions That Wraps Out-of-Range Values
In this section...
“Example Model” on page 56-24
“Generate Code Without Optimization” on page 56-25
“Generate Code with Optimization” on page 56-26

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.

Generate Code Without Optimization


1 Open the Model Configuration Parameters dialog box. On the Solver pane, for the
Type parameter, select Fixed-step.
2 On the Code Generation > Report pane, select Create code generation report.
3 On the Code Generation pane, select Generate code only, and then, in the model
window, press Ctrl+B. When code generation is complete, an HTML code generation
report opens.
4 In the Code Generation report, select the conversion_ex.c file and view the model
step function. The code generator applies the fmod function to handle out-of range-
results.

/* Model step function */


void conversion_ex_step(void)
{
real_T tmp;

/* 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);

Generate Code with Optimization


1 Open the Configuration Parameters dialog box. On the Optimization pane, select
Remove code from floating-point to integer conversions that wraps out-of-
range values. Generate code.
2 In the code generation report, select the conversion_ex.c file and view the model
step function. The generated code does not contain code that protects against out-of-
range values.

/* Model step function */


void conversion_ex_step(void)
{
/* DataTypeConversion: '<Root>/Data Type Conversion' incorporates:
* Inport: '<Root>/In1'
*/
Y = (uint8_T)U;

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

Remove Code That Maps NaN to Integer Zero


In this section...
“Example Model” on page 56-27
“Generate Code” on page 56-28
“Generate Code with Optimization” on page 56-29

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.

/* Model step function */


void nan_int_ex_step(void)
{
/* DataTypeConversion: '<Root>/Data Type Conversion' incorporates:
* Inport: '<Root>/In1'
*/
if (U < 256.0) {
if (U >= 0.0) {
Y = (uint8_T)U;
} else {
Y = 0U;
}
} else if (U >= 256.0) {

56-28
See Also

Y = MAX_uint8_T;
} else {
Y = 0U;
}

Generate Code with Optimization


1 Enable the Configuration Parameters > Optimization > Code generation >
Integer and fixed-point > Remove code from floating-point to integer
conversions that wraps out-of-range values parameter. Generate code.
2 In the Code Generation report, select the nan_int_ex.c section and view the model
step function. The generated code maps NaN to 255 and not integer zero. The
generated code is more efficient without the extra code that maps NaN to integer
zero, but the execution of the generated code does not produce the same results as
simulation for NaN values.

/* Model step function */


void nan_int_ex_step(void)
{
/* DataTypeConversion: '<Root>/Data Type Conversion' incorporates:
* Inport: '<Root>/In1'
*/
if (U < 256.0) {
if (U >= 0.0) {
Y = (uint8_T)U;
} else {
Y = 0U;
}
} else {
Y = MAX_uint8_T;
}

/* End of DataTypeConversion: '<Root>/Data Type Conversion' */

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

Disable Nonfinite Checks or Inlining for Math Functions


When the code generator produces code for math functions:

• If the model option Support non-finite numbers is selected, nonfinite number


checking is generated uniformly for math functions, without the ability to specify that
nonfinite number checking should be generated for some functions, but not for others.
• By default, inlining is applied uniformly for math functions, without the ability to
specify that inlining should be generated for some functions, while invocations should
be generated for others.

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

% Create an instance of the Code Replacement Library table for controlling


% function intrinsic inlining and nonfinite support

hTable = RTW.TflTable;

% Inline - true (if function needs to be inline)


% false (if function should not be inlined)
% SNF (support nonfinite) - ENABLE (if non-finite checking should be performed)
% DISABLE (if non-finite checking should NOT be performed)

56-31
56 Optimizations for Generated Code in Simulink Coder

% UNSPECIFIED (Default behavior)

% 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

100, 2, 'min', 'int32', 'int32', true, 'UNSPECIFIED');


registerCustomizationEntry(hTable, ...
100, 2, 'min', 'int16', 'int16', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'min', 'int8', 'int8', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'min', 'uint32', 'uint32', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'min', 'uint16', 'uint16', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'min', 'uint8', 'uint8', true, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'min', 'integer','integer',true, 'UNSPECIFIED');

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

100, 2, 'rem', 'int32', 'int32', false, 'UNSPECIFIED');


registerCustomizationEntry(hTable, ...
100, 2, 'rem', 'int16', 'int16', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'rem', 'int8', 'int8', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'rem', 'uint32', 'uint32', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'rem', 'uint16', 'uint16', false, 'UNSPECIFIED');
registerCustomizationEntry(hTable, ...
100, 2, 'rem', 'uint8', 'uint8', false, 'UNSPECIFIED');

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.

Save the file.


4 Optionally, perform a quick check of the syntactic validity of the customization table
entries by invoking the table definition file at the MATLAB command line (>> tbl =
crl_table_customization). Fix syntax errors that are flagged.
5 Optionally, view the customization table entries in the Code Replacement Viewer
(>> crviewer(crl_table_customization)). For more information about
viewing code replacement tables, see “Choose a Code Replacement Library”
(Simulink Coder).
6 To register these changes and make them appear in the Code replacement library
drop-down list located on the Code Generation > Interface pane of the
Configuration Parameters dialog box, first copy the following MATLAB function code
into an instance of the file rtwTargetInfo.m.

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)

% Register the CRL defined in local function locCrlRegFcn


cm.registerTargetInfo(@locCrlRegFcn);

end % End of RTWTARGETINFO

% Local function to define a CRL containing crl_table_customization


function thisCrl = locCrlRegFcn

% Instantiate a CRL registry entry - specify 'RTW' for GRT


thisCrl = RTW.TflRegistry('RTW');

% Define the CRL properties


thisCrl.Name = 'CRL Customization Example';
thisCrl.Description = 'Example of CRL Customization';
thisCrl.TableList = {'crl_table_customization'};
thisCrl.TargetHWDeviceType = {'*'};

end % End of LOCCRLREGFCN

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

Minimize Computations and Storage for Intermediate


Results at Block Outputs
In this section...
“Expression Folding” on page 56-37
“Example Model” on page 56-37
“Generate Code” on page 56-38
“Enable Optimization” on page 56-38
“Generate Code with Optimization” on page 56-39

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.

/* Model step function */


void exprfld_step(void)
{
/* Gain: '<Root>/Gain' incorporates:
* Inport: '<Root>/In1'
*/
exprfld_B.S1 = exprfld_P.Gain_Gain * exprfld_U.i1;

/* Gain: '<Root>/Gain1' incorporates:


* Inport: '<Root>/In2'
*/
exprfld_B.S2 = exprfld_P.Gain1_Gain * exprfld_U.i2;

/* Outport: '<Root>/Out1' incorporates:


* Product: '<Root>/Product'
*/
exprfld_Y.Out1 = exprfld_B.S1 * exprfld_B.S2;
}

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

Generate Code with Optimization


With expression folding, the code generator generates a single-line output computation,
as shown in the expfld.c file. The generated comments document the block parameters
that appear in the expression.

/* Model step function */


void exprfld_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Gain: '<Root>/Gain'
* Gain: '<Root>/Gain1'
* Inport: '<Root>/In1'
* Inport: '<Root>/In2'
* Product: '<Root>/Product'
*/
exprfld_Y.Out1 =
exprfld_P.Gain_Gain *
exprfld_U.i1 *
(exprfld_P.Gain1_Gain * exprfld_U.i2);
}

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

Inline Invariant Signals


You can optimize the generated code by selecting Inline invariant signals on the
Optimization pane. The generated code uses the numerical values of the invariant
signals instead of their symbolic names.

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.

Optimize Generated Code Using Inline Invariant Signals


This example shows how to use inline invariant signals to optimize the generated code.
This optimization transforms symbolic names of invariant signals into constant values.

The InlineInvariantSignals optimization:

• Reduces ROM and RAM consumption.


• Improves execution speed.

Example Model

Consider the model matlab:rtwdemo_inline_invariant_signals.

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();

Build the model using Simulink Coder.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_inline_invariant_signals


### Successful completion of build procedure for model: rtwdemo_inline_invariant_signal

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);

/* Output and update for atomic system: '<Root>/InlinedConstFcn' */


void rtwdemo_inline__InlinedConstFcn(int32_T rtu_In1,
B_InlinedConstFcn_rtwdemo_inl_T *localB, const ConstB_InlinedConstFcn_rtwdem_T
*localC)
{
/* Product: '<S1>/Product' */
localB->Product = rtu_In1 * localC->Sum_p;
}

56-41
56 Optimizations for Generated Code in Simulink Coder

Enable Optimization

1 Open the Configuration Parameters dialog box.


2 On the Optimization pane, select Inline Invariant Signals.

Alternatively, you can use the command-line API to enable the optimization:

set_param(model, 'InlineInvariantSignals', 'on');

Generate Code with Optimization

The generated code uses the numerical values of the folded constants instead of creating
an additional structure (rtwdemo_inline_invariant_ConstB).

Build the model using Simulink Coder.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_inline_invariant_signals


### Successful completion of build procedure for model: rtwdemo_inline_invariant_signal

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);

/* Output and update for atomic system: '<Root>/InlinedConstFcn' */


void rtwdemo_inline__InlinedConstFcn(int32_T rtu_In1,
B_InlinedConstFcn_rtwdemo_inl_T *localB)
{
/* Product: '<S1>/Product' */
localB->Product = rtu_In1 << 5;
}

Close the model and code generation report.

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

Inline Numeric Values of Block Parameters


This example shows how to optimize the generated code by inlining the numeric values of
block parameters. Block parameters include the Gain parameter of a Gain block and the
table data and breakpoint sets of an n-D Lookup Table block.

This optimization determines whether numeric block parameters occupy global memory
in the generated code. The optimization can:

• Improve execution speed.


• Reduce RAM and ROM consumption.

Explore Example Model

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 model contains blocks that have these numeric parameters:

• The Gain parameters of the Gain blocks


• The Constant value parameters of the Constant blocks
• The table data and breakpoint sets of the n-D Lookup Table blocks

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.

Generate Code Without Optimization

Create a temporary folder for the build and inspection process.

currentDir = pwd;
[~,cgDir] = rtwdemodir();

Disable the optimization by setting Configuration Parameters > Default parameter


behavior to Tunable.

set_param('rtwdemo_paraminline','DefaultParameterBehavior','Tunable')

Generate code from the model.

rtwbuild('rtwdemo_paraminline')

### Starting build procedure for model: rtwdemo_paraminline


### Successful completion of build procedure for model: 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

/* Block parameters (default storage) */


P_rtwdemo_paraminline_T rtwdemo_paraminline_P = {
/* Variable: MAX_LIFT
* Referenced by: '<Root>/Constant'
*/
10.0,

/* 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,

/* Computed Parameter: uDLookup_maxIndex

56-46
Inline Numeric Values of Block Parameters

* Referenced by: '<Root>/2D Lookup'


*/
{ 2U, 2U }
};

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);

/* Model step function */


void rtwdemo_paraminline_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Constant: '<Root>/Constant'
* Constant: '<Root>/Constant1'
* Gain: '<Root>/G1'
* Gain: '<Root>/G2'
* Inport: '<Root>/In1'
* Lookup_n-D: '<Root>/1D Lookup'
* Lookup_n-D: '<Root>/2D Lookup'
* Sum: '<Root>/Sum'
*/
rtwdemo_paraminline_Y.Out1 = rtwdemo_paraminline_P.G1_Gain *
rtwdemo_paraminline_U.In1 + rtwdemo_paraminline_P.G2_Gain * look2_binlx
(rtwdemo_paraminline_P.MAX_LIFT, look1_binlx
(rtwdemo_paraminline_P.SLIDER_POS, rtwdemo_paraminline_P.T1Break,
rtwdemo_paraminline_P.T1Data, 10U), rtwdemo_paraminline_P.T2Break,
rtwdemo_paraminline_P.T2Break, rtwdemo_paraminline_P.T2Data,
rtwdemo_paraminline_P.uDLookup_maxIndex, 3U);
}

Generate Code with Optimization

Set Default parameter behavior to Inlined.

set_param('rtwdemo_paraminline','DefaultParameterBehavior','Inlined')

Generate code from the model.

56-47
56 Optimizations for Generated Code in Simulink Coder

rtwbuild('rtwdemo_paraminline')

### Starting build procedure for model: rtwdemo_paraminline


### Successful completion of build procedure for model: 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);

/* Model step function */


void rtwdemo_paraminline_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Gain: '<Root>/G1'
* Inport: '<Root>/In1'
* Sum: '<Root>/Sum'
*/
rtwdemo_paraminline_Y.Out1 = 2.0 * rtwdemo_paraminline_U.In1 + 150.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.

Close the model and the code generation report.

bdclose('rtwdemo_paraminline')
rtwdemoclean;
cd(currentDir)

Preserve Block Parameter Tunability

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).

Inline Invariant Signals

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

Configure Loop Unrolling Threshold


The Loop unrolling threshold parameter on the Optimization pane determines when a
wide signal or parameter should be wrapped into a for loop and when it should be
generated as a separate statement for each element of the signal. The default threshold
value is 5.

For example, consider the model below:

The gain parameter of the Gain block is the vector myGainVec.

Assume that the loop unrolling threshold value is set to the default, 5.

If myGainVec is declared as

myGainVec = [1:10];

an array of 10 elements, myGainVec_P.Gain_Gain[], is declared within the


Parameters_model data structure. The size of the gain array exceeds the loop unrolling
threshold. Therefore, the code generated for the Gain block iterates over the array in a
for loop, as shown in the following code:

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];

an array of three elements, myGainVec_P.Gain_Gain[], is declared within the


Parameters data structure. The size of the gain array is below the loop unrolling
threshold. The generated code consists of inline references to each element of the array,
as in the code below.

/* 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

• “Optimize Generated Code by Combining Multiple for Constructs” on page 56-15


• “For Loop” on page 14-37

56-52
Use memcpy Function to Optimize Generated Code for Vector Assignments

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,

• Verify that your target supports the memcpy function.


• Determine whether your model uses signal vector assignments (such as
Y=expression) to move large amounts of data, for example, using the Selector block.

To apply 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];

/* Outport: '<Root>/Out2' incorporates:


* Inport: '<Root>/In2'
*/
vectorassign_Y.Out2[i] = vectorassign_U.In2[i];
}
}

Generate Code with Optimization


1 Go to the Optimization pane of the Configuration Parameters dialog box and select
the Use memcpy for vector assignment option. Leave the Memcpy threshold
(bytes) option at its default setting of 64. Apply the changes and regenerate code for
the model. When code generation completes, the HTML code generation report again
is displayed.
2 In the HTML code generation report, click the vectorassign.c section and inspect
the model output function. Notice that the vector assignments now are implemented
using memcpy function calls.

56-55
56 Optimizations for Generated Code in Simulink Coder

/* Model step function */


void vectorassign_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/In1'
*/
memcpy(&vectorassign_Y.Out1[0], &vectorassign_U.In1[0], 50U * sizeof(real_T));

/* Outport: '<Root>/Out2' incorporates:


* Inport: '<Root>/In2'
*/
memcpy(&vectorassign_Y.Out2[0], &vectorassign_U.In2[0], 50U * sizeof(real_T));
}

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

Generate Target Optimizations Within Algorithm Code


Some application components are hardware-specific and cannot simulate on a host
system. For example, consider a component that includes pragmas and assembly code for
enabling hardware instructions for saturate on add operations or a Fast Fourier
Transform (FFT) function.

The following table lists integration options to customize generated algorithm code with
target-specific optimizations.

Note Solutions marked with EC only require an Embedded Coder license.

If... Then... For More Information, See


You want to optimize the EC only—Implement “Optimize Generated Code By Developing and
execution speed and function and operator Using Code Replacement Libraries - Simulink®”
memory of the model replacements by using
code by replacing the Code
default math functions Replacement Tool,
and operators with code replacement
target-specific code library (CRL) API, and
Code Replacement
Viewer to create,
examine, validate, and
register hardware-
specific replacement
tables
You want to control how EC only—Design • rtwdemo_cscpredef
code generation (create) and apply • rtwdemo_importstruct
technology declares, custom storage classes
stores, and represents • rtwdemo_advsc
signals, tunable • “Apply Custom Storage Classes to Individual
parameters, block states, Signal, State, and Parameter Data Elements”
and data objects in on page 26-19
generated code

56-57
56 Optimizations for Generated Code in Simulink Coder

Note To simulate an algorithm that includes target-specific elements in a host


environment, you must create code that is equivalent to the target code and can run in
the host environment.

56-58
Remove Code for Blocks That Have No Effect on Computational Results

Remove Code for Blocks That Have No Effect on


Computational Results
This example shows how the code generator optimizes generated code by removing code
that has no effect on computational results. This optimization:

• Increases execution speed.


• Reduces ROM consumption.

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

Create a temporary folder for the build and inspection process.

currentDir=pwd;
[~,cgDir]=rtwdemodir();

Build the model.

set_param(model,'BlockReduction','off');
rtwbuild(model)

### Starting build procedure for model: rtwdemo_blockreduction


### Successful completion of build procedure for model: rtwdemo_blockreduction

56-59
56 Optimizations for Generated Code in Simulink Coder

Here is the code from rtwdemo_blockreduction.c.

cfile = fullfile(cgDir,'rtwdemo_blockreduction_ert_rtw','rtwdemo_blockreduction.c');
rtwdemodbtype(cfile, '/* Model step function */',...
'/* Model initialize function */', 1, 0);

/* Model step function */


void rtwdemo_blockreduction_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Gain: '<Root>/Gain'
* Inport: '<Root>/In1'
*/
rtwdemo_blockreduction_Y.Out1 = 1.0 * rtwdemo_blockreduction_U.In1;
}

Enable Optimization

1 Open the Configuration Parameters dialog box.


2 Select Block reduction. This optimization is on by default.

Alternately, use the command-line API to enable the optimization.

set_param(model,'BlockReduction','on');

Generate Code with Optimization

rtwbuild(model)

### Starting build procedure for model: rtwdemo_blockreduction


### Successful completion of build procedure for model: rtwdemo_blockreduction

Here is the optimized code from rtwdemo_blockreduction.c.

cfile = fullfile(cgDir,'rtwdemo_blockreduction_ert_rtw','rtwdemo_blockreduction.c');
rtwdemodbtype(cfile, '/* Model step function */',...
'/* Model initialize function */', 1, 0);

/* Model step function */


void rtwdemo_blockreduction_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/In1'

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

Eliminate Dead Code Paths in Generated Code


This example shows how the code generator eliminates dead (that is, unused) code paths
from generated code. This optimization increases execution speed and conserves ROM
and RAM consumption.

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);

Generate Code with an Enabled Assertion Block


1 For the Assertion block, open the block parameters dialog box.
2 Select the Enable assertion box. Alternatively, use the command-line API to enable
the Assertion block.
set_param([model '/Assert1'], 'Enabled', 'on');

Create a temporary folder for the build and inspection process.


currentDir = pwd;
[~,cgDir] = rtwdemodir();

Build the model.


rtwbuild(model)

### Starting build procedure for model: rtwdemo_deadpathElim


### Successful completion of build procedure for model: rtwdemo_deadpathElim

56-62
Eliminate Dead Code Paths in Generated Code

Because the Assertion block is enabled, these lines of rtwdemo_deadpathElim.c


include code for the Gain and Assertion blocks.
cfile = fullfile(cgDir,'rtwdemo_deadpathElim_grt_rtw','rtwdemo_deadpathElim.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize function */', 0, 1);

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;

/* Assertion: '<Root>/Assert1' incorporates:


* Gain: '<Root>/G1'
*/
utAssert(2.0 * rtwdemo_deadpathElim_Y.Out1 != 0.0);
}

Generate Code with a Disabled Assertion Block

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.

Alternatively, use the command-line API to disable the Assertion block.


set_param([model '/Assert1'], 'Enabled', 'off');

Build the model.


rtwbuild(model)

### Starting build procedure for model: rtwdemo_deadpathElim


### Successful completion of build procedure for model: rtwdemo_deadpathElim

Because the Assertion block is disabled, these lines of rtwdemo_deadpathElim.c do not


include code for the Gain and Assertion blocks.
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize function */', 0, 1);

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;
}

Close the model and clean-up.

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

Floating-Point Multiplication to Handle a Net Slope


Correction
This example shows how to use floating-point multiplication to handle a net slope
correction. When converting floating-point data types to fixed-point data types in the
generated code, a net slope correction is one method of scaling fixed-point data types.
Scaling the fixed-point data types avoids overflow conditions and minimizes quantization
errors.

For processors that support efficient multiplication, using floating-point multiplication to


handle a net slope correction improves code efficiency. If the net slope correction has a
value that is not a power of two, using division improves precision.

Note: This example requires a Fixed-Point Designer™ license.

Example

In the model rtwdemo_float_mul_for_net_slope_correction, a Convert block converts an


input signal from a floating-point data type to a fixed-point data type. The net slope
correction has a value of 3.
model = 'rtwdemo_float_mul_for_net_slope_correction';
open_system(model);

Generate Code

Create a temporary folder for the build and inspection process.


currentDir = pwd;
[~,cgDir] = rtwdemodir();

Build the model.

56-65
56 Optimizations for Generated Code in Simulink Coder

rtwbuild(model)

### Starting build procedure for model: rtwdemo_float_mul_for_net_slope_correction


### Successful completion of build procedure for model: rtwdemo_float_mul_for_net_slope

In these lines of rtwdemo_float_mul_for_net_slope_correction.c code, the code


generator divides the input signal by 3.0F .

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);

/* Model step function */


void rtwdemo_float_mul_for_net_slope_correction_step(void)
{
/* Outport: '<Root>/Output' incorporates:
* DataTypeConversion: '<Root>/Data Type Conversion'
* Inport: '<Root>/Input'
*/
rtY.Output = (int16_T)(real32_T)floor((real_T)(rtU.Input / 3.0F));
}

Enable Optimization

1 Open the Configuration Parameters dialog box.


2 On the Math and Data Types pane, select Use floating-point multiplication to
handle net slope corrections. This optimization is on by default.

Alternatively, you can use the command-line API to enable the optimization.

set_param(model, 'UseFloatMulNetSlope', 'on');

Generate Code with Optimization

rtwbuild(model)

### Starting build procedure for model: rtwdemo_float_mul_for_net_slope_correction


### Successful completion of build procedure for model: rtwdemo_float_mul_for_net_slope

In the optimized code, the code generator multiplies the input signal by the reciprocal of
3.0F , that is 0.333333343F .

rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);

56-66
See Also

/* Model step function */


void rtwdemo_float_mul_for_net_slope_correction_step(void)
{
/* Outport: '<Root>/Output' incorporates:
* DataTypeConversion: '<Root>/Data Type Conversion'
* Inport: '<Root>/Input'
*/
rtY.Output = (int16_T)(real32_T)floor((real_T)(rtU.Input * 0.333333343F));
}

Close the model and the code generation report.

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

Use Conditional Input Branch Execution


This example shows how to optimize the generated code for a model that contains Switch
and Multiport Switch blocks. When you select the model configuration parameter
Conditional input branch execution, Simulink executes only blocks that compute the
control input and data input that the control input selects. This optimization improves
execution speed.

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

The Conditional input branch execution parameter is on by default. Enter the


following command-line API to turn off the parameter.

set_param(model, 'ConditionallyExecuteInputs', 'off');

Create a temporary folder for the build and inspection process.

currentDir=pwd;
[~,cgDir]=rtwdemodir();

Build the model.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_condinput


### Successful completion of build procedure for model: rtwdemo_condinput

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);

/* Model step function */


void rtwdemo_condinput_step(void)
{
/* Switch: '<Root>/ Switch2' incorporates:
* Constant: '<Root>/ C_10'
* Constant: '<Root>/C_5'
* Gain: '<Root>/ G3'
* Inport: '<Root>/input'
* RelationalOperator: '<Root>/Relational Operator'
* Sum: '<Root>/ Sum'
*/
if (rtwdemo_condinput_U.input >= -5.0) {
rtwdemo_condinput_Y.output = 3.0 * rtwdemo_condinput_U.input;
} else {
rtwdemo_condinput_Y.output = rtwdemo_condinput_U.input + -10.0;
}

/* End of Switch: '<Root>/ Switch2' */

56-70
Use Conditional Input Branch Execution

/* Switch: '<Root>/Switch1' incorporates:


* Constant: '<Root>/C5'
* Inport: '<Root>/input'
* RelationalOperator: '<Root>/Relational Operator1'
*/
if (rtwdemo_condinput_U.input >= 5.0) {
/* Outport: '<Root>/output' incorporates:
* Constant: '<Root>/ C10'
* Sum: '<Root>/ Sum1'
*/
rtwdemo_condinput_Y.output = rtwdemo_condinput_U.input + 10.0;
}

/* End of Switch: '<Root>/Switch1' */


}

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

1 Open the Configuration Parameters dialog box.


2 Select the Conditional input branch execution parameter. Alternatively, you can
use the command-line API to enable the optimization.

set_param(model, 'ConditionallyExecuteInputs','on');

Generate Code with Optimization

rtwbuild(model)
cfile = fullfile(cgDir,'rtwdemo_condinput_grt_rtw','rtwdemo_condinput.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);

### Starting build procedure for model: rtwdemo_condinput


### Successful completion of build procedure for model: rtwdemo_condinput

/* Model step function */


void rtwdemo_condinput_step(void)
{
/* Switch: '<Root>/Switch1' incorporates:
* Constant: '<Root>/C5'
* Constant: '<Root>/C_5'
* Inport: '<Root>/input'

56-71
56 Optimizations for Generated Code in Simulink Coder

* RelationalOperator: '<Root>/Relational Operator'


* RelationalOperator: '<Root>/Relational Operator1'
* Switch: '<Root>/ Switch2'
*/
if (rtwdemo_condinput_U.input >= 5.0) {
/* Outport: '<Root>/output' incorporates:
* Constant: '<Root>/ C10'
* Sum: '<Root>/ Sum1'
*/
rtwdemo_condinput_Y.output = rtwdemo_condinput_U.input + 10.0;
} else if (rtwdemo_condinput_U.input >= -5.0) {
/* Switch: '<Root>/ Switch2' incorporates:
* Gain: '<Root>/ G3'
* Outport: '<Root>/output'
*/
rtwdemo_condinput_Y.output = 3.0 * rtwdemo_condinput_U.input;
} else {
/* Outport: '<Root>/output' incorporates:
* Constant: '<Root>/ C_10'
* Sum: '<Root>/ Sum'
* Switch: '<Root>/ Switch2'
*/
rtwdemo_condinput_Y.output = rtwdemo_condinput_U.input + -10.0;
}

/* End of Switch: '<Root>/Switch1' */


}

The generated code contains one if statement. The generated code for Switch1:Path2
only executes if the if statement evaluates to false.

Close Model and Code Generation Report

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

Optimize Generated Code for Complex Signals


This example shows how Simulink Coder handles complex signals efficiently. To view the
data types of the signals, update the model using Simulation > Update Diagram.
Complex signals are represented as structures in generated code. Simulink Coder
performs various optimizations on these structures. For example:

• 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

• “Minimize Computations and Storage for Intermediate Results at Block Outputs” on


page 56-37
• “Disable Nonfinite Checks or Inlining for Math Functions” on page 56-31

56-76
Speed Up Linear Algebra in Code Generated from a MATLAB Function Block

Speed Up Linear Algebra in Code Generated from a


MATLAB Function Block
To improve the execution speed of code generated for certain linear algebra functions in a
MATLAB Function block, specify that the code generator produce LAPACK calls. LAPACK
is a software library for numerical linear algebra. The code generator uses the LAPACKE
C interface to LAPACK. If you specify that you want to generate LAPACK calls, and the
input arrays for the linear algebra functions meet certain criteria, the code generator
produces the LAPACK calls. Otherwise, the code generator produces code for the linear
algebra functions.

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.

Specify LAPACK Library


To generate LAPACK calls, you must have access to a LAPACK callback class. A LAPACK
callback class specifies the LAPACK library and LAPACKE header file for the LAPACK
calls. To indicate that you want to generate LAPACK calls and that you want to use a
specific LAPACK library, specify the name of the LAPACK callback class. In the
Configuration Parameters dialog box, set Custom LAPACK library callback to the name
of the callback class, for example, useMyLAPACK.

Write LAPACK Callback Class


To specify the locations of a particular LAPACK library and LAPACKE header file, write a
LAPACK callback class. Share the callback class with others who want to use this LAPACK
library for LAPACK calls in generated code.

The callback class must derive from the abstract class coder.LAPACKCallback. Use
this example callback class as a template.

classdef useMyLAPACK < coder.LAPACKCallback


methods (Static)
function hn = getHeaderFilename()
hn = 'mylapacke_custom.h';
end
function updateBuildInfo(buildInfo, buildctx)

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

You must provide the getHeaderFilename and updateBuildInfo methods. The


getHeaderFilename method returns the LAPACKE header file name. In the example
callback class, replace mylapacke_custom.h with the name of your LAPACKE header
file. The updateBuildInfo method provides the information required for the build
process to link to the LAPACK library. Use code like the code in the template to specify
the location of header files and the full path name of the LAPACK library. In the example
callback class, replace mylapack with the name of your LAPACK library.

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');

Generate LAPACK Calls by Specifying a LAPACK Callback Class


This example shows how to generate code that calls LAPACK functions in a specific
LAPACK library. For this example, assume that the LAPACK callback class useMyLAPACK
specifies the LAPACK library that you want.

1 Create a Simulink model.


2 Add a MATLAB Function block to the model.
3 In the MATLAB Function block, add code that calls a linear algebra function. For
example, add the function mysvd that calls the MATLAB function svd.
function s = mysvd(A)
%#codegen
s = svd(A);
end
4 Add a Constant block to the left of the MATLAB Function block. Set the value to
zeros(500).

56-78
Speed Up Linear Algebra in Code Generated from a MATLAB Function Block

5 Add an Outport block to the right of the MATLAB Function block.


6 Connect the blocks.

7 Set the Configuration Parameters > Code Generation > Advanced parameters
> Custom LAPACK library callback parameter to useMyLAPACK.

The callback class must be on the MATLAB path.


8 Build the model.

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:

info_t = LAPACKE_dgesvd( ...


LAPACK_COL_MAJOR, 'N', 'N', (lapack_int)500, ...
(lapack_int)500, &A[0], (lapack_int)500, &S[0], ...
NULL, (lapack_int)1, NULL,(lapack_int)1, &superb[0]);

Locate LAPACK Library in Execution Environment


The LAPACK library must be available in your execution environment. If your LAPACK
library is shared, use environment variables or linker options to specify the location of the
LAPACK library.

• On a Windows platform, modify the PATH environment variable.


• On a Linux platform, modify the LD_LIBRARY_PATH environment variable or use the
rpath linker option.
• On a macOS platform, modify the DYLD_LIBRARY_PATH environment variable or use
the rpath linker option.

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

Speed Up Fast Fourier Transforms in Code Generated


from a MATLAB Function Block
This example shows how to generate calls to a specific installed FFTW library. For more
information about FFTW, see www.fftw.org.

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.

Install an FFTW Library


If you do not have access to an installed FFTW library, version 3.2 or later, then you must
install one.

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

Write FFT Callback Class


To specify your installation of the FFTW library, write an FFT callback class. Share the
callback class with others who want to use this FFTW library for FFTW calls.

The callback class must derive from the abstract class


coder.fftw.StandaloneFFTW3Interface. Use this example callback class as a
template.

% copyright 2017 The MathWorks, Inc.

classdef useMyFFTW < coder.fftw.StandaloneFFTW3Interface

methods (Static)
function th = getNumThreads
coder.inline('always');
th = int32(coder.const(1));
end

function updateBuildInfo(buildInfo, ctx)


fftwLocation = '/usr/lib/fftw';
includePath = fullfile(fftwLocation, 'include');
buildInfo.addIncludePaths(includePath);
libPath = fullfile(fftwLocation, 'lib');

%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

Implement the updateBuildInfo and getNumThreads methods. In the


updateBuildInfo method, set fftwLocation to the full path for your installation of
the library. Set includePath to the full path of the folder that contains fftw3.h. Set
libPath to the full path of the folder that contains the library files. If your FFTW
installation uses multiple threads, modify the getNumThreads method to return the
number of threads that you want to use.

Optionally, you can implement these methods:

56-82
Speed Up Fast Fourier Transforms in Code Generated from a MATLAB Function Block

• getPlanMethod to specify the FFTW planning method. See


coder.fftw.StandaloneFFTW3Interface.
• lock and unlock to synchronize multithreaded access to the FFTW planning process.
See “Synchronize Multithreaded FFTW Planning in Code Generated from a MATLAB
Function Block” (Simulink Coder).

Generate FFTW Calls by Specifying an FFT Callback Class


1 Create a Simulink model.
2 Add a MATLAB Function block to the model.
3 In the MATLAB Function block, add code that calls a MATLAB FFT function. For
example, add the function myfft that calls the MATLAB function fft.

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 callback class must be on the MATLAB path.


6 Build the model.

Locate FFTW Library in Execution Environment

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.

• On a Windows platform, modify the PATH environment variable.


• On a Linux platform, modify the LD_LIBRARY_PATH environment variable or use the
rpath linker option.

56-83
56 Optimizations for Generated Code in Simulink Coder

• On a macOS platform, modify the DYLD_LIBRARY_PATH environment variable or use


the rpath linker option.

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

Synchronize Multithreaded FFTW Planning in Code


Generated from a MATLAB Function Block
This example shows how to generate code that synchronizes multithreaded access to the
FFTW planning process for FFTW library calls 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).

You must have:

• Access to an installed FFTW library.


• A compiler that supports the OpenMP library. To use a different library, such as
pthreads, modify the supporting C code accordingly.

56-85
56 Optimizations for Generated Code in Simulink Coder

Create a Model with a MATLAB Function Block That Calls an


FFT Function
1 Create a Simulink model and add a MATLAB Functon block to it.
2 Add this code to the MATLAB Function block.

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.

Write Supporting C Code


Write C functions that initialize, set, and unset a lock. This example uses the OpenMP
library to manage the lock. For a different library, modify the code accordingly.

• Create a file mylock.c that contains this C code:

#include "mylock.h"
#include "omp.h"

static omp_nest_lock_t lockVar;

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);
}

• Create a header file mylock.h that contains:


#ifndef MYLOCK_H
#define MYLOCK_H

void mylock_initialize(void);
void mylock(void);
void myunlock(void);

#endif

Create an FFT Library Callback Class


Write an FFT callback class myfftcb that:

• Specifies the FFTW library.


• Implements lock and unlock methods that call the supporting C code to control
access to the FFTW planning.

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

function updateBuildInfo(buildInfo, ctx)


fftwLocation = '\usr\lib\fftw';
includePath = fullfile(fftwLocation, 'include');
buildInfo.addIncludePaths(includePath);
libPath = fullfile(fftwLocation, 'lib');

%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

Configure Code Generation Parameters and Build the Model


1 Configure code generation to use the FFTW callback class and the C code called by
the lock and unlock methods. Configure code generation to generate a call to
mylock_initialize in the initialization code.

In the Configuration Parameters dialog box:

• Set Custom FFT library callback to myfftcb.


• In Code Generation > Custom Code, under Additional build information, set
Source files to mylock.c.
• In Code Generation > Custom Code, under Insert custom C code in
generated, set Initialize function to mylock_initialize();.

56-88
See Also

2 Build the model.

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

Control Memory Allocation for Variable-Size Arrays in a


MATLAB Function Block
Dynamic memory allocation allocates memory on the heap as needed at run time, instead
of allocating memory statically on the stack. You can use dynamic memory allocation for
arrays inside a MATLAB Function block.

You cannot use dynamic memory allocation for:

• 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 is beneficial when:

• You do not know the upper bound of an array.


• You do not want to allocate memory on the stack for large arrays.

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:

• Provide upper bounds for variable-size arrays on page 56-90.


• Disable dynamic memory allocation for MATLAB Function blocks on page 56-91.
• Modify the dynamic memory allocation threshold on page 56-91.

Provide Upper Bounds for Variable-Size Arrays


For an unbounded variable-size array, the code generator allocates memory dynamically
on the heap. For a bounded variable-size array, if the size, in bytes, is less than the
dynamic memory allocation threshold, the code generator allocates memory statically on
the stack. To avoid dynamic memory allocation, provide upper bounds for the array
dimensions so that the size of the array, in bytes, is less than the dynamic memory
allocation threshold. See “Specify Upper Bounds for Variable-Size Arrays” (Simulink).

56-90
See Also

Disable Dynamic Memory Allocation for MATLAB Function


Blocks
By default, dynamic memory allocation for MATLAB Function blocks is enabled for GRT-
based targets and disabled for ERT-based targets. To change the setting, in the
Configuration Parameters dialog box, clear or select Dynamic memory allocation in
MATLAB Function blocks.

If you disable dynamic memory allocation, you must provide upper bounds for variable-
size arrays.

Modify the Dynamic Memory Allocation Threshold


Instead of disabling dynamic memory allocation for all variable-size arrays, you can use
the dynamic memory allocation threshold to specify when the code generator uses
dynamic memory allocation.

Use the dynamic memory allocation threshold to:

• 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

• “Use Dynamic Memory Allocation for Variable-Size Arrays in a MATLAB Function


Block” (Simulink)

56-92
Optimize Memory Usage for Time Counters

Optimize Memory Usage for Time Counters


This example shows how to optimize the amount of memory that the code generator
allocates for time counters. The example optimizes the memory that stores elapsed time,
the interval of time between two events.

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:

• Lifespan < 0.25 sec: 8 bits


• Lifespan < 1 min: 16 bits
• Lifespan < 49 days: 32 bits
• Lifespan > 50 days: 64 bits

A 64-bit time counter does not overflow for 590 million years.

Open Example Model

Open the example model rtwdemo_abstime.

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

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.

Generate Code and Report

1. Create a temporary folder for the build and inspection process.

2. Configure the model for the code generator to use the GRT system target file and a
lifespan of inf days.

3. Build the model.

### Starting build procedure for model: rtwdemo_abstime


### Successful completion of build procedure for model: rtwdemo_abstime

Review Generated Code

Open the generated source file rtwdemo_abstime.c.

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;
};

/* Block states (default storage) */


extern DW_rtwdemo_abstime_T rtwdemo_abstime_DW;

/* External inputs (root inport signals with default storage) */


extern ExtU_rtwdemo_abstime_T rtwdemo_abstime_U;

/* External outputs (root outports fed by signals with default storage) */


extern ExtY_rtwdemo_abstime_T rtwdemo_abstime_Y;

/* Model entry point functions */


extern void rtwdemo_abstime_initialize(void);
extern void rtwdemo_abstime_step(int_T tid);
extern void rtwdemo_abstime_terminate(void);

/* Real-time Model object */


extern RT_MODEL_rtwdemo_abstime_T *const rtwdemo_abstime_M;

/*-
* 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_ */

Four 32-bit unsigned integers, clockTick1 , clockTickH1 , clockTick2 , and


clockTickH2 are counters for storing the elapsed time of subsystems SS2 and SS3.

Enable Optimization and Regenerate Code

1. Reconfigure the model to set the lifespan to 1 day.

2. Build the model.


### Starting build procedure for model: rtwdemo_abstime
### Successful completion of build procedure for model: rtwdemo_abstime

Review the Regenerated Code

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;
};

/* Block states (default storage) */


extern DW_rtwdemo_abstime_T rtwdemo_abstime_DW;

/* External inputs (root inport signals with default storage) */


extern ExtU_rtwdemo_abstime_T rtwdemo_abstime_U;

/* External outputs (root outports fed by signals with default storage) */


extern ExtY_rtwdemo_abstime_T rtwdemo_abstime_Y;

56-97
56 Optimizations for Generated Code in Simulink Coder

/* Model entry point functions */


extern void rtwdemo_abstime_initialize(void);
extern void rtwdemo_abstime_step(int_T tid);
extern void rtwdemo_abstime_terminate(void);

/* Real-time Model object */


extern RT_MODEL_rtwdemo_abstime_T *const rtwdemo_abstime_M;

/*-
* 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

• “Optimization Pane” (Simulink Coder)


• “Timers in Asynchronous Tasks” (Simulink Coder)

56-98
See Also

• “Time-Based Scheduling and Code Generation” (Simulink Coder)

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

Optimize Generated Code Using Boolean Data for


Logical Signals
Optimize generated code by storing logical signals as Boolean data. When you select the
model configuration parameter Implement logic signals as Boolean data (vs.
double), blocks that generate logic signals output Boolean signals.

The optimization:

• Reduces the ROM and RAM consumption.


• Improves execution speed.

Example Model

Consider the model rtwdemo_logicalAsBoolean. The outputs of the Relational


Operator, Logical Operator and HitCrossing blocks are double, even though they
represent logical data.
model = 'rtwdemo_logicalAsBoolean';
open_system(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();

Build the model.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_logicalAsBoolean


### Successful completion of build procedure for model: rtwdemo_logicalAsBoolean

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);

/* External outputs (root outports fed by signals with default storage) */


typedef struct {
real_T Out1; /* '<Root>/Out1' */
real_T Out2; /* '<Root>/Out2' */
real_T Out3; /* '<Root>/Out3' */
} ExtY_rtwdemo_logicalAsBoolean_T;

Enable Optimization

1 Open the Configuration Parameters dialog box.


2 Select the Implement logic signals as Boolean data (vs. double) parameter.

Alternatively, you can use the command-line API to enable the optimization:

set_param(model,'BooleanDataType','on');

Generate Code with Optimization

The generated code stores the logical signal output as Boolean data.

Build the model.

56-101
56 Optimizations for Generated Code in Simulink Coder

rtwbuild(model)

### Starting build procedure for model: rtwdemo_logicalAsBoolean


### Successful completion of build procedure for model: rtwdemo_logicalAsBoolean

View the generated code with the optimization. These lines of code are in
rtwdemo_logicalAsBoolean.h.

rtwdemodbtype(hfile,'/* External outputs','/* Parameters (default storage) */',1,0);

/* External outputs (root outports fed by signals with default storage) */


typedef struct {
boolean_T Out1; /* '<Root>/Out1' */
boolean_T Out2; /* '<Root>/Out2' */
boolean_T Out3; /* '<Root>/Out3' */
} ExtY_rtwdemo_logicalAsBoolean_T;

Close the model and code generation report.

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

Reduce Memory Usage for Boolean and State


Configuration Variables
1 Open the Model Configuration Parameters dialog box.
2 In the Model Configuration Parameters dialog box, select the Optimization pane.
3 Choose from these options:

• 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:

• An external mode simulation


• A target that specifies an explicit structure alignment

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

Customize Stack Space Allocation


Your application might be constrained by limited memory. Controlling the maximum
allowable size for the stack is one way to modify whether data is defined as local or global
in the generated code. You can limit the use of stack space by specifying a positive integer
value for the “Maximum stack size (bytes)” (Simulink Coder) parameter, on the
Optimization pane of the Configuration parameter dialog box. Specifying the maximum
allowable stack size provides control over the number of local and global variables in the
generated code. Specifically, lowering the maximum stack size might generate more
variables into global structures. The number of local and global variables help determine
the required amount of stack space for execution of the generated code.

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:

set_param(model_name, 'MaxStackSize', 65000);

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.

%assign MaxStackSize = 4096

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

Optimize Generated Code Using memset Function


This example shows how to optimize the generated code by using the memset function to
clear the internal storage. When you select the model configuration parameter Use
memset to initialize floats and doubles to 0.0, the memset function clears internal
storage, regardless of type, to the integer bit pattern 0 (that is, all bits are off).

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:

• Reduces ROM consumption.


• Improves execution speed.

Example Model

Consider the model matlab:rtwdemo_memset.

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();

Build the model.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_memset


### Successful completion of build procedure for model: rtwdemo_memset

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);

/* Model initialize function */


void rtwdemo_memset_initialize(void)
{
/* Registration code */

/* initialize error status */


rtmSetErrorStatus(rtwdemo_memset_M, (NULL));

/* external outputs */
{
int32_T i;
for (i = 0; i < 50; i++) {
rtwdemo_memset_Y.Out1[i] = 0.0;
}
}

{
int32_T i;

/* ConstCode for Outport: '<Root>/Out1' */


for (i = 0; i < 50; i++) {
rtwdemo_memset_Y.Out1[i] = 56.0;
}

/* End of ConstCode for Outport: '<Root>/Out1' */


}
}

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');

Generate Code with Optimization

The code generator uses the memset function to initialize the Constant block values.

Build the model.


rtwbuild(model)

### Starting build procedure for model: rtwdemo_memset


### Successful completion of build procedure for model: rtwdemo_memset

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);

/* Model initialize function */


void rtwdemo_memset_initialize(void)
{
/* Registration code */

/* initialize error status */


rtmSetErrorStatus(rtwdemo_memset_M, (NULL));

/* external outputs */
(void) memset(&rtwdemo_memset_Y.Out1[0], 0,
50U*sizeof(real_T));

{
int32_T i;

/* ConstCode for Outport: '<Root>/Out1' */


for (i = 0; i < 50; i++) {
rtwdemo_memset_Y.Out1[i] = 56.0;
}

56-108
See Also

/* End of ConstCode for Outport: '<Root>/Out1' */


}
}

Close the model and the code generation report.

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

Vector Operation Optimization


This example shows how Simulink® Coder™ optimizes generated code by setting block
output that generates vectors to scalars, for blocks such as the Mux, Sum, Gain, and Bus.
This optimization reduces stack memory by replacing temporary local arrays with local
variables.

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();

Build the model.

rtwbuild(model)

56-110
Vector Operation Optimization

### Starting build procedure for model: rtwdemo_VectorOptimization


### Successful completion of build procedure for model: rtwdemo_VectorOptimization

The optimized code is in rtwdemo_VectorOptimization.c. The signals tmp1 and tmp2


are the local variables rtb_tmp1 and rtb_tmp2.
cfile = fullfile(cgDir,'rtwdemo_VectorOptimization_grt_rtw',...
'rtwdemo_VectorOptimization.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);

/* Model step function */


void rtwdemo_VectorOptimization_step(void)
{
int32_T i;
real_T rtb_tmp2;
real_T rtb_tmp1;
real_T rtb_Sum3;
for (i = 0; i < 10; i++) {
/* Gain: '<Root>/G2' incorporates:
* UnitDelay: '<Root>/X2'
*/
rtb_tmp2 = 0.3 * rtwdemo_VectorOptimization_DW.X2_DSTATE[i];

/* Gain: '<Root>/G1' incorporates:


* UnitDelay: '<Root>/X1'
*/
rtb_tmp1 = 0.2 * rtwdemo_VectorOptimization_DW.X1_DSTATE[i];

/* Sum: '<Root>/Sum3' incorporates:


* Gain: '<Root>/G3'
* Inport: '<Root>/In2'
* Sum: '<Root>/Sum1'
* Sum: '<Root>/Sum2'
* UnitDelay: '<Root>/X3'
*/
rtb_Sum3 = ((rtwdemo_VectorOptimization_U.In2[i] - 0.4 *
rtwdemo_VectorOptimization_DW.X3_DSTATE[i]) - rtb_tmp2) -
rtb_tmp1;

/* Outport: '<Root>/Out2' */
rtwdemo_VectorOptimization_Y.Out2[i] = rtb_Sum3;

/* Update for UnitDelay: '<Root>/X3' */


rtwdemo_VectorOptimization_DW.X3_DSTATE[i] = rtb_tmp2;

56-111
56 Optimizations for Generated Code in Simulink Coder

/* Update for UnitDelay: '<Root>/X2' */


rtwdemo_VectorOptimization_DW.X2_DSTATE[i] = rtb_tmp1;

/* Update for UnitDelay: '<Root>/X1' */


rtwdemo_VectorOptimization_DW.X1_DSTATE[i] = rtb_Sum3;
}
}

Close the model and code generation report.

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

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

Generate Code Without Optimization


1 Open the Model Configuration Parameters dialog box. Select the Solver pane. For
the Type parameter, select Fixed-step.
2 Clear the Configuration Parameters > Signal storage reuse parameter.
3 Select the Code Generation > Report pane and select Create code generation
report.
4 Select the Code Generation pane. Select Generate code only, and then, in the
model window, press Ctrl+B. When code generation is complete, an HTML code
generation report appears.
5 In the code generation report, select the local_variable_ex.c section and view
the model step function. The Gain block outputs are the global variables
local_variable_ex_B.G2 and local_variable_ex_B.G1.

/* Model step function */


void local_variable_ex_step(void)
{
/* Switch: '<Root>/Switch' incorporates:
* Inport: '<Root>/In1'
*/
if (local_variable_ex_U.In1 >= 0.0) {
/* Gain: '<Root>/G2' */
local_variable_ex_B.G2 = 2.0 * local_variable_ex_U.In1;

/* 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;
}

/* End of Switch: '<Root>/Switch' */

Enable Local Block Outputs and Generate Code


1 Select the Configuration Parameters > Signal Storage Reuse parameter. The
Signal Storage Reuse enables the following optimization parameters:

56-114
Enable and Reuse Local Block Outputs in Generated Code

• Enable local block outputs


• Reuse local block outputs
• Eliminate superfluous local variables (expression folding)
2 Clear Reuse local block outputs and Eliminate superfluous local variables
(expression folding).
3 Generate code and view the model step function. There are three local variables in
the model step function because you selected the optimization parameter Enable
Local Block Outputs. The local variables rtb_G2 and rtb_G1 hold the outputs of
the Gain blocks. The local variable rtb_Switch holds the output of the Switch block.

/* Model step function */


void local_variable_ex_step(void)
{
real_T rtb_Switch;
real_T rtb_G2;
real_T rtb_G1;

/* Switch: '<Root>/Switch' incorporates:


* Inport: '<Root>/In1'
*/
if (local_variable_ex_U.In1 >= 0.0) {
/* Gain: '<Root>/G2' */
rtb_G2 = 2.0 * local_variable_ex_U.In1;
rtb_Switch = rtb_G2;
} else {
/* Gain: '<Root>/G1' */
rtb_G1 = 3.0 * local_variable_ex_U.In1;
rtb_Switch = rtb_G1;
}

/* End of Switch: '<Root>/Switch' */

/* Outport: '<Root>/Out1' */
local_variable_ex_Y.Out1 = rtb_Switch;

Reuse Local Block Outputs and Generate Code


1 Select the Configuration Parameters > Reuse local block outputs parameter.
2 Generate code. In the local_variable_ex.c section, view the model step function.
There is one local variable, rtb_G2, that the code generator uses three times.

56-115
56 Optimizations for Generated Code in Simulink Coder

/* Model step function */


void local_variable_ex_step(void)
{
real_T rtb_G2;

/* Switch: '<Root>/Switch' incorporates:


* Inport: '<Root>/In1'
*/
if (local_variable_ex_U.In1 >= 0.0) {
/* Gain: '<Root>/G2' */
rtb_G2 = 2.0 * local_variable_ex_U.In1;
} else {
/* Gain: '<Root>/G1' */
rtb_G2 = 3.0 * local_variable_ex_U.In1;
}

/* End of Switch: '<Root>/Switch' */

/* 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

Configuration in Embedded Coder


57 Configuration in Embedded Coder

Set Hardware Implementation Parameters


Specification of target hardware device characteristics (such as word sizes for char,
short, int, and long data types, or desired rounding behaviors in integer operations)
for generated code can be critical in embedded systems development. The Hardware
Implementation category of parameters in a configuration set provides a way to control
such characteristics in simulation and code generation.

By configuring the Hardware Implementation parameters of the active configuration


set for a model to match the behaviors of your compiler and hardware, you can generate
more efficient code. For example, if you specify the Byte ordering parameter, you can
avoid generation of extra code that tests the byte ordering of the target CPU.

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

Data Copy Reduction in Embedded


Coder

• “Optimize Global Variable Usage” on page 58-2


• “Reuse Global Block Outputs in the Generated Code” on page 58-14
• “Virtualized Output Ports Optimization” on page 58-17
• “Specify Buffer Reuse by Using Simulink.Signal Objects” on page 58-19
• “Specify Buffer Reuse for MATLAB Function Blocks in a Path” on page 58-27
• “Remove Data Copies by Reordering Block Operations in the Generated Code”
on page 58-29
• “Data Copy Reduction for Data Store Read and Data Store Write Blocks”
on page 58-35
• “Reduce Data Copies for Bus Assignment Blocks” on page 58-40
• “Optimize Generated Code by Using Signal Labels to Guide Buffer Reuse”
on page 58-43
58 Data Copy Reduction in Embedded Coder

Optimize Global Variable Usage


In this section...
“Use Global to Hold Temporary Results” on page 58-2
“Minimize Global Data Access” on page 58-7

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).

Use Global to Hold Temporary Results


The code generator uses global and local variables when you select None versus when
you select Use global to hold temporary results.

58-2
Optimize Global Variable Usage

Example Model

In the model matlab:rtwdemo_optimize_global_ebf, an Assignment block assigns values


coming from the Inport and Constant blocks to an output signal. The output signal feeds
into a Gain block.

model = 'rtwdemo_optimize_global_ebf';
load_system('rtwdemo_optimize_global_ebf')

Generate Code without Optimization

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();

Build the model.

rtwbuild(model);

### Starting build procedure for model: rtwdemo_optimize_global_ebf


### Successful completion of build procedure for model: rtwdemo_optimize_global_ebf

View the generated code without the optimization. Here is a portion of


rtwdemo_optimize_global_ebf.c.

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);

/* Model step function */


void rtwdemo_optimize_global_ebf_step(void)
{
real_T rtb_Assignment[5];
int32_T i;

/* Assignment: '<Root>/Assignment' incorporates:


* Constant: '<Root>/Constant'
* Inport: '<Root>/In1'
*/
for (i = 0; i < 5; i++) {
rtb_Assignment[i] = rtCP_Constant_Value[i];
}

rtb_Assignment[1] = rtU.In1;

/* End of Assignment: '<Root>/Assignment' */

/* Outport: '<Root>/Out1' incorporates:


* Gain: '<Root>/Gain'
*/
for (i = 0; i < 5; i++) {
rtY.Out1[i] = 2.0 * rtb_Assignment[i];
}

/* End of Outport: '<Root>/Out1' */


}

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

The total number of reads and writes for global variables is 2.

Generate Code with Optimization

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');

Build the model.


rtwbuild(model);

### Starting build procedure for model: rtwdemo_optimize_global_ebf


### Successful completion of build procedure for model: rtwdemo_optimize_global_ebf

View the generated code with the optimization. Here is a portion of


rtwdemo_optimize_global_ebf.c.
cfile = fullfile(cgDir,'rtwdemo_optimize_global_ebf_ert_rtw',...
'rtwdemo_optimize_global_ebf.c');
rtwdemodbtype(cfile,'/* Model step','/* Model initialize',1, 0);

/* Model step function */


void rtwdemo_optimize_global_ebf_step(void)
{
int32_T i;

58-5
58 Data Copy Reduction in Embedded Coder

/* Assignment: '<Root>/Assignment' incorporates:


* Constant: '<Root>/Constant'
* Inport: '<Root>/In1'
*/
for (i = 0; i < 5; i++) {
rtY.Out1[i] = rtCP_Constant_Value[i];
}

rtY.Out1[1] = rtU.In1;

/* End of Assignment: '<Root>/Assignment' */

/* Outport: '<Root>/Out1' incorporates:


* Gain: '<Root>/Gain'
*/
for (i = 0; i < 5; i++) {
rtY.Out1[i] *= 2.0;
}

/* End of Outport: '<Root>/Out1' */


}

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.

Close the code generation report.

rtwdemoclean;
cd(currentDir)

Minimize Global Data Access


Generate optimized code that reads from and writes to global variables less frequently.

Example Model

In the model matlab:rtwdemo_optimize_global, five signals feed into a Multiport Switch


block.

model = 'rtwdemo_optimize_global';
load_system('rtwdemo_optimize_global')

58-7
58 Data Copy Reduction in Embedded Coder

Generate Code without Optimization

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();

Build the model.

58-8
Optimize Global Variable Usage

rtwbuild(model);

### Starting build procedure for model: rtwdemo_optimize_global


### Successful completion of build procedure for model: rtwdemo_optimize_global

View the generated code without the optimization. Here is a portion of


rtwdemo_optimize_global.c.

cfile = fullfile(cgDir,'rtwdemo_optimize_global_ert_rtw',...
'rtwdemo_optimize_global.c');
rtwdemodbtype(cfile,'/* Model step','/* Model initialize',1, 0);

/* Model step function */


void rtwdemo_optimize_global_step(void)
{
/* MultiPortSwitch: '<Root>/Multiport Switch' incorporates:
* Inport: '<Root>/In1'
*/
switch ((int32_T)rtU.In1) {
case 1:
/* Outport: '<Root>/Out1' incorporates:
* Constant: '<Root>/Constant'
*/
rtY.Out1 = 1.0;
break;

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;
}

/* End of MultiPortSwitch: '<Root>/Multiport Switch' */


}

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.

The total number of reads and writes for global variables is 5.

Enable Optimization and Generate Code

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');

Build the model.

rtwbuild(model);

58-10
Optimize Global Variable Usage

### Starting build procedure for model: rtwdemo_optimize_global


### Successful completion of build procedure for model: rtwdemo_optimize_global

View the generated code with the optimization. Here is a portion of


rtwdemo_optimize_global.c.
cfile = fullfile(cgDir,'rtwdemo_optimize_global_ert_rtw',...
'rtwdemo_optimize_global.c');
rtwdemodbtype(cfile,'/* Model step','/* Model initialize',1, 0);

/* Model step function */


void rtwdemo_optimize_global_step(void)
{
real_T tmp_Out1;

/* MultiPortSwitch: '<Root>/Multiport Switch' incorporates:


* Inport: '<Root>/In1'
*/
switch ((int32_T)rtU.In1) {
case 1:
/* Outport: '<Root>/Out1' incorporates:
* Constant: '<Root>/Constant'
*/
tmp_Out1 = 1.0;
break;

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;
}

/* End of MultiPortSwitch: '<Root>/Multiport Switch' */

/* Outport: '<Root>/Out1' */
rtY.Out1 = tmp_Out1;
}

In rtwdemo_optimize_global.c, the code assigns a constant value to the local


variable tmp_Out1 in each case statement. The last statement in the code copies the
value of tmp_Out1 to the global variable rtY.Out1. Fewer global variable references
result in fewer instructions and improved execution speed.

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.

Close the code generation report.

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

Reuse Global Block Outputs in the Generated Code


Reduce ROM and RAM consumption and data copies and increase execution speed of
generated code. Configure the code generator to reuse global variables by selecting the
model configuration parameter Reuse global block outputs.

Example

In the Command Window, type rtwdemo_reuse_global.

Generate Code without Optimization

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.

Press Ctrl+B to generate code.

### Starting build procedure for model: rtwdemo_reuse_global


### Successful completion of build procedure for model: rtwdemo_reuse_global

58-14
Reuse Global Block Outputs in the Generated Code

View the generated code without the optimization. Here is a portion of


rtwdemo_reuse_global.c.

/* Model step function */


void rtwdemo_reuse_global_step(void)
{
/* Sum: '<Root>/Sum' incorporates:
* Delay: '<Root>/Delay'
* Inport: '<Root>/In1'
*/
rtDW.Delay_DSTATE += rtU.In1;

/* Outport: '<Root>/Out1' incorporates:


* Delay: '<Root>/Delay'
*/
rtY.Out1 = rtDW.Delay_DSTATE;
}

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.

Enable Optimization and Generate Code

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.

### Starting build procedure for model: rtwdemo_reuse_global


### Successful completion of build procedure for model: rtwdemo_reuse_global

/* Model step function */


void rtwdemo_reuse_global_step(void)
{
/* Sum: '<Root>/Sum' incorporates:
* Delay: '<Root>/Delay'
* Inport: '<Root>/In1'
*/
rtY.Out1 += rtU.In1;
}

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

Virtualized Output Ports Optimization


The virtualized output ports optimization lets you store the signal entering the root output
port as a global variable. Clearing the MAT-file logging option and setting the TLC
variable FullRootOutputVector to 0, both defaults for Embedded Coder, eliminate
code and data storage associated with root output ports.

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.

/* Gain Block: <Root>/Gain */


exportedSig = rtb_PulseGen * VirtOutPortLogOFF_P.Gain_Gain;

In cases where you enable MAT-file logging or set FullRootOutputVector = 1, the


generated code represents root output ports as members of an external outputs vector.

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.

/* Gain Block: <Root>/Gain */


exportedSig = rtb_PulseGen * VirtOutPortLogON_P.Gain_Gain;

/* Outport Block: <Root>/Out1 */


VirtOutPortLogON_Y.Out1 = exportedSig;

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

Specify Buffer Reuse by Using Simulink.Signal Objects


If your model has the optimal parameter settings for removing data copies, you might be
able to remove additional data copies by using Simulink.Signal objects to specify
buffer reuse. After studying the generated code and the Static Code Metrics Report and
identifying areas where you think buffer reuse is possible, you specify signal objects on
signal lines.

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

The model rtwdemo_reusable_csc contains the nonreusable subsystem DeltaSubsystem


and the MATLAB Function block Downsample. DeltaSubsystem contains the MATLAB
Function blocks DeltaX and DeltaY.

model ='rtwdemo_reusable_csc';
open_system(model);

Specify a Simulink Signal Object for Reuse

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

Build the model.


currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild(model);

### Starting build procedure for model: rtwdemo_reusable_csc


### Successful completion of build procedure for model: rtwdemo_reusable_csc

For buffer reuse, the rtwdemo_reusable_csc.c file contains these global variables:

• static real_T RCSC_IMAG[1048576];


• static real_T RCSC_IMAG2[262144];
• static real_T RCSC_REAL[1048576];
• static real_T RCSC_REAL2[262144];

The rtwdemo_reusable_csc.c file contains this code:


cfile = fullfile(cgDir,...
'rtwdemo_reusable_csc_ert_rtw','rtwdemo_reusable_csc.c');
rtwdemodbtype(cfile,...
'/* Output and update for atomic system: ''<Root>/DeltaSubsystem'' */',...

58-20
Specify Buffer Reuse by Using Simulink.Signal Objects

'/* Output and update for atomic system: ''<Root>/Downsample'' */',1,0);


rtwdemodbtype(cfile,...
'/* Model step function */','/* Model initialize function */',1,0);

/* Output and update for atomic system: '<Root>/DeltaSubsystem' */


static void DeltaSubsystem(void)
{
/* MATLAB Function: '<S1>/DeltaX' */
DeltaX((&(RCSC_REAL2[0])), (&(RCSC_IMAG2[0])), (&(RCSC_REAL[0])),
(&(RCSC_IMAG[0])));

/* MATLAB Function: '<S1>/DeltaY' */


DeltaY((&(RCSC_REAL[0])), (&(RCSC_IMAG[0])), (&(RCSC_REAL2[0])),
(&(RCSC_IMAG2[0])));
}

/* Model step function */


void rtwdemo_reusable_csc_step(void)
{
int32_T i;

/* ComplexToRealImag: '<Root>/Complex to Real-Imag' incorporates:


* Inport: '<Root>/ComplexData'
*/
for (i = 0; i < 1048576; i++) {
RCSC_REAL[i] = rtU.ComplexData[i].re;
RCSC_IMAG[i] = rtU.ComplexData[i].im;
}

/* End of ComplexToRealImag: '<Root>/Complex to Real-Imag' */

/* MATLAB Function: '<Root>/Downsample' */


Downsample((&(RCSC_REAL[0])), (&(RCSC_IMAG[0])), (&(RCSC_REAL2[0])),
(&(RCSC_IMAG2[0])));

/* Outputs for Atomic SubSystem: '<Root>/DeltaSubsystem' */


DeltaSubsystem();

/* End of Outputs for SubSystem: '<Root>/DeltaSubsystem' */

/* Outport: '<Root>/Out1' incorporates:


* RealImagToComplex: '<Root>/Real-Imag to Complex'
*/
for (i = 0; i < 261121; i++) {

58-21
58 Data Copy Reduction in Embedded Coder

rtY.Out1[i].re = RCSC_REAL2[i];
rtY.Out1[i].im = RCSC_IMAG2[i];
}

/* End of Outport: '<Root>/Out1' */


}

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);

### Starting build procedure for model: rtwdemo_reusable_csc


### Successful completion of build procedure for model: rtwdemo_reusable_csc

The rtwdemo_reusable_csc.c file now contains this code.


cfile = fullfile(cgDir,...
'rtwdemo_reusable_csc_ert_rtw','rtwdemo_reusable_csc.c');

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);

/* Output and update for atomic system: '<Root>/DeltaSubsystem' */


static void DeltaSubsystem(void)
{
/* MATLAB Function: '<S1>/DeltaX' */
DeltaX(rtDWork.z2, rtDWork.z1, rtDWork.z1_m, rtDWork.z2_c);

/* MATLAB Function: '<S1>/DeltaY' */


DeltaY(rtDWork.z1_m, rtDWork.z2_c, &rtDWork.z1[0], &rtDWork.z2[0]);
}

/* Model step function */


void rtwdemo_reusable_csc_step(void)
{
int32_T i;

/* ComplexToRealImag: '<Root>/Complex to Real-Imag' incorporates:


* Inport: '<Root>/ComplexData'
*/
for (i = 0; i < 1048576; i++) {
rtDWork.RCSC_REAL[i] = rtU.ComplexData[i].re;
rtDWork.RCSC_IMAG[i] = rtU.ComplexData[i].im;
}

/* End of ComplexToRealImag: '<Root>/Complex to Real-Imag' */

/* MATLAB Function: '<Root>/Downsample' */


Downsample(rtDWork.RCSC_REAL, rtDWork.RCSC_IMAG, rtDWork.z2, rtDWork.z1);

/* Outputs for Atomic SubSystem: '<Root>/DeltaSubsystem' */


DeltaSubsystem();

/* End of Outputs for SubSystem: '<Root>/DeltaSubsystem' */

/* Outport: '<Root>/Out1' incorporates:


* RealImagToComplex: '<Root>/Real-Imag to Complex'
*/
for (i = 0; i < 261121; i++) {
rtY.Out1[i].re = rtDWork.z1[i];

58-23
58 Data Copy Reduction in Embedded Coder

rtY.Out1[i].im = rtDWork.z2[i];
}

/* End of Outport: '<Root>/Out1' */


}

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)

Buffer Reuse for Unit Delay and Delay Blocks

To reuse the signal of a Unit Delay or Delay block:

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.

Limitations for Root Inport and Outport Signals

These limitations apply to a model in which you specify buffer reuse for a pair of root
inport and outport signals:

• The output ports cannot be conditional.

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.

Limitations for the Model

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

Specify Buffer Reuse for MATLAB Function Blocks in a


Path
In this section...
“Example Model” on page 58-27
“Generate Code with Optimization” on page 58-27

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.

Generate Code with Optimization


Generate code for the model. The mf_inplace.c file contains this code:

58-27
58 Data Copy Reduction in Embedded Coder

void mf_inplace_MATLABFunction(real_T *rty_y)


{
*rty_y += 4.0;
}

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

Remove Data Copies by Reordering Block Operations in


the Generated Code
This example show how to remove data copies by changing the Optimize block order in
the generated code parameter from off to Improved Execution Speed. Changing
this setting indicates to the code generator to reorder block operations where possible to
remove data copies. This parameter is in the Configuration Parameters dialog box. This
optimization conserves RAM and ROM consumption.

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

Generate Code without Optimization


The image shows the model ex_optimizeblockorder after a model build. The red
numbers indicate the default block order in the generated code. The Subtract block
executes before the Concatenate block. The Product block executes before the Sum of
Elements block.

View the generated code without the optimization. Here is the


ex_optimizeblockorder_step function.
/* Model step function */
void ex_optimizeblockorder_step(void)
{
real_T rtb_Sum2x3[6];
int32_T i;
real_T rtb_Sum2x3_d;
real_T rtb_Subtract;

/* Sum: '<Root>/SumOfElements' */
rtY.Out2 = -0.0;

58-30
Remove Data Copies by Reordering Block Operations in the Generated Code

for (i = 0; i < 6; i++) {


/* Sum: '<Root>/Sum2x3' incorporates:
* Inport: '<Root>/In1'
* Inport: '<Root>/In2'
*/
rtb_Sum2x3_d = rtU.In1[i] + rtU.In2;

/* Sum: '<Root>/Subtract' incorporates:


* Inport: '<Root>/In3'
*/
rtb_Subtract = rtb_Sum2x3_d - rtU.In3;

/* Outport: '<Root>/Out1' incorporates:


* Inport: '<Root>/In4'
* Product: '<Root>/Product'
*/
rtY.Out1[i] = rtU.In4[i] * rtb_Subtract;

/* Sum: '<Root>/Sum2x3' */
rtb_Sum2x3[i] = rtb_Sum2x3_d;

/* Sum: '<Root>/SumOfElements' */
rtY.Out2 += rtb_Subtract;
}

/* Concatenate: '<Root>/MatrixConcat ' */


for (i = 0; i < 3; i++) {
/* Outport: '<Root>/Out3' incorporates:
* Inport: '<Root>/In5'
*/
rtY.Out3[i << 2] = rtb_Sum2x3[i << 1];
rtY.Out3[2 + (i << 2)] = rtU.In5[i << 1];
rtY.Out3[1 + (i << 2)] = rtb_Sum2x3[(i << 1) + 1];
rtY.Out3[3 + (i << 2)] = rtU.In5[(i << 1) + 1];
}

/* End of Concatenate: '<Root>/MatrixConcat ' */


}

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

Generate Code with Optimization


The image shows the ex_optimizeblockorder model after setting the Optimize block
order in the generated code parameter to Improved Execution Speed and building
the model. The Subtract block executes after the Concatenate block. The Product block
executes after the Sum of Elements block.

In the optimized code, the three buffers rtb_Sum2x3[6], rtb_Sum2x3_d, and


rtb_Subtract and their associated data copies are gone. The generated code does not
require these temporary variables to hold the outputs of the Sum and Subtract blocks
because the Subtract block executes after the Concatenate block and the Product block
executes after the Sum of Elements block.

/* Model step function */


void ex_optimizeblockorder_step(void)
{
int32_T i;

/* Sum: '<Root>/Sum2x3' incorporates:

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;
}

/* End of Sum: '<Root>/Sum2x3' */

/* Concatenate: '<Root>/MatrixConcat ' */


for (i = 0; i < 3; i++) {
/* Outport: '<Root>/Out3' incorporates:
* Inport: '<Root>/In5'
*/
rtY.Out3[i << 2] = rtY.Out1[i << 1];
rtY.Out3[2 + (i << 2)] = rtU.In5[i << 1];
rtY.Out3[1 + (i << 2)] = rtY.Out1[(i << 1) + 1];
rtY.Out3[3 + (i << 2)] = rtU.In5[(i << 1) + 1];
}

/* End of Concatenate: '<Root>/MatrixConcat ' */

/* 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];

/* Outport: '<Root>/Out1' incorporates:


* Inport: '<Root>/In4'
* Product: '<Root>/Product'
*/
rtY.Out1[i] *= rtU.In4[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

Data Copy Reduction for Data Store Read and Data


Store Write Blocks
This example shows how the code generator removes temporary buffers for Data Store
Read and Data Store Write blocks. This optimization improves execution speed and
reduces RAM consumption.

Example Model

The model rtwdemo_optimizedatastorebuffers contains the Function caller


UpdateFunc, which calls the Simulink Function DefineUpdateFunc. The Data Store
Read block DSR reads from mem. The Data Store Write block DSW writes to mem.
model='rtwdemo_optimizedatastorebuffers';
open_system(model);

Generate Code without Optimization

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');

Build the model.

currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild(model)

### Starting build procedure for model: rtwdemo_optimizedatastorebuffers


### Successful completion of build procedure for model: rtwdemo_optimizedatastorebuffer

View the generated code without the optimization. This code is in


rtwdemo_optimizedatastorebuffers.c.

cfile = fullfile(cgDir,'rtwdemo_optimizedatastorebuffers_ert_rtw',...
'rtwdemo_optimizedatastorebuffers.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);

/* Model step function */


void rtwdemo_optimizedatastorebuffers_step(void)
{
real_T rtb_DSR_last;
real_T rtb_SimFuncCall_o1;
real_T rtb_Sum_p;

/* DataStoreRead: '<Root>/DSR' */
rtb_DSR_last = mem.last;

/* Switch: '<Root>/Switch' incorporates:


* Constant: '<Root>/Constant'
* DataStoreRead: '<Root>/DSR'
* Inport: '<Root>/Clear'
*/
if (rtU.Clear) {
rtb_SimFuncCall_o1 = 0.0;
} else {
rtb_SimFuncCall_o1 = mem.max;
}

/* End of Switch: '<Root>/Switch' */

/* FunctionCaller: '<Root>/SimFuncCall' incorporates:


* Inport: '<Root>/DataNew'
*/

58-36
Data Copy Reduction for Data Store Read and Data Store Write Blocks

UpdateFunc(rtb_SimFuncCall_o1, rtU.DataNew, &rtb_SimFuncCall_o1, &rtb_Sum_p);

/* DataStoreWrite: '<Root>/DSW' */
mem.last = rtb_SimFuncCall_o1;
mem.max = rtb_Sum_p;

/* Outport: '<Root>/Delta' incorporates:


* Inport: '<Root>/DataNew'
* Sum: '<Root>/Sum'
*/
rtY.Delta = rtU.DataNew - rtb_DSR_last;
}

The generated code contains data copies for the Data Store Read and Data Store Write
blocks, respectively.

Generate Code with Optimization

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');

Build the model.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_optimizedatastorebuffers


### Successful completion of build procedure for model: rtwdemo_optimizedatastorebuffer

View the generated code with the optimization. This code is in


rtwdemo_optimizedatastorebuffers.c.

cfile = fullfile(cgDir,'rtwdemo_optimizedatastorebuffers_ert_rtw',...
'rtwdemo_optimizedatastorebuffers.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);

/* Model step function */


void rtwdemo_optimizedatastorebuffers_step(void)
{
real_T rtb_DSR_last;
real_T tmp;

58-37
58 Data Copy Reduction in Embedded Coder

/* DataStoreRead: '<Root>/DSR' */
rtb_DSR_last = mem.last;

/* Switch: '<Root>/Switch' incorporates:


* Constant: '<Root>/Constant'
* DataStoreRead: '<Root>/DSR'
* Inport: '<Root>/Clear'
*/
if (rtU.Clear) {
tmp = 0.0;
} else {
tmp = mem.max;
}

/* End of Switch: '<Root>/Switch' */

/* FunctionCaller: '<Root>/SimFuncCall' incorporates:


* DataStoreWrite: '<Root>/DSW'
* Inport: '<Root>/DataNew'
*/
UpdateFunc(tmp, rtU.DataNew, &mem.last, &mem.max);

/* Outport: '<Root>/Delta' incorporates:


* Inport: '<Root>/DataNew'
* Sum: '<Root>/Sum'
*/
rtY.Delta = rtU.DataNew - rtb_DSR_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:

• A Simulink Function internally writes to the Data Store Memory block.


• The Data Store Read or Data Store Write blocks select elements of an array from the
Data Store Memory block.
• The Data Store Memory block has a custom storage class.

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.

Close the model and clean up.

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

Reduce Data Copies for Bus Assignment Blocks


For models containing a Bus Assignment block, if possible, the code generator uses the
same variable for the block input and output. Reusing these variables reduces data
copies, conserves RAM consumption and increases code execution speed.

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.

Generate Code Without Optimization


Generate code without the optimization by setting the Perform inplace updates for
Bus Assignment blocks parameter to on. Without the optimization the
bus_assignoptim_step function contains this code:

void bus_assignoptim_step(void)
{
real_T rtb_Assignment[36];
int32_T i;

/* Assignment: '<Root>/Assignment' incorporates:


* Inport: '<Root>/In1'
* Inport: '<Root>/In2'
* Product: '<Root>/Product'
* Selector: '<Root>/Selector'
* Sum: '<Root>/Sum1'
*/
for (i = 0; i < 36; i++) {
rtb_Assignment[i] = bus_assignoptim_U.In1.a1_real_array[i];

58-40
Reduce Data Copies for Bus Assignment Blocks

for (i = 0; i < 2; i++) {


rtb_Assignment[(int32_T)(i + 22)] = (bus_assignoptim_U.In1.a1_real_array
[(int32_T)(i + 22)] + bus_assignoptim_U.In1.a1_num) *
bus_assignoptim_U.In2;
}

/* End of Assignment: '<Root>/Assignment' */

/* Outport: '<Root>/Out' incorporates:


* BusAssignment: '<Root>/Bus Assignment'
* Inport: '<Root>/In1'
*/
bus_assignoptim_Y.Out = bus_assignoptim_U.In1;

/* BusAssignment: '<Root>/Bus Assignment' incorporates:


* Outport: '<Root>/Out'
*/
for (i = 0; i < 36; i++) {
bus_assignoptim_Y.Out.a1_real_array[i] = rtb_Assignment[i];
}
}

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.

Generate Code with Optimization


Generate code with the optimization by setting the Perform inplace updates for Bus
Assignment blocks parameter to off. With the optimization, the
bus_assignoptim_step function contains this code:
/* Model step function */
void bus_assignoptim_step(void)
{
int32_T i;

/* Outport: '<Root>/Out' incorporates:


* Inport: '<Root>/In1'
* SignalConversion: '<Root>/TmpBusAssignmentBufferAtBus AssignmentInport1'
*/
bus_assignoptim_Y.Out = bus_assignoptim_U.In1;

58-41
58 Data Copy Reduction in Embedded Coder

/* Assignment: '<Root>/Assignment' incorporates:


* Inport: '<Root>/In1'
* Inport: '<Root>/In2'
* Outport: '<Root>/Out'
* Product: '<Root>/Product'
* Selector: '<Root>/Selector'
* Sum: '<Root>/Sum1'
*/
for (i = 0; i < 36; i++) {
bus_assignoptim_Y.Out.a1_real_array[i] =
bus_assignoptim_U.In1.a1_real_array[i];
}

for (i = 0; i < 2; i++) {


bus_assignoptim_Y.Out.a1_real_array[(int32_T)(i + 22)] =
(bus_assignoptim_U.In1.a1_real_array[(int32_T)(i + 22)] +
bus_assignoptim_U.In1.a1_num) * bus_assignoptim_U.In2;
}

/* End of Assignment: '<Root>/Assignment' */


}

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

Optimize Generated Code by Using Signal Labels to


Guide Buffer Reuse
If your model has the optimal parameter settings for removing data copies, you might be
able to remove additional data copies by using signal labels. After studying the generated
code and the Static Code Metrics Report and identifying areas where you think buffer
reuse is possible, you can add labels to signal lines. If possible, the code generator
reorders block operations to implement the reuse specification.

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.

Generate Code Without Optimization


1 Open the model.
model='rtwdemo_label_guided_reuse';
open_system(model);

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;
}

AtomicSubsystem1(rtb_Saturation, rtb_Bias, rtY.Out1);


}

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.

Generate Code with Optimization


In the Configuration Parameters dialog box, select the Use Signal Labels to Guide
Buffer Reuse parameter and build the model. The
rtwdemo_label_guided_reuse_step function contains this code:
void rtwdemo_label_guided_reuse_step(void)
{
real_T rtb_Gain1[4];
int32_T i;
AtomicSubsystem(rtU.In1, rtY.Out1);
for (i = 0; i < 4; i++) {

58-44
Optimize Generated Code by Using Signal Labels to Guide Buffer Reuse

rtb_Gain1[i] = 3.0 * rtY.Out1[i];


if (rtY.Out1[i] > 10.0) {
rtY.Out1[i] = 10.0;
} else {
if (rtY.Out1[i] < -10.0) {
rtY.Out1[i] = -10.0;
}
}
}

AtomicSubsystem1(rtY.Out1, rtb_Gain1, rtY.Out1);


}

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.

Using Label-Based Reuse Versus Reusable Custom Storage


Classes
You can also use the same Reusable custom storage class specification on different
signal lines to specify which buffers to reuse. As compared to using Reusable custom
storage classes, using signal labels to specify reuse has these benefits:

• 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

• Reuse on root inport and outport ports.


• Reuse across model reference or subsystem boundaries.
• Within a subsystem, buffer reuse on an intermediary signal and an input or output
port.

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

Execution Speed in Embedded


Coder

• “Reduce Memory Usage for Signals” on page 59-2


• “Remove Initialization Code” on page 59-4
• “Simplify Multiply Operations in Array Indexing” on page 59-10
• “Replace boolean with Specific Integer Data Type” on page 59-14
• “Remove Code That Guards Against Division Exceptions for Integers and Fixed-Point
Data” on page 59-19
• “Division Arithmetic Exceptions in Generated Code” on page 59-23
• “Optimize Generated Code by Consolidating Redundant If-Else Statements”
on page 59-25
• “Optimize Generated Code for Fixed-Point Data Operations” on page 59-30
• “Optimize Generated Code By Developing and Using Code Replacement Libraries -
Simulink®” on page 59-33
• “Improve Execution Efficiency by Reordering Block Operations in the Generated
Code” on page 59-65
59 Execution Speed in Embedded Coder

Reduce Memory Usage for Signals


The configuration parameter Signal storage reuse reduces the memory requirements of
your real-time program by enabling parameters that reuse the memory allocated for
signals with an auto storage class. These parameters are the following:

• Enable local block outputs


• Reuse local block outputs
• Reuse global block outputs
• Optimize global data access

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:

• Global signals that cross subsystem boundaries


• Global signals across Simulink and Stateflow domains
• Unused global state variables
• Redundant local Data Store Memory block signals

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.

The Optimize global data access parameter has these settings:

• 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

Remove Initialization Code


The “Remove root level I/O zero initialization” (Simulink Coder) and “Remove internal
data zero initialization” (Simulink Coder) parameters control whether the generated code
contains initialization code for internal data (block states and block outputs) and external
data (root inports and outports) whose value is zero. If your embedded application
initializes RAM to zero at startup, you might not need initialization code. Eliminating this
code accelerates model initialization, reduces ROM consumption and increases the
execution speed of the generated code.

Remove Zero Initialization Code for Internal Data


This example shows how to eliminate code that initializes internal data to zero. If your
embedded application does not require generating initialization code for internal data
whose value is zero, you can enable this optimization.

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.

Generate Code Without Optimization

Build the model using Embedded Coder.

### Starting build procedure for model: rtwdemo_internal_init


### Successful completion of build procedure for model: rtwdemo_internal_init

59-4
Remove Initialization Code

This code is in the rtwdemo_internal_init.c file.

/* Model initialize function */


void rtwdemo_internal_init_initialize(void)
{
/* Registration code */

/* initialize error status */


rtmSetErrorStatus(rtM, (NULL));

/* states (dwork) */
(void) memset((void *)&rtDWork, 0,
sizeof(D_Work));

/* SystemInitialize for Enabled SubSystem: '<Root>/Enabled Subsystem' */


/* InitializeConditions for UnitDelay: '<S1>/Unit Delay' */
rtDWork.UnitDelay_DSTATE = 0.0;

/* End of SystemInitialize for SubSystem: '<Root>/Enabled Subsystem' */


}

/*

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');

Generate Code with Optimization

Build the model using Embedded Coder.


### Starting build procedure for model: rtwdemo_internal_init
### Successful completion of build procedure for model: rtwdemo_internal_init

This code is in the rtwdemo_internal_init.c file. The generated code does not
initialize internal data by assignment to zero.

/* Model initialize function */

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

where SFcnName is the name of the S-function, or


clear mex

Remove Initialization Code for Root-Level Inports and


Outports Set to Zero
This example shows how to remove initialization code for root-level inports and outports
set to zero. If your embedded application does not require generating initialization code
for external data whose value is zero, you can enable this optimization.

Note: This example requires an Embedded Coder® license.

Example Model

In the model rtwdemo_rootlevel_zero_initialization, all of the input and output signals


have a numeric value of zero. Because signals sig1 and sig2 have data types int16 and
Boolean, respectively, and all of the output signals have data type double, these signals
also have initial values of bitwise zero. The signals have an integer bit pattern of 0,
meaning that all bits are off. Signals sig1_b and sig2_b have a fixed-point data type
with bias, so their initial value is not bitwise zero.
model = 'rtwdemo_rootlevel_zero_initialization';
open_system(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();

Build the model.

set_param(model, 'ZeroExternalMemoryAtStartup','on');
rtwbuild(model)

### Starting build procedure for model: rtwdemo_rootlevel_zero_initialization


### Successful completion of build procedure for model: rtwdemo_rootlevel_zero_initiali

These lines of rtwdemo_rootlevel_zero_initialization.c code show the


initialization of root-level inports and outports without the optimization. The four input
signals are individually initialized as global variables. The four output signals are
members of a global structure that the memset function initializes to bitwise zero.

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

1 Open the Configuration Parameters dialog box.


2 On the Optimization pane, select Remove root level I/O zero initialization.

Alternatively, use the command-line API to enable the optimization:


set_param(model, 'ZeroExternalMemoryAtStartup','off');

Generate Code with 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.

Build the model.


rtwbuild(model)

### Starting build procedure for model: rtwdemo_rootlevel_zero_initialization


### Successful completion of build procedure for model: rtwdemo_rootlevel_zero_initiali

Here is the rtwdemo_rootlevel_zero_initialization.c optimized code in the


initialization function.
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 */

59-8
See Also

/* external inputs */
sig1_b = -3;
sig2_b = -3;
}

/*

Close the model and the code generation report.

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

Simplify Multiply Operations in Array Indexing


In this section...
“Example Model” on page 59-10
“Generate Code” on page 59-11
“Generate Code with Optimization” on page 59-11

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:

The Constant blocks have the following Constant value:

• Const1: reshape(1:30,[1 5 3 2])


• Const2: reshape(1:20,[1 5 2 2])
• Const3: reshape(1:90,[1 5 9 2])

The Concatenate block parameter Mode is set to Multidimensional array. The


Constant blocks Sample time parameter is set to –1.

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;

for (i = 0; i < 2; i++) {


for (i_1 = 0; i_1 < 3; i_1++) {
for (i_0 = 0; i_0 < 5; i_0++) {
ex_arrayindex_Y.Out[(i_0 + 5 * i_1) + 70 * i] =
ex_arrayindex_P.Constant1_Value[(5 * i_1 + i_0) + 15 * i];
}
}
}

for (i = 0; i < 2; i++) {


for (i_1 = 0; i_1 < 2; i_1++) {
for (i_0 = 0; i_0 < 5; i_0++) {
ex_arrayindex_Y.Out[(i_0 + 5 * (i_1 + 3)) + 70 * i] =
ex_arrayindex_P.Constant2_Value[(5 * i_1 + i_0) + 10 * i];
}
}
}

for (i = 0; i < 2; i++) {


for (i_1 = 0; i_1 < 9; i_1++) {
for (i_0 = 0; i_0 < 5; i_0++) {
ex_arrayindex_Y.Out[(i_0 + 5 * (i_1 + 5)) + 70 * i] =
ex_arrayindex_P.Constant3_Value[(5 * i_1 + i_0) + 45 * i];
}
}
}

Generate Code with Optimization


Open the Configuration Parameters dialog box and select the Simplify array indexing
parameter. Build the model again. In the generated code, [(i_0 + tmp_1) + tmp]
replaces a multiply operation in the array index, [(i_0 + 5 * i_1) + 70 * i]. The
generated code is now:

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

Replace boolean with Specific Integer Data Type


Depending on the architecture of the processor that your production hardware uses, you
can improve the execution speed of the generated code. Select a specific integer data
type for the built-in type boolean. Using data type replacement, in the generated code
you can replace the boolean built-in data type with one of these integer types:

• 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

Generate Code That Contains the Default boolean Data Type


View the generated file rtwtypes.h. The typdef statements contain the generic type
definition of boolean_T, which is the code generation name for boolean.

/*===========================================================================*
* 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

typedef char char_T;


typedef unsigned char uchar_T;
typedef char_T byte_T;

View the generated file ex_bool.c. The code declares boolean variables by using the
type boolean_T.

/* External inputs (root inport signals with auto storage) */


typedef struct {
real_T In1; /* '<Root>/In1' */
real_T In2; /* '<Root>/In2' */
boolean_T In3; /* '<Root>/In3' */
boolean_T In4; /* '<Root>/In4' */
real_T In5; /* '<Root>/In5' */
} ExtU_ex_bool_T;

/* External outputs (root outports fed by signals with auto storage) */


typedef struct {
boolean_T Out1; /* '<Root>/Out1' */
boolean_T Out2; /* '<Root>/Out2' */
real_T Out3; /* '<Root>/Out3' */
} ExtY_ex_bool_T;

Generate Code That Contains the Target boolean Data Type


1 Define a Simulink.AliasType object with a base type of int32. Name the object
using the replacement name that you want to appear in the generated code.

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;

/* External outputs (root outports fed by signals with auto storage) */


typedef struct {
mybool Out1; /* '<Root>/Out1' */
mybool Out2; /* '<Root>/Out2' */
real_T Out3; /* '<Root>/Out3' */
} ExtY_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

Remove Code That Guards Against Division Exceptions


for Integers and Fixed-Point Data
Optimize generated code by removing code that protects against division by zero and
overflows in division INT_MIN/-1 operations for integers and fixed-point data. If you are
sure that these arithmetic exceptions do not occur during program execution, enable this
optimization.

This optimization:

• Increases execution speed.


• Reduces ROM consumption.

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();

Build the model.

set_param(model, 'NoFixptDivByZeroProtection', 'off');


rtwbuild(model);

### Starting build procedure for model: rtwdemo_nzcheck


### Successful completion of code generation for model: rtwdemo_nzcheck

View the generated code without the optimization. Here is a portion of


rtwdemo_nzcheck.c.

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;

/* Divide by zero handler */


} else {
tempAbsQuotient = (numerator < 0 ? ~(uint32_T)numerator + 1U : (uint32_T)
numerator) / (denominator < 0 ? ~(uint32_T)denominator +
1U : (uint32_T)denominator);
quotient = (numerator < 0) != (denominator < 0) ? -(int32_T)tempAbsQuotient :
(int32_T)tempAbsQuotient;
}

return quotient;
}

Enable Optimization

1 Open the Configuration Parameters dialog box.

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:

set_param(model, 'NoFixptDivByZeroProtection', 'on');

Generate Code with Optimization

The optimized code does not contain code that checks for whether or not the divisor has a
value of zero.

Build the model.

rtwbuild(model);

### Starting build procedure for model: rtwdemo_nzcheck


### Successful completion of code generation for model: rtwdemo_nzcheck

The following is a portion of rtwdemo_nzcheck.c. The code that protects against


division arithmetic exceptions is not in the generated code.

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_;

Close the model and code generation report.

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

• “Remove Code From Floating-Point to Integer Conversions That Wraps Out-of-Range


Values” on page 56-24
• “Remove Code That Maps NaN to Integer Zero” on page 56-27
• “Division Arithmetic Exceptions in Generated Code” on page 59-23

59-22
Division Arithmetic Exceptions in Generated Code

Division Arithmetic Exceptions in Generated Code


The Remove code that protects against division arithmetic exceptions parameter in
the Optimization pane of the Configuration Parameters dialog box controls the
generation of code that protects against division arithmetic exceptions in integer and
fixed-point operations. Division arithmetic exceptions include division by zero and
INT_MIN/-1, which results in a quotient that cannot be represented.

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.

The following illustrates an example of this type of exception:


a = int32(-2147483648);
b = a/-1

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.

Other Factors Affecting Generated Code of Division


Operations
In addition to the Remove code that protects against division arithmetic exceptions
parameter, there are several other factors that can affect the appearance of code
generated for division operations. The manner in which this parameter controls code
generated from blocks containing MATLAB code with integer or fixed-point division
operations differs from the built-in Divide block in Simulink. Blocks containing MATLAB
code include MATLAB Function blocks and Stateflow charts using MATLAB action
language. To balance the efficiency and semantics of fixed-point and integer divisions in
these blocks, use fi objects and set the fimath properties to fit your needs. Usage of fi
and fimath objects requires a Fixed-Point Designer license.

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

Optimize Generated Code by Consolidating Redundant


If-Else Statements
This example shows how to optimize generated code by combining if-else statements
that share the same condition. This optimization:

• Improves control flow.


• Reduces code size.
• Reduces RAM consumption.
• Increases execution speed.

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

Create a temporary folder for the build and inspection process.


currentDir = pwd;
[~,cgDir] = rtwdemodir();

Build the model.


rtwbuild(model)

### Starting build procedure for model: rtwdemo_controlflow_opt


### Successful completion of build procedure for model: rtwdemo_controlflow_opt

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);

/* Model step function */


void rtwdemo_controlflow_opt_step(void)
{
/* Switch: '<Root>/Switch3' incorporates:
* Constant: '<Root>/Const'
* Switch: '<Root>/Switch2'
*/
if (Cond) {
/* Switch: '<Root>/Switch1' */
if (Cond) {
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/In1'
*/
rtY.Out1 = rtU.In1;
} else {
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/In2'
*/
rtY.Out1 = rtU.In2;
}

/* End of Switch: '<Root>/Switch1' */


} else if (Cond) {
/* Switch: '<Root>/Switch2' incorporates:
* Inport: '<Root>/In1'
* Outport: '<Root>/Out1'
*/
rtY.Out1 = rtU.In1;
} else {
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/In2'
*/
rtY.Out1 = rtU.In2;
}

/* End of Switch: '<Root>/Switch3' */


}

59-27
59 Execution Speed in Embedded Coder

Enable Optimization

1 Open the Configuration Parameters dialog box.


2 On the Code generation-> Code Style pane, clear Preserve condition expression
in if statement. This parameter is on by default.

Alternatively, use the command-line API to turn off the parameter:

set_param(model, 'PreserveIfCondition', 'off');

Generate Code with 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.

Build the model.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_controlflow_opt


### Successful completion of build procedure for model: rtwdemo_controlflow_opt

Here is the rtwdemo_controlflow_opt.c optimized code.

rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);

/* Model step function */


void rtwdemo_controlflow_opt_step(void)
{
/* Switch: '<Root>/Switch1' incorporates:
* Constant: '<Root>/Const'
* Switch: '<Root>/Switch3'
*/
if (Cond) {
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/In1'
*/
rtY.Out1 = rtU.In1;
} else {
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/In2'

59-28
See Also

*/
rtY.Out1 = rtU.In2;
}

/* End of Switch: '<Root>/Switch1' */


}

Close the model and clean up.

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

Optimize Generated Code for Fixed-Point Data


Operations
This example shows how the code generator optimizes fixed-point operations by replacing
expensive division operations with highly efficient product operations. This optimization
improves execution speed.

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

Create a temporary folder for the build and inspection process.


currentDir = pwd;
[~,cgDir] = rtwdemodir();

Build the model.


set_param(model,'GenCodeOnly','on');
rtwbuild(model);

59-31
59 Execution Speed in Embedded Coder

### Starting build procedure for model: rtwdemo_fixptdiv


### Successful completion of code generation for model: rtwdemo_fixptdiv

View the generated code. Here is a portion of rtwdemo_fixptdiv.c.

cfile = fullfile(cgDir,'rtwdemo_fixptdiv_ert_rtw','rtwdemo_fixptdiv.c');
rtwdemodbtype(cfile,'/* Model step','/* Model initialize', 1, 0);

/* Model step function */


void rtwdemo_fixptdiv_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/In1'
* Product: '<Root>/Divide'
*/
rtY.Out1 = (int16_T)(rtU.In1 >> 3);
}

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.

Close the model and code generation report.

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®

Optimize Generated Code By Developing and Using Code


Replacement Libraries - Simulink®
Develop and use code replacement libraries to replace function and operators in
generated code. Code replacement is a technique to change the code that the code
generator produces for functions and operators to meet application code requirements.
For example, you can replace generated code to meet requirements such as:

• 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.

Steps for Developing a Code Replacement Library

1 Identify your code replacement requirements with respect to function or operating


mappings, build information, and registration information.

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.

Math Function Replacement

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

Addition and Subtraction Operator Replacement

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:

• Cast-before-operation (CBO) (RTW_CAST_BEFORE_OP), the default


• Cast-after-operation (CAO) (RTW_CAST_AFTER_OP)

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

CBO, the default algorithm, is assumed.

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.

• For the Cast_before_operation_Sub block, the code generator calculates the


subtraction operation in the accumulator data type (int8), which is smaller than the
input data type (int16). This is equivalent to a CBO because the code generator
converts the input to the output data type before calculating the result.
• For the Cast_after_operation_Sub block, the code generator calculates the
subtraction operation in the accumulator data type (int32), which is larger than the
input data type (int16). This is equivalent to a CAO because the code generator
produces the same result by calculating the result without loss of range or precision
before converting to the output data type.

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

Multiplication and Division Operator Replacement for Built-In Integers

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

Scalar Operator Replacement

This example defines and registers code replacement mappings for scalar operations:
addition, subtraction, multiplication, complex conjugate, cast, arithmetic shift right, and
arithmetic shift left.

Supported types include:

• 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.

For more information on scalar operator replacement, “Scalar Operator Code


Replacement” on page 54-174.

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

Matrix Operator Replacement

This example defines and registers code replacement mappings for matrix operations:
addition, subtraction, multiplication, transposition, conjugate, and Hermitian.

Supported types include:

• 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

Matrix Multiplication Replacement for BLAS

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

Fixed-Point Operator Replacement for Basic Operators

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.

You can define code replacements as matching:

• Slope/bias scaling combination on the inputs and output


• Binary-point scaling combination on the inputs and output
• Relative scaling between the inputs and output
• Same slope value and a zero net bias across the inputs and output.

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

Match and Replacement Process Customization for Functions

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

MATLAB Function Replacement

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 or multiple inputs


• Single or multiple outputs
• Scalar and matrix inputs and outputs

Open the model rtwdemo_crlcoderreplace. The model shows some of these


requirements. Supported types include:

• 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.

For more information on MATLAB® function replacement, see coder.replace.

open_system('rtwdemo_crlcoderreplace')

59-52
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®

Data Alignment for Function Implementations

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

Performance Gain from Data Alignment

This example shows how code replacement data alignment can accelerate execution of a
generated executable by enabling deployment of SIMD operations in generated code.

1. Open model rtwdemo_crlalignperf. This model illustrates a basic image processing


algorithm, represented by subsystem Root/Filtering/Process/ALGORITHM. The
algorithm slides a 5x5 template across the image one pixel at a time. The image area
covered by the template forms another 5x5 matrix. This matrix is element-wise multiplied
by the template matrix. The twenty-five elements in the resultant matrix are summed
together to form the new value for that pixel. This element-wise matrix multiplication is
performed for all pixels in an image, so its efficiency has a significant impact on the
overall algorithm performance.

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®

### Starting build procedure for model: rtwdemo_crlalignperf


### Successful completion of build procedure for model: rtwdemo_crlalignperf

5. Generate an optimized, data-aligned executable by selecting a library that maps


element-wise matrix multiplication operations to SIMD intrinsic calls, and then building
the model. The SIMD intrinsic calls impose an alignment requirement on data passed to
the intrinsic. The optimized executable is run ten times. Profiling hooks again capture
timing data.

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

### Starting build procedure for model: rtwdemo_crlalignperf


### Successful completion of build procedure for model: rtwdemo_crlalignperf

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;

bar([NaN, t(1), NaN, t(2), NaN]);

59-59
59 Execution Speed in Embedded Coder

set(gca, 'XLim', [0.5, 5.5], 'XTickLabel',...


{'', 'ANSI Multiply', '', 'SIMD Multiply', ''}, ...
'TickLength', [0 0], 'YLim', [0, max(t) * 1.3], 'YTick', []);
ylabel('Execution Time (CPU Cycles)');
% annotate the plot
annotation('textbox', get(gca, 'Position'), ...
'String', ['Execution Speed Increased By: ',...
num2str((1 - t(2)/t(1))*100, '%2.0f'), '%'], ...
'LineStyle', 'none', 'FitBoxToText', 'off',...
'FitHeightToText', 'on', ...
'FontWeight', 'bold', 'FontSize', 12,...
'HorizontalAlignment', 'center');
% annotate first bar (simple multiply without alignment)
text('Position', [2, t(1)], 'String', int2str(t(1)),...
'LineStyle', 'none', ...
'FontSize', 12, 'HorizontalAlignment', 'center',...
'VerticalAlignment', 'bottom');

% annotate second bar (SIMD Multiply without alignment)


text('Position', [4, t(2)], 'String', int2str(t(2)),...
'LineStyle', 'none', ...
'FontSize', 12, 'HorizontalAlignment', 'center',...
'VerticalAlignment', 'bottom');
else
warning(['The Data Alignment Performance Gain example'...
' could not be executed. %s.'], recMsg);
end

59-60
Optimize Generated Code By Developing and Using Code Replacement Libraries - Simulink®

Code Replacement Library Exploration and Verification

This example shows Code Replacement Viewer. You can use the Code Replacement
Viewer to:

• Explore which code replacement library to use


• Verify the list of tables in a library and the entries in each table
• Review table entry specifications
• Troubleshoot code replacement misses

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:

• Header file dependencies


• Source file dependencies
• Additional include paths
• Additional source paths
• Additional link flags

Additionally, you can specify RTW.copyFileToBuildDir to copy header, source, or


object files, which are required to generate replacement code, to the build folder before
code generation. You can specify RTW.copyFileToBuildDir by setting it as the value
of:

• Property GenCallback in a call to setTflCFunctionEntryParameters,


setTflCOperationEntryParameters, or setTflCSemaphoreEntryParameters.
• Argument genCallback in a call to registerCFunctionEntry,
registerCOperationEntry, or registerCSemaphoreEntry.

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

Each function implementation name defined by a code replacement table entry is


reserved as a unique identifier. You can specify other identifiers with a table on a per-
header-file basis. Providing additional reserved identifiers can help prevent duplicate
symbols and other identifier related compile and link issues.

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.

Remove Example Code Replacement Libraries

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

Improve Execution Efficiency by Reordering Block


Operations in the Generated Code
To improve execution efficiency, the code generator can change the block execution order.
In the Configuration Parameters dialog box, when you set the Optimize Block Order
parameter to Improved Execution Speed, the code generator can change the block
operation order to implement these optimizations:

• 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

Open the model matlab:rtwdemo_optimizeblockorder. This model contains three


subsystems for demonstrating how reordering block operations improves execution
efficiency.

59-65
59 Execution Speed in Embedded Coder

for Loop Fusion

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.

### 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
LoopFusionScheduling subsystem:

/* Output and update for atomic system: '<Root>/LoopFusionScheduling' */


static void LoopFusionScheduling(const real_T rtu_In1[6], const real_T rtu_In2[6],
const real_T rtu_In3[6], const real_T rtu_In4[6], real_T rty_Out1[6], real_T
rty_Out2[9], real_T rty_Out3[6], real_T rty_Out4[9])
{
int32_T i;
int32_T i_0;
int32_T tmp;
int32_T tmp_0;

/* Bias: '<S2>/Bias' incorporates:


* Gain: '<S2>/Gain'
*/
for (i = 0; i < 6; i++) {
rty_Out1[i] = -0.3 * rtu_In1[i] + 0.5;
}

/* End of Bias: '<S2>/Bias' */

/* 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];
}
}

/* End of Product: '<S2>/Product' */

59-67
59 Execution Speed in Embedded Coder

/* Bias: '<S2>/Bias1' incorporates:


* Gain: '<S2>/Gain1'
*/
for (i = 0; i < 6; i++) {
rty_Out3[i] = -0.3 * rtu_In3[i] + 0.5;
}

/* End of Bias: '<S2>/Bias1' */

/* 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];
}
}

/* End of Product: '<S2>/Product1' */


}

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

View the generated code with the optimization.

/* Output and update for atomic system: '<Root>/LoopFusionScheduling' */


static void LoopFusionScheduling(const real_T rtu_In1[6], const real_T rtu_In2[6],
const real_T rtu_In3[6], const real_T rtu_In4[6], real_T rty_Out1[6], real_T
rty_Out2[9], real_T rty_Out3[6], real_T rty_Out4[9])
{
int32_T i;
int32_T i_0;
int32_T tmp;

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>/Product' incorporates:


* Product: '<S2>/Product1'
*/
tmp_0 = 3 * i + i_0;
rty_Out2[tmp] = rty_Out2[tmp_0] + rtu_In2[i << 1] * rtu_In1[i_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];
}
}

for (i = 0; i < 6; i++) {


/* Bias: '<S2>/Bias' incorporates:
* Gain: '<S2>/Gain'
*/
rty_Out1[i] = -0.3 * rtu_In1[i] + 0.5;

/* Bias: '<S2>/Bias1' incorporates:


* Gain: '<S2>/Gain1'
*/
rty_Out3[i] = -0.3 * rtu_In3[i] + 0.5;
}
}

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:

/* Output and update for atomic system: '<Root>/RegionScheduling' */


static void RegionScheduling(const real_T rtu_In1[6], const real_T rtu_In2[6],
real_T rty_Out1[6], rtDW_RegionScheduling *localDW)
{
int32_T i;
real_T rtb_Sum;
for (i = 0; i < 6; i++) {
/* Sum: '<S3>/Sum' incorporates:
* UnitDelay: '<S3>/Delay'
* UnitDelay: '<S3>/UnitDelay'
*/
rtb_Sum = localDW->Delay_DSTATE[i] + localDW->UnitDelay_DSTATE[i];

/* UnitDelay: '<S3>/UnitDelay2' */
rty_Out1[i] = localDW->UnitDelay2_DSTATE[i];

/* Update for UnitDelay: '<S3>/Delay' incorporates:


* Bias: '<S3>/Bias'
*/
localDW->Delay_DSTATE[i] = rtu_In1[i] + 3.0;

/* Update for UnitDelay: '<S3>/UnitDelay' incorporates:

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];

/* Update for UnitDelay: '<S3>/UnitDelay2' */


localDW->UnitDelay2_DSTATE[i] = rtb_Sum;
}
}

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

View the generated code with the optimization.

/* Output and update for atomic system: '<Root>/RegionScheduling' */


static void RegionScheduling(const real_T rtu_In1[6], const real_T rtu_In2[6],
real_T rty_Out1[6], rtDW_RegionScheduling *localDW)
{
int32_T i;
for (i = 0; i < 6; i++) {
/* UnitDelay: '<S3>/UnitDelay2' */
rty_Out1[i] = localDW->UnitDelay2_DSTATE[i];

/* Update for UnitDelay: '<S3>/UnitDelay2' incorporates:


* Sum: '<S3>/Sum'
* UnitDelay: '<S3>/Delay'
* UnitDelay: '<S3>/UnitDelay'
*/
localDW->UnitDelay2_DSTATE[i] = localDW->Delay_DSTATE[i] +
localDW->UnitDelay_DSTATE[i];

/* Update for UnitDelay: '<S3>/Delay' incorporates:


* Bias: '<S3>/Bias'
*/
localDW->Delay_DSTATE[i] = rtu_In1[i] + 3.0;

/* Update for UnitDelay: '<S3>/UnitDelay' incorporates:


* Gain: '<S3>/Gain'

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.

Eliminate Data Copies for Blocks That Perform Inplace Operations

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.

### 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 InplaceScheduling
subsystem:

/* Output and update for atomic system: '<Root>/InplaceScheduling' */


static void InplaceScheduling(const real_T rtu_In1[6], real_T rtu_In3, const
real_T rtu_In2[6], real_T rty_Out2[6], real_T rty_Out1[6],
rtDW_InplaceScheduling *localDW)
{
int32_T idx1;
int32_T idx2;
real_T acc;
int32_T k;
real_T rtb_Max[6];
for (idx1 = 0; idx1 < 6; idx1++) {
/* Sum: '<S1>/Sum2x3' incorporates:
* UnitDelay: '<S1>/Unit Delay'
*/
localDW->UnitDelay_DSTATE[idx1] += rtu_In1[idx1];

/* 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

/* End of MinMax: '<S1>/Max' */


}

/* S-Function (sdsp2norm2): '<S1>/Normalization' */


idx1 = 0;
idx2 = 0;
acc = 0.0;
for (k = 0; k < 6; k++) {
acc += rtb_Max[idx1] * rtb_Max[idx1];
idx1++;
}

acc = 1.0 / (sqrt(acc) + 1.0E-10);


for (k = 0; k < 6; k++) {
rty_Out1[idx2] = rtb_Max[idx2] * acc;
idx2++;

/* Product: '<S1>/Product' incorporates:


* Bias: '<S1>/Bias'
*/
rty_Out2[k] = (rtu_In3 + 1.0) * localDW->UnitDelay_DSTATE[k];

/* 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];
}

/* End of Switch: '<S1>/Switch' */


}

/* End of S-Function (sdsp2norm2): '<S1>/Normalization' */


}

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

View the generated code with the optimization.

/* Output and update for atomic system: '<Root>/InplaceScheduling' */


static void InplaceScheduling(const real_T rtu_In1[6], real_T rtu_In3, const
real_T rtu_In2[6], real_T rty_Out2[6], real_T rty_Out1[6],
rtDW_InplaceScheduling *localDW)
{
int32_T idx1;
int32_T idx2;
real_T acc;
int32_T k;
for (idx1 = 0; idx1 < 6; idx1++) {
/* Sum: '<S1>/Sum2x3' incorporates:
* UnitDelay: '<S1>/Unit Delay'
*/
localDW->UnitDelay_DSTATE[idx1] += rtu_In1[idx1];

/* Product: '<S1>/Product' incorporates:


* Bias: '<S1>/Bias'
*/
rty_Out2[idx1] = (rtu_In3 + 1.0) * localDW->UnitDelay_DSTATE[idx1];

/* MinMax: '<S1>/Max' */
if (2.0 > localDW->UnitDelay_DSTATE[idx1]) {
localDW->UnitDelay_DSTATE[idx1] = 2.0;
}

/* End of MinMax: '<S1>/Max' */


}

/* S-Function (sdsp2norm2): '<S1>/Normalization' */


idx1 = 0;
idx2 = 0;
acc = 0.0;
for (k = 0; k < 6; k++) {
acc += localDW->UnitDelay_DSTATE[idx1] * localDW->UnitDelay_DSTATE[idx1];
idx1++;
}

59-74
See Also

acc = 1.0 / (sqrt(acc) + 1.0E-10);


for (k = 0; k < 6; k++) {
rty_Out1[idx2] = localDW->UnitDelay_DSTATE[idx2] * acc;
idx2++;
}

/* End of S-Function (sdsp2norm2): '<S1>/Normalization' */

/* Update for UnitDelay: '<S1>/Unit Delay' */


for (idx1 = 0; idx1 < 6; idx1++) {
/* Switch: '<S1>/Switch' */
if (rtu_In2[idx1] > 0.0) {
localDW->UnitDelay_DSTATE[idx1] = 0.0;
}

/* End of Switch: '<S1>/Switch' */


}

/* End of Update for UnitDelay: '<S1>/Unit Delay' */


}

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

Memory Usage in Embedded Coder

• “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

Optimize Generated Code Using Minimum and Maximum


Values
To optimize the generated code for your model, you can choose an option to use input
range information, also known as design minimum and maximum, that you specify on
signals and parameters. These minimum and maximum values usually represent
environmental limits, such as temperature, or mechanical and electrical limits, such as
output ranges of sensors.

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:

• Reducing expressions to constants


• Removing dead branches of conditional statements
• Eliminating unnecessary mathematical operations

This optimization results in:

• Reduced ROM and RAM consumption


• Improved execution speed

Configure Your Model


To make optimization more likely:

• Provide as much design minimum and maximum information as possible. Specify


minimum and maximum values for signals and parameters in the model for:

• Inport and Outport blocks


• Block outputs
• Block inputs, for example, for the MATLAB Function and Stateflow Chart blocks
• Simulink.Signal objects
• Before generating code, test the minimum and maximum values for signals and
parameters. Otherwise, optimization might result in numerical mismatch with

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.

Enable Simulation Range Checking

1 In your model, select Simulation > Model Configuration Parameters to open


the Configuration Parameters dialog box.
2 In the Configuration Parameters dialog box, select Diagnostics > Data Validity.
3 On the Data Validity pane, under Signals, set Simulation range checking to
warning or error.
• Provide design minimum and maximum information upstream of blocks as close to the
inputs of the blocks as possible. If you specify minimum and maximum values for a
block output, these values are most likely to affect the outputs of the blocks
immediately downstream.

Optimize Generated Code Using Specified Minimum and


Maximum Values
This example shows how the minimum and maximum values specified on signals and
parameters in a model are used to optimize the generated 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.

The benefits of optimizing the generated code are:

• Reducing the ROM and RAM consumption.


• Improving the execution speed.

Review Minimum and Maximum Information

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);

Generate Code Without This Optimization

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

### Starting build procedure for model: rtwdemo_minmax


### Successful completion of build procedure for model: rtwdemo_minmax

A portion of rtwdemo_minmax.c is listed below.

cfile = fullfile(cgDir,'rtwdemo_minmax_ert_rtw','rtwdemo_minmax.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);

/* Model step function */


void rtwdemo_minmax_step(void)
{
int32_T tmp;

/* Sum: '<Root>/Sum' incorporates:


* Inport: '<Root>/U1'
* Inport: '<Root>/U2'
* Sum: '<Root>/Sum2'
* Switch: '<Root>/Switch'
*/
tmp = U1 + U2;

/* Switch: '<Root>/Switch' incorporates:


* Gain: '<Root>/Gain'
* Inport: '<Root>/U3'
* RelationalOperator: '<Root>/Relational Operator'
* Sum: '<Root>/Sum'
*/
if (tmp <= k * U3) {
/* Outport: '<Root>/Out1' incorporates:
* Sum: '<Root>/Sum2'
*/
rtY.Out1 = tmp + U3;
} else {
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/U1'
* Inport: '<Root>/U2'
* Product: '<Root>/Product'
*/
rtY.Out1 = U1 * U2 * U3;
}
}

60-5
60 Memory Usage in Embedded Coder

Enable This Optimization

1 Open the Configuration Parameters dialog box.


2 On the Optimization pane, select Optimize using the specified minimum and
maximum values.

Alternatively, you can enable this optimization by setting the command-line parameter.

set_param(model, 'UseSpecifiedMinMax', 'on');

Generate Code With This Optimization

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.

Configure and build the model using Embedded Coder.

rtwconfiguredemo(model,'ERT')
rtwbuild(model)

### Starting build procedure for model: rtwdemo_minmax


### Successful completion of build procedure for model: rtwdemo_minmax

View the optimized code from rtwdemo_minmax.c.

cfile = fullfile(cgDir,'rtwdemo_minmax_ert_rtw','rtwdemo_minmax.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);

/* Model step function */


void rtwdemo_minmax_step(void)
{
/* Outport: '<Root>/Out1' incorporates:
* Inport: '<Root>/U1'
* Inport: '<Root>/U2'
* Inport: '<Root>/U3'
* Product: '<Root>/Product'
* Switch: '<Root>/Switch'
*/

60-6
Optimize Generated Code Using Minimum and Maximum Values

rtY.Out1 = U1 * U2 * U3;
}

Close the model and cleanup.

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.

Outport blocks in conditionally-executed subsystems can have an initial value


specified for use only when the system is not triggered. In this case, the
optimization cannot use the range of the block output because the range might not
cover the initial value of the block.
• If you use Polyspace software to verify code generated using this optimization, it might
mark code that was previously green as orange. For example, if your model contains a
division where the range of the denominator does not include zero, the generated code
does not include protection against division by zero. Polyspace might mark this code
orange because it does not have information about the minimum and maximum values
for the inputs to the division.

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

Flat Structures for Reusable Subsystem Parameters


This example shows how to increase the efficiency of code generated for reusable
subsystems by generating a single flat parameter structure instead of a hierarchy of
nested parameter structures.

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.

Explore Example Model

Open the example model rtwdemo_paramstruct.


model = 'rtwdemo_paramstruct';
open_system(model);

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.

Generate Code with Hierarchical Parameter Structures

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)

### Starting build procedure for model: rtwdemo_paramstruct


### Successful completion of build procedure for model: rtwdemo_paramstruct

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

/* Parameters for system: '<S1>/SubsysZ' */


struct P_SubsysZ_ {
uint16_T C; /* Variable: C
* Referenced by: '<S2>/Gain3'
*/
uint16_T D; /* Variable: D
* Referenced by: '<S2>/Gain4'
*/
};

/* Parameters for system: '<S1>/SubsysZ' */


typedef struct P_SubsysZ_ P_SubsysZ;

/* Parameters for system: '<Root>/SubsysY' */


struct P_SubsysY_ {
uint16_T A; /* Variable: A
* Referenced by: '<S1>/Gain1'
*/
uint16_T B; /* Variable: B
* Referenced by: '<S1>/Gain2'
*/
P_SubsysZ SubsysZ_m; /* '<S1>/SubsysZ' */
};

/* Parameters for system: '<Root>/SubsysY' */


typedef struct P_SubsysY_ P_SubsysY;

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.

Alternatively, enable the optimization at the command prompt.

set_param(model, 'InlinedParameterPlacement', 'NonHierarchical');

Generate Code with Flat Parameter Structure

Generate code for the model using a flat parameter structure for reusable subsystems.

rtwbuild(model)

60-10
See Also

### Starting build procedure for model: rtwdemo_paramstruct


### Successful completion of build procedure for model: rtwdemo_paramstruct

In the code generation report, view the parameter structure definition in the file
rtwdemo_paramstruct.h.

rtwdemodbtype(cfile,'/* Parameters (default storage) */',...


'/* Real-time Model Data Structure */', 1, 0);

/* Parameters (default storage) */


struct P_ {
uint16_T A; /* Variable: A
* Referenced by: '<S1>/Gain1'
*/
uint16_T B; /* Variable: B
* Referenced by: '<S1>/Gain2'
*/
uint16_T C; /* Variable: C
* Referenced by: '<S2>/Gain3'
*/
uint16_T D; /* Variable: D
* Referenced by: '<S2>/Gain4'
*/
};

/* Parameters (default storage) */


typedef struct P_ P;

The code stores all of the parameters for the reusable subsystems in a single flat
structure.

Close the model and delete build files.

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

Reduce Global Variables in Nonreusable Subsystem


Functions
In this section...
“Generate void-void Function” on page 60-13
“Generate Function with Arguments” on page 60-14

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.

Generate void-void Function


By default, when you configure a Subsystem block as a nonreusable function, it generates
a void-void interface.

1 Open the example model rtwdemo_roll.


2 Right-click the subsystem RollAngleReference. From the list select Block
Parameter (Subsystem).
3 In the Block Parameters dialog box, confirm that the Treat as atomic unit check box
is selected.
4 Click the Code Generation tab and set the Function packaging parameter to
Nonreusable function.
5 The Function interface parameter is already set to void_void.
6 Click Apply and OK.
7 Repeat steps 2–6, for the other subsystems HeadingMode and BasicRollMode.
8 Generate code and the static code metrics report for rtwdemo_roll. This model is
configured to generate a code generation report and to open the report automatically.
For more information, see “Generate Static Code Metrics Report for Simulink Model”
on page 38-37.

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.

Generate Function with Arguments


To reduce global RAM, improve ROM usage and execution speed, generate a function that
allows arguments:

1 Open the Subsystem Block Parameter dialog box for RollAngleReference.


2 Click the Code Generation tab. Set the Function interface parameter to Allow
arguments.
3 Click Apply and OK.
4 Repeat steps 2 and 3, for the other subsystems HeadingMode and BasicRollMode.
5 Generate code and the static code metrics report for rtwdemo_roll.

60-14
See Also

In the code generation report, in rtwdemo_roll.c, the generated code for subsystem
RollAngleReference now has arguments:

real32_T rtwdemo_roll_RollAngleReference(real32_T rtu_Phi,...


boolean_T rtu_AP_Eng,...
real32_T rtu_Turn_Knob)
{
...
}

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

Optimize Generated Code By Packing Boolean Data Into


Bitfields
This example shows how to optimize the generated code by packing Boolean data into
bitfields. When you select the model configuration parameter Pack Boolean data into
bitfields, Embedded Coder® packs the Boolean signals into 1-bit bitfields, reducing RAM
consumption. By default, the optimization is enabled. This optimization reduces the RAM
consumption. Be aware that this optimization can potentially increase code size and
execution speed.

Example Model

Consider the model rtwdemo_pack_boolean.

model = 'rtwdemo_pack_boolean';
open_system(model);

Disable Optimization

1 Open the Configuration Parameters dialog box.

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();

Generate Code Without Optimization

Build the model using Embedded Coder®.


rtwbuild(model)

### Starting build procedure for model: rtwdemo_pack_boolean


### Successful completion of build procedure for model: rtwdemo_pack_boolean

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);

/* Block signals and states (default storage) for system '<Root>' */


typedef struct {
boolean_T LogicalOp1; /* '<Root>/Logical Op1' */
boolean_T LogicalOp2; /* '<Root>/Logical Op2' */
boolean_T LogicalOp5; /* '<Root>/Logical Op5' */
boolean_T LogicalOp3; /* '<Root>/Logical Op3' */
boolean_T LogicalOp4; /* '<Root>/Logical Op4' */
boolean_T RelationalOperator; /* '<Root>/Relational Operator' */
boolean_T UnitDelay_DSTATE; /* '<Root>/Unit Delay' */
} DW;

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');

Generate Code with Optimization

Build the model using Embedded Coder®.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_pack_boolean


### Successful completion of build procedure for model: rtwdemo_pack_boolean

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);

/* Block signals and states (default storage) for system '<Root>' */


typedef struct {
struct {
uint_T LogicalOp1:1; /* '<Root>/Logical Op1' */
uint_T LogicalOp2:1; /* '<Root>/Logical Op2' */
uint_T LogicalOp5:1; /* '<Root>/Logical Op5' */
uint_T LogicalOp3:1; /* '<Root>/Logical Op3' */
uint_T LogicalOp4:1; /* '<Root>/Logical Op4' */
uint_T RelationalOperator:1; /* '<Root>/Relational Operator' */
uint_T UnitDelay_DSTATE:1; /* '<Root>/Unit Delay' */
} bitsForTID0;
} DW;

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.

Close the model and code generation report.

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

Optimize Generated Code By Passing Reusable


Subsystem Outputs as Individual Arguments
This example shows how passing reusable subsystem outputs as individual arguments
instead of as a pointer to a structure stored in global memory optimizes the generated
code. This optimization conserves RAM consumption and increases code execution speed
by reducing global memory usage and eliminating data copies from local variables back to
global block I/O structures.

Example Model

Consider the model rtwdemo_reusable_sys_outputs. In this model, the reusable subsystem


outputs feed the root outputs of the model.
model = 'rtwdemo_reusable_sys_outputs';
open_system(model);

Generate Code Without This Optimization

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

Build the model.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_reusable_sys_outputs


### Successful completion of build procedure for model: rtwdemo_reusable_sys_outputs

The code snippet shows portions of rtwdemo_reusable_sys_outputs.c. Notice the


global block I/O structure and in the model step function a data copy from this structure.

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);

/* Output and update for atomic system: '<Root>/ReusableSubsystem' */


static void ReusableSubsystem(real_T rtu_In1, real_T rtu_In2, real_T rtu_In3,
DW_ReusableSubsystem *localDW)
{
/* Gain: '<S1>/Gain' */
localDW->Gain = 5.0 * rtu_In1;

/* Gain: '<S1>/Gain1' */
localDW->Gain1 = 6.0 * rtu_In2;

/* Gain: '<S1>/Gain2' */
localDW->Gain2 = 7.0 * rtu_In3;
}

/* Model step function */


void rtwdemo_reusable_sys_outputs_step(void)
{
/* Outputs for Atomic SubSystem: '<Root>/ReusableSubsystem' */

/* Inport: '<Root>/In1' incorporates:


* Inport: '<Root>/In2'
* Inport: '<Root>/In3'
*/
ReusableSubsystem(rtU.In1, rtU.In2, rtU.In3, &rtDW.ReusableSubsystem_d);

/* End of Outputs for SubSystem: '<Root>/ReusableSubsystem' */

/* 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;
}

Enable This Optimization

1 Open the Configuration Parameters dialog box.


2 On the Optimization pane, set Pass reusable subsystem outputs as to
Individual arguments.

Alternatively, you can use the command-line API to enable the optimization:

set_param(model, 'PassReuseOutputArgsAs', 'Individual arguments');

Generate Code With This 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.

Build the model.

rtwbuild(model)

### Starting build procedure for model: rtwdemo_reusable_sys_outputs


### Successful completion of build procedure for model: rtwdemo_reusable_sys_outputs

The code snippet below is a portion of rtwdemo_reusable_sys_outputs.c. Observe


the optimized code.

rtwdemodbtype(cfile,'/* Output and update for atomic system',...


'/* Model initialize', 1, 0);

/* Output and update for atomic system: '<Root>/ReusableSubsystem' */


static void ReusableSubsystem(real_T rtu_In1, real_T rtu_In2, real_T rtu_In3,
real_T *rty_Out1, real_T *rty_Out2, real_T *rty_Out3)
{
/* Gain: '<S1>/Gain' */

60-22
See Also

*rty_Out1 = 5.0 * rtu_In1;

/* Gain: '<S1>/Gain1' */
*rty_Out2 = 6.0 * rtu_In2;

/* Gain: '<S1>/Gain2' */
*rty_Out3 = 7.0 * rtu_In3;
}

/* Model step function */


void rtwdemo_reusable_sys_outputs_step(void)
{
/* Outputs for Atomic SubSystem: '<Root>/ReusableSubsystem' */

/* Inport: '<Root>/In1' incorporates:


* Inport: '<Root>/In2'
* Inport: '<Root>/In3'
* Outport: '<Root>/Out1'
* Outport: '<Root>/Out2'
* Outport: '<Root>/Out3'
*/
ReusableSubsystem(rtU.In1, rtU.In2, rtU.In3, &rtY.Out1, &rtY.Out2, &rtY.Out3);

/* End of Outputs for SubSystem: '<Root>/ReusableSubsystem' */


}

Close the model and cleanup.

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

• “Standard Data Structures in the Generated Code” on page 22-26

60-24
Convert Data Copies to Pointer Assignments

Convert Data Copies to Pointer Assignments


The code generator optimizes generated code for vector signal assignments by trying to
replace for loop controlled element assignments and memcpy function calls with pointer
assignments. Pointer assignments avoid expensive data copies. Therefore, they use less
stack space and offer faster execution speed than for loop controlled element
assignments and memcpy function calls. If you assign large data sets to vector signals,
this optimization can result in significant improvements to code efficiency.

Configure Model to Optimize Generated Code for Vector Signal Assignments

To apply this optimization:

1 Verify that your target supports the memcpy function.


2 Determine whether your model uses vector signal assignments (such as
Y=expression) to move large amounts of data. For example, your model could use a
Selector block to select input elements from a vector, matrix, or multidimension
signal.
3 On the Optimization pane, the Use memcpy for vector assignment parameter,
which is on by default, enables the associated Memcpy threshold (bytes)
parameter.
4 Examine the setting of Memcpy threshold (bytes). By default, it specifies 64 bytes
as the minimum array size for which memcpy function calls or pointer assignments
can replace for loops in the generated code. Based on the array sizes in your
application's vector signal assignments, and target environment considerations on
the threshold selection, accept the default value or specify another array size.

Example Model

Consider the following model named rtwdemo_pointer_conversion. This model uses a


Switch block to assign data to a vector signal. This signal then feeds into a Bus Selector
block.

60-25
60 Memory Usage in Embedded Coder

Generate Code without Optimization


1 In the Configuration Parameters dialog box, clear the Use memcpy for vector
assignment parameter.
2 Create a temporary folder for the build and inspection process.
3 Press Ctrl+B to generate code.
### Starting build procedure for model: rtwdemo_pointer_conversion
### Successful completion of build procedure for model: rtwdemo_pointer_conversion

View the generated code without the optimization. Here is a portion of


rtwdemo_pointer_conversion.c .

/* Model step function */


void rtwdemo_pointer_conversion_step(void)
{
int16_T rtb_dataX[100];
int16_T rtb_dataY[100];
int32_T i;

/* Switch: '<Root>/Switch' incorporates:


* Constant: '<Root>/Constant'
* Constant: '<Root>/Constant1'
* Constant: '<Root>/Constant2'
* Constant: '<Root>/Constant3'

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];
}
}

/* End of Switch: '<Root>/Switch' */

/* S-Function (sfix_look1_dyn): '<Root>/Lookup Table Dynamic' incorporates:


* Inport: '<Root>/In2'
* Outport: '<Root>/Out1'
*/
/* Dynamic Look-Up Table Block: '<Root>/Lookup Table Dynamic'
* Input0 Data Type: Integer S16
* Input1 Data Type: Integer S16
* Input2 Data Type: Integer S16
* Output0 Data Type: Integer S16
* Lookup Method: Linear_Endpoint
*
*/
LookUp_S16_S16( &(rtY.Out1), &rtb_dataY[0], rtU.In2, &rtb_dataX[0], 99U);
}

Without the optimization, the generated code contains for loop controlled element
assignments.

Enable Optimization and Generate Code

1 In the Configuration Parameter dialog box, select the Use memcpy for vector
assignment parameter.
2 Generate code.

### Starting build procedure for model: rtwdemo_pointer_conversion


### Successful completion of build procedure for model: rtwdemo_pointer_conversion

View the generated code without the optimization. Here is a portion of


rtwdemo_pointer_conversion.c.

60-27
60 Memory Usage in Embedded Coder

/* Model step function */


void rtwdemo_pointer_conversion_step(void)
{
const int16_T *rtb_dataX_0;
const int16_T *rtb_dataY_0;

/* Switch: '<Root>/Switch' incorporates:


* Inport: '<Root>/In1'
*/
if (rtU.In1) {
/* Switch: '<Root>/Switch' incorporates:
* Constant: '<Root>/Constant'
* Constant: '<Root>/Constant1'
*/
rtb_dataX_0 = &rtCP_Constant_Value[0];
rtb_dataY_0 = &rtCP_Constant1_Value[0];
} else {
/* Switch: '<Root>/Switch' incorporates:
* Constant: '<Root>/Constant2'
* Constant: '<Root>/Constant3'
*/
rtb_dataX_0 = &rtCP_Constant2_Value[0];
rtb_dataY_0 = &rtCP_Constant3_Value[0];
}

/* S-Function (sfix_look1_dyn): '<Root>/Lookup Table Dynamic' incorporates:


* Inport: '<Root>/In2'
* Outport: '<Root>/Out1'
*/
/* Dynamic Look-Up Table Block: '<Root>/Lookup Table Dynamic'
* Input0 Data Type: Integer S16
* Input1 Data Type: Integer S16
* Input2 Data Type: Integer S16
* Output0 Data Type: Integer S16
* Lookup Method: Linear_Endpoint
*
*/
LookUp_S16_S16( &(rtY.Out1), &rtb_dataY_0[0], rtU.In2, &rtb_dataX_0[0], 99U);
}

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

Reuse Buffers of Different Sizes and Dimensions


You can reuse buffers for matrices that have different sizes and shapes. In the
Configuration Parameters dialog box, you enable this optimization by selecting Reuse
buffers of different sizes and dimensions. This optimization conserves RAM and ROM
usage and improves code execution speed.

Example Model

The model rtwdemo_differentsizereuse contains signals of different sizes and dimensions.


model='rtwdemo_differentsizereuse';
open_system(model);

Generate Code Without Optimization

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');

Create a folder for the build and inspection process.


currentDir = pwd;
[~,cgDir] = rtwdemodir();

Turn off comments and build the model.


set_param('rtwdemo_differentsizereuse','GenerateComments','off');
rtwbuild('rtwdemo_differentsizereuse');

### Starting build procedure for model: rtwdemo_differentsizereuse


### Successful completion of build procedure for model: rtwdemo_differentsizereuse

View the generated code without the optimization. The D_Work structure is:

60-30
Reuse Buffers of Different Sizes and Dimensions

The portion of rtwdemo_differentsizereuse.c is:


cfile = fullfile(cgDir,'rtwdemo_differentsizereuse_ert_rtw',...
'rtwdemo_differentsizereuse.c');
rtwdemodbtype(cfile,'#include "rtwdemo_differentsizereuse.h"',...
'void rtwdemo_differentsizereuse_initialize(void)',1,0);

#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

rtu_u[(((((1 + y) << 1) - 1) << 7) + ((1 + x) << 1)) - 2]) + rtu_u


[(((((1 + y) << 1) - 1) << 7) + ((1 + x) << 1)) - 1]) / 4.0;
}
}
}

static void NoninplaceableSS1(void)


{
Downsample(rtDWork.ComplextoRealImag_o1, rtDWork.z_p);
Downsample(rtDWork.ComplextoRealImag_o2, rtDWork.z_f);
}

static void DeltaX(const real_T rtu_u[4096], real_T rty_z[4032])


{
int32_T x;
int32_T y;
for (x = 0; x < 63; x++) {
for (y = 0; y < 64; y++) {
rty_z[x + 63 * y] = fabs(rtu_u[(y << 6) + x] - rtu_u[((y << 6) + x) + 1]);
}
}
}

static void NoninplaceableSS2(void)


{
DeltaX(rtDWork.z_p, rtDWork.z_j);
DeltaX(rtDWork.z_f, rtDWork.z_m);
}

static void DeltaY(const real_T rtu_u[4032], real_T rty_z[3969])


{
int32_T x;
int32_T y;
for (x = 0; x < 63; x++) {
for (y = 0; y < 63; y++) {
rty_z[x + 63 * y] = fabs(rtu_u[63 * y + x] - rtu_u[(y + 1) * 63 + x]);
}
}
}

static void NoninplaceableSS3(void)


{
DeltaY(rtDWork.z_j, rtDWork.z_i);
DeltaY(rtDWork.z_m, rtDWork.z);

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.

Generate Code with Optimization

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');

Build the model.

set_param('rtwdemo_differentsizereuse','GenerateComments','off');
rtwbuild(model);

### Starting build procedure for model: rtwdemo_differentsizereuse


### Successful completion of build procedure for model: rtwdemo_differentsizereuse

View the generated code without the optimization. The D_Work structure is:

60-33
60 Memory Usage in Embedded Coder

The portion of rtwdemo_differentsizereuse.c is:


cfile = fullfile(cgDir,'rtwdemo_differentsizereuse_ert_rtw',...
'rtwdemo_differentsizereuse.c');
rtwdemodbtype(cfile,'#include "rtwdemo_differentsizereuse.h"',...
'void rtwdemo_differentsizereuse_initialize(void)',1,0);

#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

static void NoninplaceableSS1(void)


{
Downsample(rtDWork.z_i, rtDWork.z);
Downsample(rtDWork.z_e, &rtDWork.z_i[0]);
}

static void DeltaX(const real_T rtu_u[4096], real_T rty_z[4032])

You might also like