Target Language Compiler Quick Reference Help Desk

Code Architecture:

Sample of the generated code for a model with a sine, gain, and outport. Each block places code into Mdl routines. Here we show MdlOutputs:


Blocks have inputs, outputs, parameters, states, plus other general properties. For example, block inputs and outputs are generally written to a block I/O structure (rtB). Block inputs can also come from the external input structure (rtU) or the state structure when connected to a state port of an integrator (rtX), or ground (rtGround) if unconnected or grounded. Block outputs can also go to the external output structure (rtY). The following picture shows the general block data mappings:


The model.rtw file and scopes:

TLC variables can be scalars, strings, vectors, matrices, and records. The model.rtw file is an ASCII file containing parameter-value pairs stored in a hierarchy of records defined by your model. In TLC, identifiers refer to parameters. Each record creates a new "scope". The format of model.rtw is:

Within TLC, to access parameter values of TLC variables, you need to specify a valid path to the parameter. Multiple records of the same name form a list where the index of the first record starts at 0. For example to access the above S-function block record, you would use
   CompiledModel.System[0].Block[0]
To access the name field of this block, you would use:
   CompiledModel.System[0].Block[0].Name

It is also possible to "scope" a given record. This is done via the %with directive. When inlining S-function blocks, your S-function Block record is scoped. In an inlined .tlc file, you should access fields without a fully qualified path. For example, to access the name of your block, you would use: Name. This accesses CompiledModel.System[i].Block[j].Name, since CompiledModel.
System[i].Block[j]
is currently scoped.

TLC Directives 
%% text

Single line comment where text is the comment.

/% text %/

Single (or multi-line) comment where text is the comment.

%<expr>

Target language expressions which are evaluated. For example if we have a TLC variable which was created via: %assign varName = "foo", then
%<varName> would expand to foo. Expressions can also be function calls as in %<FcnName(param1,param2)>. On directive lines, TLC expressions do not need to be placed within the %<> syntax. Doing so will cause a double evaluation. For example, %if %<x> == 3 is processed by creating a hidden variable for the evaluated value of the variable x. The %if statement then evaluates this hidden variable and compares it against 3. The efficient way to do this operation is to do: %if x == 3. In Matlab notation, this would equate to doing if eval('x') == 3 as opposed to if x = 3. The exception to this is during a %assign for format control as in:
  %assign str = "value is: %<var>"

%if expr
%elseif expr
%else
%endif

Conditional inclusion, where the constant-expression expr must evaluate to an integer. It is not necessary to expand variables or expressions using the %<expr> notation. Expanding the expression may be necessary when the expression needs to be re-evaluated. For example, assume k represents the value of a the gain block parameter which may be a number or a string variable. The following code will check if k is the numeric value 0.0 by executing a TLC library function to check for equality. Notice that the %<expr> syntax isn't used since we are operating on a directive line. Unlike other languages, expression evaluation do not short circuit.

%if LibIsEqual(k, 0.0)
  <text and directives to be processed if, k is 0.0>
%endif

%switch expr
  %case expr
  %break
  %default
  %break
%endswitch

Conditional inclusion which works very similar to the C Language switch statement. The expression, expr, can be of any type. If the %break is not included after a %case statement, then it will fall through to the next statement.

%with
%endwith

model.rtw is organized as a hierarchy of records. The   
  %with
recordName
  %endwith
directives let you make a given record the current scope.

%setcommandswitch

Used to change the value of a command-line switch as in
  %setcommandswitch "-v1"

%error
%warning
%trace
%exit

Flow control directives:
%error tokens -- The tokens are expanded and displayed.

%warning tokens -- The tokens are expanded and displayed.

%trace tokens -- The tokens are expanded and displayed only when the command line option -v[1|2|3] is specifed.

%exit tokens -- The tokens are expanded, displayed, and TLC exits.

Note, when reporting errors, you should use:
  %exit Error Message
if the error is produced by an incorrect configuration that the user needs to correct in their model. If you are adding assert code (i.e., code that should never be reached), use:
  %setcommandswitch "-v1" %% force TLC stack trace
  %exit Assert message

%assign

This is used to create identifiers (variables). The general form is:
  %assign [::]variable = expression

The :: specifies that the variable being created is a global variable, otherwise it is a local variable in the current scope (i.e. a local variable in the function).
If you need to format the variable, say, within a string based upon other TLC variables, then you should perform a double evaluation as in:
  %assign nameInfo = "The name of this is %<Name>"
or alternately (faster execution):
  %assign nameInfo = "The name of this is " + Name
To create a record, use:
  %assign tempVar = Rec2 {Name "Name1"; Type "t1"}
this creates tempVar which is a record called Rec2 with fields Name and Type. To add Rec2 to Rec1 (an existing record), use: %assign Rec1 = Rec1 + tempVar

%define

Macro definition used to simplify complicated references:
  %define ident opt-arg-list replacement-list
As in C++, usage of %define is not recommended (see %assign or %function)

%undef ident

This can be used to "remove" a TLC variable, ident, which was created via %assign%define, or loaded from the model.rtw file. Care should be taken when using this directive within inlined S-functions -- make sure you are removing a local variable. By convention, local variables start with a lower case letter. Global (and model.rtw) variables start with an upper case letter.

%realformat

Specifies how to format real variables. To format in exponential notation with 16 digits of precision, use:
  %realformat "EXPONENTIAL"
To format without loss of precision and minimal number of characters, use
  %realformat "CONCISE"
When inlining S-functions, the format is set to concise. You can switch to exponential, but should switch it back to concise when done.

%language

This must appear before the first GENERATE or GENERATE_TYPE function call. This specifies the name of the language as a string which is being generated as in %language "C". Generally, this is added to your system target file.

%implements

Placed within the .tlc file for a specific record type, when mapped via
%generatefile. The syntax is: %implements "Type" "Language". When inlining an S-function in C, this should be the first non-comment line in the file as in:
  %implements "s_function_name" "C"
The next non-comment lines will be %function directives specifying the functionality of the S-function.

%generatefile

Provides a mapping between a record Type and functions contained in a file. Each record can have functions of the same name, but different contents mapped to it (i.e. polymorphism). Generally, this is used to map a Block record Type to the .tlc file which implements the functionality of the block as in:
  %generatefile "Sin" "sin_wave.tlc"

%include
%addincludepath

%include "file.tlc" - insert specified target file at the current point. Use
%addincludepath "directory" to add additional paths to be searched. Be sure to escape backslashes in PC directory names as in "C:\\mytlc".

%roll
%endroll

Multiple inclusion plus intrinsic loop rolling based upon a specified threshold. This directive can be used by most Simulink blocks which have the concept of an overall block width which is usually the width of the signal passing through the block. An example of the %roll directive is (for y = u * k):

    %function Outputs(block, system) Output
      /* %<Type> Block: %<Name> */
      %assign rollVars = ["U", "Y", "P"]
      %roll sigIdx = RollRegions, lcv = RollThreshold, block,...
            "Roller", rollVars
        %assign y = LibBlockOutputSignal(0, "", lcv, sigIdx)
        %assign u = LibBlockInputSignal(0, "", lcv, sigIdx)
        %assign k = LibBlockParameter(Gain, "", lcv, sigIdx)
          %<y> = %<u> * %<k>;
      %endroll
    %endfunction
    
    
The %roll directive is similar to %foreach, except that it iterates the identifier (here it is called sigIdx) over roll regions. Roll regions are computed by looking at the input signals and generating regions where the inputs are contiguous. For blocks, the variable RollRegions is automatically computed and placed in the Block record. An example of a roll regions vector is [0:19, 20:39] where we have two contiguous ranges of signals passing through the block. The first is 0:19 and the second is 20:39. Each roll region is either placed in a loop body (e.g. the C Language for statement) or inlined depending upon whether or not the length of the region is less than the roll threshold.

Each time through the %roll loop, sigIdx will be an integer for the start of the current roll region or an offset relative to the overall block width when the current roll region is less than the roll threshold. The TLC global variable
RollThreshold is the general model wide value used to decide when to place a given roll region into a loop. When the decision is made to place a given region into a loop, the loop control variable will be a valid identifier (e.g. "i"), otherwise it will be "".

The block parameter is the current block which is being rolled. The "Roller" parameter specifies the name for an internal GENERATE_TYPE calls made by %roll. The default %roll handler is, "Roller", which is responsible for setting up the default block loop rolling structures (e.g. a C for loop).

%roll
(continued)

The rollVars (roll variables) are passed to "Roller" functions so that they can create the correct roll structures. The defined loop variables relative to a block are:

"U" All inputs to the block. It is assumed that you will be using
LibBlockInputSignal(portIdx, "", lcv, sigIdx) to access each input, where portIdx starts at 0 for the first input port.

"Ui" Similar to "U", except only for specific input, i.

"Y" All outputs of the block. It is assumed that you will be using
LibBlockOutputSignal(portIdx, "", lcv, sigIdx) to access each output, where portIdx starts at 0 for the first output port.

"Yi"Similar to "Y", except only for specific output, i.

"P" All parameters of the block. It is assumed that you will be using
LibBlockParameter(name, "", lcv, sigIdx) to access them.

"<param>/name" Similar to P, except specific for a specific name.

RWorkAll RWork vectors of the block. It is assumed that you will be using
LibBlockRWork(name, "", lcv, sigIdx) to access them.

"<RWork>/name" Similar to RWork, except for a specific name.

IWorkAll IWork vectors of the block. It is assumed that you will be using
LibBlockIWork(name, "", lcv, sigIdx) to access them.

"<IWork>/name" Similar to IWork, except for a specific name.

PWorkAll PWork vectors of the block. It is assumed that you will be using
LibBlockPWork(name, "", lcv, sigIdx) to access them.

"<PWork>/name" Similar to PWork, except for a specific name.

"Mode"The mode vector. It is assumed that you will be using
LibBlockMode("",lcv,sigIdx) to access it.

"PZC" Previous zero crossing state. It is assumed that you will be using LibPrevZCState("",lcv, sigIdx) to access it.

To roll your own vector based upon the block's roll regions you need to walk a pointer to your vector. Assuming your vector is pointed to by the first PWork, called name,

    datatype *buf = (datatype*)%<LibBlockPWork(name,"","",0)
    %roll sigIdx = RollRegions, lcv = RollThreshold, block, ...
          "Roller", rollVars
      *buf++ = whatever;
    %endroll
    
%function
%return
%endfunction












A function which returns a value is defined as:
  %function name(optional-arguments)
    %return
value
  %endfunction

A void function does not produce any output and has no return value:
  %function name(optional-arguments) void
  %endfunction

A function which produces outputs to the current stream and has no return value is defined as:
  %function name(optional-arguments) Output
  %endfunction

For block target files, the you can add to your inlined .tlc file the following functions which will get called by the model wide target files during code generation:
%function BlockInstanceSetup(block, system) void
This is called for each instance of the block with in the model.

%function BlockTypeSetup(block, system) void
This is called once for each block type that exists in the model.

%function BlockInstanceData(block, system) Output
This is called once during model initialization to place code in the registration function (model.reg) to allocate persistent data.

%function Enable(block, system) Output
Use this if the block is placed within an enabled subsystem and it has to take specific actions when the subsystem enables. This code is placed within a subsystem enable routine.

%function Disable(block, system) Output
Use this if the block is placed within a disabled subsystem and it has to take specific actions when the subsystem is disabled. This code is placed within a subsystem disable routine.

%function Start(block, system) Output
Include this function if your block has startup initialization code which needs to be placed within MdlStart.

%function InitializeConditions(block, system) Output
Use this function if your block has state which needs to be initialized at the start of execution and when an enabled subsystem resets states. This code is placed in MdlStart and/or subsystem initialization routines.

(continued)
%function
%return
%endfunction

%function Outputs(block, system) Output
This is the primary function of your block. This code is placed in MdlOutputs.

%function Update(block, system) Output
Use this if your block has actions to be performed once per simulation loop, such as updating discrete states. This code is placed in MdlUpdate

%function Derivatives(block,system) Output
Used this if your block has derivatives for MdlDerivatives.

%function Terminate(block, system) Output
Use this if your block has actions that need to be in MdlTerminate.

%foreach
%endforeach

Multiple inclusion which iterates from 0 to the upperLimit-1 constant integer expression. Each time through the loop, the loopIdentifier, (e.g. x) is assigned the current iteration value.
  %foreach loopIdentifier = upperLimit
     %break    
-- use this to exit the loop
     %continue -- use this to skip the following code and continue
                 to the next iteration
  %endforeach

%openfile
%selectfile
%closefile

These are used to manage the files which are created. The syntax is:

    %openfile streamId="filename.ext" mode     {open for writing}
    %selectfile streamId                       {select an open file}
    %closefile streamId                        {close an open file}
    
Note that the "filename.ext" is optional. If not specified, streamId and file name will be the same and a variable (string buffer) is created containing the output. The mode argument is optional. If specified it can be "a" for appending, "r" for reading, or "w" for writing. NULL_FILE is a special streamId which specifies that no output occur.

To create a buffer of text, use:

    %openfile buffer
    text to be placed in the `buffer' variable.
    %closefile buffer
    
Now buffer contains the expanded text specified between the %openfile and %closefile directives.

TLC Reserved Constants

For double precision values, we define the following for infinite and not-a-number IEEE values:

   rtInf, inf, rtMinusInf, -inf, rtNaN, nan

and their corresponding version when complex:

   rtInfi, infi, rtMinusInfi, -infi, rtNaNi

For integer values, we define the following:

   INT8MIN, INT8MAX, INT16MIN, INT16MAX, INT32MIN, INT32MAX,

   UINT8MAX, UINT16MAX, UINT32MAX

TLC Values

Variables (identifiers) within TLC can be of the following value type

TLC Values
Value Type String
Example
Description
"Boolean"
1==1
Result of a comparison or other Boolean operator. Note: There are no Boolean constants, and Boolean values are 1 or 0 as in C. 1 is still a number and not a Boolean value.
"Complex"
3.0+5.0i
A 64-bit double-precision complex number.
"Complex32"
3.0F+5.0Fi
A 32-bit single-precision complex number.
"File"
%openfile x
String buffer opened with %openfile.
"File"
%openfile x = "out.c"
File opened with %openfile.
"Function"
%function foo
A user-defined function.
"Gaussian"
3+5i
A 32-bit integer imaginary number.
"Identifier"
abc
Identifier values can only appear within the model.rtw file and cannot appear in expressions (within the context of an expression, identifiers are interpreted as values). To compare against an identifier value, use a string; the identifier will be converted as appropriate to a string.
"Macro"
%define MACRO
A user-defined macro.
"Matrix"
Matrix (3,2) [[1, 2] [3, 4] [5, 6]]
Matrices are simply lists of vectors. The individual elements of the matrix do not need to be the same type, and can be any type except vectors or matrices. The Matrix (3,2) text in the example is optional.
"Number"
15
An integer number.
"Range"
[1:5]
A range of integers between 1 and 5, inclusive.
"Real"
3.14159
A floating-point number (including exponential notation).
"Real32"
3.14159F
A 32-bit single-precision floating-point number.
"Scope"
Block {}
A block record.
"Special"
N/A
A special built-in function, such as FILE_EXISTS.
"String"
"Hello, World"
ASCII character strings. In all contexts, two strings in a row are concatenated to form the final value, as in
"Hello, " "World", which is combined to form
"Hello, World". These strings include all of the ANSI C standard escape sequences such as \n, \r, \t, etc.
"Subsystem"
<sub1>
A subsystem identifier. Within the context of an expansion, be careful to escape the delimiters on a subsystem identifier as in:
%<x == <sub\>>.
"Unsigned"
15U
A 32-bit unsigned integer.
"Unsigned
Gaussian"

3U+5Ui
A 32-bit complex unsigned integer.
"Vector"
[1, 2] or
Vector(2) [1, 2]

Vectors are lists of values. The individual elements of a vector do not need to be the same type, and may be any type except vectors or matrices.

Variables (identifiers) can take on the following constant values. Note the suffix on the value one:

Constant Form
TLC Type
1.0
"Real"
1.0[F/f]
"Real32"
1
"Number"
1[U|u]
"Unsigned"
1.0i
"Complex"
1[Ui|ui]
"UnsignedGaussian"
1i
"Gaussian"
1.0[Fi|fi]
"Complex32"

TLC Expressions

In any place throughout a target file, you can include an expression of the form %<expression>. TLC replaces %<expression> with a calculated replacement value based upon the type of the variables within the %<> operator. Integer constant expressions are folded and replaced with the resultant value; string constants are concatenated (e.g., two strings in a row "a" "b" are replaced with "ab"). Note, on directive lines it is not necessary to place the expression in the %< > format. Doing so causes a double evaluation.

Within the context of an expression, each identifier must evaluate to a identifier or function argument currently in scope. You can use the %< > directive on any line to perform textual substitution. To include the > character within a replacement, you must escape it with a "\" character as in:
  %<x \> 1 ? "ABC" : "123">

In the following table, expressions are listed in order from highest to lowest precedence. The horizontal lines distinguish the order of operations.

As opposed to C expressions, conditional operators are not short-circuited. Therefore, if the expression includes a function call with side effects, the effects are noticed as if the entire expression were evaluated. In the following table, numeric refers to one of Boolean, Number, Unsigned, Real, Real32, Complex, Complex32, Gaussian, or UnsignedGaussian. Also, integral refers to one of Number, Unsigned, or Boolean.

TLC Expressions 
Expression
Definition
constant
Any constant parameter value, including vectors and matrices.
variable-name
Any valid in-scope variable name, including the local function scope, if any, and the global scope.
::variable-name
Used within a function to indicate that the function scope is ignored when looking up the variable. This accesses the global scope.
expr[expr]
Index into an array parameter. Array indices range from 0 to N-1. This syntax is used to index into vectors, matrices, and repeated scope variables.
expr([expr[,expr]])
Function call or macro expansion. The expression outside of the parentheses is the function/macro name; the expressions inside are the arguments to the function or macro. Note: Since macros are text-based, they cannot be used within the same expression as other operators.
expr.expr
The first expression must have a valid scope; the second expression is a parameter name within that scope.
(expr)
Use () to override the precedence of operations.
!expr
Logical negation (always generates 1 or 0 as in C). The argument must be numeric or Boolean.
-expr
Unary minus negates the expression. The argument must be numeric.
+expr
No effect; the operand must be numeric.
~expr
Bitwise negation of the operand. The argument must be integral.
expr * expr
Multiply the two expressions together; the operands must be numeric.
expr / expr
Divide the two expressions; the operands must be numeric.
expr % expr
Take the integer modulo of the expressions; the operands must be integral.
expr + expr
Works on numeric types, strings, vectors, matrices, and records as follows:
Numeric Types - Add the two expressions together; the operands must be numeric.
Strings - The strings are concatenated.
Vectors - If the first argument is a vector and the second is a scalar, it appends the scalar to the vector.
Matrices - If the first argument is a matrix and the second is a vector of the same column-width as the matrix, it appends the vector as another row in the matrix.
Records - If the first argument is a record, it adds the second argument as a parameter identifier (with its current value).
Note, the addition operator is associative.
expr - expr
Subtracts the two expressions; the operands must be numeric.
expr << expr
Left shifts the left operand by an amount equal to the right operand; the arguments must be integral.
expr >> expr
Right shifts the left operand by an amount equal to the right operand; the arguments must be integral.
expr > expr
Tests if the first expression is greater than the second expression; the arguments must be numeric.
expr < expr
Tests if the first expression is less than the second expression; the arguments must be numeric.
expr >= expr
Tests if the first expression is greater than or equal to the second expression; the arguments must be numeric.
expr <= expr
Tests if the first expression is less than or equal to the second expression; the arguments must be numeric.
expr == expr
Tests if the two expressions are equal.
expr != expr
Tests if the two expressions are not equal.
expr & expr
Performs the bitwise AND of the two arguments; the arguments must be integral.
expr ^ expr
Performs the bitwise XOR of the two arguments; the arguments must be integral.
expr | expr
Performs the bitwise OR of the two arguments; the arguments must be integral.
expr && expr
Performs the logical AND of the two arguments and returns 1 or 0. This can be used on either numeric or Boolean arguments.
expr || expr
Performs the logical OR of the two arguments and returns 1 or 0. This can be used on either numeric or Boolean arguments.
expr ? expr : expr
Tests the first expression for logical truth. If true, the first expression is returned; otherwise the second expression is returned.
Note: Both are evaluated.
expr , expr
Returns the value of the second expression.

TLC Data Promotions

When the Target Language Compiler operates on mixed types of expressions, it promotes the result to the common types indicated in the following table, where the notation is (B) for Boolean, (N) for Number, (U) for Unsigned, (F) for Real32, (D) for Real, (G) for Gaussian, (UG) for UnsignedGaussian, (C32) for Complex32, and (C) for Complex.

The top row (in bold) and first column (in bold) show the types of expression used in the operation. The intersection of the row and column shows the resulting type of expression.

For example, if the operation involves a Boolean expression (B) and an unsigned expression (U), the result will be an unsigned expression (U).

Usual Promotions

B
N
U
F
D
G
UG
C32
C
B
B
N
U
F
D
G
UG
C32
C
N
N
N
U
F
D
G
UG
C32
C
U
U
U
U
F
D
UG
UG
C32
C
F
F
F
F
F
D
C32
C32
C32
C
D
D
D
D
D
D
C
C
C
C
G
G
G
UG
C32
C
G
UG
C32
C
UG
UG
UG
UG
C32
C
UG
UG
C32
C
C32
C32
C32
C32
C32
C
C32
C32
C32
C
C
C
C
C
C
C
C
C
C
C

Built-In Functions and Values

The following table lists the built-in functions and values that are added to the list of parameters that appear in the model.rtw file. These TLC functions and values are defined in uppercase so that they are visually distinct from other parameters in the model.rtw file, and by convention, from user-defined parameters.

TLC Built-in Functions and Values 
Special Macro Name
Description
CAST(expr, expr)
The first expression must be a string that corresponds to one of the type names in the TLC Values table, and the second expression will be cast to that type. A typical use might be to cast a variable to a real format as in:
  CAST("Real", variable-name)
An example of this is in working with parameter values for S-functions. To use them within C code, you need to typecast them to real so that a value such as "1" will be formatted as "1.0" (see also %realformat)
EXISTS(expr)
expr must be a string. If the identifier is not currently in scope, the result is 0. If the identifier is in scope, the result is 1. expr can be a single identifier or an expression involving the . and [] operators.
FEVAL(matlab-command, TLC-expr)
Performs an evaluation in MATLAB. For example
  %assign result = FEVAL("sin",3.14159)
The %matlab directive can be used to call a MATLAB function which does not return a results. For example:
  %matlab disp(2.718)
FILE_EXISTS(expr)
expr must be a string. If a file by the name expr does not exist on the path, the result is 0. If a file by that name exists on the path, the result is 1.
FORMAT(realvalue, format)
The first expression is a Real value to format. The second expression is either "EXPONENTIAL" or "CONCISE". Outputs the Real value in the designated format where "EXPONENTIAL" uses exponential notation with 16 digits of precision, and "CONCISE" outputs the number in a more readable format while maintaining numerical accuracy.
GENERATE(record, function-name,
   ...)
This is used to execute function calls mapped to a specific record type (i.e. Block record functions). For example, this is used to execute the functions in the .tlc files for built-in blocks. Note, TLC automatically "scopes" or adds the first argument to the list of scopes search as if it appears on a %with directive line.
GENERATE_FILENAME(type)
For the specified record type, does a .tlc file exist? This is used to see if the GENERATE_TYPE call will succeed.
GENERATE_FUNCTION_EXISTS
   (record, function-name)

Determines if a given block function exists. The first expression is the same as the first argument to GENERATE, namely a block scoped variable containing a Type. The second expression is a string that should match the function name.
GENERATE_TYPE
   (record, function-name,    type, ...)

Similar to GENERATE, except "type" overrides the Type field of the record. This is used when executing functions mapped to specific S-function blocks records based upon the S-function name (i.e. name becomes type).
GENERATE_TYPE_FUNCTION_EXISTS
   (record, function-name,    type)

Same as GENERATE_FUNCTION_EXISTS except it overrides the Type built into the record.
GET_COMMAND_SWITCH
Returns the value of command-line switches.
IDNUM(expr)
expr must be a string. The result is a vector where the first element is a leading string (if any) and the second element is a number appearing at the end of the input string. For example:
   IDNUM("ABC123") yields ["ABC", 123]
IMAG(expr)
Returns the imaginary part of a complex number.
INT8MAX
127
INT8MIN
-128
INT16MAX
32767
INT16MIN
-32768
INT32MAX
2147483647
INT32MIN
-2147483648
ISINF(expr)
Returns 1 if the value of the expression is inf.
ISNAN(expr)
Returns 1 if the value of the expression is NAN.
ISFINITE(expr)
Returns 1 if the value of the expression is not +/- inf or NAN.
NULL_FILE
A predefined file for no output that you can use as an argument to %selectfile to prevent output.
NUMTLCFILES
The number of target files used thus far in expansion.
OUTPUT_LINES(expr)
Accepts a file variable as input and returns the number of lines that have been written to the given file or buffer.
REAL(expr)
Returns the real part of a complex number.
ROLL_ITERATIONS()
Returns the number of times the current roll regions are looping or NULL if not inside a %roll construct.
SIZE(expr[,expr])
Calculates the size of the first expression and generates a two-element, row vector. If the second operand is specified, it is used as an integral index into this row vector; otherwise the entire row vector is returned. SIZE(x) applied to any scalar returns [1 1]. SIZE(x) applied to any scope returns the number of repeated entries of that scope type (e.g., SIZE(Block) returns
[1,<number of blocks>].
STDOUT
A predefined file for stdout output. You can use as an argument to %selectfile to force output to stdout.
STRING(expr)
Expands the expression into a string; the characters \, \n, and " are escaped by preceding them with \ (backslash). All the ANSI escape sequences are translated into string form.
STRINGOF(expr)
Accepts a vector of ASCII values and returns a string that is constructed by treating each element as the ASCII code for a single character. Used primarily for S-function string parameters in RTW.
SYSNAME(expr)
Looks for specially formatted strings of the form <x>/y and returns x and y as a 2-element string vector. This is used to resolve subsystem names in RTW. For example:
  %<sysname("<sub>/Gain")>
returns
  ["sub","Gain"]
In Block records, the Name of the block is written similar to <sys/blockname> where sys is S# or Root. You can obtain the full path name by calling LibGetBlockPath(block), this will include newlines and other troublesome characters which cause display difficulties. To obtain a full path name suitable for one line comments, but not identical to the Simulink path name, use LibGetFormattedBlockPath(block).
TLCFILES
Returns a vector containing the names of all the target files included thus far in the expansion. Also, see NUMTLCFILES.
TLC_TIME
The date and time of compilation.
TLC_VERSION
The version and date of the Target Language Compiler.
TYPE(expr)
Evaluates expr and determines the result type. The result of this function is a string that corresponds to the type of the given expression. See value type string in the Target Language Values table for possible values.
UINT8MAX
255U
UINT8MIN
65535U
UINT32MAX
4294967295U
WHITE_SPACE(expr)
Accepts a string and returns 1 if the string contains only whitespace characters ( \t\h\r\n) and 0 otherwise.
WILL_ROLL(expr1, expr2)
The first expression is a roll vector and the second expression is a roll threshold. This function returns true if the vector contains a range that will roll.

Commonly used functions in the TLC Function Library

The file funclib.tlc contains the RTW TLC function library. This file contains the necessary TLC functions required to write a block target file. In this section we give a description of the more common functions. The following table describes arguments to these functions.:

portIdx
Refers to an input or output port index, starting at zero, for example the first input port of an S-function is 0.
ucv
User control variable. This is an advanced feature and overrides the lcv and sigIdx parameters. When used within inlined S-function, it should generally be specified as "".
lcv
Loop control variable. This is generally generated by the %roll directive via the second %roll argument (e.g. lcv=RollThreshold) and should be passed directly to the library function. It will contain either "", indicating that the current pass through the %roll is being inlined, otherwise it will be the name of a loop control variable such as "i" indicating that the current pass through the %roll is being placed in a loop. Outside of the %roll directive, this is usually specified as "".
sigIdx
Signal index. Sometimes referred to as the signal element index. When accessing specific elements of a input or output signal directly, the call to the various library routines should have ucv="", lcv="", and sigIdx equal to the desired integer signal index starting at 0. When accessing these items inside of a %roll, the sigIdx generated by the %roll directive should be used.
continued

sigIdx

sigIdx an overloaded argument. Specifically, the index when passed to a Lib function can be of the form:

"%<tImagPart>%<idx>" (e.g. "im3"). The imaginary part of the signal element or "" if the signal is not complex. Usually "%<tImagPart>%<sigIdx>" when sigIdx is generated by the %roll directive.
paramIdx
Parameter index. Sometimes referred to as the parameter element index. The handling of this parameter is very similar to sigIdx (i.e, it can be #, re#, or im#).
stateIdx
State index. Sometimes referred to as the state vector element index (it must evaluate to an integer where the first element starts at 0).

Input Signal Functions

LibBlockInputSignal(portIdx, ucv, lcv, sigIdx) --
Based on the output port index (portIdx), the user control variable (ucv), the loop control variable (lcv), and the signal index (sigIdx), this function returns a reference to the source signal. The text string returned can be decomposed into four parts:
  inputSignal = <vect><ioq><id><index>.

The first part, <vect>, depends on where this signal originates. This is derived from the attributes of the signal source. The possibilities are:

The second part, <ioq>, is the I/O qualifier (or the selection operator), which is largely determined by the code format. The possibilities are:

The third part, <id>, is the unique identifier assigned to this signal. This identifier is obtained from either the signal label specified in the Simulink diagram or, if a signal label is not present, the name of the block from which this signal originates.

For invariant block I/O signals, whose value is set by a #define statement, an additional _ is appended between the <id> and <index> positions.

The final part, <index>, is the index into the appropriate element and/or real/imaginary part of the input signal, if it is either wide and/or complex. This depends on ucv, lcv, and idx.

If you combine all of them, you get strings such as rtB.s7_Gain1[2], where:

[2] is the <index> part.

Examples:

Function (case 1, 2, 3):
Example return value
LibBlockInputSignal(0, "i", "", sigIdx)
rtB.blockname[i]
LibBlockInputSignal(0, "", lcv, sigIdx)
u0[i1]
LibBlockInputSignal(0, "", lcv, sigIdx)
rtB.blockname[0]

This function returns the appropriate reference to the block's input signal. The value returned depends on what the input signal is connected to in the block diagram and how the function is being invoked (e.g. in a %roll or directly). In the above example, case 1 occurs when an explicit call is made with the ucv set to "i". Cases 2 and 3 receive the same arguments, lcv and sigIdx however they produce different return values. Case 2 occurs when LibBlockInputSignal is called within a %roll directive and the current roll region is being rolled. Case 3 occurs when LibBlockInputSignal is called within a %roll directive and the current roll region is not being rolled.

When called within a %roll directive, this function looks at ucv, lcv, and sigIdx, the current roll region, and the current roll threshold to determine the return value. The variable ucv has highest precedence, lcv has the next highest precedence, and sigIdx has the lowest precedence. That is, if ucv is specified, it will be used (thus, when called in a %roll directive it is usually ""). If ucv is not specified and lcv and sigIdx are specified, the returned value depends on whether or not the current roll region is being placed in a for loop or being expanded. If the roll region is being placed in a loop then, lcv is used, otherwise sigIdx is used.

A direct call to this function (inside or outside of a %roll directive) will use sigIdx when ucv and lcv are specified as "".

For an example of this function, see matlabroot/toolbox/simulink/blocks/tlc_c/sfun_multiport.tlc.

Related input signal functions:

LibBlockInputSignalWidth(portIdx) -- Return the width of the input port specified by portIdx.

LibBlockInputSignalAddr(portIdx, ucv, lcv, sigIdx) -- Similar to LibBlockInputSignal except the address is returned (e.g. &rtB.blockname[0]). In Ada, this function returns the identifier and the caller must append the 'Address attribute.

LibBlockInputSignalBufferDstPort(portIdx) Þ-- Returns the output port corresponding to input port (portIdx) which share the same memory, otherwise (-1) is returned. You will need to use this function when you specify ssSetInputPortOverWritable(S,portIdx,TRUE) in your S-function.

LibBlockSrcSignalBlock(portIdx, sigIdx) -- Returns the signal source for specified input port element. Return values will be: [systemIdx, blockIdx] if source is a block output or a block state, ExternalInput if the source is a root inport, Ground if the source is grounded or unconnected, or 0 if the source is not unique (i.e. connected to a Merge block or it is a reused signal due to block I/O optimizations).

LibBlockSrcSignalIsDiscrete(portIdx, sigIdx) -- Returns 1 if source signal is discrete; otherwise 0 (or if the signal cannot be uniquely determined). The signal cannot be uniquely determined if it is a merged or reused signal (i.e., the source is a Merge block or if the signal has been reused due to block I/O optimization).

LibBlockSrcSignalIsGlobalAndModifiable(portIdx, sigIdx) -- Returns 1 if the block's specified source signal is in global memory, 0 otherwise. If the signal is in global memory: 1) it visible everywhere in the generated code, 2) it can be referenced by its address, and 3) its value can change (i.e., it is not declared as a constant).

LibBlockSrcSignalIsInvariant(portIdx, sigIdx) -- Returns 1 if the specified block input signal element is invariant, 0 otherwise. An invariant signal source signal has a constant (purple sample time). In this case the value of the signal does not change during model execution.

Output Signal Functions

LibBlockOutputSignal(portIdx, ucv, lcv, sigIdx) --
Based on the input port number (portIdx), the user control variable (ucv), the loop-control variable (lcv), the signal index (idx), and the location of this output signal, LibBlockOutputSignal returns the appropriate for a block output signal. Calling conventions, usage, and return values are similar to LibBlockInputSignal.

Related output signal functions:

LibBlockOutputSignalWidth(portIdx) -- Return the width of the output port specified by portIdx.

LibBlockOutputSignalAddr(portIdx, ucv, lcv, sigIdx) -- Similar to LibBlockOutputSignal except the address is returned (e.g. &rtB.blockname[0]). In Ada, this function returns the identifier and the caller must append the 'Address attribute.

LibBlockOutputSignalIsInBlockIO(portIdx) -- Check if the specified block output port exists in the global Block I/O data structure. You may need to use this if you specify ssSetOutputPortReusable(S,portIdx,TRUE) in your S-function.

See matlabroot/toolbox/simulink/blocks/tlc_c/sfun_multiport.tlc.

Parameter Functions

LibBlockParameter(param, ucv, lcv, paramIdx) --
The behavior of this function is similar to LibBlockInputSignal (in the handling of ucv and lcv). This function returns the appropriate reference to a block's parameter. The function can only be used for parameters of type Scalar or Vector. The first argument, param, is a reference to a block parameter (i.e. the value of Parameter[i].Name). The last argument, paramIdx identifies which element of the parameter we need to access. This is very similar to the sigIdx of the LibBlockInputSignal function. For example,

Function
Example return value
LibBlockParameter(Gain, "i", "", paramIdx)
rtP.Gain[i]
LibBlockParameter(Gain, "", lcv, paramIdx)
p_Gain[i1]
LibBlockParameter(Gain, "", lcv, paramIdx)
rtP.Gain[0]
LibBlockParameter(Gain, "", lcv, paramIdx)
2.5

For an example of this function, see matlabroot/toolbox/simulink/blocks/tlc_c/sfun_multiport.tlc.

Related parameter functions:

LibBlockParameterAddr(param, ucv, lcv, paramIdx) Þ-- Similar to LibBlockParameter except it return the address of the parameter and guarantees that the parameter will be in the global parameter vector. In Ada, the caller must append a 'Address attribute.

LibBlockParameterSize(param) -- Returns the size of the parameter in a two element vector: [nRows, nCols].

LibBlockParameterValue(param, paramIdx) -- Returns the numeric value of the specified parameter element.

LibBlockParameterFormattedValue(param, paramIdx) -- Similar to LibBlockParameterValue except it has been formatted into a string suitable for writing to the generated code file.

LibBlockMatrixParameter(param, rowUcv, rowLcv, rowParamIdx, colUcv, colLcv, colParamIdx) -- Return the appropriate matrix parameter for a block given the row and column user control variables, loop control variables, and indices. Currently, rowLcv and colLcv must be "" (i.e. loop rolling is not supported). The row and column index arguments are similar to the arguments for LibBlockParameter. The column index (colParamIdx) is overloaded to handle complex numbers.

LibBlockMatrixParameterAddr(param, rowUcv, rowLcv, rowParamIdx, colUcv, colLcv, colParamIdx) -- This function returns the appropriate address of a block's matrix parameter. The function is similar to LibBlockParameterAddr.

LibBlockMatrixParameterValue(param, rowParamIdx, colParamIdx) -- Returns the numeric value of a matrix parameter.

LibBlockMatrixParameterFormattedValue(param, rowParamIdx, colParamIdx) -- Similar to LibBlockMatrixParmaeterValue except it has been formatted into a string suitable for writing to the generated code file.

Block State and Work Vector Functions

LibBlockContinuousState(ucv, lcv, stateIdx) -- Used to access a block's continuous state vector from outside (ucv = "", lcv = "", stateIdx specified) of or within a %roll directive (ucv= "", lcv, stateIdx specified).

LibBlockDiscreteState(ucv, lcv, stateIdx) -- Used to access a block's discrete state vector from outside (ucv = "", lcv = "", stateIdx specified) of or within a %roll directive (ucv= "", lcv, stateIdx specifed).

LibBlockRWork(rworkRef, ucv, lcv, workIdx)
LibBlockIWork(iworkRef, ucv, lcv, workIdx)
LibBlockPWork(pworkRef, ucv, lcv, workIdx)
-- The behavior of these functions is similar to LibBlockInputSignal with respect to handling of ucv, lcv, and workIdx (sigIdx specified as integer). These functions return the appropriate reference to the block's RWork, IWork, and PWork. The additional arguments, rworkRef, iworkRef, and pworkRef, are references to the block internal records RWorkDefine, IWorkDefine, and PWorkDefine, respectively.

If the block records RWorkDefine, IWorkDefine, and PWorkDefine are not defined, then the reference to the work records is replaced with a reference to the block's vector identifier, RWork, IWork, and PWork, respectively. Use the mdlRTW S-function method to add [R|I|P]WorkDefine records to the model.rtw file.

LibBlockMode(ucv, lcv, modeIdx) -- The behavior of this function is similar to the LibBlockRWork function.

Sample Time Functions

LibBlockSampleTime(block) -- Returns the block's sample time. The return value is the actual block's sample time (a real number greater than zero) if it is discrete. If the block is triggered, -1.0 is returned. If the block is constant then -2.0 is returned. If the block is continuous then 0.0 is returned.

LibIsSFcnSampleHit(sfcnTID) -- Returns the code required to check for a sample hit. This function should only be used when your block has multiple sample times. For block-based sample times, specify sfcnTID as an integer corresponding to the local sample time of the block
(i.e. ssIsSampleHit(S,sfcnTID)). For port-based sample times, specify sfcnTID as a string of the form InputPortIdx# (e.g. InputPortIdx3 for the 4th input port) or OutputPortIdx#. If a block is single rate, it doesn't need sample time checks (i.e, don't use LibIsSFcnSampleHit).

LibGetNumSFcnSampleTimes(block) -- Returns the integer number of sample times the S-function block has.

LibGetSFcnTIDType(sfcnTID) -- Returns "continuous", "discrete", "triggered", or "constant". See LibIsSFcnSampleHit for specification of the sfcnTid argument.

LibIsContinuous(tid) -- Returns 1 if the specified model task id (TID field of a block) is continuous. Note that TIDs equal to "triggered" or "constant" are not continuous.

LibIsDiscrete(tid) -- Returns 1 if the specified model task id (TID field of a block) is discrete. Note that TIDs equal to "triggered" or "constant" are not discrete.

LibIsSFcnSingleRate(block) -- Returns 1 if an S-function is single rate (one sample time), 0 otherwise.

LibIsSampleHit(tid) -- Returns the code required to check for a sample hit. The argument, tid can be specified as an integer corresponding to a model sample time or a string variable used to index the sample hit array. In general, S-functions should use LibIsSFcnSampleHit except when checking for sample hits in a loop, in this case LibIsSampleHit("loopindex") should be used. This would typically be done for an advanced port-based sample time S-function.

LibTID() -- Returns %<tTID>, the task identifier needed when checking for sample hits. Note, in general only advanced S-functions should use this. S-functions should never directly access %<tTID> since this may result in code that doesn't compile. LibTID guarantees that %<tTID> will exist.

LibGetGlobalTIDFromLocalTid(sfcnTid) -- This function returns the integer model task id for a local S-function task id. Each S-function block has the concept of local task identifiers (TIDs). For example, if an S-function has two sample times, then the local TIDs are 0 for the first sample time and 1 for the second sample time. These local TIDs map one-to-one with the model task ids. For our example, local task id 0 could map to the 3rd model task id. See LibIsSFcnSampleHit for specification of the sfcnTid argument.

Time Functions

If your block accesses time, it must use one of the following functions; otherwisethe generated code may fail to compile.

LibGetT() -- Returns a string giving access to the model time corresponding to task id 0. If your block accesses model time corresponding to task id 0, it must use this function.

LibGetTaskTimeFromTID(block) -- Returns a string giving access to the time for the current task.

Block Name Functions

LibGetBlockPath(block) -- Returns the full path name string for a block record. This includes carriage returns and other special characters. You use the full path name including special characters when accessing blocks from within MATLAB.

LibGetFormattedBlockPath(block) Þ-- Returns the full path name string for a block record with special characters removed. This is useful when issuing information, warnings, or error messages from within TLC.

Model Code Functions

LibCacheDefine(buffer) Þ-- Generally called from within a BlockTypeSetup function to add #define statements to model.h.

LibCacheExtern(buffer) -- Generally called from within a BlockTypeSetup function to add extern definitions for variables to model.h.

LibCacheFunctionPrototype(buffer) -- Generally called from within a BlockTypeSetup function to add extern function prototypes to model.h.

LibCacheIncludes(buffer) -- Generally called from within a BlockTypeSetup function to add #include statements to model.h.

LibCacheNonFiniteAssignment(buffer) -- Generally called from within a BlockTypeSetup function to add assignments for non-finite values which needed to be initialized in the model registration function model.reg.

LibCacheTypedefs(buffer) -- Generally called from within a BlockTypeSetup function to add typedef statements to model.h.

Utility Functions

LibIsEmpty(arg) -- Returns 1 if arg is empty (i.e. "", [], etc.), 0 otherwise. This is useful to use when you aren't sure of arg's type.

LibIsEqual(expr1,expr2) -- Returns 1 if expr1 equals expr2, 0 otherwise. This is useful when you aren't sure of the expr1, expr2 types.

LibAddIdentifier(record, name, value) -- Adds the name/value pair to the specified scope (record). An error is reported if the identifier (name) already exists. This is generally called in a BlockTypeSetup function for the block. To avoid name conflicts, choose a name that starts with a lowercase character. It is recommended that you prefix the name to be added with your company name or initials.

LibAddToCompiledModel(name, value) Þ-- Adds a name/value pair to the CompiledModel scope. An error is reported if the identifier (name) already exists. To avoid conflicts, you should choose names which do not start with an uppercase letter. In addition, prefixing with gblCompanyName is recommended.

LibIsFinite(value) -- Return 1 if value is finite (e.g. not equal to NaN, Inf, etc.), 0 otherwise.

LibRealNonFinite(value) -- Returns a text string suitable for placement in the generated code corresponding to the specified nonfinite value. The input argument, value can be one of: inf, -inf, or nan in the form of a string or number (i.e. quotes are optional).