Main Content

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 matlabroot/rtw/c/tlc/blocks/lookup2d.tlc for an example of the BlockInstanceSetup 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.

Related Topics