Main Content

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(...)

Note

Functions declared inside a system file are global; functions declared inside a block file are local.

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 constant.tlc.

d.

For consistency, use the variables sysIdx and blkIdx for system index and block index, respectively.

e.

Use the variable rollVars when using the %roll construct.

f.

When naming loop control variables, use sigIdx and lcv when looping over RollRegions and xidx and xlcv when looping over the states.

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)>;

Related Topics