Creating Function Replacement Tables

Overview of Function Replacement Table Creation

To create a TFL table containing replacement information for supported functions and operators, you perform the following steps:

  1. Create a table definition M-file containing a function definition in the following general form:

    function hTable = tfl_table_name()
    %TFL_TABLE_NAME - Describe entries for a Target Function Library table.
    .
    .
    .

    For example, the following sample function definition is from the Target Function Libraries Quick-Start Example:

    function hTable = tfl_table_sinfcn()
    %TFL_TABLE_SINFCN - Describe function entries for a Target Function Library table.
    .
    .
    .
  2. Within the function body, instantiate a TFL table with a command such as the following:

    hTable = RTW.TflTable;
  3. Use the TFL table creation functions (listed in the table below) to add table entries representing your replacements for supported functions and operators. For each individual function or operator entry, you issue one or more function calls to

    1. Instantiate a table entry.

    2. Add conceptual arguments, implementation arguments, and other attributes to the entry.

    3. Add the entry to the table.

    Creating Table Entries describes this procedure in detail, including two methods for creating function entries. The following sample function entry is from the Target Function Libraries Quick-Start Example:

    % Create entry for double data type sine function replacement
    hTable.registerCFunctionEntry(100, 1, 'sin', 'double', 'sin_dbl', ...
                                                 'double', '<sin_dbl.h>','','');
  4. Save the table definition M-file using the name of the table definition function, for example, tfl_table_sinfcn.m.

After you have created a table definition M-file, you can do the following:

After you register a TFL with the Simulink software, it appears in the Simulink GUI and can be selected for use in building models.

The following table provides a functional grouping of the TFL table creation functions.

FunctionDescription
Table entry creation
addEntryAdd table entry to collection of table entries registered in TFL table
copyConceptualArgsToImplementationCopy conceptual argument specifications to matching implementation arguments for TFL table entry
createAndAddConceptualArgCreate conceptual argument from specified properties and add to conceptual arguments for TFL table entry
createAndAddImplementationArgCreate implementation argument from specified properties and add to implementation arguments for TFL table entry
createAndSetCImplementationReturnCreate implementation return argument from specified properties and add to implementation for TFL table entry
setTflCFunctionEntryParametersSet specified parameters for function entry in TFL table
setTflCOperationEntryParametersSet specified parameters for operator entry in TFL table
Alternative method for conceptual argument creation
addConceptualArgAdd conceptual argument to array of conceptual arguments for TFL table entry
getTflArgFromStringCreate TFL argument based on specified name and built-in data type
Alternative method for function entry creation
registerCFunctionEntryCreate TFL function entry based on specified parameters and register in TFL table
registerCPromotableMacroEntryCreate TFL promotable macro entry based on specified parameters and register in TFL table (for abs function replacement only)
Build information
addAdditionalHeaderFileAdd additional header file to array of additional header files for TFL table entry
addAdditionalIncludePathAdd additional include path to array of additional include paths for TFL table entry
addAdditionalLinkObjAdd additional link object to array of additional link objects for TFL table entry
addAdditionalLinkObjPathAdd additional link object path to array of additional link object paths for TFL table entry
addAdditionalSourceFileAdd additional source file to array of additional source files for TFL table entry
addAdditionalSourcePathAdd additional source path to array of additional source paths for TFL table entry
Reserved identifiers
setReservedIdentifiersRegister specified reserved identifiers to be associated with TFL table

Creating Table Entries

Overview of Table Entry Creation

You define TFL table entries by issuing TFL table creation function calls inside a table definition M-file. The function calls must follow a function declaration and a TFL table instantiation, such as the following:

function hTable = tfl_table_sinfcn()
%TFL_TABLE_SINFCN - Describe function entries for a Target Function Library table.

hTable = RTW.TflTable;

Within the function body, you use the TFL table creation functions to add table entries representing your replacements for supported functions and operators. For each individual function or operator entry, you issue one or more function calls to

  1. Instantiate a table entry.

  2. Add conceptual arguments, implementation arguments, and other attributes to the entry.

  3. Add the entry to the table.

The general method for creating function and operator entries, described in General Method for Creating Function and Operator Entries, uses the functions shown in the following table.

FunctionDescription
Table entry creation
addEntryAdd table entry to collection of table entries registered in TFL table
copyConceptualArgsToImplementationCopy conceptual argument specifications to matching implementation arguments for TFL table entry
createAndAddConceptualArgCreate conceptual argument from specified properties and add to conceptual arguments for TFL table entry
createAndAddImplementationArgCreate implementation argument from specified properties and add to implementation arguments for TFL table entry
createAndSetCImplementationReturnCreate implementation return argument from specified properties and add to implementation for TFL table entry
setTflCFunctionEntryParametersSet specified parameters for function entry in TFL table
setTflCOperationEntryParametersSet specified parameters for operator entry in TFL table
Alternative method for conceptual argument creation
addConceptualArgAdd conceptual argument to array of conceptual arguments for TFL table entry
getTflArgFromStringCreate TFL argument based on specified name and built-in data type

A simpler alternative creation method is available for function entries, with the constraints that input types must be uniform and implementation arguments must use default Simulink naming. The alternative method uses the following functions and is described in Alternative Method for Creating Function Entries.

FunctionDescription
Alternative method for function entry creation
registerCFunctionEntryCreate TFL function entry based on specified parameters and register in TFL table
registerCPromotableMacroEntryCreate TFL promotable macro entry based on specified parameters and register in TFL table (for abs function replacement only)

General Method for Creating Function and Operator Entries

The general workflow for creating TFL table entries applies equally to function and operator replacements, and involves the following steps.

  1. Within the function body of your table definition M-file, instantiate a TFL table entry for a function or operator, using one of the following lines of code:

    (RTW.TflCOperationEntryGenerator provides advanced fixed-point parameters, described in Mapping Fixed-Point Operators to Target-Specific Implementations, that are not available in RTW.TflCOperationEntry.)

  2. Set the table entry parameters, which are passed in parameter/value pairs to one of the following functions:

    For example:

    setTflCFunctionEntryParameters(fcn_entry, ...
                                   'Key',                 'sin', ...
                                   'Priority',            30, ...
                                   'ImplementationName',  'mySin', ...
                                   'ImplementationHeaderFile', 'basicMath.h',...
                                   'ImplementationSourceFile', 'basicMath.c');

    For detailed descriptions of the settable function and operator attributes, see the setTflCFunctionEntryParameters and setTflCOperationEntryParameters reference pages in the Real-Time Workshop Embedded Coder documentation.

  3. Create and add conceptual arguments to the function or operator entry. Output arguments must precede input arguments, and the function signature (including argument naming, order, and attributes) must fulfill the signature match sought by function or operator callers. Conceptual argument names follow the default Simulink naming convention:

    You can create and add conceptual arguments in either of two ways:

  4. Create and add implementation arguments, representing the signature of your implementation function, to the function or operator entry. The implementation argument order must match the conceptual argument order. You can create and add implementation arguments in either of two ways:

  5. Add the function or operator entry to the TFL table using the addEntry function. For example:

    addEntry(hTable, fcn_entry);

For complete examples of function entries and operator entries created using the general method, see Example: Mapping Floating-Point Math Functions to Target-Specific Implementations and Example: Mapping Operators to Target-Specific Implementations. For syntax examples, see the examples in the TFL table creation function reference pages in the Real-Time Workshop Embedded Coder documentation.

Alternative Method for Creating Function Entries

You can use a simpler alternative method for creating TFL function entries if your function implementation meets the following criteria:

The alternative method for creating function entries involves a single step. Call one of the following functions to create and add conceptual and implementation arguments and register the function entry:

For example:

hTable = RTW.TflTable;

registerCFunctionEntry(hTable, 100, 1, 'sqrt', 'double', ...
                       'sqrt', 'double', '<math.h>', '', '');

For detailed descriptions of the function arguments, see the registerCFunctionEntry and registerCPromotableMacroEntry reference pages in the Real-Time Workshop Embedded Coder documentation.

Example: Mapping Floating-Point Math Functions to Target-Specific Implementations

The Real-Time Workshop Embedded Coder software supports the following floating-point math functions for replacement with custom library functions using target function library (TFL) tables.

abscoslog10tan
acoscoshpow (Simulink)/power (Embedded MATLAB)tanh
asinexpsin 
atanfloorsinh 
ceillogsqrt 

The following example uses the method described in General Method for Creating Function and Operator Entries to create a TFL table entry for the sin function.

  1. Create and save the following TFL table definition file, tfl_table_sinfcn2.m. This file defines a TFL table containing a function replacement entry for the sin function.

    The function body sets selected sine function entry parameters, creates the y1 and u1 conceptual arguments individually, and then copies the conceptual arguments to the implementation arguments. Finally the function entry is added to the table.

    function hTable = tfl_table_sinfcn2()
    %TFL_TABLE_SINFCN2 - Describe function entry for a Target Function Library table.
    
    hTable = RTW.TflTable;
    
    % Create entry for sine function replacement
    fcn_entry = RTW.TflCFunctionEntry;
    setTflCFunctionEntryParameters(fcn_entry, ...
                                   'Key',                 'sin', ...
                                   'Priority',            30, ...
                                   'ImplementationName',  'mySin', ...
                                   'ImplementationHeaderFile', 'basicMath.h',...
                                   'ImplementationSourceFile', 'basicMath.c');
    
    createAndAddConceptualArg(fcn_entry, 'RTW.TflArgNumeric', ...
                              'Name',         'y1',... 
                              'IOType',       'RTW_IO_OUTPUT',...
                              'DataTypeMode', 'double');
    
    createAndAddConceptualArg(fcn_entry, 'RTW.TflArgNumeric', ...
                              'Name',         'u1', ...
                              'IOType',       'RTW_IO_INPUT',...
                              'DataTypeMode', 'double');
    
    copyConceptualArgsToImplementation(fcn_entry);
    
    addEntry(hTable, fcn_entry);
  2. Optionally, perform a quick check of the validity of the sine function entry by invoking the table definition file at the MATLAB command line (>> tbl = tfl_table_sinfcn2) and by viewing it in the TFL Viewer (>> RTW.viewTfl(tfl_table_sinfcn2)). For more information about validating TFL tables, see Examining and Validating Function Replacement Tables.

  3. Create and save the following TFL registration file, which references the tfl_table_sinfcn2 table.

    The file specifies that the TFL to be registered is named 'Sine Function Example 2' and consists of tfl_table_sinfcn2, with the default ANSI[1] math library as the base TFL table.

    function sl_customization(cm)
    % sl_customization function to register a target function library (TFL)
    
      % Register the TFL defined in local function locTflRegFcn
      cm.registerTargetInfo(@locTflRegFcn);
    
    end % End of SL_CUSTOMIZATION
    
    
    % Local function to define a TFL containing tfl_table_sinfcn2
    function thisTfl = locTflRegFcn
    
      % Instantiate a TFL registry entry
      thisTfl = RTW.TflRegistry;
    
      % Define the TFL properties
      thisTfl.Name = 'Sine Function Example 2'; 
      thisTfl.Description = 'Demonstration of sine function replacement';
      thisTfl.TableList = {'tfl_table_sinfcn2'};
      thisTfl.BaseTfl = 'C89/C90 (ANSI)';
      thisTfl.TargetHWDeviceType = {'*'};
    
    end % End of LOCTFLREGFCN

    Place this sl_customization.m file in the MATLAB search path or in the current working directory, so that the TFL is registered at each Simulink startup.

    For more information about registering TFLs with Simulink or Embedded MATLAB Coder software, see Registering Target Function Libraries.

  4. With your sl_customization.m file in the MATLAB search path or in the current working directory, open an ERT-based Simulink model and navigate to the Interface pane of the Configuration Parameters dialog box. Verify that the Target function library option lists the TFL name you specified and select it.

    Optionally, you can relaunch the TFL Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered TFLs, including Sine Function Example 2.

  5. Create an ERT-based model with a Trigonometric Function block set to the sine function, such as the following:

    Make sure that the TFL you registered, Sine Function Example 2, is selected for this model.

  6. Go to the Real-Time Workshop > Report pane of the Configuration Parameters dialog box and select the options Create code generation report and Model-to-code. Then go to the Real-Time Workshop pane, select the Generate code only option, and generate code for the model.

  7. Go to the model window and use model-to-code highlighting to trace the code generated using your TFL entry. For example, right-click the Trigonometric Function block and select Real-Time Workshop > Navigate to Code. This selection highlights the sin function code within the model step function in sinefcn.c. In this case, sin has been replaced with mySin in the generated code.

Example: Mapping the memcpy Function to a Target-Specific Implementation

The Real-Time Workshop Embedded Coder software supports the memcpy function for replacement with custom library functions using target function library (TFL) tables.

The following example uses the method described in General Method for Creating Function and Operator Entries to create a TFL table entry for the memcpy function.

  1. Create and save the following TFL table definition file, tfl_table_memcpy.m. This file defines a TFL table containing a function replacement entry for the memcpy function.

    The function body sets selected memcpy function entry parameters, creates the y1, u1, u2, and u3 conceptual arguments individually, adds each argument to the conceptual arguments array for the function, and then copies the conceptual arguments to the implementation arguments. Finally the function entry is added to the table.

    function hTable = tfl_table_memcpy()
    %TFL_TABLE_MEMCPY - Describe memcpy function entry for a TFL table.
    
    hTable = RTW.TflTable;
    
    % Create function replacement entry for void* memcpy(void*, void*, size_t)
    fcn_entry = RTW.TflCFunctionEntry;
    setTflCFunctionEntryParameters(fcn_entry, ...
                                   'Key',                 'memcpy', ...
                                   'Priority',            90, ...
                                   'ImplementationName',  'memcpy_int', ...
                                   'ImplementationHeaderFile', 'memcpy_int.h',...
                                   'SideEffects',         true);
    % Set SideEffects to 'true' for function returning void to prevent it being
    % optimized away
    
    arg = getTflArgFromString(hTable, 'y1', 'void*');
    arg.IOType = 'RTW_IO_OUTPUT';
    addConceptualArg(fcn_entry, arg);
    
    arg = getTflArgFromString(hTable, 'u1', 'void*');
    addConceptualArg(fcn_entry, arg);
    
    arg = getTflArgFromString(hTable, 'u2', 'void*');
    addConceptualArg(fcn_entry, arg);
    
    arg = getTflArgFromString(hTable, 'u3', 'size_t');
    addConceptualArg(fcn_entry, arg);
    
    copyConceptualArgsToImplementation(fcn_entry);
    addEntry(hTable, fcn_entry);
  2. Optionally, perform a quick check of the validity of the memcpy entry by invoking the table definition file at the MATLAB command line (>> tbl = tfl_table_memcpy) and by viewing it in the TFL Viewer (>> RTW.viewTfl(tfl_table_memcpy)). For more information about validating TFL tables, see Examining and Validating Function Replacement Tables.

  3. Create and save the following TFL registration file, which references the tfl_table_memcpy table.

    The file specifies that the TFL to be registered is named 'Memcpy Function Example' and consists of tfl_table_memcpy, with the default ANSI[2] math library as the base TFL table.

    function sl_customization(cm)
    % sl_customization function to register a target function library (TFL)
    
      % Register the TFL defined in local function locTflRegFcn
      cm.registerTargetInfo(@locTflRegFcn);
    
    end % End of SL_CUSTOMIZATION
    
    
    % Local function to define a TFL containing tfl_table_memcpy
    function thisTfl = locTflRegFcn
    
      % Instantiate a TFL registry entry
      thisTfl = RTW.TflRegistry;
    
      % Define the TFL properties
      thisTfl.Name = 'Memcpy Function Example'; 
      thisTfl.Description = 'Demonstration of memcpy function replacement';
      thisTfl.TableList = {'tfl_table_memcpy'};
      thisTfl.BaseTfl = 'C89/C90 (ANSI)';
      thisTfl.TargetHWDeviceType = {'*'};
    
    end % End of LOCTFLREGFCN

    Place this sl_customization.m file in the MATLAB search path or in the current working directory, so that the TFL is registered at each Simulink startup.

    For more information about registering TFLs with Simulink or Embedded MATLAB Coder software, see Registering Target Function Libraries.

  4. With your sl_customization.m file in the MATLAB search path or in the current working directory, open an ERT-based Simulink model and navigate to the Interface pane of the Configuration Parameters dialog box. Verify that the Target function library option lists the TFL name you specified and select it.

    Optionally, you can relaunch the TFL Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered TFLs, including Memcpy Function Example.

  5. Create an ERT-based model that uses memcpy for vector assignments. For example,

    1. Use In, Out, and Mux blocks to create the following model. (Alternatively, you can open rtwdemo_tflmath/Subsystem1 and copy the subsystem contents to a new model.)

    2. Select the diagram and use Edit > Subsystem to make it a subsystem.

    3. Select an ERT-based system target file on the Real-Time Workshop pane of the Configuration Parameters dialog box, and select the TFL you registered, Memcpy Function Example, on the Interface pane. You should also select a fixed-step solver on the Solver pane. Leave the memcpy options on the Optimization pane at their default settings, that is, Use memcpy for vector assignment selected, and Memcpy threshold (bytes) at 64. Apply the changes.

    4. Open Model Explorer and configure the Signal Attributes for the In1, In2, and In3 source blocks. For each, set Port dimensions to [1,100], and set Data type to int32. Apply the changes. Save the model. In this example, the model is saved to the name memcpyfcn.mdl.

  6. Go to the Real-Time Workshop > Report pane of the Configuration Parameters dialog box and select the Create code generation report. Then go to the Real-Time Workshop pane, select the Generate code only option, and generate code for the model. When code generation completes, the HTML code generation report is displayed.

  7. In the HTML code generation report, click on the model.c section (for example, memcpyfcn.c) and inspect the model step function to confirm that memcpy has been replaced with memcpy_int in the generated code.

Example: Mapping Nonfinite Support Utility Functions to Target-Specific Implementations

The Real-Time Workshop Embedded Coder software supports the following nonfinite support utility functions for replacement with custom library functions using target function library (TFL) tables.

GetInf
GetMinusInf
GetNaN

The following example uses the method described in General Method for Creating Function and Operator Entries to create TFL table entries for the nonfinite functions.

  1. Create and save the following TFL table definition file, tfl_table_nonfinite.m. This file defines a TFL table containing function replacement entries for the nonfinite functions.

    For each nonfinite function, the function body uses the local function locAddFcnEnt to create entries for single and double replacement. For each entry, the local function sets selected function entry parameters, creates the y1 and u1 conceptual arguments individually, and then copies the conceptual arguments to the implementation arguments. Finally the function entry is added to the table.

    function hTable = tfl_table_nonfinite()
    %TFL_TABLE_NONFINITE - Describe function entries for a TFL table.
    
    hTable = RTW.TflTable;
    
    %% Create enries for nonfinite support utility functions
    %locAddFcnEnt(hTable, key,          implName,        out,      in1,    hdr )
    locAddFcnEnt(hTable, 'getNaN',      'getNaN',       'double', 'void', 'nonfin.h');
    locAddFcnEnt(hTable, 'getNaN',      'getNaNF',      'single', 'void', 'nonfin.h');
    locAddFcnEnt(hTable, 'getInf',      'getInf',       'double', 'void', 'nonfin.h');
    locAddFcnEnt(hTable, 'getInf',      'getInfF',      'single', 'void', 'nonfin.h');
    locAddFcnEnt(hTable, 'getMinusInf', 'getMinusInf',  'double', 'void', 'nonfin.h');
    locAddFcnEnt(hTable, 'getMinusInf', 'getMinusInfF', 'single', 'void', 'nonfin.h');
    
    %% Local Function
    function locAddFcnEnt(hTable, key, implName, out, in1, hdr)
      if isempty(hTable)
        return;
      end
      
      fcn_entry = RTW.TflCFunctionEntry;
      setTflCFunctionEntryParameters(fcn_entry, ...
                                     'Key', key, ...
                                     'Priority', 90, ...
                                     'ImplementationName', implName, ...
                                     'ImplementationHeaderFile', hdr);
    
      arg = getTflArgFromString(hTable, 'y1', out);
      arg.IOType = 'RTW_IO_OUTPUT';
      addConceptualArg(fcn_entry, arg);
    
      arg = getTflArgFromString(hTable, 'u1', in1);
      addConceptualArg(fcn_entry, arg);
    
      copyConceptualArgsToImplementation(fcn_entry);
    
      addEntry(hTable, fcn_entry);
    
      %EOF
  2. Optionally, perform a quick check of the validity of the nonfinite function entries by invoking the table definition file at the MATLAB command line (>> tbl = tfl_table_nonfinite) and by viewing it in the TFL Viewer (>> RTW.viewTfl(tfl_table_nonfinite)). For more information about validating TFL tables, see Examining and Validating Function Replacement Tables.

  3. Create and save the following TFL registration file, which references the tfl_table_nonfinite table.

    The file specifies that the TFL to be registered is named 'Nonfinite Functions Example' and consists of tfl_table_nonfinite, with the default ANSI[3] math library as the base TFL table.

    function sl_customization(cm)
    % sl_customization function to register a target function library (TFL)
    
      % Register the TFL defined in local function locTflRegFcn
      cm.registerTargetInfo(@locTflRegFcn);
    
    end % End of SL_CUSTOMIZATION
    
    
    % Local function to define a TFL containing tfl_table_nonfinite
    function thisTfl = locTflRegFcn
    
      % Instantiate a TFL registry entry
      thisTfl = RTW.TflRegistry;
    
      % Define the TFL properties
      thisTfl.Name = 'Nonfinite Functions Example'; 
      thisTfl.Description = 'Demonstration of nonfinite functions replacement';
      thisTfl.TableList = {'tfl_table_nonfinite'};
      thisTfl.BaseTfl = 'C89/C90 (ANSI)';
      thisTfl.TargetHWDeviceType = {'*'};
    
    end % End of LOCTFLREGFCN

    Place this sl_customization.m file in the MATLAB search path or in the current working directory, so that the TFL is registered at each Simulink startup.

    For more information about registering TFLs with Simulink or Embedded MATLAB Coder software, see Registering Target Function Libraries.

  4. With your sl_customization.m file in the MATLAB search path or in the current working directory, open an ERT-based Simulink model and navigate to the Interface pane of the Configuration Parameters dialog box. Verify that the Target function library option lists the TFL name you specified and select it.

    Optionally, you can relaunch the TFL Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered TFLs, including Nonfinite Functions Example.

  5. Create an ERT-based model with a Math Function block set to the rem function, such as the following:

    Open Model Explorer and configure the Signal Attributes for the In1 and Constant source blocks. For each, set Data type to double. Apply the changes. Save the model. In this example, the model is saved to the name nonfinitefcns.mdl.

    Make sure that the TFL you registered, Nonfinite Functions Example, is selected for this model.

  6. Go to the Real-Time Workshop > Report pane of the Configuration Parameters dialog box and select the option Create code generation report. Then go to the Real-Time Workshop pane, select the Generate code only option, and generate code for the model.

  7. In the HTML code generation report, click on the rtnonfinite.c link and inspect the rt_InitInfAndNaN function to confirm that your replacements for nonfinite support functions are present in the generated code.

Example: Mapping Operators to Target-Specific Implementations

The Real-Time Workshop Embedded Coder software supports the following scalar operators for replacement with custom library functions using target function library (TFL) tables:

+ (addition)
(subtraction)
* (multiplication)
/ (division)

The following example uses the method described in General Method for Creating Function and Operator Entries to create a TFL table entry for the + (addition) operator.

  1. Create and save the following TFL table definition file, tfl_table_add_uint8.m. This file defines a TFL table containing an operator replacement entry for the + (addition) operator.

    The function body sets selected addition operator entry parameters, creates the y1, u1, and u2 conceptual arguments individually, and then copies the conceptual arguments to the implementation arguments. Finally, the operator entry is added to the table.

    function hTable = tfl_table_add_uint8
    %TFL_TABLE_ADD_UINT8 - Describe operator entry for a Target Function Library table.
    
    hTable = RTW.TflTable;
    
    % Create entry for addition of built-in uint8 data type
    % Saturation on, Rounding no preference
    op_entry = RTW.TflCOperationEntry;
    setTflCOperationEntryParameters(op_entry, ...
                        'Key',                      'RTW_OP_ADD', ...
                        'Priority',                 90, ...
                        'SaturationMode',           'RTW_SATURATE_ON_OVERFLOW', ...
                        'RoundingMode',             'RTW_ROUND_UNSPECIFIED', ...
                        'ImplementationName',       'u8_add_u8_u8', ...
                        'ImplementationHeaderFile', 'u8_add_u8_u8.h', ...
                        'ImplementationSourceFile', 'u8_add_u8_u8.c' );
    
    arg = getTflArgFromString(hTable, 'y1', 'uint8');
    arg.IOType = 'RTW_IO_OUTPUT';
    addConceptualArg(op_entry, arg);
    
    arg = getTflArgFromString(hTable, 'u1', 'uint8');
    addConceptualArg(op_entry, arg );
    
    arg = getTflArgFromString(hTable, 'u2', 'uint8');
    addConceptualArg(op_entry, arg );
    
    copyConceptualArgsToImplementation(op_entry);
    
    addEntry(hTable, op_entry);
  2. Optionally, perform a quick check of the validity of the sine function entry by invoking the table definition file at the MATLAB command line (>> tbl = tfl_table_add_uint8) and by viewing it in the TFL Viewer (>> RTW.viewTfl(tfl_table_add_uint8)).

    For more information about validating TFL tables, see Examining and Validating Function Replacement Tables.

  3. Create and save the following TFL registration file, which references the tfl_table_add_uint8 table.

    The file specifies that the TFL to be registered is named 'Addition Operator Example' and consists of tfl_table_add_uint8, with the default ANSI math library as the base TFL table.

    function sl_customization(cm)
    % sl_customization function to register a target function library (TFL)
    
      % Register the TFL defined in local function locTflRegFcn
      cm.registerTargetInfo(@locTflRegFcn);
    
    end % End of SL_CUSTOMIZATION
    
    
    % Local function to define a TFL containing tfl_table_add_uint8
    function thisTfl = locTflRegFcn
    
      % Instantiate a TFL registry entry
      thisTfl = RTW.TflRegistry;
    
      % Define the TFL properties
      thisTfl.Name = 'Addition Operator Example'; 
      thisTfl.Description = 'Demonstration of addition operator replacement';
      thisTfl.TableList = {'tfl_table_add_uint8'};
      thisTfl.BaseTfl = 'C89/C90 (ANSI)';
      thisTfl.TargetHWDeviceType = {'*'};
    
    end % End of LOCTFLREGFCN

    Place this sl_customization.m file in the MATLAB search path or in the current working directory, so that the TFL is registered at each Simulink startup.

    For more information about registering TFLs with Simulink or Embedded MATLAB Coder software, see Registering Target Function Libraries.

  4. With your sl_customization.m file in the MATLAB search path or in the current working directory, open an ERT-based Simulink model and navigate to the Interface pane of the Configuration Parameters dialog box. Verify that the Target function library option lists the TFL name you specified and select it.

    Optionally, you can relaunch the TFL Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered TFLs, including Addition Operator Example.

  5. Create an ERT-based model with an Add block, such as the following:

    Make sure that the TFL you registered, Addition Operator Example, is selected for this model.

  6. Go to the Real-Time Workshop > Report pane of the Configuration Parameters dialog box and select the options Create code generation report and Model-to-code. Then go to the Real-Time Workshop pane, select the Generate code only option, and generate code for the model.

  7. Go to the model window and use model-to-code highlighting to trace the code generated using your TFL entry. For example, right-click the Add block and select Real-Time Workshop > Navigate to Code. This selection highlights the Sum block code within the model step function in add8.c. In this case, code containing the + operator has been replaced with u8_add_u8_u8 in the generated code.

Mapping Fixed-Point Operators to Target-Specific Implementations

Overview of Fixed-Point Operator Replacement

The Real-Time Workshop Embedded Coder software supports TFL-based function replacement for the following scalar operations on fixed-point data types:

+ (addition)
(subtraction)
* (multiplication)
/ (division)

Fixed-point operator table entries can be defined as matching:

Fixed-Point Numbers and Arithmetic

Fixed-point numbers use integers and integer arithmetic to represent real numbers and arithmetic with the following encoding scheme:

where

The general equation for an operation between fixed-point operands is as follows:

The objective of TFL fixed-point operator replacement is to replace an operator that accepts and returns fixed-point or integer inputs and output with a function that accepts and returns built-in C numeric data types (not fixed-point data types). The following sections provide additional programming information for each supported operator.

Addition.   The operation V0 = V1 + V2 implies that

If an addition replacement function is defined such that the scaling on the operands and sum are equal and the net bias

is zero (for example, a function s8_add_s8_s8 that adds two signed 8-bit values and produces a signed 8-bit result), then the TFL operator entry must set the operator entry parameters SlopesMustBeTheSame and MustHaveZeroNetBias to true. (For parameter descriptions, see the reference page for the function setTflCOperationEntryParameters.)

Subtraction.   The operation V0 = V1 − V2 implies that

If a subtraction replacement function is defined such that the scaling on the operands and difference are equal and the net bias

is zero (for example, a function s8_sub_s8_s8 that subtracts two signed 8-bit values and produces a signed 8-bit result), then the TFL operator entry must set the operator entry parameters SlopesMustBeTheSame and MustHaveZeroNetBias to true. (For parameter descriptions, see the reference page for the function setTflCOperationEntryParameters.)

Multiplication.   There are different ways to specify multiplication replacements. The most direct way is to specify an exact match of the input and output types. This is feasible if a model contains only a few (known) slope and bias combinations. For this, use the TflCOperationEntry class and specify the exact values of slope and bias on each argument. For scenarios where there are numerous slope/bias combinations, it is not feasible to specify each value with a different TFL entry. For this, use a relative scaling factor (RSF) entry or a net slope entry:

Division.   There are different ways to specify division replacements. The most direct way is to specify an exact match of the input and output types. This is feasible if a model contains only a few (known) slope and bias combinations. For this, use the TflCOperationEntry class and specify the exact values of slope and bias on each argument. For scenarios where there are numerous slope/bias combinations, it is not feasible to specify each value with a different TFL entry. For this, use a relative scaling factor (RSF) entry or a net slope entry:

Creating Fixed-Point Operator Entries

To create TFL table entries for fixed-point operators, you use the General Method for Creating Function and Operator Entries and specify fixed-point parameter/value pairs to the functions shown in the following table.

FunctionDescription
createAndAddConceptualArgCreate conceptual argument from specified properties and add to conceptual arguments for TFL table entry
createAndAddImplementationArgCreate implementation argument from specified properties and add to implementation arguments for TFL table entry
createAndSetCImplementationReturnCreate implementation return argument from specified properties and add to implementation for TFL table entry
setTflCOperationEntryParametersSet specified parameters for operator entry in TFL table

The following table maps some common methods of matching TFL fixed-point operator table entries to the associated fixed-point parameters that you need to specify in your TFL table definition file.

To match...Instantiate class...Minimally specify parameters...
A specific binary-point-only scaling combination on the operator inputs and output


See Example: Creating Fixed-Point Operator Entries for Binary-Point-Only Scaling.
RTW.TflCOperationEntrycreateAndAddConceptualArg function:
  • CheckSlope: Specify the value true.

  • CheckBias: Specify the value true.

  • DataTypeMode (or DataType/Scaling equivalent): Specify fixed-point binary-point-only scaling.

  • FractionLength: Specify a fraction length (for example, 3).

A specific [slope bias] scaling combination on the operator inputs and output


See Example: Creating Fixed-Point Operator Entries for [Slope Bias] Scaling.
RTW.TflCOperationEntrycreateAndAddConceptualArg function:
  • CheckSlope: Specify the value true.

  • CheckBias: Specify the value true.

  • DataTypeMode (or DataType/Scaling equivalent): Specify fixed-point [slope bias] scaling.

  • Slope (or SlopeAdjustmentFactor/FixedExponent equvalent): Specify a slope value (for example, 15).

  • Bias: Specify a bias value (for example, 2).

Relative scaling between operator inputs and output (multiplication and division)


See Example: Creating Fixed-Point Operator Entries for Relative Scaling (Multiplication and Division).
RTW.TflCOperationEntryGeneratorsetTflCOperationEntryParameters function:
  • RelativeScalingFactorF: Specify the slope adjustment factor (F) part of the relative scaling factor, F2E (for example, 1.0).

  • RelativeScalingFactorE: Specify the fixed exponent (E) part of the relative scaling factor, F2E (for example, -3.0).

createAndAddConceptualArg function:

  • CheckSlope: Specify the value false.

  • CheckBias: Specify the value false.

  • DataType: Specify the value 'Fixed'.

Net slope between operator inputs and output (multiplication and division)


See Example: Creating Fixed-Point Operator Entries for Net Slope (Multiplication and Division).
RTW.TflCOperationEntryGenerator_NetSlopesetTflCOperationEntryParameters function:
  • NetSlopeAdjustmentFactor: Specify the slope adjustment factor (F) part of the net slope, F2E (for example, 1.0).

  • NetSlopeFixedExponent: Specify the fixed exponent (E) part of the net slope, F2E (for example, -3.0).

createAndAddConceptualArg function:

  • CheckSlope: Specify the value false.

  • CheckBias: Specify the value false.

  • DataType: Specify the value 'Fixed'.

Equal slope and zero net bias across operator inputs and output (addition and subtraction)


See Example: Creating Fixed-Point Operator Entries for Equal Slope and Zero Net Bias (Addition and Subtraction).
RTW.TflCOperationEntryGeneratorsetTflCOperationEntryParameters function:
  • SlopesMustBeTheSame: Specify the value true.

  • MustHaveZeroNetBias: Specify the value true.

createAndAddConceptualArg function:

  • CheckSlope: Specify the value false.

  • CheckBias: Specify the value false.

Example: Creating Fixed-Point Operator Entries for Binary-Point-Only Scaling

TFL table entries for operations on fixed-point data types can be defined as matching a specific binary-point-only scaling combination on the operator inputs and output. These binary-point-only scaling entries can map the specified binary-point-scaling combination to a replacement function for addition, subtraction, multiplication, or division.

The following example uses the method described in General Method for Creating Function and Operator Entries to create a TFL table entry for multiplication of fixed-point data types where arguments are specified with binary-point-only scaling. In this example:

hTable = RTW.TflTable;

op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
                    'Key',                      'RTW_OP_MUL', ...
                    'Priority',                 90, ...
                    'SaturationMode',           'RTW_SATURATE_ON_OVERFLOW', ...
                    'RoundingMode',             'RTW_ROUND_UNSPECIFIED', ...
                    'ImplementationName',       's32_mul_s16_s16_binarypoint', ...
                    'ImplementationHeaderFile', 's32_mul_s16_s16_binarypoint.h', ...
                    'ImplementationSourceFile', 's32_mul_s16_s16_binarypoint.c');

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric',...
                          'Name',           'y1', ... 
                          'IOType',         'RTW_IO_OUTPUT', ...
                          'CheckSlope',     true, ...
                          'CheckBias',      true, ...
                          'DataTypeMode',   'Fixed-point: binary point scaling', ...
                          'IsSigned',       true, ...
                          'WordLength',     32, ...
                          'FractionLength', 28);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'u1', ...
                          'IOType',         'RTW_IO_INPUT', ...
                          'CheckSlope',     true, ...
                          'CheckBias',      true, ...
                          'DataTypeMode',   'Fixed-point: binary point scaling', ...
                          'IsSigned',       true, ...
                          'WordLength',     16, ...
                          'FractionLength', 15);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'u2', ...
                          'IOType',         'RTW_IO_INPUT', ...
                          'CheckSlope',     true, ...
                          'CheckBias',      true, ...
                          'DataTypeMode',   'Fixed-point: binary point scaling', ...
                          'IsSigned',       true, ...
                          'WordLength',     16, ...
                          'FractionLength', 13);

createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
                              'Name',           'y1', ...
                              'IOType',         'RTW_IO_OUTPUT', ...
                              'IsSigned',       true, ...
                              'WordLength',     32, ...
                              'FractionLength', 0);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
                              'Name',           'u1', ...
                              'IOType',         'RTW_IO_INPUT', ...
                              'IsSigned',       true, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);
                               
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
                              'Name',           'u2', ...
                              'IOType',         'RTW_IO_INPUT', ...
                              'IsSigned',       true, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);

addEntry(hTable, op_entry);

To generate code using this table entry, you can follow the general procedure in Example: Mapping Operators to Target-Specific Implementations, substituting in the code above and an ERT-based model such as the following:

For this model,

Example: Creating Fixed-Point Operator Entries for [Slope Bias] Scaling

TFL table entries for operations on fixed-point data types can be defined as matching a specific [slope bias] scaling combination on the operator inputs and output. These [slope bias] scaling entries can map the specified [slope bias] combination to a replacement function for addition, subtraction, multiplication, or division.

The following example uses the method described in General Method for Creating Function and Operator Entries to create a TFL table entry for division of fixed-point data types where arguments are specified using [slope bias] scaling. In this example:

hTable = RTW.TflTable;

op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
                    'Key',                      'RTW_OP_DIV', ...
                    'Priority',                 90, ...
                    'SaturationMode',           'RTW_SATURATE_ON_OVERFLOW', ...
                    'RoundingMode',             'RTW_ROUND_CEILING', ...
                    'ImplementationName',       's16_div_s16_s16_slopebias', ...
                    'ImplementationHeaderFile', 's16_div_s16_s16_slopebias.h', ...
                    'ImplementationSourceFile', 's16_div_s16_s16_slopebias.c');

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'y1', ... 
                          'IOType',         'RTW_IO_OUTPUT', ...
                          'CheckSlope',     true, ...
                          'CheckBias',      true, ...
                          'DataTypeMode',   'Fixed-point: slope and bias scaling', ...
                          'IsSigned',       true, ...
                          'WordLength',     16, ...
                          'Slope',          15, ...
                          'Bias',           2);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'u1', ...
                          'IOType',         'RTW_IO_INPUT', ...
                          'CheckSlope',     true, ...
                          'CheckBias',      true, ...
                          'DataTypeMode',   'Fixed-point: slope and bias scaling', ...
                          'IsSigned',       true, ...
                          'WordLength',     16, ...
                          'Slope',          15, ...
                          'Bias',           2);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'u2', ...
                          'IOType',         'RTW_IO_INPUT', ...
                          'CheckSlope',     true, ...
                          'CheckBias',      true, ...
                          'DataTypeMode',   'Fixed-point: slope and bias scaling', ...
                          'IsSigned',       true, ...
                          'WordLength',     16, ...
                          'Slope',          13, ...
                          'Bias',           5);

createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
                              'Name',           'y1', ...
                              'IOType',         'RTW_IO_OUTPUT', ...
                              'IsSigned',       true, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
                              'Name',           'u1', ...
                              'IOType',         'RTW_IO_INPUT', ...
                              'IsSigned',       true, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);
                               
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
                              'Name',           'u2', ...
                              'IOType',         'RTW_IO_INPUT', ...
                              'IsSigned',       true, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);

addEntry(hTable, op_entry);

To generate code using this table entry, you can follow the general procedure in Example: Mapping Operators to Target-Specific Implementations, substituting in the code above and an ERT-based model such as the following:

For this model,

Example: Creating Fixed-Point Operator Entries for Relative Scaling (Multiplication and Division)

TFL table entries for multiplication or division of fixed-point data types can be defined as matching relative scaling between operator inputs and output. These relative scaling entries can map a range of slope and bias values to a replacement function for multiplication or division.

The following example uses the method described in General Method for Creating Function and Operator Entries to create a TFL table entry for division of fixed-point data types using a relative scaling factor. In this example:

hTable = RTW.TflTable;

op_entry = RTW.TflCOperationEntryGenerator;
setTflCOperationEntryParameters(op_entry, ...
                    'Key',                      'RTW_OP_DIV', ...
                    'Priority',                 90, ...
                    'SaturationMode',           'RTW_WRAP_ON_OVERFLOW', ...
                    'RoundingMode',             'RTW_ROUND_CEILING', ...
                    'RelativeScalingFactorF',   1.0, ...
                    'RelativeScalingFactorE',   -3.0, ...
                    'ImplementationName',       's16_div_s16_s16_rsf0p125', ...
                    'ImplementationHeaderFile', 's16_div_s16_s16_rsf0p125.h', ...
                    'ImplementationSourceFile', 's16_div_s16_s16_rsf0p125.c');

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'y1', ... 
                          'IOType',         'RTW_IO_OUTPUT', ...
                          'CheckSlope',     false, ...
                          'CheckBias',      false, ...
                          'DataType',       'Fixed', ...
                          'IsSigned',       true, ...
                          'WordLength',     16);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'u1', ...
                          'IOType',         'RTW_IO_INPUT', ...
                          'CheckSlope',     false, ...
                          'CheckBias',      false, ...
                          'DataType',       'Fixed', ...
                          'IsSigned',       true, ...
                          'WordLength',     16);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'u2', ...
                          'IOType',         'RTW_IO_INPUT', ...
                          'CheckSlope',     false, ...
                          'CheckBias',      false, ...
                          'DataType',       'Fixed', ...
                          'IsSigned',       true, ...
                          'WordLength',     16);

createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
                              'Name',           'y1', ...
                              'IOType',         'RTW_IO_OUTPUT', ...
                              'IsSigned',       true, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
                              'Name',           'u1', ...
                              'IOType',         'RTW_IO_INPUT', ...
                              'IsSigned',       true, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);
                               
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
                              'Name',           'u2', ...
                              'IOType',         'RTW_IO_INPUT', ...
                              'IsSigned',       true, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);

addEntry(hTable, op_entry);

To generate code using this table entry, you can follow the general procedure in Example: Mapping Operators to Target-Specific Implementations, substituting in the code above and an ERT-based model such as the following:

For this model,

Example: Creating Fixed-Point Operator Entries for Net Slope (Multiplication and Division)

TFL table entries for multiplication or division of fixed-point data types can be defined as matching net slope between operator inputs and output. These net slope entries can map a range of slope and bias values to a replacement function for multiplication or division.

The following example uses the method described in General Method for Creating Function and Operator Entries to create a TFL table entry for division of fixed-point data types using a net slope. In this example:

function hTable = make_net_slope_tfl_table()
%MAKE_NET_SLOPE_TFL_TABLE - Describe entries for a Target Function Library table.
hTable = RTW.TflTable;

wv = [16,32];
for iy = 1:2
  for inum = 1:2
    for iden = 1:2
      hTable = getDivOpEntry(hTable, ...
                             fixdt(1,wv(iy)),fixdt(1,wv(inum)),fixdt(1,wv(iden)));
    end
  end
end


%---------------------------------------------------------
function hTable = getDivOpEntry(hTable,dty,dtnum,dtden)
%---------------------------------------------------------
% Create an entry for division of fixed-point data types where
% arguments are specified using Slope and Bias scaling
% Saturation on, Rounding unspecified

funcStr = sprintf('user_div_%s_%s_%s',...
        typeStrFunc(dty),...
        typeStrFunc(dtnum),...
        typeStrFunc(dtden)); 

op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
setTflCOperationEntryParameters(op_entry, ...
                                'Key',                      'RTW_OP_DIV', ...
                                'Priority',                 90, ...
                                'SaturationMode',           'RTW_WRAP_ON_OVERFLOW',...
                                'RoundingMode',             'RTW_ROUND_UNSPECIFIED',...
                                'NetSlopeAdjustmentFactor', 1.0, ...
                                'NetFixedExponent',         0.0, ...
                                'ImplementationName',       funcStr, ...
                                'ImplementationHeaderFile', [funcStr,'.h'], ...
                                'ImplementationSourceFile', [funcStr,'.c'] );

createAndAddConceptualArg(op_entry, ...
                          'RTW.TflArgNumeric', ...
                          'Name',           'y1',... 
                          'IOType',         'RTW_IO_OUTPUT',...
                          'CheckSlope',     false,...
                          'CheckBias',      false,...
                          'DataTypeMode',   'Fixed-point: slope and bias scaling',...
                          'IsSigned',       dty.Signed,...
                          'WordLength',     dty.WordLength,...
                          'Bias',           0);

createAndAddConceptualArg(op_entry, ...
                          'RTW.TflArgNumeric',...
                          'Name',           'u1', ...
                          'IOType',         'RTW_IO_INPUT',...
                          'CheckSlope',     false,...
                          'CheckBias',      false,...
                          'DataTypeMode',   'Fixed-point: slope and bias scaling',...
                          'IsSigned',       dtnum.Signed,...
                          'WordLength',     dtnum.WordLength,...
                          'Bias',           0);

createAndAddConceptualArg(op_entry, ...
                          'RTW.TflArgNumeric', ...
                          'Name',           'u2', ...
                          'IOType',         'RTW_IO_INPUT',...
                          'CheckSlope',     false,...
                          'CheckBias',      false,...
                          'DataTypeMode',   'Fixed-point: slope and bias scaling',...
                          'IsSigned',       dtden.Signed,...
                          'WordLength',     dtden.WordLength,...
                          'Bias',           0);

arg = getTflArgFromString(hTable, 'y1', typeStrBase(dty));
op_entry.Implementation.setReturn(arg);

arg = getTflArgFromString(hTable, 'u1', typeStrBase(dtnum));
op_entry.Implementation.addArgument(arg);

arg = getTflArgFromString(hTable, 'u2',typeStrBase(dtden));
op_entry.Implementation.addArgument(arg);

addEntry(hTable, op_entry);

%-------------------------------------------------------------
function str = typeStrFunc(dt)
%-------------------------------------------------------------

if dt.Signed
    sstr = 's';
else
    sstr = 'u';
end
str = sprintf('%s%d',sstr,dt.WordLength); 

%-------------------------------------------------------------
function str = typeStrBase(dt)
%-------------------------------------------------------------

if dt.Signed
    sstr = ;
else
    sstr = 'u';
end
str = sprintf('%sint%d',sstr,dt.WordLength);

Example: Creating Fixed-Point Operator Entries for Equal Slope and Zero Net Bias (Addition and Subtraction)

TFL table entries for addition or subtraction of fixed-point data types can be defined as matching relative slope and bias values (equal slope and zero net bias) across operator inputs and output. These entries allow you to disregard specific slope and bias values and map relative slope and bias values to a replacement function for addition or subtraction.

The following example uses the method described in General Method for Creating Function and Operator Entries to create a TFL table entry for addition of fixed-point data types where slopes must be equal and net bias must be zero across the operator inputs and output. In this example:

hTable = RTW.TflTable;

op_entry = RTW.TflCOperationEntryGenerator;
setTflCOperationEntryParameters(op_entry, ...
                    'Key',                     'RTW_OP_ADD', ...
                    'Priority',                 90, ...
                    'SaturationMode',           'RTW_WRAP_ON_OVERFLOW', ...
                    'RoundingMode',             'RTW_ROUND_UNSPECIFIED', ...
                    'SlopesMustBeTheSame',      true, ...
                    'MustHaveZeroNetBias',      true, ...
                    'ImplementationName',       'u16_add_SameSlopeZeroBias', ...
                    'ImplementationHeaderFile', 'u16_add_SameSlopeZeroBias.h', ...
                    'ImplementationSourceFile', 'u16_add_SameSlopeZeroBias.c');

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'y1', ...
                          'IOType',         'RTW_IO_OUTPUT', ...
                          'CheckSlope',     false, ...
                          'CheckBias',      false, ...
                          'IsSigned',       false, ...
                          'WordLength',     16);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'u1', ...
                          'IOType',         'RTW_IO_INPUT', ...
                          'CheckSlope',     false, ...
                          'CheckBias',      false, ...
                          'IsSigned',       false, ...
                          'WordLength',     16);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'u2', ...
                          'IOType',         'RTW_IO_INPUT', ...
                          'CheckSlope',     false, ...
                          'CheckBias',      false, ...
                          'IsSigned',       false, ...
                          'WordLength',     16);

createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
                              'Name',           'y1', ...
                              'IOType',         'RTW_IO_OUTPUT', ...
                              'IsSigned',       false, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
                              'Name',           'u1', ...
                              'IOType',         'RTW_IO_INPUT', ...
                              'IsSigned',       false, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);
                               
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
                              'Name',           'u2', ...
                              'IOType',         'RTW_IO_INPUT', ...
                              'IsSigned',       false, ...
                              'WordLength',     16, ...
                              'FractionLength', 0);

addEntry(hTable, op_entry);

To generate code using this table entry, you can follow the general procedure in Example: Mapping Operators to Target-Specific Implementations, substituting in the code above and an ERT-based model such as the following:

For this model,

Specifying Build Information for Function Replacements

Functions for Specifying Table Entry Build Information

As you create TFL table entries for function or operator replacement, you specify the header and source file information for each function implementation using one of the following:

Also, each table entry can specify additional header files, source files, and object files to be included in model builds whenever the TFL table entry is matched and used to replace a function or operator in generated code. To add an additional header file, source file, or object file, use the following TFL table creation functions.

FunctionDescription
addAdditionalHeaderFileAdd additional header file to array of additional header files for TFL table entry
addAdditionalIncludePathAdd additional include path to array of additional include paths for TFL table entry
addAdditionalLinkObjAdd additional link object to array of additional link objects for TFL table entry
addAdditionalLinkObjPathAdd additional link object path to array of additional link object paths for TFL table entry
addAdditionalSourceFileAdd additional source file to array of additional source files for TFL table entry
addAdditionalSourcePathAdd additional source path to array of additional source paths for TFL table entry

For function descriptions and examples, see the function reference pages in the Real-Time Workshop Embedded Coder reference documentation.

Using RTW.copyFileToBuildDir to Copy Files to the Build Directory

If a TFL table entry uses header, source, or object files that reside in external directories, and if the table entry is matched and used to replace a function or operator in generated code, the external files will need to be copied to the build directory before the generated code is built. The RTW.copyFileToBuildDir function can be invoked after code generation to copy the table entry's specified header file, source file, additional header files, additional source files, and additional link objects to the build directory. The copied files are then available for use in the build process.

To direct that a table entry's external files should be copied to the build directory after code generation, specify the argument 'RTW.copyFileToBuildDir' to the genCallback parameter of the TFL function that you use to set the table entry parameters, among the following:

RTW.copyFileToBuildDir Examples

The following example defines a table entry for an optimized multiplication function that takes signed 32-bit integers and returns a signed 32-bit integer, taking saturation into account. Multiplications in the generated code will be replaced with calls to your optimized function. Your optimized function resides in an external directory and must be copied into the build directory to be compiled and linked into the application.

The multiplication table entry specifies the source and header file names as well as their full paths. To request the copy to be performed, the table entry specifies the argument 'RTW.copyFileToBuildDir' to the genCallback parameter of the setTflCOperationEntryParameters function. In this example, the header file s32_mul.h contains an inlined function that invokes assembly functions contained in s32_mul.s. If the table entry is matched and used to generate code, the RTW.copyFileToBuildDir function will copy the specified source and header files into the build directory.

function hTable = make_my_tfl_table

hTable = RTW.TflTable;

op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
                'Key',                      'RTW_OP_MUL', ...
                'Priority',                 100, ...
                'SaturationMode',           'RTW_SATURATE_ON_OVERFLOW', ...
                'RoundingMode',             'RTW_ROUND_UNSPECIFIED', ...
                'ImplementationName',       's32_mul_s32_s32_sat', ...
                'ImplementationHeaderFile', 's32_mul.h', ...
                'ImplementationSourceFile', 's32_mul.s', ...
                'ImplementationHeaderPath', {fullfile('$(MATLAB_ROOT)','tfl')}, ...
                'ImplementationSourcePath', {fullfile('$(MATLAB_ROOT)','tfl')}, ...
                'GenCallback',              'RTW.copyFileToBuildDir');
.
.
.
addEntry(hTable, op_entry);

The following example shows the use of the addAdditional* functions along with RTW.copyFileToBuildDir.

hTable = RTW.TflTable;

% Path to external source, header, and object files
libdir = fullfile('$(MATLAB_ROOT)','..', '..', 'lib');

op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
                'Key',                      'RTW_OP_ADD', ...
                'Priority',                 90, ...
                'SaturationMode',           'RTW_SATURATE_UNSPECIFIED', ...
                'RoundingMode',             'RTW_ROUND_UNSPECIFIED', ...
                'ImplementationName',       's32_add_s32_s32', ...
                'ImplementationHeaderFile', 's32_add_s32_s32.h', ...
                'ImplementationSourceFile', 's32_add_s32_s32.c'...
                'GenCallback',              'RTW.copyFileToBuildDir');

addAdditionalHeaderFile(op_entry, 'all_additions.h');
addAdditionalIncludePath(op_entry, fullfile(libdir, 'include'));
addAdditionalSourceFile(op_entry, 'all_additions.c');
addAdditionalSourcePath(op_entry, fullfile(libdir, 'src'));
addAdditionalLinkObj(op_entry, 'addition.o');
addAdditionalLinkObjsPath(op_entry, fullfile(libdir, 'bin'));
.
.
.
addEntry(hTable, op_entry);

Adding Target Function Library Reserved Identifiers

The Real-Time Workshop software reserves certain words for its own use as keywords of the generated code language. Real-Time Workshop keywords are reserved for use internal to the Real-Time Workshop software or C programming and should not be used in Simulink models as identifiers or function names. Real-Time Workshop reserved keywords include many TFL identifiers, the majority of which are function names, such as acos. To view the base list of TFL reserved identifiers, see Reserved Keywords in the Real-Time Workshop documentation.

In a TFL table, each function implementation name defined by a table entry is registered as a reserved identifier. You can register additional reserved identifiers for the table on a per-header-file basis. Providing additional reserved identifiers can help prevent duplicate symbols and other identifier-related compile and link issues.

To register additional TFL reserved identifiers, use the following function.

FunctionDescription
setReservedIdentifiersRegister specified reserved identifiers to be associated with TFL table

You can register up to four reserved identifier structures in a TFL table. One set of reserved identifiers can be associated with an arbitrary TFL, while the other three (if present) must be associated with ANSI, ISO®[4] , or GNU[5] libraries. The fo