TLC Coding Conventions
These guidelines can help you apply programming style in each target file consistently.
Begin Identifiers with Uppercase Letters
Identifiers in the file begin with an uppercase letter. For example,
NumModelInputs 1 NumModelOutputs 2 NumNonVirtBlocksInModel 42 DirectFeedthrough yes NumContStates 10
Because a Name
identifier may be promoted into the parent scope,
block records that contain a Name
identifier should start the name with
an uppercase letter. For example, a block might contain
Block { : : RWork [4, 0] : NumRWorkDefines 4 RWorkDefine { Name "TimeStampA" Width 1 StartIndex 0 } }
Because the Name
identifier within the RWorkDefine
record is promoted to PrevT
in its parent scope, it must start with an
uppercase letter. The promotion of the Name
identifier into the parent
block scope is currently done for the Parameter
,
RWorkDefine
, IWorkDefine
, and
PWorkDefine
block records.
The Target Language Compiler assignment directive (%assign
) generates a warning if you assign a value to an
“unqualified” code generator identifier. For example,
%assign TID = 1
produces an error because the TID
identifier is not qualified by
Block
. However, a “qualified” assignment does not
generate a warning. For example,
%assign Block.TID = 1
does not generate a warning because the assignment contains a qualifier. The Target Language Compiler therefore assumes that the programmer is intentionally modifying an identifier.
Begin Global Variable Assignments with Uppercase Letters
Global TLC variable assignments should start with uppercase letters. A global variable is a
variable declared in a system target file (grt.tlc
,
mdlwide.tlc
, mdlhdr.tlc
,
mdlbody.tlc
, mdlreg.tlc
, or
mdlparam.tlc
), or within a function that uses the
operator. Global assignments have the same scope as code generator variables. An
example of a global TLC variable defined in mdlwide.tlc
is
%assign InlineParameters = 1
An example of a global reference in a function is
%function foo() void %assign ::GlobalIdx = ::GlobalIdx + 1 %endfunction
Begin Local Variable Assignments with Lowercase Letters
Local TLC variable assignments should start with lowercase letters. A local TLC variable is a variable assigned inside a function. For example,
%assign numBlockStates = ContStates[0]
Begin Functions Declared in block.tlc Files with Fcn
When you declare a function inside a block.tlc
file, it should start
with Fcn
. For example,
%function FcnMyBlockFunc(...)
Do Not Hard-Code Variables Defined in commonsetup.tlc
Because the code generator tracks use of variables and generates code based on usage, you should use access routines instead of directly using a variable. For example, you should not use the following in your TLC file:
x = %<tInf>;
You should use
x = %<LibRealNonFinite(inf)>;
Similarly, instead of using %<tTID>
, use
%<LibTID()>
. For a complete list of functions, see TLC Function
Library Reference in Target Language Compiler.
Simulink®
Coder™ global variables start with rt
and Simulink
Coder global functions start with
rt_
.
Avoid naming global variables in modules that start with rt
or
rt_
because they might conflict with Simulink
Coder global variables and functions. These TLC variables are declared in commonsetup.tlc
.
This convention creates consistent variables throughout the target files. For example,
the Gain block contains the following Outputs
function.
Notes about this TLC code
a. | The code section for each block begins with a comment specifying the block type and name. |
b. | Include a blank line immediately after the end of the function to create consistent spacing between blocks in the output code. |
c. | Try to stay within 80 columns per line for the function banner. You
might set up an 80 column comment line at the top of each function. As an
example, see |
d. | For consistency, use the variables |
e. | Use the variable |
f. | When naming loop control variables, use |
Example: Output
function in gain.tlc
%roll sigIdx = RollRegions, lcv = RollThreshold, ... block, "Roller", rollVars
Example: InitializeConditions
function in linblock.tlc
%roll xidx = [0:nStates-1], xlcv = RollThreshold,... block, "Roller", rollVars
Conditional Inclusion in Library Files
The Target Language Compiler function library files are conditionally included with guard code so you can reference
them multiple times using %include
without worrying if they have
previously been included. Follow this practice for TLC library files that you create.
The convention is to use a variable with the same name as the base filename, uppercase
and with underscores attached at both ends. So, a file named
customlib.tlc
should have the variable _CUSTOMLIB_
guarding it.
As an example, the main Target Language Compiler function library,
funclib.tlc
, contains this TLC code to prevent multiple
inclusion:
%if EXISTS("_FUNCLIB_") == 0 %assign _FUNCLIB_ = 1 . . . %endif %% _FUNCLIB_
Code Defensively
As the code your TLC generates could be used in referenced models in unpredictable
contexts, do not assume too much about name spaces. For example, when writing TLC code for a
block and adding a typedef
, guard it with if/def
, as
the following example illustrates:
%openfile tmpBuff #ifndef RESOLUTION_TYPEDEF typedef enum { LO_RES, HI_RES } Resolution; typedef struct { Resolution res; int8_T value; } Data; #define RESOLUTION_TYPEDEF #endif /* RESOLUTION_TYPEDEF */ %closefile tmpBuff %<LibCacheTypedefs(tmpBuff)>;