Main Content

Code Generation Concepts

TLC interprets a target language, which is a general programming language, and you can use it as such. It is important, however, to remember that TLC was designed for one purpose: to convert a model.rtw file to generated code. Thus, the target language provides many features that are useful for this task but does not provide some of the features that other languages like C and C++ provide.

You might find some of the following general programming examples useful to familiarize yourself with the basic constructs used within TLC.

Output Streams

The typical “Hello World” example is rather simple in the target language. Type the following in a file named hello.tlc:

%selectfile STDOUT 
Hello, World

To run this TLC program, type

tlc hello.tlc

at the MATLAB® prompt.

This simple script illustrates some important concepts underlying the purpose (and hence the design) of TLC. Since the primary purpose of TLC is to generate code, it is output (or stream) oriented. It makes it easy to handle buffers of text and output them easily. In the above script, the %selectfile directive tells TLC to send any following text that it generates or does not recognize to the standard output device. Syntax that TLC recognizes begins with the % character. Because Hello, World is not recognized, it is sent directly to the output. You could easily change the output destination to be a file. Do not open the STDOUT stream, but select to write to the Command Window.

%openfile foo = "foo.txt"  
%openfile bar = "bar.txt" 
%selectfile foo 
This line is in foo. 
%selectfile STDOUT 
Line has been output to foo. 
%selectfile bar 
This line is in bar. 
%selectfile NULL_FILE 
This line will not show up anywhere. 
%selectfile STDOUT 
About to close bar. 
%closefile bar 
%closefile foo

You can switch between buffers to display status messages. The semantics of the three directives %openfile, %selectfile, and %closefile are given in Target Language Compiler Directives.

Variable Types

The absence of explicit type declarations for variables is another feature of TLC. See Target Language Compiler for more information on the implicit data types of variables.

Records

One of the constructs most relevant to generating code from the model.rtw file is a record. A record is similar to a structure in C or a record in Pascal. The syntax of a record declaration is

%createrecord recVar { ... 	
   field1		value1  ...
   field2		value2 ...
 	 ... 	
  fieldN		valueN ... 
}

where recVar is the name of the record being declared, fieldi is a string, and valuei is the corresponding TLC value.

Records can have nested records, or subrecords, within them. The model.rtw file is essentially one large record, named CompiledModel, containing levels of subrecords.

Unlike MATLAB, TLC requires that you explicitly load function definitions not located in the same target file. In MATLAB, the line A = myfunc(B) causes MATLAB to automatically search for and load a MATLAB file or MEX-file named myfunc. TLC requires that you specifically include the file that defines the function using the %addincludepath directive.

TLC provides a %with directive that facilitates using records. See Target Language Compiler Directives.

Note

The format and structure of the model.rtw file are subject to change from one release of the code generator to another.

A record read in from a file is changeable, like other records that you declare in a program. The record CompiledModel is modified many times during code generation. CompiledModel is the global record in the model.rtw file. It contains variables used for code generation, such as NumNonvirtSubsystems, NumBlocks. It is also appended during code generation with many new variables, options, and subrecords.

Functions such as LibGetFormattedBlockPath are provided in TLC libraries located in matlabroot/rtw/c/tlc/lib/*.tlc (open). For a complete list of available functions, refer to TLC Function Library Reference on Target Language Compiler.

Assign Values to Fields of Records

To assign a value to a field of a record, you must use a qualified variable expression. A qualified variable expression references a variable in one of the following forms:

  • An identifier

  • A qualified variable followed by “.” followed by an identifier, such as

    var[2].b
  • A qualified variable followed by a bracketed expression such as

    var[expr]

Record Aliases

In TLC, it is possible to create what is called an alias to a record. Aliases are similar to pointers to structures in C. You can create multiple aliases to a single record. Modifications to the aliased record are visible to every place that holds an alias.

The following code fragment illustrates the use of aliases:

%createrecord foo { field 1 }
%createrecord a { } 
%createrecord b { } 
%createrecord c { }  

%addtorecord a foo foo 
%addtorecord b foo foo 
%addtorecord c foo { field 1 }  

%% notice we are not changing field through a or b. 
%assign foo.field  = 2  

ISALIAS(a.foo) = %<ISALIAS(a.foo)>
ISALIAS(b.foo) = %<ISALIAS(b.foo)>
ISALIAS(c.foo) = %<ISALIAS(c.foo)>

a.foo.field = %<a.foo.field>
b.foo.field = %<b.foo.field> 
c.foo.field = %<c.foo.field> 
%% note that c.foo.field is unchanged

Saving this script as record_alias.tlc and invoking it with

tlc -v record_alias.tlc

produces the output

ISALIAS(a.foo) = 1
ISALIAS(b.foo) = 1
ISALIAS(c.foo) = 0

a.foo.field = 2
b.foo.field = 2 
c.foo.field = 1 

When inside a function, it is possible to create an alias to a locally created record that is within the function. If the alias is returned from the function, it remains valid even after exiting the function, as in the following example:

%function func(value) Output   
  %createrecord foo { field value }
  %createrecord a { foo foo }
ISALIAS(a.foo) = %<ISALIAS(a.foo)>
   %return a.foo
 %endfunction

 %assign x = func(2)
 ISALIAS(x) = %<ISALIAS(x)>
 x = %<x>
 x.field = %<x.field>

Saving this script as alias_func.tlc and invoking it with

tlc -v alias_func.tlc

produces the output

ISALIAS(a.foo) = 1 
ISALIAS(x) = 1
x = { field 2 } 
x.field = 2

As long as there is some reference to a record through an alias, that record is not deleted. This allows records to be used as return values from functions.

Related Topics