Target Language Compiler | ![]() ![]() |
%foreach
The syntax of the %foreach
multiple inclusion directive is
The constant-expression
must evaluate to an integral expression, which then determines the number of times to execute the foreach
loop. The identifier
increments from 0
to one less than the specified number. Within the foreach
loop, you can use x
, where x
is the identifier, to access the identifier variable. %break
and %continue
are optional directives that you can include in the %foreach
directive:
%break
can be used to exit the nearest enclosing %for
, %foreach
, or %switch
statement.
%continue
can be used to begin the next iteration of a loop.
%for
The syntax of the %for multiple inclusion directive is
The first portion of the %for
directive is identical to the %foreach
statement in that it causes a loop to execute from 0
to N-1
times over the body of the loop. In the normal case, it includes only the lines between %body
and %endbody
, and the lines between the %for
and %body
, and ignores the lines between the %endbody
and %endfor
.
The %break
and %continue
directives act the same as they do in the %foreach
directive.
const-exp2
is a Boolean expression that indicates whether the loop should be rolled. If const-exp2
is true, ident2 receives the value of const-exp3
; otherwise it receives the null string. When the loop is rolled, all of the lines between the %for
and the %endfor
are included in the output exactly one time. ident2 specifies the identifier to be used for testing whether the loop was rolled within the body. For example:
%for Index = <NumNonVirtualSubsystems>3, rollvar="i" { int i; for (i=0; i< %<NumNonVirtualSubsystems>; i++) { %body x[%<rollvar>] = system_name[%<rollvar>]; %endbody } } %endfor
If the number of nonvirtual subsystems (NumNonVirtualSubsystems
) is greater than or equal to 3, the loop is rolled, causing all of the code within the loop to be generated exactly once. In this case, Index
= 0
.
If the loop is not rolled, the text before and after the body of the loop is ignored and the body is generated NumNonVirtualSubsystems
times.
This mechanism gives each individual loop control over whether or not it should be rolled.
The syntax of the %roll
multiple inclusion directive is
%roll ident1 = roll-vector-exp, ident2 = threshold-exp, ... block-exp [, type-string [,exp-list] ] %break %continue %endroll
This statement uses the roll-vector-exp
to expand the body of the %roll
statement multiple times as in the %foreach
statement. If a range is provided in the roll-vector-exp
and that range is larger than the threshold-exp
expression, the loop will roll. When a loop rolls, the body of the loop is expanded once and the identifier (ident2
) provided for the threshold expression is set to the name of the loop control variable. If no range is larger than the specified rolling threshold, this statement is identical in all respects to the %foreach
statement.
In this case, the body of the %roll
statement expands 10 times as in the %foreach
statement since there are no regions greater than or equal to 10. Idx
counts from 1 to 10, and lcv
is set to the null string, ""
.
When the Target Language Compiler determines that a given block will roll, it performs a GENERATE_TYPE
function call to output the various pieces of the loop (other than the body). The default type used is Roller
; you can override this type with a string that you specify. Any extra arguments passed on the %roll
statement are provided as arguments to these special-purpose functions. The called function is one of these four functions.
RollHeader(block, ...). This function is called once on the first section of this roll vector that will actually roll. It should return a string that is assigned to the lcv
within the body of the %roll
statement.
LoopHeader(block, StartIdx, Niterations, Nrolled, ...). This function is called once for each section that will roll prior to the body of the %roll
statement.
LoopTrailer(block, Startidx, Niterations, Nrolled, ...). This function is called once for each section that will roll after the body of the %roll
statement.
RollTrailer(block, ...). This function is called once at the end of the %roll
statement if any of the ranges caused loop rolling.
These functions should output any language-specific declarations, loop code, and so on as required to generate correct code for the loop. An example of a Roller.tlc
file is
%implements Roller "C" %function RollHeader(block) Output { int i; %return ("i") %endfunction %function LoopHeader(block,StartIdx,Niterations,Nrolled) Output for (i = %<StartIdx>; i < %<Niterations+StartIdx>; i++) { %endfunction %function LoopTrailer(block,StartIdx,Niterations,Nrolled) Output } %endfunction %function RollTrailer(block) Output } %endfunction
Note
The Target Language Compiler function library provided with Real-Time Workshop has the capability to extract references to the block I/O and other Real-Time Workshop vectors that vastly simplify the body of the %roll statement. These functions include LibBlockInputSignal , LibBlockOutputSignal , LibBlockParameter , LibBlockRWork , LibBlockIWork , LibBlockPWork , and LibDeclareRollVars , LibBlockMatrixParameter , LibBlockParameterAddr , LibBlockContinuousState , and LibBlockDiscreteState function reference pages in TLC Function Library Reference. This library also includes a default implementation of Roller.tlc an a "flat" roller.
|
Extending the former example to a loop that rolls
%language "C" %assign ablock = BLOCK { Name "Hi" } %roll Idx = [ 1:20, 21, 22, 23:25, 26:46], lcv = 10, ablock Block[%< lcv == "" ? Idx : lcv>] *= 3.0; %endroll
This Target Language Compiler code produces this output:
{ int i; for (i = 1; i < 21; i++) { Block[i] *= 3.0; } Block[21] *= 3.0; Block[22] *= 3.0; Block[23] *= 3.0; Block[24] *= 3.0; Block[25] *= 3.0; for (i = 26; i < 47; i++) { Block[i] *= 3.0; } }
![]() | Conditional Inclusion | Object-Oriented Facility for Generating Target Code | ![]() |