Contenido principal

Customize Code Match and Replacement for Functions

This example shows how to use custom code replacement table entries to refine the match and replacement logic for functions. The example shows how to:

  • Modify a sine function replacement only if the integer size on the current target platform is 32 bits.

  • Change the replacement such that the implementation function passes in a degrees-versus-radians flag as an input argument.

To exercise the table entries that you create in this example, open CRLMath.slx, which is an ERT-based model with a sine function block.

model = "CRLMath";
open_system(model)

The model contains a Sin block with input and output that have Data type set to double.

In the Configuration Parameters, set Hardware Implementation > Device type to a target platform with a 32-bit integer size. For example, set it to x86-64 (Windows 32).

set_param(model,"ProdHWDeviceType",'Intel->x86-32 (Windows32)')

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

type TflCustomFunctionEntry.m
classdef TflCustomFunctionEntry < RTW.TflCFunctionEntryML
  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 will check additional data and perhaps modify
      % the implementation function.

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

      % Match sine function only if the target int size is 32 bits
      if targetBitPerInt == 32
        % Need to modify the default implementation, starting from a copy
        % of the standard TflCFunctionEntry.
        ent = RTW.TflCFunctionEntry(hThis);

        % If the target int size is 32 bits, the implementation function
        % takes an additional input flag argument indicating degress vs.
        % radians. The additional argument can be created and added either
        % in the CRL table definition file that instantiates this class, or
        % here in the class definition, as follows:
        createAndAddImplementationArg(ent, 'RTW.TflArgNumericConstant', ...
                                      'Name',           'u2', ...
                                      'IsSigned',       true, ...
                                      'WordLength',     32, ...
                                      'FractionLength', 0, ...
                                      'Value',          1);
      else
        error('Implementation supports only targets with 32 bits in the int data type')
      end
    end
  end
end

The derived class defines a do_match method with the 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 TflCFunctionEntry 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 a 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:

  • Creates a copy of an existing type of code replacement entry.

  • Adds required additional match criteria that the base class does not provide.

  • Makes required modifications to the implementation signature.

In this case, the do_match method must match only targetBitPerInt, representing the number of bits in the C int data type for the current target, to the value 32. If the code generator finds a match, the method sets the return handle and creates and adds an input argument. The input argument represents whether units are expressed as degrees or radians, to the replacement function signature.

Alternatively, create and add the additional implementation function argument for passing a units flag in each code replacement table definition file that instantiates this class. In that case, this class definition code does not create the argument. That code sets only the argument value.

Create a code replacement table definition file. For example, use the file crl_table_custom_sinfcn_double.m. This file defines a code replacement table that contains a function table entry for sine with double input and output. This entry instantiates the derived class from the previous step, TflCustomFunctionEntry.function hTable = crl_table_custom_sinfcn_double

open("crl_table_custom_sinfcn_double.m");

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

tbl = crl_table_custom_sinfcn_double
tbl = 
  TflTable with properties:

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

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

crviewer(crl_table_custom_sinfcn_double)

Register the code replacement library. Create a file named rtwTargetInfo.m. For this example, copy the contents from the example text file to rtwTargetInfo.m.

delete ("rtwTargetInfo.m")
copyfile CRLCustomEntriesRtwTargetInfo.txt rtwTargetInfo.m
type rtwTargetInfo.m
function rtwTargetInfo(cm)

cm.registerTargetInfo(@loc_register_crl);

end

function this = loc_register_crl

% Register a code replacement library for use with CRLMath
this(1) = RTW.TflRegistry;
this(1).Name = 'My Sin CRL';
this(1).TableList = {'crl_table_custom_sinfcn_double'};
this(1).BaseTfl = '';
this(1).TargetHWDeviceType = {'*'};
this(1).Description = '';

% Register a code replacement library for use with CRLMultiplicationDivision
this(2) = RTW.TflRegistry;
this(2).Name = 'My Element-Wise Multiplication CRL';
this(2).TableList = {'myElemMultCrlTable'};
this(2).BaseTfl = '';
this(2).TargetHWDeviceType = {'*'};
this(2).Description = '';

end

Refresh your current MATLAB session.

sl_refresh_customizations;

Set these configuration parameters for the model:

  • System target fileert.tlc

  • Code replacement librariesMy Sin CRL

set_param(model,"SystemTargetFile","ert.tlc");
set_param(model,"CodeReplacementLibrary",'My Sin CRL');
sl_refresh_customizations;

When you generate code from the model, the generated code calls the replacement source code.

slbuild(model);
### Searching for referenced models in model 'CRLMath'.
### Total of 1 models to build.
### Starting build procedure for: CRLMath
### Successful completion of code generation for: CRLMath

Build Summary

Top model targets:

Model    Build Reason                                         Status           Build Duration
=============================================================================================
CRLMath  Information cache folder or artifacts were missing.  Code generated.  0h 0m 45.451s

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 50.197s
cfile = fullfile("CRLMath_ert_rtw","CRLMath.c");
coder.example.extractLines(cfile,'  rtY.Y3 = asin(rtU.U3) + tanh(rtU.U3);','rtY.Y5 = mySin(rtU.U6, 1);',0, 1);
  /* Outport: '<Root>/Y5' incorporates:
   *  Inport: '<Root>/U6'
   *  Trigonometry: '<Root>/Trigonometric Function'
   */
  rtY.Y5 = mySin(rtU.U6, 1);