主要内容

Customize Code Match and Replacement for Matrix Operations

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

This example restricts the match criteria for an element-wise multiplication replacement to entries with a specific dimension range. When a match occurs, the custom do_match method modifies the replacement signature to pass the number of elements into the function.

Open the model CRLMultiplicationDivision.slx, which will use the code replacement library.

model = "CRLMultiplicationDivision";
open_system(model)

The model contains the block MultiplyElements, which has:

  • Two Input ports with Data type Int32 and Port dimensions set to [3 3]

  • Integer rounding mode set to Floor

  • Saturate on integer overflow de-selected

Create the replacement function source and header files. For this example, use the directory named src, which contains myMulImplLib.c and myMulImplLib.h.

type src/myMulImplLib.c
#include "myMulImplLib.h"

void myElemMul_s32(int32_T* u1, int32_T* u2, int32_T* y1, uint32_T numElements)
{
    int idx;
    for(idx = 0; idx<numElements; ++idx)
    {
        y1[idx] = u1[idx] * u2[idx];
    }
}
type src/myMulImplLib.h
#ifndef __myMulImplLib_h
#define __myMulImplLib_h

#include "rtwtypes.h"

void myElemMul_s32(int32_T* u1, int32_T* u2, int32_T* y1, uint32_T numElements);

#endif /*__myMulImplLib_h*/

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

type MyElemMultEntry.m
classdef MyElemMultEntry < RTW.TflCOperationEntryML
    methods
        function ent = do_match(hThis, ...
            hCSO, ... %#ok
            targetBitPerChar, ... %#ok
            targetBitPerShort, ... %#ok
            targetBitPerInt, ... %#ok
            targetBitPerLong, ... %#ok
            targetBitPerLongLong ) %#ok
            
            %  Fourth implementation arg represents number of elements for producing matches.
            assert(strcmp(hThis.Implementation.Arguments(4).Name,'numElements'));
            
            ent = RTW.TflCOperationEntry(hThis);
            
            % Calculate number of elements and set value of injected constant.
            ent.Implementation.Arguments(4).Value = prod(hCSO.ConceptualArgs(1).DimRange(1,:));
        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, ent is returned as empty or as an error message that you specify by calling error in the entry.

  • hThis is the handle to the derived 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 match criteria that the base class does not provide.

  • Makes changes to the implementation signature.

The do_match method relies on the base class for checking data types and dimension ranges. If the code generator finds a match, do_match:

  • Sets the return handle.

  • Uses the conceptual arguments to compute the number of elements in the array. In the replacement entry returned, sets the value of the constant implementation argument as the number of elements of the array.

Create a code replacement table definition file. For example, use the file myElemMultCrlTable.m.

open("myElemMultCrlTable.m")

This file defines a code replacement table that contains an operator entry generator for element-wise multiplication. The table entry:

  • Instantiates the derived class myElemMultEntry from the previous step.

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

  • Creates conceptual arguments y1, u1, and u2. The argument class RTW.TflArgMatrix specifies matrix arguments to match. The three arguments are set up to match 2-dimensional matrices with at least two elements in each dimension.

  • Calls the getTflArgFromString function to create a return value and four implementation arguments. Arguments u1 and u2 are the operands, y1 is the product, and the fourth argument is the number of elements. Alternatively, the do_match method of the derived class myElemMultEntry can create and add the 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 code replacement table entry. At the command prompt, invoke the table definition file.

tbl = myElemMultCrlTable
tbl = 
  TflTable with properties:

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

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

crviewer(myElemMultCrlTable)

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 by using the command sl_refresh_customizations.

sl_refresh_customizations;

Set these configuration parameters for the model:

  • System target fileert.tlc

  • Code replacement librariesMy CRL Lib

set_param(model,"SystemTargetFile","ert.tlc");
set_param(model,"CodeReplacementLibrary",'My Element-Wise Multiplication 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 'CRLMultiplicationDivision'.
### Total of 1 models to build.
### Starting build procedure for: CRLMultiplicationDivision
### Successful completion of code generation for: CRLMultiplicationDivision

Build Summary

Top model targets:

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

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 23.365s
cfile = fullfile("CRLMultiplicationDivision_ert_rtw","CRLMultiplicationDivision.c");
coder.example.extractLines(cfile, '  rtY.Out8 = (int16_T)(rtU.In15 / rtU.In16);','/* Model initialize function */',1, 0);
  rtY.Out8 = (int16_T)(rtU.In15 / rtU.In16);

  /* Outport: '<Root>/Out9' incorporates:
   *  Inport: '<Root>/In17'
   *  Inport: '<Root>/In18'
   *  Product: '<Root>/MultiplyElements'
   */
  myElemMul_s32(&rtU.In17[0], &rtU.In18[0], &rtY.Out9[0], 9U);
}

See Also

Topics