Contenido principal

Customize Code Match and Replacement for Fixed-Point Operations

This example shows how to create custom code replacement entries that add logic to the code match and replacement process for a scalar operation. Custom entries specify additional match criteria or modify the replacement function signature to meet application needs.

For example:

  • When fraction lengths are within a specific range, replace an operator with a fixed-point implementation function.

  • When a match occurs, modify the replacement function signature based on compile-time information, such as passing fraction-length values into the function.

This example modifies a fixed-point addition replacement such that the implementation function passes in the fraction lengths of the input and output data types as arguments.

Create a class that is derived from the base class RTW.TflCOperationEntryML. For this example, use the pre-written class TflCustomOperationEntry.

type TflCustomOperationEntry.m
classdef TflCustomOperationEntry < RTW.TflCOperationEntryML
  methods
    function ent = do_match(hThis, ...
        hCSO, ... %#ok
        targetBitPerChar, ... %#ok
        targetBitPerShort, ... %#ok
        targetBitPerInt, ... %#ok
        targetBitPerLong, ... %#ok
        targetBitPerLongLong) %#ok

      % DO_MATCH - Create a custom match function. The base class
      % checks the types of the arguments prior to calling this
      % method. This class will check additional data and can
      % modify the implementation function.

      % The base class checks word size and signedness. Slopes and biases
      % have been wildcarded, so the only additional checking to do is
      % to check that the biases are zero and that there are only three
      % conceptual arguments (one output, two inputs)

      ent = []; % default the return to empty, indicating the match failed

      if length(hCSO.ConceptualArgs) == 3 && ...
          hCSO.ConceptualArgs(1).Type.Bias == 0 && ...
          hCSO.ConceptualArgs(2).Type.Bias == 0 && ...
          hCSO.ConceptualArgs(3).Type.Bias == 0

        % Modify the default implementation. Since this is a
        % generator entry, a concrete entry is created using this entry
        % as a template. The type of entry being created is a standard
        % TflCOperationEntry. Using the standard operation entry
        % provides required information, and you do not need
        % a custom match function.
        ent = RTW.TflCOperationEntry(hThis);

        % Set the fraction-length values in the implementation function.
        ent.Implementation.Arguments(3).Value = ...
           -1.0*hCSO.ConceptualArgs(2).Type.FixedExponent;
        ent.Implementation.Arguments(4).Value = ...
           -1.0*hCSO.ConceptualArgs(3).Type.FixedExponent;
        ent.Implementation.Arguments(5).Value = ...
           -1.0*hCSO.ConceptualArgs(1).Type.FixedExponent;
      end
    end
  end
end

The derived class defines a do_match method with the following signature:function ent = do_match(hThis, ...

hCSO, ...

targetBitPerChar, ...

targetBitPerShort, ...

targetBitPerInt, ...

targetBitPerLong, ...

targetBitPerLongLong)

In the do_match signature:

  • ent is the return handle. If the match succeeds, ent is returned as a TflCOperationEntry handle. If the match fails, enty is returned as empty or as an error message that you specify by calling error in the entry.

  • hThis is the handle to the class instance.

  • hCSO is a handle to an object that the code generator creates for querying the library for a replacement.

  • Remaining arguments are the number of bits for various data types of the current target.

The do_match method adds match criteria that the base class does not provide. The method makes modifications to the implementation signature. In this case, the do_match method relies on the base class for checking word size and signedness. do_match must match only the number of conceptual arguments to the value 3 (two inputs and one output) and the bias for each argument to value 0. If the code generator finds a match, do_match:

  • Sets the return handle.

  • Removes slope and bias wild cards from the conceptual arguments (the match is for specific slope and bias values).

  • Writes fraction-length values for the inputs and output into replacement function arguments 3, 4, and 5.

You can create and add three additional implementation function arguments for passing fraction lengths in the class definition or in each code replacement entry definition that instantiates this class. This example creates the arguments, adds them to a code replacement table definition file, and sets them to specific values in the class definition code.

Create a code replacement table definition file. For this example, use crl_table_custom_add_ufix32.m.

open("crl_table_custom_add_ufix32.m");

This file defines a code replacement table that contains a single operator entry, an entry generator for unsigned 32-bit fixed-point addition operations, with arbitrary fraction-length values on the inputs and the output. The table entry:

  • Instantiates the derived class TflCustomOperationEntry from the previous step. If you want to replace word sizes and signedness attributes, you can use the same derived class, but not the same entry, because you cannot use a wild card with the WordLength and IsSigned arguments. For example, to support uint8, int8, uint16, int16, and int32, add five other distinct entries. To use different implementation functions for saturation and rounding modes other than overflow and round to floor, add entries for those match permutations.

  • Sets operator entry parameters with the call to the setTflCOperationEntryParameters function.

  • Calls the createAndAddConceptualArg function to create conceptual arguments y1, u1, and u2.

  • Calls createAndSetCImplementationReturn and createAndAddImplementationArg to define the signature for the replacement function. Three of the calls to createAndAddImplementationArg create implementation arguments to hold the fraction-length values for the inputs and output. Alternatively, the entry can omit those argument definitions. Instead, the do_match method of the derived class TflCustomOperationEntry can create and add the three implementation arguments. When the number of additional implementation arguments required can vary based on compile-time information, use the alternative approach.

  • Calls addEntry to add the entry to a code replacement table.

Check the validity of the operator entry. At the command prompt, invoke the table definition file.

tbl = crl_table_custom_add_ufix32
tbl = 
  TflTable with properties:

                Version: '1.0'
        ReservedSymbols: []
    StringResolutionMap: []
             AllEntries: [1×1 TflCustomOperationEntry]
            EnableTrace: 1

In the Code Replacement Viewer, view the table definition file.

crviewer(crl_table_custom_add_ufix32)

See Also

Topics