Block Target File Methods
Block Functions Overview
Each block has a target file that determines what code should be generated for the block. The code can vary depending on the exact parameters of the block or the types of connections to it (e.g., wide vs. scalar input).
Within each block target file, block functions specify the code
to be output for the block in the model’s or subsystem’s start
function, output function, update function, and so
on.
The functions declared inside each of the block target files are called by the system target files. In these tables,
block refers to a Simulink® block name (e.g., gain for the Gain block) and
system refers to the subsystem in which the block resides. The first
table lists the two functions that are used for preprocessing and setup. Neither of these
functions outputs generated code.
The following functions generate executable code that the code generator places appropriately:
In object-oriented programming terms, these functions are polymorphic in nature, because
each block target file contains the same functions. The Target Language Compiler dynamically
determines at run-time which block function to execute depending on the block’s type. That
is, the system file only specifies that the Outputs function, for
example, is to be executed. The particular Outputs function is
determined by the Target Language Compiler depending on the block’s type.
To write a block target file, use these polymorphic block functions combined with the Target Language Compiler library functions. For a complete list of the Target Language Compiler library functions, see TLC Function Library Reference on Target Language Compiler.
BlockInstanceSetup(block, system)
The BlockInstanceSetup function executes for the blocks that have
this function defined in their target files in a model. For example, if a model includes 10
From Workspace blocks, then the BlockInstanceSetup function in
fromwks.tlc executes 10 times, once for each From Workspace block
instance. Use BlockInstanceSetup to generate code for each instance of
a given block type.
See TLC Function Library Reference on Target Language Compiler for available utility processing functions to call from inside
this block function. See the file
for an example of the
matlabroot/rtw/c/tlc/blocks/lookup2d.tlcBlockInstanceSetup function.
Syntax
BlockInstanceSetup(block, system) void
block = Reference to a Simulink block
system = Reference to a nonvirtual Simulink subsystemThis example uses BlockInstanceSetup:
%function BlockInstanceSetup(block, system) void
%if (block.InMask == "yes")
%assign blockName = LibParentMaskBlockName(block)
%else
%assign blockName = LibGetFormattedBlockPath(block)
%endif
%if (CodeFormat == "Embedded-C")
%if !(ParamSettings.ColZeroTechnique == "NormalInterp" && ...
ParamSettings.RowZeroTechnique == "NormalInterp")
%selectfile STDOUT
Note: Removing repeated zero values from the X and Y axes will
produce more efficient code for block: %<blockName>. To locate
this block, type
open_system('%<blockName>')
at the MATLAB command prompt.
%selectfile NULL_FILE
%endif
%endif
%endfunctionBlockTypeSetup(block, system)
BlockTypeSetup executes once per block type before code generation
begins. That is, if 10 Lookup Table blocks exist in the model, the
BlockTypeSetup function in look_up.tlc is called
only one time. Use this function to perform general work for multiple blocks of a given
type.
See TLC Function Library Reference on Target Language Compiler for a list of relevant functions to call from inside this block
function. See look_up.tlc for an example of the
BlockTypeSetup function.
Syntax
BlockTypeSetup(block, system) void
block = Reference to a Simulink block
system = Reference to a nonvirtual Simulink subsystemAs an example, given the S-function foo, which requires a
#define and two function declarations in the header file, you could
define:
%function BlockTypeSetup(block, system) void
%% Place a #define in the model's header file
%openfile buffer
#define A2D_CHANNEL 0
%closefile buffer
%<LibCacheDefine(buffer)>
%% Place function prototypes in the model's header file
%openfile buffer
void start_a2d(void);
void reset_a2d(void);
%closefile buffer
%<LibCacheFunctionPrototype(buffer)>
%endfunctionThe remaining block functions execute once for each block in the model.
Enable(block, system)
The code generator creates Enable functions for nonvirtual
subsystem whenever a Simulink subsystem contains a block with an Enable function.
Including the Enable function in a block’s target file places the
block’s specific enable code in this subsystem Enable function. For
example:
%% Function: Enable ============================================
%% Abstract:
%% Subsystem Enable code is required only for the discrete form
%% of the Sine Block. Setting the Boolean to TRUE causes the
%% Output function to resync its last values of cos(wt) and
%% sin(wt).
%%
%function Enable(block, system) Output
%if LibIsDiscrete(TID)
/* %<Type> Block: %<Name> */
%<LibBlockIWork(SystemEnable, "", "", 0)> = (int_T) TRUE;
%endif
%endfunctionDisable(block, system)
Nonvirtual subsystem Disable functions are created whenever a
Simulink subsystem contains a block with a Disable function.
Including the Disable function in a block’s target file places the
block’s specific disable code into this subsystem Disable
function.
Start(block, system)
Include a Start function to place code in the
Start function. The code inside the Start
function executes once and only once. Typically, you include a Start
function to execute code once at the beginning of the simulation (e.g., initialize values in
the work vectors) or code that does not need to be re-executed when the subsystem in which
it resides is enabled. See constant.tlc for an example of the
Start function.
%% Function: Start ============================================
%% Abstract:
%% Set the output to the constant parameter value if the block
%% output is visible in the model's start function scope, i.e.,
%% it is in the global rtB structure.
%%
%function Start(block, system) Output
%if LibBlockOutputSignalIsInBlockIO(0)
/* %<Type> Block: %<Name> */
%assign rollVars = ["Y", "P"]
%roll idx = RollRegions, lcv = RollThreshold, block, ...
"Roller", rollVars
%assign yr = LibBlockOutputSignal(0,"", lcv, ...
"%<tRealPart>%<idx>")
%assign pr = LibBlockParameter(Value, "", lcv, ...
"%<tRealPart>%<idx>")
%<yr> = %<pr>;
%if LibBlockOutputSignalIsComplex(0)
%assign yi = LibBlockOutputSignal(0, "", lcv, ...
"%<tImagPart>%<idx>")
%assign pi = LibBlockParameter(Value, "", lcv, ...
"%<tImagPart>%<idx>")
%<yi> = %<pi>;
%endif
%endroll
%endif
%endfunction %% StartInitializeConditions(block, system)
TLC code that is generated from the block’s InitializeConditions function appears in one of two places. A
nonvirtual subsystem contains an Initialize function when it is
configured to reset states on enable. In this case, the TLC code generated by this block
function is placed in the subsystem Initialize function, and the start
function calls this subsystem Initialize function. If, however, the
Simulink block resides in the root system or in a nonvirtual subsystem that does not
require an Initialize function, the code generated from this block
function is placed directly (inlined) into the start function.
There is a subtle difference between the block functions Start and
InitializeConditions. Typically, you include a
Start function to execute code that does not need to re-execute when
the subsystem in which it resides is enabled. You include an
InitializeConditions function to execute code that must re-execute
when the subsystem in which it resides is enabled. For example:
%% Function: InitializeConditions ============================= %% %% Abstract: Invalidate the stored output and input in %% rwork[1 2*blockWidth] by setting the time stamp stored %% in rwork[0]) to rtInf. %% %function InitializeConditions(block, system) Output /* %<Type> Block: %<Name> */ %<LibBlockRWork(PrevT, "", "", 0)> = %<LibRealNonFinite(inf)>; %endfunction
Note
To parse the InitializeConditions function, the S-function must
have at least one registered continuous or discrete state.
Outputs(block, system)
A block should generally include an Outputs function. The TLC code
generated by a block’s Outputs function is placed in one of two places.
The code is placed directly in the model’s Outputs function if the
block does not reside in a nonvirtual subsystem, and in a subsystem’s
Outputs function if the block resides in a nonvirtual subsystem. For
example:
%% Function: Outputs ==========================================
%% Abstract:
%% Y[i] = fabs(U[i]) if U[i] is real or
%% Y[i] = sqrt(U[i].re^2 + U[i].im^2) if U[i] is complex.
%%
%function Outputs(block, system) Output
/* %<Type> Block: %<Name> */
%%
%assign inputIsComplex = LibBlockInputSignalIsComplex(0)
%assign RT_SQUARE = "RT_SQUARE"
%%
%assign rollVars = ["U", "Y"]
%if inputIsComplex
%roll sigIdx = RollRegions, lcv = RollThreshold, ...
block, "Roller", rollVars
%%
%assign ur = LibBlockInputSignal( 0, "", lcv, ...
"%<tRealPart>%<sigIdx>")
%assign ui = LibBlockInputSignal( 0, "", lcv, ...
"%<tImagPart>%<sigIdx>")
%%
%assign y = LibBlockOutputSignal(0, "", lcv, sigIdx)
%<y> = sqrt( %<RT_SQUARE>( %<ur> ) + %<RT_SQUARE>( %<ui> ) );
%endroll
%else
%roll sigIdx = RollRegions, lcv = RollThreshold, ...
block, "Roller", rollVars
%assign u = LibBlockInputSignal (0, "", lcv, sigIdx)
%assign y = LibBlockOutputSignal(0, "", lcv, sigIdx)
%<y> = fabs(%<u>);
%endroll
%endif
%endfunction
Note
Zero-crossing reset code is placed in the Outputs
function.
If you write TLC code to generate inlined code from an S-function, and if the TLC code
contains an Outputs function, you must modify the TLC code if
all of these conditions are true:
An output port uses or inherits constant sample time. The output port has a constant value.
The S-function is a multirate S-function or uses port-based sample times.
In this case, the TLC code must generate code for the constant-valued output port by
using the function OutputsForTID instead of the function
Outputs. For more information, see Specifying Constant Sample Time (Inf) for a Port.
Update(block, system)
Include an Update function if the block has code that needs to be
updated at each major time step. Code generated from this function is placed in either the
model’s or the subsystem’s Update function, depending on whether or not
the block resides in a nonvirtual subsystem. For example:
%% Function: Update ============================================
%% Abstract:
%% X[i] = U[i]
%%
%function Update(block, system) Output
/* %<Type> Block: %<Name> */
%assign rollVars = ["U", "Xd"]
%roll idx = RollRegions, lcv = RollThreshold, block, ...
"Roller", rollVars
%assign u = LibBlockInputSignal(0, "", lcv, idx)
%assign x = LibBlockDiscreteState("", lcv, idx)
%<x> = %<u>;
%endroll
%endfunction %% UpdateDerivatives(block, system)
Include a Derivatives function when generating code to compute the
block’s continuous states. Code generated from this function is placed in either the model’s
or the subsystem’s Derivatives function, depending on whether or not
the block resides in a nonvirtual subsystem.
Terminate(block, system)
Include a Terminate function to place code in MdlTerminate. User-defined S-function target files can use this function to save data, free memory, reset
hardware on the target, and so on. See tofile.tlc for an example of the
Terminate function.