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 subsystem
This 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 %endfunction
BlockTypeSetup(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 subsystem
As 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)> %endfunction
The 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 %endfunction
Disable(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 %% Start
InitializeConditions(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 %% Update
Derivatives(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.