Mathworks REAL-TIME WORKSHOP 7 Target Language Compiler

®
Real-Time Worksho
p
7
Target Language Compiler
How to Contact The MathWorks
www.mathworks. comp.soft-sys.matlab Newsgroup www.mathworks.com/contact_TS.html T echnical Support
suggest@mathworks.com Product enhancem ent suggestions bugs@mathwo doc@mathworks.com Documentation error reports service@mathworks.com Order status, license renewals, passcodes info@mathwo
com
rks.com
rks.com
Bug reports
Sales, prici
ng, and general information
508-647-7000 (Phone)
508-647-7001 (Fax)
The MathWorks, Inc. 3 Apple Hill Drive Natick, MA 01760-2098
For contact information about worldwide offices, see the MathWorks Web site.
®
Real-Time Workshop
© COPYRIGHT 1997–20 10 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 MathW orks, 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 theuse,modification,reproduction,release,performance,display,anddisclosureoftheProgramand 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 Docu mentation, 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
The MathWorks products are protected by one or more U.S. patents. Please see
www.mathworks.com/patents for more information.
Target Language Compiler
Revision History
May 1997 First printing New for Target Language Compiler 1.0 September 2000 Online only Revised for Version 4.0 (Release 12) April 2001 Online only Revised for Version 4.1 (Release 12.1) July 2002 Online only Revised for Version 5.0 (Release 13) June 2004 Online only Revised for Version 6.0 (Release 14) October 2004 Online only Revised for Version 6.1 (Release 14SP1) September 2005 Online only Revised for Version 6.3 (Release 14SP3) March 2006 Online only Revised for Version 6.4 (Release 2006a) September 2006 Online only Revised for Version 6.5 (Release 2006b) March 2007 Online only Revised for Version 6.6 (Release 2007a) September 2007 Online only Revised for Version 7.0 (Release 2007b) March 2008 Online only Revised for Version 7.1 (Release 2008a) October 2008 Online only Revised for Version 7.2 (Release 2008b) March 2009 Online only Revised for Version 7.3 (Release 2009a) September 2009 Online only Revised for Version 7.4 (Release 2009b) March 2010 Online only Revised for Version 7.5 (Release 2010a)
Introducing the Target Language Compiler
1
What Is the Target Language Compiler? ............. 1-2
Target Language Compiler Overview Overview o f the TLC Process Overview o f the Code Generation Process
........................ 1-3
................. 1-2
.............. 1-5
Contents
Target Language Compiler Capabilities
Why Use TLC? Customizing Output Inlining S-Functions Modifying and Diversifying Code Generation
Code Generation Process
Process Overview How TLC Determines S-Function Inlining Status A Look at Inlined and Noninlined S-Function Code
The Advantages of Inlining S-Functions
Goals Inlining Process Search Algorithm for Locating TLC Files Availability for Inlining and Noninlining
Where to Go from Here
Topics Covered in This Manual Related Manuals
........................................... 1-16
.................................... 1-8
............................... 1-8
............................... 1-9
........................... 1-11
................................. 1-11
................................... 1-17
............................. 1-20
...................... 1-20
.................................. 1-21
............. 1-8
............. 1-16
.............. 1-18
.............. 1-19
........... 1-9
....... 1-11
...... 1-12
Getting Started
2
Code Architecture ................................. 2-2
v
Target Language Compiler Overview ................ 2-4
The Target Language Compiler Process Operating Sequence
............................... 2-5
............... 2-4
Inlining S-Functions
Inlining an S-function Noninlined S-Function Types of Inlining Fully Inlined S-Function Example Wrapper Inlined S-Function Example
............................... 2-6
.............................. 2-6
............................. 2-6
.................................. 2-7
.................... 2-8
................. 2-11
Target Language Compiler Tutorials
3
Introduction ...................................... 3-2
Reading Record Files w ith TLC
Tutorial Overv iew Learning About the Structure of Record Files Interpreting Records Learning About the Anatomy o f a TLC Script Modifying Passing and Using a Parameter Review
read-guide.tlc ......................... 3-17
.......................................... 3-24
................................. 3-4
............................... 3-6
..................... 3-4
.......... 3-5
........... 3-7
...................... 3-22
vi Contents
Inlining S-Functions with T LC
timesN T utorial Overview .......................... 3-26
Learning About Noninlined Code Generation Understand Why You Use TLC to Inline S-Functions Creating an Inlined S-Function
Exploring Variable Names and Loop Rolling
timesN L ooping Tutorial Overview ................... 3-32
Getting Started Modifying the Model Changing the Loop Rolling Threshold Learning More About TLC Loop Rolling
................................... 3-32
............................... 3-34
...................... 3-26
........... 3-26
.... 3-29
...................... 3-29
......... 3-32
................. 3-36
............... 3-37
Debugging Your TLC Code ......................... 3-41
tlcdebug Tutorial Overview ........................ 3-41
Getting Started Generating and Running Code from the Model Start the Debugger and Use its Commands Debugging Fixing the Bug and Verifying the Fix
................................... 3-42
.......... 3-44
............ 3-45
timesN.tlc ............................. 3-47
................. 3-48
Using TLC Code Coverage to Aid Debugging
tlcdebug Execute Tutorial Overview ................. 3-50
Getting Started Opening the Model and Generating Code
Wrapping User Code with TLC
wrapper Tutorial Overview ......................... 3-53
Understanding Why You Might Wrap Getting Started Generating Code Without a Wrapper Generating Code Using a Wrapper
................................... 3-50
...................... 3-53
................. 3-53
................................... 3-56
................. 3-58
................... 3-59
......... 3-50
.............. 3-51
Code Generation Architecture
4
Build Process ..................................... 4-2
Build Proces s Overview A Basic Example
Configuring TLC
Setting Command-Line Arguments Configuring for TLC Debugging
.................................. 4-2
.................................. 4-9
............................ 4-2
................... 4-9
...................... 4-11
Code Generation Concepts
Overview Output Streams Variable Types Records Record Alias es
........................................ 4-12
................................... 4-12
.................................... 4-13
.......................................... 4-13
.................................... 4-15
......................... 4-12
vii
TLC Files ......................................... 4-18
TLC Program Available Targ et Files Summary of Target File Usage System Target Files
..................................... 4-18
.............................. 4-19
...................... 4-20
............................... 4-20
Data Handling with TLC: an Example
Matrix Parameters Real-Time Workshop Matrix Parameters
................................ 4-22
............... 4-22
.............. 4-22
Understanding the model.rtw File
5
Introduction to the model.rtw File ................... 5-2
Using Scopes in the
ObjectInformationinthe
Object Overview Object Records for Parameters Object Records for Signals Accessing Object Information via TLC
Data References in the
Data Reference Overview Controlling the Data Reference Threshold Expanding Data References Avoiding Data Reference Expansion Restarting Code Generation
model.rtw File .................. 5-4
model.rtw File ............. 5-7
.................................. 5-7
....................... 5-7
.......................... 5-8
................ 5-9
model.rtw File ............... 5-12
........................... 5-12
............. 5-12
......................... 5-13
.................. 5-13
......................... 5-13
viii Contents
Using Library Functions to Access
Library Functions Overview Caution Against Directly Accessing Record Fields Exception to Using the Library Functions
......................... 5-14
model.rtw ......... 5-14
....... 5-14
.............. 5-15
6
Directives and Built-In Functions
Target Language
Syntax Directives Comments Line Continuat Target Langua Target Langua Formatting Conditional Multiple Inc Object-Orie Output File Input File C Asserts, Er Built-In F TLC Reserv Identifie Variable Target La
Command
Target L Filenam
.......................................... 6-2
........................................ 6-3
....................................... 6-19
ge Value Types ge Expressions
....................................... 6-29
Inclusion lusion
nted Facility for Generating Target Code
Control ontrol
rors, Warnings, and Debug Messages
unctions and Values
ed Constants
r Definition
Scoping
nguage Functions
-Line Arguments
anguage Compiler Switches
es and Search Paths
Compiler Directives
ion
.................................
...............
.......................
.......................
..............................
.................................
................................
.................................
........
.......................
...........................
...............................
..................................
.........................
.........................
..................
........................
.....
6-2
6-20 6-20 6-22
6-29 6-31 6-36 6-38 6-40 6-41 6-42 6-53 6-53 6-57 6-67
6-72 6-72 6-74
7
ut the TLC Debugger
Abo
Debugger Ov erv iew
TLC
s for Debugging TLC Code
Tip
ing the TLC Debugger
Us
voking the Debugger
In
C Debugger Command Summary
TL
Debug
ging TLC Files
...........................
...........................
.......................
...........................
.............................
..................
7-2 7-2 7-2
7­7­7-
3 3 4
ix
TLC Coverage ..................................... 7-8
Using the TLC Coverage Option Example .log File Analyzing the Results
.................................. 7-9
.............................. 7-12
..................... 7-8
TLC Profiler
Using the Profiler Analyzing the Report Nonexecutable Directives Improving Performance
...................................... 7-13
................................. 7-13
.............................. 7-14
........................... 7-15
............................ 7-15
Inlining S-Functions
8
Introduction ...................................... 8-2
Writing Block Target Files to Inline S-Functions
When to Inline S-Functions Fully Inlined S-Functions Function-Based or Wrapped Code Generation
Inlining C MEX S-Functions
Inline S-Function Overview S-Function Parameters ACompleteExample
............................... 8-8
......................... 8-2
........................... 8-2
.......... 8-3
........................ 8-4
......................... 8-4
............................. 8-7
..... 8-2
x Contents
Inlining MA TLA B File S -Functions
Inlining Fortran (F-MEX) S-Functions
TLC Coding Conventions
Overview Begin Identifiers with Uppercase Letters Begin Global Variable Assignments with Uppercase
Letters
Begin Local Variable Assignments with Lowercase
Letters
Begin Functions Declared in block.tlc Files with Fcn
........................................ 8-25
........................................ 8-26
........................................ 8-27
........................... 8-25
.................. 8-18
............... 8-21
.............. 8-25
..... 8-27
Do Not Hard-Code Variables Defined in
commonsetup.tlc Conditional Inclusion in Library Files Code Defensively
................................ 8-27
................. 8-29
.................................. 8-29
Block Target File Methods
Block Functions Overview BlockInstanceSetup(block, system) BlockTypeSetup(block, sy stem) Enable(block, system) Disable(block, system) Start(block, system) InitializeConditions(block, system) Outputs(block, system ) Update(block, system) Derivatives(block, system) Terminate(block, system)
Loop Rolling
Error Reporting
...................................... 8-41
9
.......................... 8-31
.......................... 8-31
................... 8-32
...................... 8-33
.............................. 8-35
............................. 8-35
............................... 8-35
................... 8-36
............................. 8-37
.............................. 8-39
.......................... 8-40
........................... 8-40
................................... 8-44
TLC Function Library Reference
Obsolete Functions ................................ 9-3
Target Language Compiler Function Conventions
Common Function Arguments Overloading sigIdx
Input Signal Functions
LibBlockInputPortIndexMode(block, pidx) LibBlockInputSignal(portIdx, ucv, lcv, sigIdx) LibBlockInputSignalAddr(portIdx, ucv, lcv, sigIdx) LibBlockInputSignalAliasedThruDataTypeName(portIdx,
reim)
.......................................... 9-18
LibBlockInputSignalConnected(portIdx)
................................ 9-7
............................. 9-9
....................... 9-5
............. 9-9
.......... 9-10
............... 9-19
.... 9-5
...... 9-17
xi
LibBlockInputSignalDataTypeId(portIdx) ............. 9-19
LibBlockInputSignalDataTypeName(portIdx, reim) LibBlockInputSignalDimensions(portIdx) LibBlockInputSignalIsComplex(portIdx) LibBlockInputSignalIsFrameData(portIdx) LibBlockInputSignalLocalSampleTimeIndex(portIdx) LibBlockInputSignalNumDimensions(portIdx) LibBlockInputSignalOffsetTime(portIdx) LibBlockInputSignalSampleTime(portIdx) LibBlockInputSignalSampleTimeIndex(portIdx) LibBlockInputSignalWidth(portIdx) LibBlockNumInputPorts(block)
...................... 9-21
.............. 9-20
............... 9-20
............ 9-20
.............. 9-20
............. 9-21
.................. 9-21
..... 9-19
.... 9-20
......... 9-20
........ 9-21
Output Signal Functions
LibBlockNumOutputPorts(block) LibBlockOutputPortIndexMode(block, pidx) LibBlockOutputSignal(portIdx,ucv,lcv,sigIdx) LibBlockOutputSignalAddr(portIdx,ucv,lcv,sigIdx) LibBlockOutputSignalAliasedThruDataTypeName(portIdx,
reim)
.......................................... 9-25
LibBlockOutputSignalBeingMerged(portIdx) LibBlockOutputSignalConnected(portIdx) LibBlockOutputSignalDataTypeId(portIdx) LibBlockOutputSignalDataTypeName(portIdx, reim) LibBlockOutputSignalDimensions(portIdx) LibBlockOutputSignalIsComplex(portldx) LibBlockOutputSignalIsFrameData(portIdx) LibBlockOutputSignalLocalSampleTimeIndex(portIdx) LibBlockOutputSignalNumDimensions(portIdx) LibBlockOutputSignalOffsetTime(portIdx) LibBlockOutputSignalSampleTime(portIdx) LibBlockOutputSignalSampleTimeIndex(portIdx) LibBlockOutputSignalWidth(portIdx)
Parameter Functions
LibBlockMatrixParameter(param, rucv, rlcv, ridx, cucv,
clcv, cidx)
LibBlockMatrixParameterAddr(param, rucv, rlcv, ridx,
cucv, clcv, cidx) LibBlockMatrixParameterBaseAddr(param) LibBlockParamSetting(bType, psType) LibBlockParameter(param, ucv, lcv, sigIdx) LibBlockParameterAddr(param, ucv, lcv, idx)
...................................... 9-29
................................. 9-30
........................... 9-22
..................... 9-22
............ 9-23
......... 9-23
........... 9-25
............. 9-26
............ 9-26
............ 9-27
............. 9-27
........... 9-27
........ 9-27
............. 9-28
............ 9-28
....... 9-28
................. 9-28
.............................. 9-29
........... 9-30
................ 9-30
............ 9-31
.......... 9-33
..... 9-24
.... 9-26
.. 9-27
xii Contents
LibBlockParameterBaseAddr(param) ................. 9-33
LibBlockParameterDataTypeId(param) LibBlockParameterDataTypeName(param, reim) LibBlockParameterDimensions(param) LibBlockParameterIsComplex(param) LibBlockParameterSize(param) LibBlockParameterString(param) LibBlockParameterValue(param, elIdx) LibBlockParameterWidth(param)
...................... 9-34
............... 9-33
....... 9-33
............... 9-34
................ 9-34
.................... 9-35
............... 9-35
.................... 9-36
Block State and Work Vector Functions
LibBlockContinuousState(ucv, lcv, idx) LibBlockContinuousStateDerivative(ucv, lcv, idx) LibBlockContStateDisabled(ucv, lcv, idx) LibBlockDWork(dwork, ucv, lcv, idx) LibBlockDWorkAddr(dwork, ucv, lcv, idx) LibBlockDWorkDataTypeId(dwork) LibBlockDWorkDataTypeName(dwork, reim) LibBlockDWorkIsComplex(dwork) LibBlockDWorkName(dwork) LibBlockDWorkStorageClass(dwork) LibBlockDWorkStorageTypeQualifier(dwork) LibBlockDWorkUsedAsDiscreteState(dwork) LibBlockDWorkWidth(dwork) LibBlockDiscreteState(ucv, lcv, idx) LibBlockIWork(definediwork, ucv, lcv, idx) LibBlockMode(ucv, lcv, idx) LibBlockNonSampledZC(ucv, lcv, NSZCIdx) LibBlockPWork(definedpwork, ucv, lcv, idx) LibBlockRWork(definedrwork, ucv, lcv, idx) LibBlockZCSignalValue(ucv, lcv, zcsIdx, zcElIdx)
Block Path and Error Reporting Functions
LibBlockReportError(block, errorstring) LibBlockReportFatalError(block, errorstring) LibBlockReportWarning(block, warnstring) LibGetBlockName(block) LibGetBlockPath(block) LibGetFormattedBlockPath(block)
....................... 9-39
....................... 9-40
......................... 9-41
........................... 9-44
............................ 9-44
................ 9-37
.............. 9-38
.................. 9-38
.................. 9-39
.................... 9-39
................. 9-39
.................. 9-40
............... 9-43
................... 9-45
............. 9-37
....... 9-38
............. 9-39
.......... 9-39
.......... 9-40
........... 9-40
............. 9-40
........... 9-41
............ 9-41
............ 9-41
....... 9-42
.......... 9-43
.......... 9-43
............ 9-44
Code Configuration Functions
LibAddSourceFileCustomSection(file, builtInSection,
newSection)
.................................... 9-47
...................... 9-46
xiii
LibAddToCommonIncludes(incFileName) .............. 9-48
LibAddToModelSources(newFile) LibCacheDefine(buffer) LibCacheExtern(buffer) LibCacheFunctionPrototype(buffer) LibCacheTypedefs(buffer) LibCallModelInitialize() LibCallModelStep(tid) LibCallModelTerminate() LibCallSetEventForThisBaseStep(buffername) LibCreateSourceFile(type, creator, name) LibGetMdlPrvHdrBaseName() LibGetMdlPubHdrBaseName() LibGetMdlSrcBaseName() LibGetModelDotCFile() LibGetModelDotHFile() LibGetModelName() LibGetNumSourceFiles() LibGetRTModelErrorStatus() LibGetSourceFileCustomSection(file, attrib) LibGetSourceFileFromIdx(fileIdx) LibGetSourceFileTag(fileIdx) LibMdlRegCustomCode(buffer, location) LibMdlStartCustomCode(buffer, location) LibMdlTerminateCustomCode(buffer, locatio n) LibSetRTModelErrorStatus(str) LibSetSourceFileCodeTemplate(opFile, name) LibSetSourceFileCustomSection(file, attrib, value) LibSetSourceFileOutputDirectory(opFile, name) LibSetSourceFileSection(fileH, section, value) LibSystemDerivativeCustomCode(system, buffer,
location) LibSystemDisableCustomCode(system, buffer, location) LibSystemEnableCustomCode(system, buffe r, location) LibSystemInitializeCustomCode(system, buffer,
location) LibSystemOutputCustomCode(system, buffer, location) LibSystemUpdateCustomCode(system, buffer, location) LibWriteModelData() LibWriteModelInput(tid, rollThreshold) LibWriteModelInputs() LibWriteModelOutput(tid, rollThreshold) LibWriteModelOutputs()
....................................... 9-63
....................................... 9-67
............................. 9-49
............................ 9-49
........................... 9-50
............................ 9-51
.............................. 9-51
........................... 9-51
............................. 9-53
............................ 9-54
............................... 9-54
........................... 9-54
.............................. 9-71
............................. 9-72
........................... 9-73
..................... 9-48
................... 9-50
......... 9-51
.............. 9-52
....................... 9-53
...................... 9-53
.......................... 9-53
........................ 9-55
........... 9-55
.................... 9-55
........................ 9-56
............... 9-56
............. 9-57
......... 9-58
..................... 9-59
.......... 9-60
...... 9-60
........ 9-61
.......... 9-62
.. 9-65 .. 9-66
.. 9-68 .. 9-70
............... 9-71
.............. 9-72
xiv Contents
Sample Time Functions ............................ 9-74
LibAsynchronousTriggeredTID(tid) LibAsyncTaskAccessTimeInFcn(tid, fcnType) LibBlockSampleTime(block) LibGetClockTick(tid) LibGetClockTickDataTypeId(tid) LibGetClockTickHigh(tid) LibGetClockTickStepSize(tid) LibGetElapseTime(system) LibGetElapseTimeCounter(system) LibGetElapseTimeCounterDTypeId(system) LibGetElapseTimeResolution(system) LibGetGlobalTIDFromLocalSFcnTID(sfcnTID) LibGetNumAsyncTasks() LibGetNumSFcnSampleTimes(block) LibGetNumSyncPeriodicTasks() LibGetNumTasks() LibGetSampleTimePeriodAndOffset(tid, idx) LibGetSFcnTIDType(sfcnTID) LibGetTaskTime(tid) LibGetTaskTimeFromTID(block) LibGetTID01EQ() LibIsContinuous(TID) LibIsDiscrete(TID) LibIsSFcnSampleHit(sfcnTID) LibIsSFcnSingleRate(block) LibIsSFcnSpecialSampleHit(sfcnSTI, sfcnTID) LibIsSingleRateModel() LibIsSingleTasking() LibIsZOHContinuous(TID) LibNumAsynchronousSampleTimes() LibNumDiscreteSampleTimes() LibNumSynchronousSampleTimes() LibPortBasedSampleTimeBlockIsTriggered(block) LibSetVarNextHitTime(block, tNext) LibTriggeredTID(tid)
............................... 9-76
................................ 9-80
................................. 9-82
................................ 9-82
............................... 9-84
......................... 9-75
.......................... 9-76
......................... 9-77
........................... 9-79
.............................. 9-81
.............................. 9-82
......................... 9-83
............................ 9-84
.......................... 9-85
.............................. 9-86
................... 9-75
........... 9-75
..................... 9-76
....................... 9-76
................... 9-77
........... 9-77
................. 9-77
......... 9-78
................. 9-79
..................... 9-79
........... 9-80
....................... 9-80
..................... 9-81
....................... 9-82
......... 9-83
................. 9-85
...................... 9-85
.................. 9-85
...... 9-85
................. 9-86
Other Useful Functions
LibBlockExecuteFcnCall(sfcnBlock, callIdx) LibBlockInputSignalAliasedThruDataTypeId(idx) LibBlockOutputSignalAliasedThruDataTypeId(idx) LibCallFCSS(system, simObject, portEl, tidVal) LibDisableFCSS(system, simObject, portEl, tidVal) LibEnableFCSS(system, simObje ct, portEl, tidVal)
............................ 9-87
............ 9-88
....... 9-89
..... 9-89
........ 9-89
...... 9-90
...... 9-91
xv
LibExecuteFcnCall(ssBlock, portEl, tidVal) ............ 9-92
LibExecuteFcnDisable(ssBlock, portEl, tidVal) LibExecuteFcnEnable(ssBlock, portEl, tidVal) LibGenConstVectWithInit(data, typeId, varId) LibGetBlockAttribute(block, attr) LibGetCallerClockTickCounter(sfcnBlock) LibGetCallerClockTickCounterHigh(sfcnBlock) LibGetDataTypeComplexNameFromId(id) LibGetDataTypeEnumFromId(id) LibGetDataTypeIdAliasedThruToFromId(id) LibGetDataTypeIdAliasedToFromId(id) LibGetDataTypeIdResolvesToFromId(id) LibGetDataTypeNameFromId(id) LibGetDataTypeSLSizeFromId(id) LibGetDataTypeStorageIdFromId(id) LibGetFcnCallBlock(sfcnblock,callIdx) LibGetRecordDataTypeId(rec) LibGetRecordDimensions(rec) LibGetRecordIsComplex(rec) LibGetRecordWidth(rec) LibGetT() LibIsComplex(arg) LibIsFirstInitCond() LibIsMajorTimeStep() LibIsMinorTimeStep() LibManageAsyncCounter(sfcnBlock, callIdx) LibMaxIntValue(dtype) LibMinIntValue(dtype) LibNeedAsyncCounter(sfcnBlock, callIdx) LibSetAsyncClockTicks(sfcnBlock, callIdx, buf1, buf2) LibSetAsyncCounter(sfcnBlock, callIdx, buf) LibSetAsyncCounterHigh(sfcnBlock, callIdx, buf) LibTIDInSystem(system, fcnType)
........................................ 9-98
............................ 9-98
................................. 9-99
............................... 9-99
.............................. 9-99
............................. 9-99
............................ 9-100
............................. 9-100
.................... 9-94
.................... 9-96
............... 9-96
.................... 9-97
................... 9-97
................. 9-97
................ 9-97
....................... 9-98
....................... 9-98
........................ 9-98
................... 9-103
......... 9-92
.......... 9-93
......... 9-94
............. 9-95
......... 9-95
............. 9-95
........... 9-96
.............. 9-96
........... 9-100
............. 9-100
... 9-101
........... 9-102
....... 9-102
xvi Contents
Advanced Functions
LibAppendToModelReferenceUserData(data) LibBlockInputSignalBufferDstPort(portIdx) LibBlockInputSignalStorageClass(portIdx, sigIdx) LibBlockInputSignalStorageTypeQualifier(portIdx,
sigIdx) LibBlockOutputSignalIsGlobal(portIdx) LibBlockOutputSignalIsInBlockIO(portIdx) LibBlockOutputSignalIsValidLValue(portIdx) LibBlockOutputSignalStorageClass(portIdx)
........................................ 9-107
............................... 9-104
............... 9-108
........... 9-104
............ 9-105
...... 9-107
............ 9-108
.......... 9-108
........... 9-109
LibBlockOutputSignalStorageTypeQualifier(portIdx) .... 9-109
LibBlockSrcSignalBlock(portIdx, sigIdx) LibBlockSrcSignalIsDiscrete(portIdx, sigIdx) LibBlockSrcSignalIsGlobalAndModifiable(portIdx,
sigIdx) LibBlockSrcSignalIsInvaria n t( p ortIdx, sigId x) LibGetModelReferenceUserData(modelName) LibGetReferencedModelNames() LibIsModelReferenceRTWTarget() LibIsModelReferenceSimTarget() LibIsModelReferenceTarget()
........................................ 9-110
..................... 9-111
........................ 9-113
............... 9-109
........... 9-110
.......... 9-111
.......... 9-111
................... 9-112
.................... 9-112
TLC Error Handling
A
Generating Errors from TLC Files .................. A-2
How to Generate Usage Errors Usage Errors Fatal (Internal) TLC Coding Errors Formatting Error Messages
..................................... A-2
...................... A-2
................... A-3
......................... A-4
TLC Error Messages
Using TLC Error Messages to Troubleshoot Alphabetical List of Error Messages
TLC Function Library Error Messages
............................... A-6
.................. A-6
............ A-6
.............. A-33
Index
xvii
xviii Contents

Introducing the Target Language Compiler

“What Is the Target Language Compiler?” on page 1-2
“Target Language Compiler Capabilities” on page 1-8
“Code Generation Process” on page 1-11
“The Advantages of Inlining S-Functions” on page 1-16
“Where to Go from Here” on page 1-20
1
1 Introducing the Target Language Compiler

What Is the Target Language Compiler?

In this section...
“Target Language Compiler Overview” on page 1-2
“Overview of the TLC Process” on page 1-3
“Overview of the Code Generation Process” on page 1-5

Tar get Language Compiler Overview

Target Language Compiler (TLC) is an integral part of the Real-Time Workshop customization, y ou 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.
The TLC includes:
®
product. It enables you to customize generated code. Through
1-2
A set of TLC files corresponding to a subset of the provided Simulink
blocks.
TLC files for model-wide information that specify header and parameter
information.
The TLC files are ASCII files that explicitly control the way code is generated. By editing a TLC file, you can alter the way code is generated.
The Target Language Compiler provides a complete set of ready-to-use TLC files for generating ANSI make minor — or extensive — changes to them. This open environment gives you tremendous flexibility when it comes to customizing the generated code.
The overall code generation processisdiscussedindetailin“Building Executables” i n the Real-Time Workshop documentation. This book describes theTargetLanguageCompiler,itsfiles,andhowtousethemtogether. This information is provided for thoseuserswhoneedtocustomizetarget files to generate specialized output or to inline S-functions to improve the performance and readability of the generated code.
®
C or C++ code. You can view the TLC files and
®
What Is the Target Language Compiler?
Note You should not customize T LC files in the directory
matlabroot/rtw/c/tlc even though the capability exists to do so. Such TLC
customizations might not be applied during the code generation process and can lead to unpredictable results.

Overview of the TLC Process

This top-level diagram shows how th e Target Language Compiler fits in with the Real-Time Workshop code generation process.
Simulink
model.mdl
Real-Time Workshop
TLC program:
System target file
Real-Time
Workshop Build
model.rtw
Block target files
Inlined S-function target files
Target Language
Compiler
Target Language Compiler function library
Run-time interface support files
model.c
model.mk
Make
model.exe
TheTargetLanguageCompiler(TLC)isdesignedforonepurpose—toconvert the model description file code or text.
The Target Language Compiler transforms an intermediate form of a Simulink block diagram, called
model.rtw (or similar files) into target-specific
model.rtw, into C or C++ code. The model .rtw
1-3
1 Introducing the Target Language Compiler
file contains a “compiled” representation of the model describing the execution semantics of the block diagram in a very high-level language. The format of this file is described in Chapter 5, “Understanding the
The word target in Target Language Compiler refers not only to the high-level language to be output, but also to the nature of the real-time system on which the code will be executed. TLC-generated code is thus able to respect and exploit the capabilities and limitations of specific processor architectures (the target).
model.rtw File”.
After reading the
model.rtw file, the Target Language Compiler generates its
code based on target files, which specify particular code for each block, and model-wide files, which specify the overall code style. The TLC works like
a text processor, using the target files and the
model.rtw file to generate
ANSI C or C++ code.
To create a target-specific application, the Real-Time Workshop code generator requires a template makefile that specifies the appropriate C or C++ compiler and compiler options for the build process. The code generator transforms the template makefile into a target makefile (
model.mk)by
performing token expan sion specific to a g iven model. The target makefile is a modified version of the generic
rt_main file (or grt_main), which you must
modify to conform to the target’s specific requirements, such as interrupt service routines. A complete description of template makefiles and
rt_main is
included in the Real-Time Workshop documentation.
The Target Language Compiler has similarities with HTML, Perl, and MATLAB
®
. It has markup syntax similar to HTML, the power and flexibility of Perl and other scripting languages, and the data handling power of MATLAB (TLC can invoke MATLAB functions). The code generated by TLC is highly optimized and fully commented, and can be generated from any Simulink model, including linear, nonlinear, continuous, discrete, or hybrid. All Simulink blocks are automatically converted to code, with the exception of MATLAB function blocks and S-function blocks that invoke MATLAB files. The Target Language Compiler uses block target files to transform each block in the
model.rtw file and a model-wide target file for global customization
of the code.
1-4
You can incorporate C MEX S-functions, along with the generated code, into the program ex ecutable . You can also write a target file for your C MEX
What Is the Target Language Compiler?
S-function to inline the S-function (see “Inlining C MEX S-Functions” on page 8-4), thus improving performance by eliminating function calls to the S-function itself and the memory overhead of the Inlining an S-function incorporates the S-function block’s code into the generated code for the model. When no TLC target file is present for the S-function, its C or C++ code file is invoked via a function call. For more information on inlining S-functions, see Chapter 8, “Inlining S-Functions”. You can also write target files for MATLAB language files or Fortran S-functions.
SimStruct of the S-function.

Overview of the Code Generation Process

The following figu re shows h ow the Target Language Compiler works with its target files and the Real-Time Workshop code generator output to produce code.
1-5
1 Introducing the Target Language Compiler
Simulink Model (sample.mdl)
Target files
Real-Time Workshop
*.tlc
sample.rtw
Target Language Compiler
1-6
Generated makefile Generated source code files
in build directory./sample_xxx_rtw/
When generating code from a Simulink model, the first step in the automated process is to generate a model-specific information required for generating code from the Simulink model. in combination with a set of included system target files and block target files to generate the code.
model.rtw is passed to the Target Language Compiler, which uses it
model.rtw file. The model.rtw file includes all the
What Is the Target Language Compiler?
Only the final executable file is written directly to the current directory. For all o ther files created during code generation, including the
model.rtw file,
a build directory is used. This directory is created in the current directory and is named target environment, e.g.,
.model_target_rtw,wheretarget is the abbreviation for the
grt for the generic real-time target.
Files placed in the build directory include
The body for the generated C or C++ source code (
Header files (
Header file
model.h)
model_private.h defining parameters and data structures
model.c or model.cpp)
privatetothegeneratedcode
Amakefile,
model.mk, for building the application
Additional files, described in “Files and Directories Created by the Build
Process” in the Real-Time Workshop documentation
1-7
1 Introducing the Target Language Compiler

Target Language Compiler Capabilities

In this section...
“Why Use TLC?” on page 1-8
“Customizing Output” on page 1-8
“Inlining S-Functions” on page 1-9
“Modifying and Diversifying Code Generation” on pag e 1-9

Why Use TLC?

If you simply need to produce ANSI C or C++ code from Simulink models, you do not need to know how to prepare files for the Target Language Compiler. If you need to customize the output, you must run the Target Language Compiler. Use the Target Language Compiler if you need to
Customize the set of options specified by your system target file
1-8
Inline the code for S-Function blocks
Generate additional or different types of files
Both the Embedded MATLAB Function block and the Real-Time Workshop Embedded Coder™ product facilitate code customization in a variety of ways. You might be able to accomplish what you need with them, without the need towriteTLCfiles. However,youdoneedtoprepareTLCfilesifyouintend to inline S-functions.
®

Customizing Output

To produce customized output using the Target Language Compiler, it helps if you understand how blocks perform their functions, what data types are being manipulated, the structure of the target files to produce the desired output. Chapter 6, “Directives and Built-In Functions” describes the target language directives and their associated constructs. You will use the Target Language Compiler directives and constructs to modify existing target files or create new ones, depending on your needs. See “TLC Files” on page 4-18 for more information about target files.
model.rtw file, and how to modify
Target Language Compiler Capabilities
Note You should not customize T LC files in the directory
matlabroot/rtw/c/tlc even though the capability exists to do so. Such TLC
customizations might not be applied during the code generation process and can lead to unpredictable results.

Inlining S-Functions

The Target Language Compiler provides a great deal of freedom for altering, optimizing, and enhancing the generated code. One of the most important TLC features is that it lets you inline S-functions that you write to add your own algorithms, device drivers, and custom blocks to a Simulink model.
To create an S-function, you write code following a well-defined application program interface (API). By d ef a ult, the Target L a nguage Compiler will generate noninlined code for S-functions that invokes them using this same API. This generalized interface incurs a fair amount of overhead due to the presence of a large data structure called the each S-Function block in your model. In addition, extra run-time overhead is involved whenever methods (functions) within your S-function are called. You can eliminate all this overhead by using the Target Language Compiler to inline the S-function, by creating a TLC file named that generates source code for the S-function as if it were a built-in block. Inlining an S-function improves the efficiency of the generated code and reduces memory usage.
SimStruct for each instance of
sfunction_name.tlc

Modifying and Diversifying Code Generation

In principle, you can use the Target Language Compiler to convert the
model.rtw file into any form of output (for example, OODBMS objects)
by replacing the supplied TLC files for each block it uses. Likewise, you can also replace some or all of the shipping system-wide TLC files. The MathWorks™ supports, but does not recommend, doing this. To maintain such customizations, you might need to update your TLC files with each Real-Time Workshop product release. The MathWorks continues to improve code generation by adding features, improving efficiency, and altering the contents of backwards compatible, but cannot guarantee it. Inlined TLC files that you
model.rtw. The MathWorks tries to make such changes
1-9
1 Introducing the Target Language Compiler
create, on the other hand, generally are backward compatible, provided that they invoke only documented TLC library and built-in functions.
1-10

Code Generation Process

In this section...
“Process Overview” on page 1-11
“How T LC Determines S-Function Inlining Status” on page 1-11
“A Look at Inlined and Noninlined S-Function Code” on page 1-12

Process Overview

The Real-Time Workshop code generator invokes the Target Language Compiler after a Simulink model is compiled into an intermediate form (
model.rtw) that is suitable for generating code. To generate code
appropriately, the Target Language Compiler uses its library of functions to transform two classes of target files:
System target files
Block target files
Code Generation Process
System target files are used to specify the overall structure of the generated code, tailoring for specific target environments. Block target files are used to implement the functionality of Simulink blocks, including user-defined S-function blocks.
You can create block target files for C MEX, Fortran, and MATLAB language S-functions to fully inline block f unctionality into the body of the generated code. C MEX S-functions can be noninlined, wrapper-inlined, or fully inlined. Fortran S-functions must be wrapper-inlined or fully inlined.

How TLC Determines S-Function Inlining Status

Whenever the Target Language Compiler encounters an entry for a n S-function block in the call to the S-function or to inline it.
Because they cannot use S-functions must be inlined. This inlining can either be in the form of a full
model.rtw file, it must decide whether to generate a
SimStructs, Fortran and M ATLAB language
1-11
1 Introducing the Target Language Compiler
block target file or a one-line block target file that refers to a substitute C MEX S-function source file.
The Target Language Compiler selects a C MEX S-function for inlining if there is an explicit target file for the current target language for the current block in the TLC file search path. If a C MEX S-function has an explicit must be a corresponding target file or an error condition results.
ThetargetfileforanS-functionmusthavethesamerootnameas the S-function and must have the extension C MEX S-function
matlabroot/toolbox/simulink/fixedandfloat/:
mdlRTW() function in the S-function code or if there is a
mdlRTW() function, there
.tlc. For example, the
sfix_bitop uses these files, which are a vailable in
Location and Filen ame(s)
sfix_bitop.c
sfix_bitop.mex*
tlc_c/sfix_bitop.tlc
Purpose
C source file
Compiled files
TLC target file

A Look at Inlined and Noninlined S-Function Code

This example focuses on the C MEX S-function sfix_bitop in
matlabroot/toolbox/simulink/fixedandfloat/sfix_bitop.c.Thecode
generation options are set to allow reuse of signal memory for signal lines that were not set as tunable signals.
1-12
Code Generation Process
The code generated for the bit-wise operator block reuses a temporary variable that is set up for the output of the sum block to save memory. This results in one very efficient line of code, as seen here.
/* Bitwise Logic Block: <Root>/Bitwise Logical Operator */ /* [input] OR 'F00F' */ rtb_temp2 |= 0xF00F;
There is no initialization or setup code required for this inlined block.
If this block were not inlined, the source code for the S-function itself with all its various options would be added to the generated code base, memory would be allocated in the generated code for the block’s
SimStruct data, and calls to
the S-function methods would be generated to initialize, run, and terminate the S-function code. To execute the
mdlOutputs function of the S-function,
code would be generated like this:
/* Level2 S-Function Block: <Root>/Bitwise Logical Operator (sfix_bitop) */
{
SimStruct *rts = ssGetSFunction(rtS, 0);
sfcnOutputs(rts, tid);
}
The entire mdlOutputs function is called and runs just as it does during simulation. That’s not everything, though. There is also registration, initialization, and termination code for the noninlined S-function. The
1-13
1 Introducing the Target Language Compiler
initialization and termination calls are similar to the fragment above. Then, the registration code for an S-function with just one inport and one outport is 72 lines of C code generated as part of file
/*Level2 S-Function Block: <Root>/Bitwise Logical Operator (sfix_bitop) */
{
extern void untitled_sf(SimStruct *rts);
SimStruct *rts = ssGetSFunction(rtS, 0);
/* timing info */
static time_T sfcnPeriod[1];
static time_T sfcnOffset[1];
static int_T sfcnTsMap[1];
{
int_T i;
for(i = 0; i < 1; i++) {
sfcnPeriod[i] = sfcnOffset[i] = 0.0;
}
}
ssSetSampleTimePtr(rts, &sfcnPeriod[0]);
ssSetOffsetTimePtr(rts, &sfcnOffset[0]);
ssSetSampleTimeTaskIDPtr(rts, sfcnTsMap);
ssSetMdlInfoPtr(rts, ssGetMdlInfoPtr(rtS));
model_reg.h.
1-14
/* inputs */
{
static struct _ssPortInputs inputPortInfo[1];
_ssSetNumInputPorts(rts, 1);
ssSetPortInfoForInputs(rts, &inputPortInfo[0]);
/* port 0 */
{
static real_T const *sfcnUPtrs[1];
sfcnUPtrs[0] = &rtU.In1;
ssSetInputPortSignalPtrs(rts, 0, (InputPtrsType)&sfcnUPtrs[0]);
_ssSetInputPortNumDimensions(rts, 0, 1);
Code Generation Process
ssSetInputPortWidth(rts, 0, 1);
}
}
.
.
.
This continues until all S-function sizes and methods are declared, allocated, and initialized. The amount of registration code generated is essentially proportional to the number and size of the input ports and output ports.
A n oninlined S-function will typically have a significant impa ct on the size of the generated code, whereas an inlined S-function can give handwritten size and performance to the generated code.
1-15
1 Introducing the Target Language Compiler

The Advantages of Inlining S-Functions

In this section...
“Goals” on page 1-16
“Inlining Process” on page 1-17
“Search A lgorithm for Locating TLC Files” on page 1-18
“Availability for Inlining and Noninlining” on page 1-19

Goals

The goals of generated code usually include compactness and speed. On the other hand, S-functions are run-time-loadable extension modules for adding block-level functionality to Simulink. As such, the S-function interface is optimized for flexibility in configuring and using blocks in a simulation environment with capability to allow run-time changes to a block’s operation via parameters. These changes typically take the form of algorithm selection and numerical constants for the block algorithms.
1-16
While switching algorithms is a desirable feature in the design phase of a system, when the time comes to generate code, this type of flexibility is often dropped in favor of optimal calculation speed and code size. The Target Language Compiler was designed to allow the generation of code that is compactandfastbyselectivelygeneratingonlythecodeyouneedforone instance of a block’s parameter set.
When Inlining Is Not Appropriate
You might decide that inlining is not appropriate for certain C MEX S-functions. This might be the case if an S-function has
Few or no numerical parameters
One algorithm that is already fixed in capability (i.e., it has no optional
modes or a lternate algorithms)
Support for only one data type
The Advantages of Inlining S-Functions
A significant or large code size in the mdlOutputs() function
Multiple instances of this block in your models
Whenever you encounter this situation, the effort of inlining the block might not improve execution speed and could actually increase the size of the generated code. The tradeoff is in the size of the block’s body code generated for each instance versus the size of the child SimStruct created for each instance of a noninlined S-function in the generated code.
Alternatively, you can use a hybrid inlining method known as a C MEX wrapped S-function, where the block target file simply generates a call to a custom code function that the S-function itself also calls. This approach might b e the optimal solution for code generation in the case of a large piece of existing code. See Chapter 8, “Inlining S-Functions” for the procedure and an example of a wrapped S-function.

Inlining Process

The strategy for achieving compact, high-performance code from Simulink blocks centers on determining what part of a block’s operations are active and necessary in the generated code and what parts can be predetermined or left out.
In practice, this means the TLC code in the block target file will select an algorithm that is a subset of the algorithms contained in the S-function itself and then selectively hard-code numerical parameters that are not to be changed at run time. This reduces code memory size and results in code that is often much faster than its S-function counterpart when mode selection is a significant part of S-function processing. Additionally, all function-call overhead is eliminated for inlined S-functions, as the code is generated directly in the body of t he code unless there is an explicit call to a library function in the generated code.
The algorithm selections and parameters for each block are output in the initial phase of the code generation process from the registered S-function parameter set or the in the model’s in the target language for the block is then called to read the entries in the
.rtw file for that block at code generation time. A file written
mdlRTW() function (if present), which results in entries
1-17
1 Introducing the Target Language Compiler
model.rtw file and compute the generated code for this instance of the block.
This TLC code is contained in the block target file.
One special case for inlined S-functionsisforthecaseofI/Oblocksanddrivers such as A/D converters or communications ports. For simulation, the I/O driver is typically coded in the S-function as a pure source, a pass-through, or a pure sink. In the generated code, however, an actual interface to the I/O device must be made, typically through direct coding with the common
_out() functions, inlined assembly code, or a specific set of I/O library calls
unique to the device and target environment.

Search Algorithm for Locating TLC Files

The T arge t Language Compiler uses the following search order to locate TLC files:
1 The current directory.
2 The locations specified by any %addincludepath directives. The compiler
evaluates multiple
_in(),
%addincludepath directives from the bottom up.
1-18
3 The locations specified by any -I options. The compiler evaluates multiple
-I options from right to left.
For inlined S-functions TLC files, the Real-Time Workshop build process supports the following locations:
The directory where the S-function executable (MEX or
S-function directory’s subdirectory
./tlc_c (for C or C++ language targets).
.m) file is located.
The current directory when the Real-Time Workshop build process is
initiated.
Note Note: Placing the inlined S-function TLC file elsewhere is not supported, even if the location is in the TLC include pa th.
The first target file encountered with therequirednamethatimplementsthe proper language is used in processing the S-function
model.rtw file entry.
The Advantages of Inlining S-Functions
Note The compiler does not search the MATLAB path, and will not find any file that is available only on that path. The compiler searches only the locations described above.

Availability for Inlining and Noninlining

S-functions can be written in MATLAB language, Fortran, C, and C++. TLC inlining of S-functions is available as indicated in this table.

Inline TLC Support by S-Function Type

Noninlining
S-Function Type
Supported Inlining Supported
MATLAB language
Fortran MEX No Yes
C
C++
No Yes
Yes Yes
Yes Yes
1-19
1 Introducing the Target Language Compiler

WheretoGofromHere

In this section...
“Topics Covered in This Manual” on page 1-20
“Related Manuals” on page 1-21

Topics Covered in This Manual

The remainder of this book contains both explanatory and reference material for the Target Language Compiler:
Chapter 2, “Getting Started” describes the process that the Target
Language Compiler uses to generate code, and general inlining S-function concepts.
Chapter 4, “Code Generation Architecture” describes the TLC files and the
build process. It also provides a tutorial on how to write target language files.
1-20
Chapter 5, “Understanding the
file.
Chapter 6, “Directives and Built-In Functions” contains the language
syntax for the Target Language Compiler.
Chapter 7, “Debugging TLC Files” explains how to use the TLC debugger.
Chapter 8, “Inlining S-Functions” describes how to use the Target
Language Compiler and how to inline S-functions.
Chapter 9, “TLC Function Library Reference” contains abstracts for the
TLC functions.
Appendix A, “TLC Error Handling” lists the error messages that the Target
Language Compiler can generate, as well as how to best use the errors.
model.rtw File” describes the model.rtw

Related Manuals

The items listed creation of TLC f
below are sections of other manuals that relate to the
iles:
Where to Go from Here
The Real-Time W
architecture Executables” Compiler fits Signals and T and customiz
The Real-Ti
details on g covers data storage cla restricti
The Simuli
informat MEX S-fun Target La how to wr on the
of the Real-Time Workshop product. The “Building
chapter presents information on how Target Language into the overall code generation process. The “Monitoring
uning Parameters” chapter offers furthe r useful examples
ation guidelines.
me Workshop Embedded Coder documentation presents
enerating code for embedded targets. Among other topics, it
structures and program execution, code generation, custom
sses, module packaging, and specifies system requirements and
ons on target files.
nk Developing S-Functions documentation p resents detailed
ion on all aspects of writing Fortran, MATLAB language, and C
ctions. The most pertinent chapter from the point of view of the
nguage Compiler is “Writing S-Functions in C” which explains
ite wrapped and fully inlined S-functions, with a special emphasis
lRTW()
md
orkshop documentation describes the use and internal
function.
1-21
1 Introducing the Target Language Compiler
1-22

Getting Started

“Code Architecture” on page 2-2
“Target Language Compiler Overview” on page 2-4
“Inlining S-Functions” on page 2-6
2
2 Getting Started

Code Architecture

Before investigating the specific code generation pieces of the Target Language Compiler (TLC), consider how Target Language Compiler generates code for a simple model. From the next figure, you see that blocks place code into
Mdl routines. This shows MdlOutputs.
static void simple_output(int_T tid) {
/* Sin Block: '<Root>/Sine Wave' */
simple_B.SineWave_d = simple_P.SineWave_Amp *
sin(simple_P.SineWave_Freq * simple_M->Timing.t[0] + simple_P.SineWave_Phase) + simple_P.SineWave_Bias;
2-2
/* Gain: '<Root>/Gain' */ simple_B.Gain_d = simple_B.SineWave_d * simple_P.Gain_Gain;
/* Outport: '<Root>/Out1' */ simple_Y.Out1 = simple_B.Gain_d;
}
Blockshaveinputs,outputs,parameters,states,plusothergeneralproperties. For example, block inputs and outputs are generally written to a block I/O structure (generated with identifiers of the type
model_B), where model
is the model name). Block inputs can also come from the external input structure ( integrator ( outputs can also go to the external output structure, (
model_U) or the state structure when connected to a state port of an
model_X), or ground (rtGround) if unconnected or grounded. Block
model_Y). The following
diagram shows the general block data mappings.
Code Architecture
Start Execution
MdlStart
MdlOutputs
MdlUpdate
MdlDerivatives
Execution Loop
MdlOutputs
MdlDerivatives
Integration
External Inputs Struct,
model_U
rtGround
Block I/O Struct,
model_B
Block
External Outputs Struct,
model_Y
Work Structs,
rtRWork,
MdlTerminate
End
States Struct,
model_X
Parameter Struct,
model_P
rtIWork, rtPWork, rtDWork, ...
This discussion should give you a general sense of what the block object looks like. Now , you can look at specific pieces of the code generation process that arespecifictotheTargetLanguageCompiler.
2-3
2 Getting Started

Target Language Compiler Overview

In this section...
“The Target Language Compiler Process” on page 2-4
“Operating Sequence” on page 2-5

The Target Language Compiler Process

To write TLC code for your S-function, you need to understand the Target Language Compiler pro cess for code generation. As previously described, the Simulink software generates a representation of the execution semantics of the block diagram. T he
model.rtw file is an ASCII file that contains a data structure in the form of
a nested set of TLC records. The records comprise property name/property value pairs. The Target Language Compiler reads the converts it into an internal representation.
Next, the Target Language Compiler runs (interprets) the TLC files, starting first with the s ystem target file, for example, to all the system TLC and block files, that is, other TLC files included in or generated from the TLC file passed to Target Language Compiler on its command line ( is run, it uses, appends to, and modifies the existing property name/property value pairs and records initially loaded from t h e
grt.tlc). As the TLC code in the system and block target files
model.rtw file that contains a high-level
model.rtw file and
grt.tlc. This is the entry point
model.rtw file.
2-4
model.rtw Structure
The structure of the model.rtw file mirrors the block diagram’s structure:
Foreachnonvirtualsysteminthemodel, there is a corresponding system
record in the
For each nonvirtual block within a nonvirtual system, there is a block
record in the
The basic structure of
CompiledModel {
System {
model.rtw file.
model.rtw file in the corresponding system.
model.rtw is
Target Language Compiler Overview
Block {
DataInputPort {
... } DataOutputPort{
... } ParamSettings {
... } Parameter {
... }
}
}
}

Operating Sequence

For each occurrence of a given block in the model, a corresponding block record exists in the block records and calls the functions in the corresponding block target file for that block type. For inlined S-functions, it calls the inlining TLC file.
model.rtw file. The system target file TLC code loops through all
There is a method for getting block-specific information (internal block information, as opposed to inputs, outputs, parameters, etc.) into the block record in the
model.rtw file for a block by using the mdlRTW function in the C
MEX function of the block.
Among other things, the settings (
ParamSettings), that is, unique information pertaining to this block.
mdlRTW function allows you to write out parameter
For parameter settings in the block TLC file, direct accesses to these fields are made from the block TLC code and can be used to affect the generated code as desired.
2-5
2 Getting Started

Inlining S-Functions

In this section...
“Inlining an S-function” on page 2-6
“Noninlined S-Function” on page 2-6
“Types of Inlining” on page 2-7
“Fully Inlined S-Function Example” on page 2-8
“Wrapper Inlined S-Fun ction Example” on p ag e 2-11

Inlining an S-function

To inline an S-function means to provide a TLC file for an S-Function block that will replace the C, C++, Fortran or MATLAB language version of the block that was used during simulation.

Noninlined S-Function

If an inlining TLC file is not provided, most targets support the block by recompiling the C MEX S-function for the block. As discussed earlier, there is overhead in memory usage and speed when using a C/C++ coded S-function andalimitedsubsetof context. If you want the most efficient generated code, you must inline S-functions by writing a TLC file for them.
mx* API calls supported within the code generator
2-6
When the simulation needs to execute one of the functions for an S-function block, it calls the MEX-file for that function. When the code generator executes a noninlined S-function, it does so in a similar manner, as this diagram illustrates.
model.mdl
uy
sfcn
sfcn.c
mdlOutputs() { *y = my_alg(u); }
my_alg.c
sfcn.mex
real_T my_alg(real_T u) { return(2.0*u); }
Inlining S-Functions
model.c
MdlOutputs() { model_B.y=sfcnOutputs(rtS,tid) ;
Call through a function pointer to access static mdlOutputs.

Types of Inlining

It is helpful to define two categories of inlining:
Fully inlined S-functions
2-7
2 Getting Started
Wrapper inlined S-functions
While both effectively inline the S-function and remove the overhead of a noninlined S-function, the two approaches are different. The first example below, using full implementation of the block is contained in the TLC file for the block.
The second example uses a wrapper TLC file. Instead of generating all the algorithmic code in place, this example calls a C function that contains the body of code. There are several potential benefits for using the wrapper TLC file:
It provides a way for the C MEX S-function and the generated code to share
the C code. There is no need to write the code twice.
The called C function is an optimized routine.
Several of the blocks might exist in the model, and it is more efficient in
termsofcodesizetohavethemcallafunction, as opposed to each creating identical algorithmic code.
timestwo.tlc, is considered a f ully inlined TLC file, where the
2-8
It provides a way to incorporate legacy C code seamlessly into generated
code.

Fully Inlined S-Function Example

Inlining an S-function provides a mechanism to directly embed code for an S-function block into the generated code for a model. Instead of calling into a separate source file via f unction pointers and maintaining a separate data structure ( shows.
SimStruct) for it, the code appears “inlined” as the next figure
sfcn.tlc
%function(block,system) Output %<y>=2.0*<u>; %endfunction
model.c
MdlOutputs() { model_B.y=2.0*model_B.u; }
Inlining S-Functions
Your TLC code specifies the algorithm.
TLC lets you customize the generated code by embedding my_alg.
The S-function timestwo.c provides a simple example of a fully inlined S-function. This block multiplies its input by 2 and outputs it. The C MEX version of the block is in
matlabroot/simulink/src/timestwo.c, and the inlining TLC file for the
block is in
matlabroot/toolbox/simulink/blocks/tlc_c/timestwo.tlc.
timestwo.tlc
%implements "timestwo" "C"
%% Function: Outputs ==========================================
%%
%function Outputs(block, system) Output
/* %<Type> Block: %<Name> */
%%
2-9
2 Getting Started
/* Multiply input by two */
%assign rollVars = ["U", "Y"]
%roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
%<LibBlockOutputSignal(0, "", lcv, idx)> = \
%<LibBlockInputSignal(0, "", lcv, idx)> * 2.0;
%endroll
%endfunction
TLC Block Analysis
The %implements directive is required by all TLC block files and is used by the Target Language Compiler to verify correct block type and correct language support by the block. The and shows the name of the function,
block and system. These are the relevant records from the model.rtw file
for this instance of the block.
%function directive starts a function declaration
Outputs, and the arguments passed to it,
The last piece of the prototype is
Output. This means that any line that is not
a TLC directive is output by the function to the current file that is selected in TLC. So, any nondirective lines in the
Outputs function become generated
code for the block.
The mo st complicated piece of this TLC block example is the TLC uses this directive to provide automatic generation of
%roll directive.
for loops,
depending on input/output widths and whether the inputs are contiguous in memory. This example uses the typical form of accessing outputs and inputs from within the b ody of the roll, using
LibBlockInputSignal to access the outputs and inputs and perform the
LibBlockOutputSignal and
multiplication and assignment. N ote that this TLC file supports any signal width.
The only function needed to implement this block is
Outputs.
For more complicated blocks, other functions are declared as well. You can find examp les of more complicated inlining TLC files in
matlabroot/toolbox/simulink/blocks/tlc_c, and by lo oking at the code
for built-in blocks in
matlabroot/toolbox/simulink/blocks and
matlabroot/rtw/c/tlc/blocks.
2-10
Inlining S-Functions
The timestwo Model
This simple model uses the timestwo S-function and shows the MdlOutputs function from the generated model.c file, which contains the inlined S-function code.
Model Outputs Code
/* Model output function */ static void timestwo_ex_output(int_T tid) {
/* S-Function Block: <Root>/S-Function */ /* Multiply input by two */ timestwo_ex_B.timestwo_output = timestwo_ex_P.Constant_Value *2.0;
/* Outport: '<Root>/Out1' */ timestwo_ex_Y.Out1 = timestwo_ex_B.timestwo_output;
}

Wrapper Inlined S-Function Example

The following diagram illustrates inlining an S-function as a wrapper. The algorithm is directly called from the generated model code, removing the S-function overhead but maintaining the user function.
2-11
2 Getting Started
sfcn.tlc
%function(block,system) Output %<y>=my_alg(%<u>); %endfunction
Your TLC code specifies how to call my_alg directly.
model.c
MdlOutputs() { model_B.y=my_alg(model_B.u); }
TLC lets you customize the generated code to produce a direct call to my_alg.
2-12
This is the inlining TLC file for a wrapper version of the timestwo block.
%implements "timestwo" "C"
%% Function: BlockTypeSetup ==================================
%%
%function BlockTypeSetup(block, system) void
%% Add function prototype to model's header file
%<LibCacheFunctionPrototype...
("extern void mytimestwo(real_T* in,real_T* out,int_T els);")>
%% Add file that contains "myfile" to list of files to be compiled
%<LibAddToModelSources("myfile")>
%endfunction
%% Function: Outputs ==========================================
%%
%function Outputs(block, system) Output
/* %<Type> Block: %<Name> */
Inlining S-Functions
%assign outPtr = LibBlockOutputSignalAddr(0, "", "", 0)
%assign inPtr = LibBlockInputSignalAddr(0, "", "",0)
%assign numEls = LibBlockOutputSignalWidth(0)
/* Multiply input by two */
mytimestwo(%<inPtr>,%<outPtr>,%<numEls>);
%endfunction
Analysis
The function BlockTypeSetup is called once for each type of block in a model; it doesn’t produce output directly like the
BlockTypeSetup to include a function prototype in the model.h file and to tell
thebuildprocesstocompile an additional file,
Outputs function. Use
myfile.c.
Instead of performing the multiplication directly, the calls the function
mytimestwo. So, all instances of this block in the model will
Outputs function now
call the same function to perform the mul t ip li cation. The resulting model function,
static void timestwo_ex_output(int_T tid) {
model_Y.Out1 = model_B.S_Function;
}
MdlOutputs, then becomes
/* S-Function Block: <Root>/S-Function */ /* Multiply input by two */ mytimestwo(&
model_B.Constant_Value,&model_B.S_Function,1);
/* Outport Block: <Root>/Out1 */
2-13
2 Getting Started
2-14
3

Target Language Compiler Tutorials

“Introduction” on page 3-2
“Reading Record Files with TLC” on page 3-4
“Inlining S-Functions with TLC” on page 3-26
“Exploring Variable Names and Loop Rolling” on page 3-32
“Debugging Your TLC Code” on page 3-41
“Using TLC Code Coverage to Aid Debugging” on page 3-50
“Wrapping User Code with TLC” on page 3-53
3 Target Language Compiler Tutorials

Introduction

The fastest and easiest way to understand the Target Language Compiler (TLC) is to run it, payin g attention to how TLC scripts transform compiled Simulink models ( chapter are designed to highlight the principal reasons for and techniques of using TLC. The tutorials provide a number of TLC exercises, each one organized as a major section.
All example models, S-functions, and TLC files needed for the exercises, are located in
matlabroot is the MATLAB root directory on your system. In this chapter,
this directory is referred to as separate subdirectory within find solutions to the problem in a
Note Before you begin the tutorial, copy the entire tlctutorial directory to a local working directory. All the needed files are together, and if you make mistakes or want fresh examples to try again, you can recopy files from the original
model.rtw files) into source code. The tutorials in this
matlabroot/toolbox/rtw/rtwdemos/tlctutorial,where
tlctutorial. Each example is located in a
tlctutorial. Within that subdirectory, you can
solutions subdirectory.
tlctutorial directory.
3-2
Each tutorial exercise is limited in scope, requiring just a small amount of experimentation. The tutorial explains details about TLC that will help customize and optimize code for Real-Time Workshop projects.
Note You should not customize T LC files in the directory
matlabroot/rtw/c/tlc even though the capability exists to do so. Such TLC
customizations might not be applied during the code generation process and can lead to unpredictable results.
The tutorials progress in difficulty from basic to more advanced. To get the most out of them, you should be familiar with
Working in the MATLAB environment
Building Simulink models
Introduction
Using Real-Time Workshop software to generate code for target systems
High-level language concepts (for example, C or Fortran programming)
If you encounter terms in the tutorials that you do not understand, it may be helpful to read “Code Generation Concepts”onpage4-12toacquaintyourself with the basic goals an d methods of TLC programming. Similarly, if you see TLC keywords, built-in functions, or directives that you would like to know more about, see Chapter 6, “Directives and Built-In Functions”. Descriptions of TLC library functions are provided in Chapter 9, “TLC Function Library Reference”.
The examples used in the tutorial are:
Example
guide
timesN
tlcdebug
wrapper
Description
Illustrative record file
An example C file S-function for multiplying an input by N
An example using TLC Debugger
Example TLC file for S-function
wrapsfcn.c
3-3
3 Target Language Compiler Tutorials

Reading Record Files with TLC

In this section...
“Tutorial Overview” on page 3-4
“Learning About the Structure of Record Files” on page 3-5
“Interpreting Records” on page 3-6
“Learning About the Anatomy of a TLC Script” on page 3-7
“Modifying read-guide.tlc”onpage3-17
“Passing and Using a Parameter” on page 3-22
“Review” on page 3-24

Tutorial Overview

Objective: Understand the structure of record files and learn how to parse them with TLC directives.
3-4
Directory:
In this tutorial you interpret a simple file of structured records with a series of TLC scripts. You will learn how records are structured, and how TLC and %<> token expansion directives are used to process them. In addition, the tutorial illustrates loops using
The t utorial includes these steps, w h ich you should follow sequentially:
1 Learning About the Structure of Record Files — Some background
and a simple example
2 Interpreting Records — Presenting contents of the record file
arning About the Anatomy of a TLC Script — Deconstructing the
3 Le
esentation
pr
4 Modifying read-guide.tlc — Experiment with TLC
5 Passing and Using a Parameter— Pass parameters from the command
line to TLC files
tlctutorial/guide
%assign
%foreach, and scoping using %with.
Reading Record Files with TLC
6 Review

Learning About the Structure of Record Files

The Real-Time Workshop code generator compiles models into a structured form called a record file, referred to as are s imilar in syntax and organization to s ource model ( that they contain a series of hierarchically nested records of the form
recordName {itemName itemValue}
Item names are alphabetic. Item values can be strings or numbers. Numeric values can be scalars, vectors, or matrices. Curly braces set off the contents of each record, which may contain one or more items, delimited by space, tab, or return characters.
In a
model.rtw file, the top-level (first) record’s name is CompiledModel.Each
block is represented by a subrecord within it, identified by the block’s name. TLC can parse any well-formed record file, as this exercise demonstrates.
model.rtw. Such compiled model file s
model.mdl)files,in
The following listing is a valid record file that TLC can parse, although not one for which it can generate code. Comments are indicated by a pound sign (#):
# $Revision: 1.1.4.36 $
# File: guide.rtw Illustrative record file, which can't be used by Simulink
# Note: string values MUST be in quotes
Top { # Outermost Record, called Top
Date "21-Aug-2008" # Name/Value pair named Top.Date
Employee { # Nested record within the Top record
FirstName "Arthur" # Alpha field Top.Employee.FirstName
LastName "Dent" # Alpha field Top.Employee.LastName
Overhead 1.78 # Numeric field Top.Employee.Overhead
PayRate 11.50 # Numeric field Top.Employee.PayRate
GrossRate 0.0 # Numeric Field Top.Employee.GrossRate
} # End of Employee record
NumProject 3 # Indicates length of following list
Project { # First list item, called Top.Project[0]
Name "Tea" # Alpha field Name, Top.Project[0].Name
Difficulty 3 # Numeric field Top.Project[0].Difficulty
} # End of first list item
Project { # Second list item, called Top.Project[1]
3-5
3 Target Language Compiler Tutorials
Name "Gillian" # Alpha field Name, Top.Project[1].Name
Difficulty 8 # Numeric field Top.Project[1].Difficulty
} # End of second list item
Project { # Third list item, called Top.Project[2]
Name "Zaphod" # Alpha field Name, Top.Project[2].Name
Difficulty 10 # Numeric field Top.Project[2].Difficulty
} # End of third list item
} # End of Top record and of file
As long as programmers know the names of records and fields, and their expected contents, they can compose TLC statements to read, parse, and manipulate record file data.

Interpreting Records

Here is the output from a TLC program script that reads guide.rtw, interprets its records, manipulates field data, and formats descriptions, which are directed to the MATLAB Command Window:
3-6
Using TLC you can:
* Directly access any field's value, e.g.
%<Top.Date> -- evaluates to:
"21-Aug-2008"
* Assign contents of a field to a variable, e.g.
"%assign worker = Top.Employee.FirstName"
worker expands to Top.Employee.FirstName = Arthur
* Concatenate string values, e.g.
"%assign worker = worker + " " + Top.Employee.LastName"
worker expands to worker + " " + Top.Employee.LastName = "Arthur Dent"
* Perform arithmetic operations, e.g.
"%assign wageCost = Top.Employee.PayRate * Top.Employee.Overhead"
wageCost expands to Top.Employee.PayRate * Top.Employee.Overhead <- 11.5 * 1.78 = 20.47
* Put variables into a field, e.g.
Top.Employee.GrossRate starts at 0.0
"%assign Top.Employee.GrossRate = wageCost"
Top.Employee.GrossRate expands to wageCost = 20.47
Reading Record Files with TLC
* Index lists of values, e.g.
"%assign projects = Top.Project[0].Name + ", " + Top.Project[1].Name..."
"+ ", " + Top.Project[2].Name"
projects expands to Top.Project[0].Name + ", " + Top.Project[1].Name
+ ", " + Top.Project[2].Name = Tea, Gillian, Zaphod
* Traverse and manipulate list data via loops, e.g.
- At top of Loop, Project = Tea; Difficulty = 3
- Bottom of Loop, i = 0; diffSum = 3.0
- At top of Loop, Project = Gillian; Difficulty = 8
- Bottom of Loop, i = 1; diffSum = 11.0
- At top of Loop, Project = Zaphod; Difficulty = 10
- Bottom of Loop, i = 2; diffSum = 21.0
Average Project Difficulty expands to diffSum / Top.NumProject = 21.0 / 3 = 7.0
This output from guide.rtw was produced by invoking TLC from the MATLAB Command Window, executing a script called
read-guide.tlc.Do
this yourself now, by following these steps:
1 In MATLAB, change directory (cd)toyourcopyoftlctutorial/guide
within your working directory.
2 To produce the output just listed, process guide.rtw with the TLC script
read-guide.tlc by typing the following command:
tlc -v -r guide.rtw read-guide.tlc
Note command usage:
The
-r switch (for read) is needed to identify the input data file, in this
case
guide.rtw.
TheTLCscripthandlingthedatafileisspecifiedbythelasttokentyped.
The
-v switch (for verbose) is needed to direct output to the command
window, unless the TLC file handles this itself.

Learning About the Anatomy of a TLC Script

You now dissect the script you just ran. Each “paragraph” of output from
guide.tlc is discussed in sequence in the following brief sections:
3-7
3 Target Language Compiler Tutorials
“Coding Conventions” on page 3-8 — Before you beg in
“File Header” on page 3-9 — Header info and a formatting directive
“Token Expansion” on page 3-9— Evaluating field and variable identifiers
“General Assignment” on page 3-10 — Using the
%assign directive
“String Processing Plus” on page 3-11 — Methods of assembling strings
“Arithmetic Operations” on page 3-13 — Computations on fields and
variables
“Modifying Records” on page 3-14 — Changing, copying, appending to
records
“Indexing Lists” on page 3-15 — Referencing list elements with subscripts
“Looping over Lists” on page 3-16 — Details on loop construction and
behavior
Coding Conventions
These are some basic TLC syntax and coding conventions:
%% Comment
/* comment */
%keyword
%<expr>
. (period) Scoping operato r, for example, Top.Lev2.Lev3
TLC comment, which is not output
Comment, to be output
TLC directive (keyword), start with “%
TLC token operator
3-8
...
(at end-of-line) Statement continuation (no line break output)
\ (at end-of-line) Statement continuation (line break is output)
localvarIdentifier
GlobalvarIdentifier
RecordIdentifier
EXISTS()
Local variables start in lowercase
Global variables start in uppercase
Record identifiers start in uppercase
TLC built-in functions are named in uppercase Note: All TLC identifiers are case-sensitive.
Reading Record Files with TLC
For further information, see “TLC Coding Conventions” on page 8-25.
File Header
The file read-guide.tlc begins with:
%% File: read-guide.tlc (This line is a TLC Comment, and will not print)
%% $Revision: 1.1.4.36 $
%% To execute this file, type: tlc -v -r guide.rtw read-guide.tlc
%% Set format for displaying real values (default is "EXPONENTIAL")
%realformat "CONCISE"
Lines 1 through 4 — All text on a line following the characters %% is treated
as a comment (ignored, not interpreted or output).
Line 5 — As explained in the text of the fourth line, is the TLC directive
(keyword) numbers are formatted when displayed in output. Here we want to minimize the digits displayed.
%realformat, which controls how subsequent floating-point
Token Expansion
The first section of output is p roduced by the script lines:
Using TLC you can: * Directly access any field's value, e.g. %assign td = "%" + "<Top.Date>"
%<td> -- evaluates to: "%<Top.Date>"
Lines 1 and 2 — (and any line that contains no TLC directives or tokens) are
simply echoed to the output stream, includ ing lea di n g and t ra iling sp aces.
Line 3 — Creates a variable named
%<Top.Date> to it. The %assign directive creates new and modifies existing
variables. Its general syntax is:
%assign ::variable = expression
The optional double colon prefix specifies that the variable being assigned to is a global variable. In its absence, TLC creates or modifies a local variable in the current scope.
td and assigns the string value
3-9
3 Target Language Compiler Tutorials
Line 4 — Displays
%<Top.Date> -- evaluates to:
The preceding line enables TLC to print %<Top.Date> without expanding it. It constructs the string by pasting together two literals.
%assign td = "%" + "<Top.Date>"
As discussed in “String Pro cessing Plus” on page 3-11, the plus operator concatenates strings as and adds numbers, vectors, matrices, and records.
Line 5 — Evaluates (expands) the record
evaluates the field
Date whichexistsinscopeTop. The syntax %<expr>
Top.Date. More precisely, it
causes expression expr (which can be a record, a variable, or a function) to be evaluated. This operation is sometimes referred to as an eval.
Note You cannot nest the %<expr> operator (that is, %<foo%<bar>> is not allowed).
Note When you use the %<expr> operator within quotation marks, for example, result in quotation marks. However, placing for example,
"%<Top.Date>", TLC expands the expression and then encloses the
%assign within quotation marks,
"assign foo = 3", simply echoes the statement enclosed in
quotation marks to the output stream. No assignment results (the value of
foo remains unchanged or undefined).
General Assignment
The second section of output is produced by the script lines:
* Assign contents of a field to a variable, e.g. %assign worker = Top.Employee.FirstName
"%assign worker = Top.Employee.FirstName" worker expands to Top.Employee.FirstName = %<worker>
3-10
Line 1 — Echoed to output.
Reading Record Files with TLC
Line 2 — An assignment of field FirstName in the Top.Employee record
scope to a new local variable called
worker.
Line 3 — Repeats the previous statement, producing output by enclosing it
in quotation marks.
Line 4 — Explains the following assignment and illustrates the token
expansion. The token
%<worker> expands to Arthur.
String Processing Plus
The n ext section o f the script illustrates string concatenation, one of the uses of the “
Line 1 — Echoed to output.
+” operator:
* Concatenate string values, e.g. %assign worker = worker + " " + Top.Employee.LastName
"%assign worker = worker + " " + Top.Employee.LastName" worker expands to worker + " " + Top.Employee.LastName = "%<worker>"
Line 2 — Performs the concatenation.
Line 3 — Echoes line 2 to the output.
Line 4 — Describes the operation, in which a variable is concatenated to a
field separated by a s pace character. An alternative way to do this, without using the
%assign worker = "%<Top.Employee.FirstName> %<Top.Employee.LastName>"
+ operator, is
The alternative method uses evals of fields and is equally efficient.
The
+ operator, which is associative, also works for numeric types, vectors,
matrices, and records:
Numeric Types — Add two expressions together; both operands must be
numeric. For example:
* Numeric Type example, e.g.
Top.Employee.PayRate = %<Top.Employee.PayRate> Top.Employee.Overhead = %<Top.Employee.Overhead>
%assign td = Top.Employee.PayRate + Top.Employee.GrossRate
td = Top.Employee.PayRate + Top.Employee.Overhead
3-11
3 Target Language Compiler Tutorials
Output:
* Numeric Type example, e.g.
Vectors — If the first argument is a vector and the second is a scalar value,
TLC appends the scalar value to the vector. For example:
* Vector example, e.g. %assign v1 = [0, 1, 2, 3]
%assign tp1d = Top.Project[1].Difficulty
%assign v2 = v1 + tp1d
td evaluates to %<td>
Top.Employee.PayRate = 11.5 Top.Employee.Overhead = 1.78 td = Top.Employee.PayRate + Top.Employee.Overhead td evaluates to 13.28
v1 is %<v1>
Top.Project[1].Difficulty is %<tp1d>
v2 = v1 + Top.Project[1].Difficulty v2 evaluates to: %<v2>
3-12
Output:
* Vector example, e.g.
v1 is [0, 1, 2, 3] Top.Project[1].Difficulty is 8 v2 = v1 + Top.Project[1].Difficulty v2 evaluates to: [0, 1, 2, 3, 8]
Matrices — If the first argument is a matrix and the second is a vector of
the same column-width as the matrix, TLC appends the vector as another row to the matrix. For example:
* Matrices example, e.g. %assign mx1 = [[4, 5, 6, 7]; [8, 9, 10, 11]]
mx1 is %<mx1> v1 is %<v1>
%assign mx = mx1 + v1
mx = mx1 + v1 mx evaluates to %<mx>
Reading Record Files with TLC
Output:
* Matrices example, e.g.
mx1 is [ [4, 5, 6, 7]; [8, 9, 10, 11] ] v1 is [0, 1, 2, 3] mx = mx1 + v1 mx evaluates to [ [4, 5, 6, 7]; [8, 9, 10, 11]; [0, 1, 2, 3] ]
Records — If the first argument is a record, TLC adds the second argument
as a parameter identifier (with its current value). For example:
* Record example, e.g. %assign StartDate = "August 28, 2008"
StartDate is %<StartDate>
%assign tsd = Top + StartDate
Top + StartDate Top.StartDate evaluates to %<Top.StartDate>
Output:
* Record example, e.g.
StartDate is August 28, 2008 Top + StartDate Top.StartDate evaluates to August 28, 2008
Arithmetic Operations
TLC provides a full complement of arithmetic operators for numeric data. In the nex t portion of our TLC script, two numeric fields are multiplied:
* Perform arithmetic operations, e.g.
%assign wageCost = Top.Employee.PayRate * Top.Employee.Overhead
"%assign wageCost = Top.Employee.PayRate * Top.Employee.Overhead"
wageCost expands to Top.Employee.PayRate * Top.Employee.Overhead ...
<- %<Top.Employee.PayRate> * %<Top.Employee.Overhead> = %<wageCost>
Line 1 — Echoed to output.
Line 2 —
in local variable
Line 3 — Echoes the operation in line 2.
%assign statement that computes the value, which TLC stores
wageCost.
3-13
3 Target Language Compiler Tutorials
Lines 4 and 5 — Compose a single statement. The ellipsis (typed as
three consecutive periods, for example, continued on the following line, but if the statement has output, TLC does not insert a line break. To continue a statement and insert a line break, replace the ellipsis with a backslash (
Modifying Records
Once read into memory, you can modify and manipulate records just like variables you create by assignment. The next segment of replaces the value of record field Top.Employee.GrossRate:
* Put variables into a field, e.g.
%assign Top.Employee.GrossRate = wageCost
"%assign Top.Employee.GrossRate = wageCost"
Top.Employee.GrossRate expands to wageCost = %<Top.Employee.GrossRate>
Such changes to records are nonpersistent (because record files are inputs to TLC; other file types, such as C source code, are outputs), but can be useful.
... ) signals that a statement is
\).
read-guide.tlc
3-14
You can use sev eral TLC directives besides
%createrecord
Creates new top-level records, and might also specify subrecords within them, including name/value pairs.
%addtorecord
Adds fields to an existing record. The new fields can be name/value pairs or aliases to existing records.
%mergerecord
Combines one or more records. The first record contains itself plus copies of all the other records’ contents specified by the command, in sequence.
%assign to modify records:
Reading Record Files with TLC
%copyrecord
Creates a new record as %createrecord does, except the components of the record come from the existing record you specify.
%undef var
Removes (deletes) var (a variable or a record) from scope. If the field from the record. If
var is a field in a record, TLC removes
var is a record
array ( list), TLC removes the first eleme nt of the array; the remaining elements remain accessible. You can remove only records you create with
%createrecord or %copyrecord.
See “Target Language Compiler Dire ctive s” on page 6-2 for details on these directives.
Indexing Lists
Record files can contain lists, o r sequences of records having the same identifier. Our example contains a list of three records identified as within the Top scope. List references are indexed, numbered from 0, in the order in which they appear in the record file. Here is TLC code that compiles data from the
* Index lists of values, e.g.
%assign projects = Top.Project[0].Name + ","+Top.Project[1].Name...
+ ", " + Top.Project[2].Name
"%assign projects = Top.Project[0].Name + ", " + Top.Project[1].Name..."
"+","+Top.Project[2].Name"
projects expands to Top.Project[0].Name + ", " + Top.Project[1].Name
+ ", " + Top.Project[2].Name = %<projects>
Name field of the Project list:
Project
The Scope.Record[n].Field syntax is similar to that used in C to reference elements in an array of structures.
While explicit indexing, such as the above, is perfectly acceptable, it is often preferable to use a loop construct when traversing entire lists, as shown in “Looping over Lists” on page 3-16.
3-15
3 Target Language Compiler Tutorials
Looping over Lists
By convention, the section of a record file that a list occupies is preceded by a record that indicates how many list elements are present. In such parameters are declared as used for records in the list that follows. In like this:
NumProject 3 # Indicates length of following list
Project { # First list item, called Top.Project[0]
Name "Tea" # Alpha field Name, Top.Project[0].Name
Difficulty 3 # Numeric field Top.Project[0].Difficulty
} # End of first list item
Project { # Second list item, called Top.Project[1]
Name "Gillian" # Alpha field Name, Top.Project[1].Name
Difficulty 8 # Numeric field Top.Project[1].Difficulty
} # End of second list item
Project { # Third list item, called Top.Project[2]
Name "Zaphod" # Alpha field Name, Top.Project[2].Name
Difficulty 10 # Numeric field Top.Project[2].Difficulty
} # End of third list item
model.rtw files,
NumIdent,whereIdent is the identifier
guide.rtw,theProject list looks
3-16
Thus, the value of NumProject describes how many Project records occur.
Note model.rtw files might also contain records that start with Num but are not list-size parameters. TLC does not require that list size parameters start with
Num. Therefore you need to be cautious when interpreting NumIdent
record identifiers. The built-in TLC function SIZE() can determine the number o f records in a specified scope, hence the length of a list.
The last segment of read-guide.tlc uses a %foreach loop, controlled by the
NumProject parameter, to iterate the Project list and manipulate its values.
* Traverse and manipulate list data via loops, e.g.
%assign diffSum = 0.0
%foreachi=Top.NumProject
- At top of Loop, Project = %<Top.Project[i].Name>; Difficulty =...
%<Top.Project[i].Difficulty>
%assign diffSum = diffSum + Top.Project[i].Difficulty
Reading Record Files with TLC
- Bottom of Loop, i = %<i>; diffSum = %<diffSum>
%endforeach
%assign avgDiff = diffSum / Top.NumProject
Average Project Difficulty expands to diffSum / Top.NumProject = %<diffSum> ...
/ %<Top.NumProject> = %<avgDiff>
As you may reca
* Traverse and manipulate list data via loops, e.g.
- At top of Loop, Project = Tea; Difficulty = 3
- Bottom of Loop, i = 0; diffSum = 3.0
- At top of Loop, Project = Gillian; Difficulty = 8
- Bottom of Loop, i = 1; diffSum = 11.0
- At top of Loop, Project = Zaphod; Difficulty = 10
- Bottom of Loop, i = 2; diffSum = 21.0
Average Project Difficulty expands to diffSum / Top.NumProjects = 21.0 / 3 = 7.0
ll, the TLC output looks like this:
After initializing the summation variable diffSum,a%foreach loop is entered, with variable
i declared as the loop counter, iterating up to NumProject.
The scope of the loop is all statements encountered until the corresponding
%endforeach is reached (%foreach loops may be nested).
Note Loop iterations implicitly start at ze r o and range to one less than the index t ha t specifies the upper bound. The loop index is local to the loop body.

Modifying read-guide.tlc

Now that you have studied read-guide.tlc, it is tim e to modify it. This exercise introduces two important TLC facilities, file control and scoping control. You implement both within the
read-guide.tlc script.
File Control Basics
TLC scripts almost invariably produce output in the form of streams of characters. Output is normally directed to one or more buffers and files, collectively called streams. So far, you have directed output from
read-guide.tlc to the MATLAB Command Window because you included
the
-v switch on the command line. Prove this by omitting -v when you run
read-guide.tlc.Type
3-17
3 Target Language Compiler Tutorials
tlc -r guide.rtw read-guide.tlc
Nothing appears to happen. In fact, the script was executed, but all output was directed to a null device (sometimes called the “bit bucket”).
There is always one active output file, even if it is null. To specify, open, and close files, use the following TLC directives:
%openfile streamid ="filename" , "mode" %closefile streamid %selectfile streamid
If y ou do not give a filename, subsequent output flows to the memory buffer named by writing and deletes any existing content (subject to system-level file protection mechanisms). Va li d mode ide n t if iers are Enclose these characters in quotes.
The
%openfile directive creates a file/buffer (in w mode), or opens an existing
one (in number of streams can be open for writing, but only one can be active at one time. To switch output streams, use the need to close files until you are done with them.
streamid. If you do not specify a mode, TLC opens the file for
a (append) and w (write, the default).
a mode). Note the required equals sign for file specification. Any
%selectfile directive. You do not
3-18
The default output stream, which youcanrespecifywiththestreamID
NULL_FILE,isnull. Another built-in stream is STDOUT.Whenactivatedusing %selectfile, STDOUT directs output to the MATLAB Command Window.
Note The streams NULL_FILE and STDOUT are always open. Specifying them with
%openfile generates errors. Use %selectfile to activate them.
The directive %closefile closes the current output file or buffer. Until an
%openfile or a %selectfile directive is encountered, output goes to the
previously opened stream (or, if none exists, to null). U se
%selectfile to
designate an open stream for reading or writing. In practice, many TLC scripts write pieces of output data to separate buffers, which are then selected in a sequence and their contents spooled to one or more files.
Reading Record Files with TLC
Implement Output File Control
In your tlctutorial/guide directory, find the file
read-guide-file-src.tlc. The supplied version of this file contains
comments and three l ines of text added. Edit this file to implement output file control, as follows:
1 Open read-guide-file-src.tlc in your text edit or.
2 Save the file as read-guide-file.tlc.
3 Note five comment lines that begin with %% ->.
Under each of these comments, insert a TLC directive as indicated.
4 Save the edited file as read-guide-file.tlc.
5 Execute read-guide-file.tlc w ith the following command:
tlc -r guide.rtw read-guide-file.tlc
If you succeeded, TL C creates the file guidetext.txt which contains the expected output, and the MATLAB Com mand Window displays
*** Output being directed to file: guidetext.txt *** We're almost done . . . *** Processing completed.
If y ou did not see these messages, or if no text file was p roduced, review the material and try again. If problems persist, inspect the
guide/solutions subdirectory to see how you should specify file control.
read-guide-file.tlc in
Scope Basics
“Learning About the Structure of Record F iles” on page 3-5 explains the hierarchical organization of records. Each record exists within a scope defined by the records in which it is nested. The example file, the following scopes:
Top Top.Employee Top.Project[0] Top.Project[1]
guide.rtw,contains
3-19
3 Target Language Compiler Tutorials
Top.Project[2]
To refer to a field or a record, it is normally necessary to specify its scoping, even if there is no other context that contains the identifier. For example, in
guide.rtw,thefieldFirstName exists only in the scope Top.Employee.You
must refer to it as
When models present scopes that are deeply nested, this can lead to extremely long identifiers that are tedious and error prone to type. For example:
CompiledModel.BlockOutputs.BlockOutput.ReusedBlockOutput
This identifier has a scope that is long and has similar item names that you could easily enter incorrectly.
The
%with/%endwith directive eases the burden of correctly coding TLC
scripts and clarifies their flow of control. The syntax is
%with RecordName
[TLC statements]
%endwith
Top.Employee.FirstName whenever accessing it.
3-20
Every %with is eventually followed by an %endwith,andthesepairsmightbe nested (but not overlapping). If
RecordName is below the top level, you need
notincludethetop-levelscopeinitsdescription. Forexample,tomakethe current scope of
%with Employee
[TLC statements]
%endwith
guide.rtw Top.Employee, you can specify
Naturally, %with Top.Employee is also valid syntax. Once bracketed by
%with/%endwith, record identifiers in TLC statements no longer requires you
to specify their outer scope. H ow ev er, note the following conditions :
You can access records outside of the current
%with scope, but you must
qualify them fully (for example, using record name and fields).
Whenever you make assignments to records inside a
%with directive, you
must qualify them fully.
Reading Record Files with TLC
Change Scope Using %with
In the last segment of this exercise, you modify the TLC script by adding a
%with/%endwith directive. You also need to edit record identifier names (but
not those of local variables) to account for the changes of scope resulting from the
%with directives.
1 Open the TLC script read-guide-scope-src.tlc in the text editor.
2 Savethefileasread-guide-scope.tlc.
3 Note comment lines that commence with %% ->.
Under each of these comments, insert a TLC directive or modify statements already present, as indicated.
4 Save the edited file as read-guide-scope.tlc.
5 Execute read-guide-scope.tlc w ith the follow ing command:
tlc -v -r guide.rtw read-guide-scope.tlc
The output should be exactly the same as from read-guide.tlc,except possibly for white space that you might have introduced by indenting sections of code inside
Fullyspecifyingascopeinsidea
%with/%endwith or by eliminating blank li nes.
%with context is not an error, it is simply
unnecessary. However, failing to fully specify its scope when assigning it to a record (for example,
%assign GrossRate = wageCost)isinvalid.
If errors result from running the script, review the discussion of scoping above and edit inspect
read-guide-scope.tlc in the /solutions subdirectory to see how
read-guide-scope.tlc to eliminate them. As a last resort,
you should have handled scoping in this exercise.
For additional information, see “Using Scopes in the
model.rtw File” on page
5-4 and “Variable Scoping” on page 6-57.
3-21
3 Target Language Compiler Tutorials
Passing and Usin
You can use the TL from the command command switch
tlc -r input.rtw -avar=1 -afoo= abc any.tlc
is
g a Parameter
Ccommandsandbuilt-infunctionstopassparameters line to the TLC file being executed. The most general
-a, which assigns arbitrary variables. For example:
The result of passing this pair of strings via -a is the same as declaring and initializing local variables in the file being executed (here,
any.tlc). For
example:
%assign var = 1 %assign foo = abc
You do not need to declare such variables in the TLC file, and they are available for use when set with undeclared variables that you do not specify with the the file. Also note that (in contrast to the
-a from the parameter you are declaring.
-a. However, errors result if the code assigns
-a switch when invoking
-r switch) no space should separat
In the final section of this tutorial, you use the built-in function
GET_COMMAND_SWITCH() to print the name of the record file being used in the
TLCscript,andprovideaparametertocontrolwhetherornotthecodeis suppressed. By default the code is executed, but is suppressed if the comma line contains
-alist=0:
e
nd
3-22
1 Open the TLC script read-guide-param-src.tlc in your text editor.
2 Savethefileasread-guide-param.tlc.
3 To enable your program to access the input filename from the command
line, do the following:
a Below the line %selectfile STDOUT,addtheline:
%assign inputfile = GET_COMMAND_SWITCH ("r")
The %assign directive declares and sets variables. In this instance, it holds a string filename identifier.
GET_COMMAND_SWITCH() returns
whatever string argument follows a specified TLC command switch. You must alw ays use UPPERCASE for built-in function names.
Reading Record Files with TLC
b Change the line “*** WORKING WITH RECORDFILE”toreadasfollows:
*** WORKING WITH RECORDFILE %<inputfile>
4 To control whether or not a section of TLC code is executed, do the following:
a Below the line “%assign inputfile = GET_COMMAND_SWITCH ("r")”,
add:
%if (!EXISTS(list))
%assign list = 1
%endif
The program checks whether a list parameter has been declared, via the intrinsic (built-in) function program assigns one. This code ensures that default its value is
b Enclose lines of code within an %if block.
%if (list)
* Assign contents of a field to a variable, e.g.
%assign worker = FirstName
"%assign worker = FirstName" worker expands to FirstName = %<worker>
%endif
TRUE.
EXISTS(). If no list variable exists, the
list is defined and by
Now the code to assign worker is sent to the output only when list is TRUE.
c Save read-guide-param.tlc.
5 Execute read-guide-param.tlc and examine the output, using the
command
tlc -r guide.rtw read-guide-param.tlc
This yields
*** WORKING WITH RECORDFILE [guide.rtw] * Assign contents of a field to a variable, e.g.
"%assign worker = FirstName" worker expands to FirstName = Arthur
3-23
3 Target Language Compiler Tutorials
***END
6 Executeread-guide-param.tlc with the command:
tlc -r guide.rtw -alist=0 read-guide-param.tlc
With the -alist=0 switch, the output displays only the information outside of the
*** WORKING WITH RECORDFILE [guide.rtw] ***END

Review

The p receding exercises examined the structure of record files, and expanded on how to use TLC directives. The following TLC directives are commonly used in TLC scripts (see Chapter 6, “Directives and Built-In Functions”, for detailed descriptions):
if statement.
%addincludepath
%addtorecord
%assign
%copyrecord
%createrecord
%foreach/%endforeach
%if/%endif
%include
%mergerecord
Enable TL C to find included files.
Add fields to existing record. New fields can be name/value pairs or aliases to existing records.
Create or modify variables.
Create new record, and if appropriate specify subrecords within them, including name/value pairs. The components of the record come from the existing record specified.
Create new top-level records, and if appropriate specify subrecords within them, including name/value pairs.
Iterate loop variable from 0 to upper limit.
Control whether code is executed, as in C.
Insertonefileintoanother,asinC.
Combine one or more records. The first record contains itself plus copies of all the other records contents specified by the command, in sequence.
3-24
Reading Record Files with TLC
%selectfile
%undef var
Direct outputs to a stream or file.
Remove (delete) var (a variable or a record) from scope. If removes the field from the record. If
var is a field in a record, TLC
var is
a record array (list), TLC removes the first element of the array; the remaining elements remain accessible. Only records created via
%createrecord or %copyrecord can be
removed.
%with/%endwith
Add scope to simplify referencing blocks.
In “Passing and Using a Parameter” on page 3-22, you used TLC built in functions. See Chapter 6, “Directives and Built-In Functions” for more information.
3-25
3 Target Language Compiler Tutorials

Inlining S-Functions with TLC

In this section...
timesN Tutorial Overview” on page 3-26
“Learning About Noninlined Code Generation” on page 3-26
“Understand Why You Use TLC to Inline S-Functions” on page 3-29
“Creating an Inl in ed S-Function” on page 3-29

timesN Tutorial Overview

Objective: To understand how TLC works with a n S-function.
Directory:
In this tutorial, you generate versions of C code for existing S-function timesN.
The tutorial includes these steps:
1 Learning About Noninlined Code Generation — Via SimStructs and
generic API
2 Understanding Why You Use TLC to Inline S-functions —Benefitsof
inlining
3 Creat
er tutorial provides information and practice with “wrapping” S-functions.
Alat
Lear
tutorial directory
The
tains Simulink S-function
con
unctions, see “Overview of S-Functions” in the Simulink documentation.
S-f
this exercise, you generate noninlined code from the model
In
nd the file
1 Fi
le to
fi
tlctutorial/timesN
ing an Inlined S-Function — Via custom TLC code
ning About Noninlined Code Generation
tlctutorial/timesN in your working directory
timesN.c. For general information on
sfun_xN.mdl.
rename_timesN.tlc in tlctutorial/timesN.Renamethis
timesN.tlc. Thisallowsyoutogeneratecode.
3-26
Inlining S-Functions with TLC
2 In the MATLAB Comm and Window, create a MEX-file for the S-function:
mex timesN.c
This is needed to avoid picking up the version shipped with Simulink.
Note An error might occur if you have not previously run mex -setup.For more information on MEX-files, see “MEX Programming” in the MATLAB Function Reference.
3 Open the model sfun_xN.mdl, which uses the timesN S-function. The block
diagram looks like this.
4 Open the Configuration Parameters dialog box and select the Solver pane.
5 Set Stop time to 10.0.
ttheSolver Options.
6 Se
3-27
3 Target Language Compiler Tutorials
Type to Fixed-step
Solver to Discrete (no continuous states)
Fixed-step size to 0.01
7 Select the Optimization pane, and make sure that Inline parameters is
unchecked.
8 Select Real-Time Workshop > Comments pane, and notice that Include
comments is checked by default.
9 Select the Real-Time Workshop pane and check Generate code only.
The text of the Build button changes to Generate code.ClickApply.
10 Click Generate code to generate C code for the model.
11 Open the resulting file sfun_xN_grt_rtw/sfun_xN.c and view the
sfun_xN_output portion, shown below.
3-28
/* Model output function */
static void sfun_xN_output(int_T tid)
{
/* Sin: '<Root>/Sin' */
sfun_xN_B.Sin = sin(sfun_xN_M->Timing.t[0] * sfun_xN_P.Sin_Freq +
sfun_xN_P.Sin_Phase) * sfun_xN_P.Sin_Amp +
sfun_xN_P.Sin_Bias;
/* S-Function Block: <Root>/S-Function */
/* Multiply input by 3.0 */
sfun_xN_B.timesN_output = sfun_xN_B.Sin * 3.0;
/* Outport: '<Root>/Out' */
sfun_xN_Y.Out = sfun_xN_B.timesN_output;
UNUSED_PARAMETER(tid);
}
Comments appear in the code because, in the Real-Time Workshop > Comments pane of the Configuration Parameters dialog box, Include comments is selected by default.
Inlining S-Functions with TLC
Understand Why Y
The Real-Time Wo usetoinvokeuse of callback fun and so on — as wel in memory and i invocation in
rkshop code generator includes a generic API that you can
r-written algorithms and drivers. The API includes a variety
ctions — for initialization, output, derivatives, termination,
l as data structures. Once coded, these are instantiated
nvoked during execution via indirect function calls. Each
volves stack frames and other overhead that adds to execution
ou Use TLC to Inline S-Functions
time.
In a real-tim generic API c up S-functi user-writt indirectly called in l
e environment, especially when many solution steps are involved,
alls can be unacceptably slow. The code generator can speed
ons in standalone applications that it generates by embedding
en algorithms within auto-generated functions, rather than
calling S-functions via the generic API. This form of optimization is
ining. TLC always inlines S-functions, resulting in faster, optimized
code.
You shoul S-functi code S-fu use of TL S-funct
Creati
TLC cre same na it dir S-fun compl
d understand that TLC is not a substitute for writing C code
ons. To invoke custom blocks within Simulink, it is still necessary to
nctions in C (or as MATLAB files), since simulations do not make
C files. You can, however, prepare TLC files that inline specified
ions to make your target code much more efficient.
ng an Inlined S-Function
ates an inlined S-function wh enever it detects a
me as an S-function. Assuming the
.tlc file is properly formed,
ects construction of code that functionally duplicates the external
ction without incurring API overhead. See how this process works by
eting the following steps:
.tlc file with the
1 If yo
u have not done so already, find the file
utorial/timesN
tlct
rate code. The executableportionofthefileis
gene
%implements "timesN" "C"
%% Function: Outputs ===========================================================
%%
%function Outputs(block, system) Output
.RenamethisfiletotimesN.tlc,soyoucanuseitto
rename_timesN.tlc in
3-29
3 Target Language Compiler Tutorials
%endfunction
2 Create the inline version of the S-function.
a In the Optimization pane of the Configuration Parameters dialog box,
check Inline parameters and click Apply.
b Change the diagram’s label from model: sfun_xN to model:
sfun_xN_ilp
c Save the model as sfun_x2_ilp.mdl.
%assign gain =SFcnParamSettings.myGain
/* %<Type> Block: %<Name> */
%%
/* Multiply input by %<gain> */
%assign rollVars = ["U", "Y"]
%roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
%<LibBlockOutputSignal(0, "", lcv, idx)> = \
%<LibBlockInputSignal(0, "", lcv, idx)> * %<gain>;
%endroll
.
3-30
d In the Real-Time Workshop pane of the Configuration Parameters
dialog box, click Generate code. Source files are created in a new subdirectory called
e Inspect the code in generated file sfun_xN_ilp.c:
/* Model output function */ static void sfun_xN_ilp_output(int_T tid) {
/* Sin: '<Root>/Sin' */ sfun_xN_ilp_B.Sin = sin(sfun_xN_ilp_M->Timing.t[0]);
/* S-Function Block: <Root>/S-Function */ /* Multiply input by 3.0 */ sfun_xN_ilp_B.timesN_output = sfun_xN_ilp_B.Sin * 3.0;
/* Outport: '<Root>/Out' */ sfun_xN_ilp_Y.Out = sfun_xN_ilp_B.timesN_output; UNUSED_PARAMETER(tid);
}
sfun_xN_ilp_grt_rtw.
Inlining S-Functions with TLC
Note When the Real-Time Workshop software generates code and builds executables, it creates or uses a specific subdirectory (called the build directory) to hold s ource, object, and m ake files. By default, the build directory is named
model_grt_rtw.
Notice that checking the Inline parameters box did not change the code. This is because TLC always inlines S-functions.
3 Continue the exercise by creating a standalone simulation.
a In the Real-Time Workshop pane of the Configuration Parameters
dialog box , clear Generate code only and click Apply.
b In the Data Import/Export pane of the Configuration Parameters
dialog box, under Save to workspace,checkOutput.
This specification causes the model’s output data t o be logged in your MATLAB workspace.
c In the Real-Time Workshop pane of the Configuration Parameters
dialog box, click Build to generate code, compile, and link the model into an executable, named
sfun_xN_ilp).
d Confirm that the timesN.tlc file produces the correct output by running
sfun_xN_ilp.exe (or, on UNIX
®
systems,
the standalone executable. To run it, in the MATLAB Command Window, type
!sfun_xN_ilp
The following response appears:
** starting the model ** ** created sfun_xN_ilp.mat **
e View or plot the contents of the sfun_xN_ilp.mat file to verify that the
standalone model generated sine output ranging from -3 to +3. In the MATLAB Command Window, type
load sfun_xN_ilp.mat plot (rt_yout)
3-31
3 Target Language Compiler Tutorials

Exploring Variable Names and Loop Rolling

In this section...
timesN Looping Tutorial Overview” on page 3-32
“Getting Started” on page 3-32
“Modifying the Model” on page 3-34
“Changing the Loop Rolling Threshold” on page 3-36
“Learning More About TLC Loop Rolling” on page 3-37

timesN Looping Tutorial Overview

Objective: This example shows how you can influence looping behavior of generated code.
Directory:
Work with the model tlctutorial/timesN/sfun_xN.mdl, it has one source (a Sine Wave generator block), a times N gain block, an Out block, and a Scope block.
The tutorial guides you through following steps:
1 Getting Started — Set up the exercise and run the model
2 Modifying the Model — Change the input width and see the results
3 Chan
the r
4 Learning More About TLC Loop Rolling — Parameterize loop behavior
tlctutorial/timesN
ging the Loop Rolling Threshold — Change the threshold and see
esults

Getting Started

1 Make tlctutorial/timesN your current directory, so that you can use
the files provided.
3-32
Exploring Variable Names and Loop Rolling
Note You must use or create a working directory outside of matlabroot for Simulink models you make. You cannot build models in source directories.
2 In the MATLAB Comm and Window, create a MEX-file for the S-function:
mex timesN.c
This is needed to avoid picking up the version shipped with Simulink.
Note An error might occur if you have not previously run mex -setup.For more information on MEX-files, see “MEX Programming” in the MATLAB Function Reference.
3 Open the model file sfun_xN.mdl.
3-33
3 Target Language Compiler Tutorials
4 View the previously generated code in sfun_xN_grt_rtw/sfun_xN.c.Note
that no loops exist in the code. This is because the input and output signals are scalar.

Modifying the Model

1 Replace the Sine Wave block with a Constant block.
2 Set the parameter for the Constant block to 1:4, and change the top label,
model: sfun_xN,tomodel: sfun_vec.
3 Save the edited model as sfun_vec.mdl (in tlctutorial/timesN). The
model now looks like this.
3-34
4 Beca
use the Co nstant block generates a vector of values, this is a vectorize d
el. Generate code for the model and view the
mod
ction */
fun
for loops are handled. This function appears as follows:
and
/* Model output function */
static void sfun_vec_output(int_T tid)
section of sfun_vec.c in your editor to observe how variables
/*Model output
Exploring Variable Names and Loop Rolling
{
/* S-Function Block: <Root>/S-Function */
/* Multiply input by 3.0 */
sfun_vec_B.timesN_output[0] = sfun_vec_P.Constant_Value[0] * 3.0;
sfun_vec_B.timesN_output[1] = sfun_vec_P.Constant_Value[1] * 3.0;
sfun_vec_B.timesN_output[2] = sfun_vec_P.Constant_Value[2] * 3.0;
sfun_vec_B.timesN_output[3] = sfun_vec_P.Constant_Value[3] * 3.0;
/* Outport: '<Root>/Out' */
sfun_vec_Y.Out[0] = sfun_vec_B.timesN_output[0];
sfun_vec_Y.Out[1] = sfun_vec_B.timesN_output[1];
sfun_vec_Y.Out[2] = sfun_vec_B.timesN_output[2];
sfun_vec_Y.Out[3] = sfun_vec_B.timesN_output[3];
UNUSED_PARAMETER(tid);
}
Notice that there are four instances of the code that generates model outputs, corresponding to four iterations.
5 Set the parameter for the Constant block to 1:10, and save the model.
6 Generate code for the model and view the /*Model output function */
section of sfun_vec.c in your editor to observe how variables and for loops are handled. This function appears as follows:
/* Model output function */
static void sfun_vec_output(int_T tid)
{
/* S-Function Block: <Root>/S-Function */
/* Multiply input by 3.0 */
{
int_T i1;
const real_T *u0 = &sfun_vec_P.Constant_Value[0];
real_T *y0 = sfun_vec_B.timesN_output;
for (i1=0; i1 < 10; i1++) {
y0[i1] = u0[i1] * 3.0;
}
}
{
int32_T i;
3-35
3 Target Language Compiler Tutorials
}
Notice that:
The code that generates model outputs gets “rolled” into a loop. This occurs
by default when the number of iterations exceeds 5.
for(i=0;i<10;i++) {
/* Outport: '<Root>/Out' */
sfun_vec_Y.Out[i] = sfun_vec_B.timesN_output[i];
}
}
UNUSED_PARAMETER(tid);
Loop index
Pointer
i1 runs from 0 to 9.
*y0 is used and initialized to the output signal array.

Changing the Loop Rolling Threshold

The code generator creates iterations or loops depending on the current value of RollThreshold.FormoreaboutRollThreshold, see “Loop unrolling threshold”.
ThedefaultvalueofRollThreshold is for all blocks in a model by changing RollThreshold. For example:
1 In the Optimization pane of the Configuration Pa rameters dialog box, set
Loop unrolling threshold to
RollThreshold is now
12. Loops will be generated only when the width of
signals passing through a block exceeds 12.
Note You cannot modify RollThreshold for specific b locks from the Configuration Parameters dialog box.
2 In the Real-Time Workshop pane of the Configuration Parameters dialog
box, click Generate Code to regenerate the output.
5. You can change looping behavior
12 and click Apply.
3-36
3 Inspect sfun_vec.c. It will look like this:
Exploring Variable Names and Loop Rolling
/* Model output function */
static void sfun_vec_output(int_T tid)
{
/* S-Function Block: <Root>/S-Function */
/* Multiply input by 3.0 */
sfun_vec_B.timesN_output[0] = sfun_vec_P.Constant_Value[0] * 3.0;
sfun_vec_B.timesN_output[1] = sfun_vec_P.Constant_Value[1] * 3.0;
sfun_vec_B.timesN_output[2] = sfun_vec_P.Constant_Value[2] * 3.0;
sfun_vec_B.timesN_output[3] = sfun_vec_P.Constant_Value[3] * 3.0;
sfun_vec_B.timesN_output[4] = sfun_vec_P.Constant_Value[4] * 3.0;
sfun_vec_B.timesN_output[5] = sfun_vec_P.Constant_Value[5] * 3.0;
sfun_vec_B.timesN_output[6] = sfun_vec_P.Constant_Value[6] * 3.0;
sfun_vec_B.timesN_output[7] = sfun_vec_P.Constant_Value[7] * 3.0;
sfun_vec_B.timesN_output[8] = sfun_vec_P.Constant_Value[8] * 3.0;
sfun_vec_B.timesN_output[9] = sfun_vec_P.Constant_Value[9] * 3.0;
/* Outport: '<Root>/Out' */
sfun_vec_Y.Out[0] = sfun_vec_B.timesN_output[0];
sfun_vec_Y.Out[1] = sfun_vec_B.timesN_output[1];
sfun_vec_Y.Out[2] = sfun_vec_B.timesN_output[2];
sfun_vec_Y.Out[3] = sfun_vec_B.timesN_output[3];
sfun_vec_Y.Out[4] = sfun_vec_B.timesN_output[4];
sfun_vec_Y.Out[5] = sfun_vec_B.timesN_output[5];
sfun_vec_Y.Out[6] = sfun_vec_B.timesN_output[6];
sfun_vec_Y.Out[7] = sfun_vec_B.timesN_output[7];
sfun_vec_Y.Out[8] = sfun_vec_B.timesN_output[8];
sfun_vec_Y.Out[9] = sfun_vec_B.timesN_output[9];
UNUSED_PARAMETER(tid);
}
4 To activate loop rolling again, change the RollThreshold to 10 (or less)
in the Optimization pane.
Loop rolling is an important TLC capability for optimizing generated code. Take some time to study and explore its implications before generating code for production requirements.

Learning More About TLC Loop Rolling

The following TLC %roll code is the Outputs function of timesN.tlc:
3-37
3 Target Language Compiler Tutorials
%function Outputs(block, system) Output
/* %<Type> Block: %<Name> */
%%
/* Multiply input by %<gain> */
%assign rollVars = ["U", "Y"]
%roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
%<LibBlockInputSignal(0, "", lcv, idx)> * %<gain>;
%endroll
%endfunction %% Outputs
Arguments for %roll
The lines between %roll and %endroll may be either repeated or looped. The key to understanding the
%roll sigIdx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
%<LibBlockOutputSignal(0, "", lcv, idx)> = \
%roll directive is in its arguments:
Argument
sigIdx
lcv
block
Description
Specify the appropriate index into a (signal) vector that is used in the generated code. If the signal is scalar, when analyzing that block of the
model.rtw file, TLC
determines that only a single line of code is required. In this case, it sets
sigIdx to 0 so as to access only the first
element o f a vector, and no loop is constructed.
A control variable generally specified in the %roll directive as lcv = RollThreshold. RollThreshold is a global (model-wide) threshold with the default value of 5. Therefore, whenever a block contains more than five contiguous and rollable variables, TLC collapses the lines neste d between
%roll and %endroll into a
loop. If fewer than five contiguous rollable variables exist,
%roll does not create a loop and i ns te ad produces
individual lines of code.
This tells TLC that it is operating on block objects. TLC code for S-function s use this ar gu ment.
3-38
Exploring Variable Names and Loop Rolling
Argument
"Roller"
Description
This, specified in rtw/c/tlc/roller.tlc,formats the loop. Normally you pass this as is, but other loop control constructs are possible for advanced uses (see
LibBlockInputSignal in Chapter 9, “TLC Function
Library Reference”.
rollVars
Tells TLC what types of items should be rolled: input signals, output signals, and/or parameters. It is not necessary to use all of them. In a previous line,
rollVars is defined using %assign.
%assign rollVars = ["U", "Y"]
This list tells TL C that it is rolling through input signals (
U) and output signals (Y). In cases where blocks specify
an array of parameters instead of a scalar parameter,
rollvars is specified as
%assign rollVars = ["U", "Y", "P"]
Input Signals, Output Signals, and Parameters
Look at the lines that appear between %roll and %endroll:
%<LibBlockOutputSignal(0, "", lcv, idx)> = \ %<LibBlockInputSignal (0, "", lcv, idx)> * 2.0;
The TLC library functions LibBlockInputSignal and LibBlockOutputSignal expandtoproducescalarorvectoridentifiers that are appropriately named and indexed. They and a number of related TLC functions are passed four canonical arguments:
3-39
3 Target Language Compiler Tutorials
Argument
Description
first argument — 0 Corresponds to the input port index
for a given block. The first input port has index 0. The second input port has index 1, and so on.
second argument — ""
An index variable reserved for advanced use. For now, specify the second argument as an empty string. In advanced applications, you may define your own variable name to be used as an index with
%roll.Insuch
a case, TLC declares this variable as an integer in an appropriate location in the generated code.
third argument — lcv
As described previously, lcv =
RollThreshold
is set in %roll to indicate that a loop be constructed whenever
RollThreshold (default
value of 5) is exceeded.
fourth argument — sigIdx Enables TLC to handle special cases.
In the event that the
RollThreshold
is not exce eded (for example, if the block is only connected to a scalar input signal) TLC does not roll it into a loop. Instead, TLC provides an integer value for the appropriate index variable in a corresponding line of “inline” code. Whenever the
RollThreshold is exceeded, TLC
creates a
for lo op and uses an index
variable to access inputs, outputs and parameters within the loop.
3-40
For details, see “%roll” on page 6-33 in the TLC Directives.

Debugging Your TLC Code

In this section...
tlcdebug Tutorial Overview” on page 3-41
“Getting Started” on page 3-42
“Generating and Running Code from the Model” on page 3-44
“Start the Debugger and Use its Commands” on page 3-45
“Debugging timesN.tlc”onpage3-47
“Fixing the Bug and Verifying the Fix” on page 3-48

tlcdebug Tutorial Overview

Objective: Intro duces the TLC debugger. You will learn how to set breakpoints and familiarize yourself with TLC debugger commands.
Debugging Your TLC Code
Directory:
tlctutorial/tlcdebug
You can cause the TLC debugger to be invoked whenever the Real-Time Workshop build process is invok ed . In this tutorial, you u s e it t o detect a bug in a
.tlc file for a model called simple_log. The bug causes the generated
code output from the standalone version of the model to differ from its simulation output. The tutorial guides you through following steps:
1 Getting Started — Run the model and inspect output
2 Generating and Running Code from the Model — Compare compiled
results to original output
rting the Debugger and Exploring Commands — Things you can
3 Sta
ith the debugger
do w
4 Debugging timesN.tlc — Find out what went wrong
5 Fixing the B ug and Verifying the Fix — Easy ways to fix bugs and
verify fixes
3-41
3 Target Language Compiler Tutorials

Getting Started

1 Make tlctutoria
the files provi
2 In the MATLAB Comm and Window, create a MEX-file for the S-function:
mex timesN.c
This is needed to avoid picking up the version shipped with your Simulink software.
Note An error might occur if you have not previously run mex -setup.For more information on MEX-files, see “MEX Programming” in the MATLAB Function Reference.
3 Open the model simple_log.mdl. The model looks like this.
l/tlcdebug
ded.
your current directory, so that you can use
3-42
Debugging Your TLC Code
4 In the Data Import/Export pane of the Configuration Parameters dialog
box, under Save to workspace,checkTime and Output.Thiscauses model variables to be logged to the MATLAB workspace.
5 Run the model by selecting Start from the Simulation menu. Variables
tout and yout appear in your MATLAB workspace.
6 Double-click yout in th e Workspace pane of the MATLAB Command
Window. The Variable Editor displays the 6x1 array output from
simple_log. T he display looks like this:
Column 1 contains discrete pulse output for six time steps (3s and 0s), collected at port
Next, you generate a standalone version of
out1.
simple_log.mdl. You execute it
and com pare its results to the output from Simulink displayed above.
Note For the purpose of this exercise, the TLC file provided, timesN.tlc, contains a bug. This version must be in the same directory as the model that uses it.
3-43
3 Target Language Compiler Tutorials

Generating and Running Code from the Model

1 In the Real-Time Workshop pane of the Configuration Parameters dialog
box, click Build (or type Ctrl+B).
The code generator produces, compiles, and links C source code. The MATLAB Command Window shows the progress of the build, which ends with these messages:
### Created executable: simple_log.exe ### Successful completion of Real-Time Workshop build procedure
2 Run the standalone model just created by typing
!simple_log
This results in the messages
** starting the model ** ** created simple_log.mat **
for model: simple_log
3-44
3 Inspect results by placing the variables in you
Directory pane, double-click
simple_log.mat
(the standalone version of variable yout)inth
Compare surmise what caused values in
rt_yout with yout.Doyounoticeanydifferences? Can you
rt_yout to change?
rworkspace. IntheCurrent
,thendouble-clickrt_yout
e Workspace pane.
A look at the generated C code that TLC placed in your build directory (
simple_log_grt_rtw) helps to identify the problem.
uts
4 Edit simple_log.c and look at its MdlOutp
function, which should
appear as shown below :
/* Model output function */
static void simple_log_output(int_T tid)
{
/* DiscretePulseGenerator: '<Root>/Discrete Pulse Generator' */
simple_log_B.DiscretePulseGenerator = ((real_T)
simple_log_DWork.clockTickCounter < 1.0) &&
(simple_log_DWork.clockTickCounter >= 0) ? 1.0 : 0.0;
Debugging Your TLC Code
if ((real_T)simple_log_DWork.clockTickCounter >= 2.0 - 1.0) {
simple_log_DWork.clockTickCounter = 0;
}else{
simple_log_DWork.clockTickCounter = simple_log_DWork.clockTickCounter + 1;
}
/* S-Function Block: <Root>/Gain1st */
/* Multiply input by 3.0 */
simple_log_B.first_output = simple_log_B.DiscretePulseGenerator * 1;
/* Outport: '<Root>/Out1' */
simple_log_Y.Out1 = simple_log_B.first_output;
UNUSED_PARAMETER(tid);
}
Notethelineneartheend:
simple_log_B.first_output = simple_log_B.DiscretePulseGenerator * 1;
How did a constant value get passed to the output when it was supposed to receive a variable that alternates between 3.0 and 0.0? Use the debugger to find out.

Start the Debugger and Use its Commands

You use the TLC debugger to monitor the code generation process. As it is not invoked by default, you need to request the debugger explicitly.
1 Set up the TLC debugging environment and start to build the application:
a Select the Real-Time Workshop > Debug pane, and check Retain
.rtw file and Start TLC debugger when generating code.Click Apply.
b Click Build on the Real-Time Workshop pane.
The MATLAB Command Window describes the building process. The build stops at the
TLC-DEBUG>
timesN.tlc file and displays the command prompt:
3-45
3 Target Language Compiler Tutorials
2 Type help to list the TLC debugger commands. Here are some things you
can do in the debugger.
View and query various entities in the TLC scope.
Examine the statements in your current context.
Move to the next line of code.
Step into a function.
TLC-DEBUG> whos CompiledModel TLC-DEBUG> print CompiledModel.NumSystems TLC-DEBUG> print TYPE(CompiledModel.NumSystems)
TLC-DEBUG> list TLC-DEBUG> list 10,40
TLC-DEBUG> next
TLC-DEBUG> step
3-46
Assign a constant value to a variable, such as the input signal %<u>.
TLC-DEBUG> assign u = 5.0
Set a breakpoint where you are or in some other part of the code.
TLC-DEBUG> break timesN.tlc:10
Execute until the next breakpoint.
TLC-DEBUG> continue
Clear breakpoints you have established.
TLC-DEBUG> clear 1 TLC-DEBUG> clear all
3 IfyouhavetriedtheTLCdebuggercommands, execute the remaining code
to finish the build process, then build the
timesN.tlc file and displays the command prompt:
TLC-DEBUG>
simple_log again. The build stops at
Loading...