Real-Time Workshop | ![]() ![]() |
Utilizing Expression Folding in Your TLC Block
Implementation
To take advantage of expression folding, an inlined S-Function must be modified in two ways:
In this section, we discuss required modifications to the TLC implementation.
Expression Folding Compliance
In the BlockInstanceSetup function of your S-function, you must ensure that your block registers that it is compliant with expression folding. If you fail to do this, any expression folding requested or allowed at the block's outputs or inputs will be disabled, and temporary variables will be utilized. To register expression folding compliance, call the TLC library function
Note that you can conditionally disable expression folding at the inputs and outputs of a block by making the call to this function conditionally.
If you have overridden one of the TLC block implementations provided by Real-Time Workshop with your own implementation, you should not make the above call until you have updated your implementation, as described by the guidelines for expression folding in the following sections.
Outputting Expressions
The BlockOutputSignal function
is used to generate code for a scalar output expression, or one element of a non-scalar output expression. If your block outputs an expression, you should add a BlockOutputSignal
function. The prototype of the BlockOutputSignal is
The arguments to BlockOutputSignal
are as follows:
block
: the record for the block for which an output expression is being generated.
system
: the record for the system containing the block.
portIdx
: zero-based index of the output port for which an expression is being generated.
ucv
: user control variable defining the output element for which code is being generated.
lcv
: loop control variable defining the output element for which code is being generated
idx
: signal index defining the output element for which code is being generated
retType
: string defining the type of signal access desired:
The BlockOutputSignal
function returns an appropriate text string for the output signal or address. The string should enforce the precedence of the expression by utilizing opening and terminating parentheses, unless the expression consists of a function call. The address of an expression may only be returned for a constant expression; it is the address of the parameter whose memory is being accessed. The code implementing the BlockOutputSignal
function for the Constant block is shown below.
%% Function: BlockOutputSignal ================================================= %% Abstract: %% Return the appropriate reference to the parameter. This function *may* %% be used by Simulink when optimizing the Block IO data structure. %% %function BlockOutputSignal(block,system,portIdx,ucv,lcv,idx,retType) void %switch retType %case "Signal" %return LibBlockParameter(Value,ucv,lcv,idx) %case "SignalAddr" %return LibBlockParameterAddr(Value,ucv,lcv,idx) %default %assign errTxt = "Unsupported return type: %<retType>" %<LibBlockReportError(block,errTxt)> %endswitch %endfunction
The code implementing the BlockOutputSignal
function for the Relational Operator block is shown below.
%% Function: BlockOutputSignal ================================================= %% Abstract: %% Return an output expression. This function *may* %% be used by Simulink when optimizing the Block IO data structure. %% %function BlockOutputSignal(block,system,portIdx,ucv,lcv,idx,retType) void %switch retType %case "Signal" %assign logicOperator = ParamSettings.Operator %if ISEQUAL(logicOperator, "~=") %assign op = "!=" %elseif ISEQUAL(logicOperator, "==") %assign op = "==" %else %assign op = logicOperator %endif %assign u0 = LibBlockInputSignal(0, ucv, lcv, idx) %assign u1 = LibBlockInputSignal(1, ucv, lcv, idx) %return "(%<u0> %<op> %<u1>)" %default %assign errTxt = "Unsupported return type: %<retType>" %<LibBlockReportError(block,errTxt)> %endswitch %endfunction
Expression Folding for Blocks with Multiple Outputs
When a block has a single output, the Outputs
function in the block's TLC file is called only if the output is not an expression. Otherwise, the BlockOutputSignal
function is called.
If a block has multiple outputs, the Outputs
function will be called if any output port is not an expression. The Outputs
function should guard against generating code for output ports that are expressions. This is achieved by guarding sections of code corresponding to individual output ports with calls to LibBlockOutputSignalIsExpr()
.
For example, consider an S-Function with two inputs and two outputs, where:
The Outputs
and BlockOutputSignal
functions for the S-function are shown in the following code excerpt.
%% Function: BlockOutputSignal ================================================= %% Abstract: %% Return an output expression. This function *may* %% be used by Simulink when optimizing the Block IO data structure. %% %function BlockOutputSignal(block,system,portIdx,ucv,lcv,idx,retType) void %switch retType %assign u = LibBlockInputSignal(portIdx, ucv, lcv, idx) %case "Signal" %if portIdx == 0 %return "(2 * %<u>)" %elseif portIdx == 1 %return "(4 * %<u>)" %endif %default %assign errTxt = "Unsupported return type: %<retType>" %<LibBlockReportError(block,errTxt)> %endswitch %endfunction %% Function: Outputs ================================================= %% Abstract: %% Compute output signals of block %% %function Outputs(block,system) Output %roll sigIdx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars %assign u0 = LibBlockInputSignal(0, ucv, lcv, idx) %assign u1 = LibBlockInputSignal(1, ucv, lcv, idx) %assign y0 = LibBlockOutputSignal(0, ucv, lcv, idx) %assign y1 = LibBlockOutputSignal(1, ucv, lcv, idx) if !LibBlockOutputSignalIsExpr(0) %<y0> = 2 * %<u0>; %endif %if !LibBlockOutputSignalIsExpr(1) %<y1> = 4 * %<u1>; %endif %endroll %endfunction
Comments for Blocks That Are Expression Folding Compliant
In the past, all blocks preceded their outputs code with comments of the form
When a block is expression folding compliant, the initial line shown above is generated automatically. You should not include the comment as part of the block's TLC implementation. Additional information should be registered using the LibCacheBlockComment
function.
The LibCacheBlockComment
function takes a string as an input, defining the body of the comment, except for the opening header, the final newline of a single or multi-line comment, and the closing trailer.
The following TLC code illustrates registering a block comment. Note the use of the function LibBlockParameterForComment
, which returns a string, suitable for a block comment, specifying the value of the block parameter.
%openfile commentBuf $c(*) Gain value: %<LibBlockParameterForComment(Gain)> %closefile commentBuf %<LibCacheBlockComment(block, commentBuf)>
![]() | Acceptance or Denial of Requests for Input Expressions | Conditional Branch Execution | ![]() |