Skip to Main Content Skip to Search
Product Documentation

Code Replacement

Introduction to Code Replacement Libraries

Overview of Code Replacement Libraries

The Embedded Coder software provides the code replacement library (CRL) API, which allows you to create and register code replacement tables. When selected for a model, these CRL tables provide the basis for replacing default math functions and operators in your model code with target-specific code. The ability to control function and operator replacements potentially allows you to optimize target speed and memory and better integrate model code with external and legacy code.

A code replacement library (CRL) is a set of one or more code replacement tables that define the target-specific implementations of math functions and operators to be used in generating code for your Simulink model. The code generation software provides default CRLs, described in the following table. You select these CRLs from the Code replacement library drop-down list on the Interface pane of the Configuration Parameters dialog box.

CRLDescriptionContains Tables...
C89/C90 (ANSI)Generates calls to the ISO/IEC 9899:1990 C standard math library for floating-point functions.ansi_tfl_table_tmw.mat
C99 (ISO)Generates calls to the ISO/IEC 9899:1999 C standard math library.iso_tfl_table_tmw.mat
ansi_tfl_table_tmw.mat
GNU99 (GNU)Generates calls to the GNU[a] gcc math library, which provides C99 extensions as defined by compiler option -std=gnu99.gnu_tfl_table_tmw.mat
iso_tfl_table_tmw.mat
ansi_tfl_table_tmw.mat
C++ (ISO)Generates calls to the ISO/IEC 14882:2003 C++ standard math library.iso_cpp_tfl_table_tmw.mat
private_iso_cpp_tfl_table_tmw.mat
iso_tfl_table_tmw.mat
ansi_tfl_table_tmw.mat

[a] GNU is a registered trademark of the Free Software Foundation.

When a CRL contains multiple tables, the order in which they are listed reflects the order in which they are searched. The CRL API allows you to create your own CRLs, made up of your own function tables in combination with one of the default CRLs. For example, you could create a CRL for an embedded processor that combines some special-purpose function customizations with a processor-specific library of function and operator implementations:

MyProcessor (ANSI)Generates calls to my custom function implementations or a processor-specific library.crl_table_sinfcns.m
crl_table_myprocessor.m
ansi_tfl_table_tmw.mat

Each CRL code replacement table contains one or more table entries, with each table entry representing a potential replacement for a single math function or an operator. Each table entry provides a mapping between a conceptual view of the function or operator (similar to the Simulink block view of the function or operator) and a target-specific implementation of that function or operator.

The conceptual view of a function or operator is represented in a CRL table entry by the following elements, which identify the function or operator entry to the code generation process:

The target-specific implementation of a function or operator is represented in a CRL table entry by the following elements:

Additionally, a CRL table entry includes a priority value (0–100, with 0 as the highest priority), which defines the entry's priority relative to other entries in the table.

During code generation for your model, when the code generation process encounters a call site for a math function or operator, it creates and partially populates a CRL entry object, for the purpose of querying the CRL for a replacement function. The information provided for the CRL query includes the function or operator key and the conceptual argument list. The CRL entry object is then passed to the CRL. If a matching table entry exists in the CRL, a fully-populated CRL entry, including the implementation function name, argument list, and build information, is returned to the call site and used to generate code.

Within the CRL that is selected for your model, the tables that comprise the CRL are searched in the order in which they are listed (by RTW.viewTFL or by the CRL's Code replacement library tool tip). Within each table, if multiple matches are found for a CRL entry object, priority level determines the match that is returned. A higher-priority (lower-numbered) entry is used over a similar entry with a lower priority (higher number).

The CRL API supports the following functions for replacement with custom library functions using CRL tables:

Math Functions

absacosacoshasin
asinhatanatan2atanh
ceilcoscoshexactrSqrt
expfixfloorfrexp
hypotldexplnlog
log10maxminmod/fmod
powremroundrSqrt
saturatesignsinsincos
sinhsqrtroundtanh
Memory Utility Functions
memcmpmemcpymemsetmemset2zero1
Nonfinite Support Utility Functions2
getInfgetMinusInfgetNaNisInf3
isNaN3   
Notes:
1 Some target processors provide optimized memset functions for use when performing a memory set to zero. The CRL API supports replacing memset to zero functions with more efficient target-specific functions.
2 Replacement of nonfinite functions is supported for Simulink code generation (not for Stateflow or MATLAB Coder code generation).
3 Replacement of isInf and isNaN is supported only for complex floating-point inputs.

The CRL API also supports the following operations for replacement with custom library functions using CRL tables:

OperatorKeyScalar InputsNonscalar Inputs
Addition (+)RTW_OP_ADDYesYes
Subtraction (-)RTW_OP_MINUSYesYes
Multiplication (*)RTW_OP_MULYesYes, including the ability to map to Basic Linear Algebra Subroutine (BLAS) multiplication functions
Division (/)RTW_OP_DIVYes
Data type conversion (cast)RTW_OP_CASTYes
Shift left (<<)RTW_OP_SLYes, for integer and fixed-point data types
Shift right (>>)RTW_OP_SRA (arithmetic)1
RTW_OP_SRL (logical)
Yes, for integer and fixed-point data types
Element-wise matrix multiplication (.*)RTW_OP_ELEM_MUL2Yes
Matrix right division (/)RTW_OP_RDIV3Yes
Matrix left division (\)RTW_OP_LDIV3Yes
Matrix inversion (inv)RTW_OP_INV3Yes
Complex conjugationRTW_OP_CONJUGATEYesYes
Transposition (.')RTW_OP_TRANSYes
Hermitian (complex conjugate) transposition (')RTW_OP_HERMITIANYes
Multiplication with transpositionRTW_OP_TRMULYes, including the ability to map to BLAS multiplication functions
Multiplication with Hermitian transpositionRTW_OP_HMMULYes, including the ability to map to BLAS multiplication functions
Notes:
1 CRLs that provide arithmetic shift right implementations should also provide logical shift right implementations, because some arithmetic shift rights are converted to logical shift rights during code generation.
2 For scalar multiplication, use RTW_OP_MUL.
3 Matrix division and inversion are supported for Simulink code generation (not for Stateflow or MATLAB Coder code generation).

Code Replacement Libraries General Workflow

The general steps for creating and using a code replacement library are as follows:

  1. Create one or more CRL tables containing replacement entries for math operators (+, –, *, /) and functions using an API based on the MATLAB API. (The demo rtwdemo_crl_script provides example tables that can be used as a starting point for customization.)

  2. Register a code replacement library, consisting of one or more replacement tables, for use with Simulink or MATLAB Coder software. The MATLAB APIs sl_customization and rtwTargetInfo are provided for this purpose.

  3. Open your Simulink model and select the desired code replacement library from the Code replacement library drop-down list located on the Interface pane of the Configuration Parameters dialog box. For MATLAB Coder applications, instantiate a Simulink Coder configuration object, set the Code Replacement Library, and provide the configuration object in a call to the codegen function, as follows:

    cfg = coder.config('lib','ecoder',true);
    cfg.CodeReplacementLibrary = 'Addition & Subtraction Examples';
    codegen -config cfg addsub_tow_int16 -args {t,t};

  4. Build your Simulink model or MATLAB Coder application.

See the demo rtwdemo_crl_script, which illustrates how to use CRLs to replace operators and functions in generated code. With each example model included in this demo, a separate CRL is provided to illustrate the creation of operator and function replacements and how to register the replacements with Simulink software.

Code Replacement Libraries Quick-Start Example

This section steps you through a simple example of the complete CRL workflow. (The materials for this example can easily be created based on the file and model displays in this section.)

  1. Create and save a CRL table definition file that instantiates and populates a CRL table entry, such as the file crl_table_sinfcn.m shown below. This file creates function table entries for the sin function. For detailed information on creating table definition files for math functions and operators, see Create Code Replacement Tables.

    function hTable = crl_table_sinfcn()
    %CRL_TABLE_SINFCN - Describe function entries for a Code Replacement Library table.
    
    hTable = RTW.TflTable;
    
    % Create entry for double data type sine function replacement
    hTable.registerCFunctionEntry(100, 1, 'sin', 'double', 'sin_dbl', ...
                                                 'double', 'sin_dbl.h','','');
    
    % Create entry for single data type sine function replacement
    hTable.registerCFunctionEntry(100, 1, 'sin', 'single', 'sin_sgl', ...
                                                 'double', 'sin_sgl.h','','');

  2. As a first check of the validity of your table entries, invoke the CRL table definition file as follows:

    >> tbl = crl_table_sinfcn
     
    tbl =
     
    RTW.TflTable
                    Version: '1.0'
                 AllEntries: [2x1 RTW.TflCFunctionEntry]
            ReservedSymbols: []
        StringResolutionMap: []
    >> 

    Any errors found during the invocation are displayed.

  3. As a further check of your table entries, invoke the Code Replacement Viewer using the following MATLAB command:

    >> RTW.viewTfl(crl_table_sinfcn)

    Select entries in your table and verify that the graphical display of the contents of your table meets your expectations. (The Code Replacement Viewer can also help you debug issues with the order of entries in a table, the order of tables in a CRL, and function signature mismatches. For more information, see Examine and Validate Code Replacement Tables.)

  4. Create and save a CRL registration file that includes the crl_table_sinfcn table, such as the sl_customization.m file shown below. The file specifies that the CRL to be registered is named 'Sine Function Example' and consists of crl_table_sinfcn, with the default ANSI[2] math library as the base CRL table.

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

    If you place this sl_customization.m file in the MATLAB search path or in the current working folder, the CRL is registered at each Simulink startup.

      Tip   To refresh Simulink customizations within the current MATLAB session, use the command sl_refresh_customizations. (To refresh MATLAB Coder CRL registration information within a MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');.)

    For more information about registering CRLs with Simulink or MATLAB Coder software, see Register Code Replacement Libraries.

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

      Note   If you hover over the selected library with the cursor, a tool tip appears. This tip contains information derived from your CRL registration file, such as the CRL description and the list of tables it contains.

    Optionally, you can relaunch the Code Replacement Viewer, using the command RTW.viewTFL with no argument, to examine all registered CRLs, including Sine Function Example.

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

    Check that the CRL you registered, Sine Function Example, is selected for this model.

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

  8. Go to the model window and use model-to-code highlighting to trace the code generated using your CRL entry. For example, right-click the Trigonometric Function block and select Code Generation > 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 sin_dbl in the generated code.

  9. If functions were not replaced as you intended, you can use the techniques described in Examine and Validate Code Replacement Tables to help you determine why the code generation process was unable to match a function signature with the CRL table entry you created for it.

    For example, you can view the CRL cache hits and misses logged during the most recent build. For the code generation step in this example, there was one cache hit and zero cache misses, as shown in the following HitCache and MissCache entries:

    >> a=get_param('sinefcn','TargetFcnLibHandle')
     
    a =
     
    RTW.TflControl
            Version: '1.0'
           HitCache: [1x1 RTW.TflCFunctionEntry]
          MissCache: [0x1 handle]
        TLCCallList: [0x1 handle]
          TflTables: [2x1 RTW.TflTable]
    
    >> a.HitCache(1)
     
    ans =
     
    RTW.TflCFunctionEntry
                            Key: 'sin'
                       Priority: 100
                 ConceptualArgs: [2x1 RTW.TflArgNumeric]
                 Implementation: [1x1 RTW.CImplementation]
    .
    .
    .
    >> 

Create Code Replacement Tables

Overview of Code Replacement Table Creation

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

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

    function hTable = crl_table_name()
    %CRL_TABLE_NAME - Describe entries for a Code Replacement Library table.
    .
    .
    .

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

    function hTable = crl_table_sinfcn()
    %CRL_TABLE_SINFCN - Describe function entries for a Code Replacement Library table.
    .
    .
    .
  2. Within the function body, instantiate a CRL table with a command such as the following:

    hTable = RTW.TflTable;
  3. Use the CRL 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.

    Create Table Entries describes this procedure in detail, including two methods for creating function entries. The following sample function entry is from the Code Replacement 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 file using the name of the table definition function, for example, crl_table_sinfcn.m.

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

After you register a CRL 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 CRL table creation functions.

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

Create Table Entries

Overview of Table Entry Creation.  You define CRL table entries by issuing CRL table creation function calls inside a table definition file. The function calls must follow a function declaration and a CRL table instantiation, such as the following:

function hTable = crl_table_sinfcn()
%CRL_TABLE_SINFCN - Describe function entries for a Code Replacement Library table.

hTable = RTW.TflTable;

Within the function body, you use the CRL 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 CRL table
copyConceptualArgsToImplementationCopy conceptual argument specifications to matching implementation arguments for CRL table entry
createAndAddConceptualArgCreate conceptual argument from specified properties and add to conceptual arguments for CRL table entry
createAndAddImplementationArgCreate implementation argument from specified properties and add to implementation arguments for CRL table entry
createAndSetCImplementationReturnCreate implementation return argument from specified properties and add to implementation for CRL table entry
enableCPPEnable C++ support for function entry in CRL table
setNameSpaceSet name space for C++ function entry in CRL table
setTflCFunctionEntryParametersSet specified parameters for function entry in CRL table
setTflCOperationEntryParametersSet specified parameters for operator entry in CRL table
Alternative method for conceptual argument creation
addConceptualArgAdd conceptual argument to array of conceptual arguments for CRL table entry
getTflArgFromStringCreate CRL 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 CRL function entry based on specified parameters and register in CRL table
registerCPPFunctionEntryCreate CRL C++ function entry based on specified parameters and register in CRL table
registerCPromotableMacroEntryCreate CRL promotable macro entry based on specified parameters and register in CRL table (for abs function replacement only)

General Method for Creating Function and Operator Entries.  The general workflow for creating CRL table entries applies equally to function and operator replacements, and involves the following steps.

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

    fcn_entry = RTW.TflCFunctionEntry;Supports function replacement
    fcn_entry = MyCustomFunctionEntry;
    (where MyCustomFunctionEntry is a class derived from RTW.TflCFunctionEntry)
    Supports function replacement using custom CRL table entries, described in Refine CRL Matching and Replacement Using Custom CRL Table Entries
    op_entry = RTW.TflCOperationEntry;Supports operator replacement
    op_entry = RTW.TflCOperationEntryGenerator;Provides relative scaling factor (RSF) fixed-point parameters, described in Map Fixed-Point Operators to Target-Specific Implementations, that are not available in RTW.TflCOperationEntry
    op_entry = RTW.TflCOperationEntryGenerator_NetSlope;Provides net slope parameters, described in Map Fixed-Point Operators to Target-Specific Implementations, that are not available in RTW.TflCOperationEntry
    op_entry = RTW.TflBlasEntryGenerator;Supports replacement of nonscalar operators with MathWorks BLAS functions, described in Map Nonscalar Operators to Target-Specific Implementations
    op_entry = RTW.TflCBlasEntryGenerator;Supports replacement of nonscalar operators with ANSI/ISO C BLAS functions, described in Map Nonscalar Operators to Target-Specific Implementations
    op_entry = MyCustomOperationEntry;
    (where MyCustomOperationEntry is a class derived from RTW.TflCOperationEntry)
    Supports operator replacement using custom CRL table entries, described in Refine CRL Matching and Replacement Using Custom CRL Table Entries

  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.

  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:

    • For return argument, y1

    • For input argument names, u1, u2, ..., un

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

    • Call the createAndAddConceptualArg function to create the argument and add it to the table entry. For example:

      createAndAddConceptualArg(fcn_entry, 'RTW.TflArgNumeric', ...
                                'Name',         'y1',... 
                                'IOType',       'RTW_IO_OUTPUT',...
                                'DataTypeMode', 'double');
    • Call the getTflArgFromString function to create an argument based on a built-in data type, and then call the addConceptualArg function to add the argument to the table entry.

        Note   If you use getTflArgFromString, the IOType property of the created argument defaults to 'RTW_IO_INPUT', indicating an input argument. For an output argument, you must change the IOType value to 'RTW_IO_OUTPUT' by directly assigning the argument property, as shown in the following example.

      arg = getTflArgFromString(hTable, 'y1', 'int16');
      arg.IOType = 'RTW_IO_OUTPUT';
      addConceptualArg(op_entry, arg);

  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:

    • Call the copyConceptualArgsToImplementation function to populate all of the implementation arguments as copies of the previously created conceptual arguments. For example:

      copyConceptualArgsToImplementation(fcn_entry);
    • Call the createAndSetCImplementationReturn function to create the implementation return argument and add it to the table entry, and then call the createAndAddImplementationArg function to individually create and add each of your implementation arguments. This method allows you to vary argument attributes, including argument naming, as long as conceptual argument order is maintained. For example:

      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', 32, ...
                                    'FractionLength', 0 );
                                     
      createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
                                    'Name',       'u2', ...
                                    'IOType',     'RTW_IO_INPUT',...
                                    'IsSigned',   true,...
                                    'WordLength', 32, ...
                                    'FractionLength', 0 );

  5. Add the function or operator entry to the CRL 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 Map Math Functions to Target-Specific Implementations and Map Scalar Operators to Target-Specific Implementations. For syntax examples, see the examples in the CRL table creation function reference pages.

Alternative Method for Creating Function Entries.  You can use a simpler alternative method for creating CRL 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, registerCPPFunctionEntry, and registerCPromotableMacroEntry reference pages.

Map Math Functions to Target-Specific Implementations

The Embedded Coder software supports the following math functions for replacement with custom library functions using code replacement library (CRL) tables.

Math FunctionSimulink SupportStateflow SupportMATLAB functions and MATLAB Coder Support
abs1
  • Floating-point

  • Integer

  • Fixed-point

  • Floating-point

  • Integer

Floating-point
acos2Floating-pointFloating-pointFloating-point
acosh2Floating-pointNot available (NA)Not replaceable (NR)
asin2Floating-pointFloating-pointFloating-point
asinh2Floating-pointNANR
atan2Floating-pointFloating-pointFloating-point
atan2Floating-pointFloating-pointFloating-point
atanh2Floating-pointNANR
ceilFloating-pointFloating-pointFloating-point
cos2,3Floating-pointFloating-pointFloating-point
cosh2Floating-pointFloating-pointFloating-point
exactrSqrt
  • Floating-point

  • Integer

NANA
expFloating-pointFloating-pointFloating-point
fixFloating-pointNAFloating-point
floorFloating-pointFloating-pointFloating-point
frexpFloating-pointNANA
hypotFloating-pointNAFloating-point
ldexpFloating-pointFloating-pointFloating-point
lnFloating-pointNANA
logFloating-pointFloating-pointFloating-point
log10Floating-pointFloating-pointFloating-point
max
  • Floating-point

  • Integer

  • Fixed-point

  • Floating-point

  • Integer

  • Floating-point

  • Integer

min
  • Floating-point

  • Integer

  • Fixed-point

  • Floating-point

  • Integer

  • Floating-point

  • Integer

mod/fmod
  • Floating-point (mod)

  • Integer (mod)

Floating-point (fmod)NR
powFloating-pointFloating-pointFloating-point
remFloating-pointNAFloating-point
roundFloating-pointNAFloating-point
rSqrt
  • Floating-point

  • Integer

NANA
saturate
  • Floating-point

  • Integer

  • Fixed-point

NANA
sign
  • Floating-point

  • Integer

  • Fixed-point

NAFloating-point
sin2,3Floating-pointFloating-pointFloating-point
sincos2,3Floating-pointNANA
sinh2Floating-pointFloating-pointFloating-point
sqrt
  • Floating-point

  • Integer

  • Fixed-point

Floating-pointFloating-point
tan2Floating-pointFloating-pointFloating-point
tanh2Floating-pointFloating-pointFloating-point
Notes:
1abs is supported for wrap on integer overflow only; the block option Saturate on integer overflow must be cleared.
2 Complex/real type combinations are supported for acos, acosh, asin, asinh, atan, atanh, cos, cosh, sin, sincos, sinh, tan, and tanh for Simulink code generation (not for Stateflow or MATLAB Coder code generation). Combinations include complex input/complex output and real input/complex output.
3 The CORDIC approximation method is supported for sin, cos,and sincos for Simulink code generation (not for Stateflow or MATLAB Coder code generation).

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

  1. Create and save the following CRL table definition file, crl_table_sinfcn2.m. This file defines a CRL table containing a code 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 = crl_table_sinfcn2()
    %CRL_TABLE_SINFCN2 - Describe function entry for a Code Replacement 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 function entry by invoking the table definition file at the MATLAB command line (>> tbl = crl_table_sinfcn2) and by viewing it in the Code Replacement Viewer (>> RTW.viewTfl(crl_table_sinfcn2)). For more information about validating CRL tables, see Examine and Validate Code Replacement Tables.

  3. Create and save the following CRL registration file, which references the crl_table_sinfcn2 table.

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

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

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

      Tip   To refresh Simulink customizations within the current MATLAB session, use the command sl_refresh_customizations. (To refresh MATLAB Coder CRL registration information within a MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');.)

    For more information about registering CRLs with Simulink or MATLAB Coder software, see Register Code Replacement Libraries.

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

      Note   If you hover over the selected library with the cursor, a tool tip appears. This tip provides information derived from your CRL registration file, such as the CRL description and the list of tables it contains.

    Optionally, you can relaunch the Code Replacement Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered CRLs, 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:

    Check that the CRL you registered, Sine Function Example 2, is selected for this model.

  6. Go to the Code Generation > Report pane of the Configuration Parameters dialog box and select the options Create code generation report and Model-to-code. Then go to the Code Generation 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 CRL entry. For example, right-click the Trigonometric Function block and select Code Generation > 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.

Map the memcpy Function to a Target-Specific Implementation

The Embedded Coder software supports the following memory utility functions for replacement with custom library functions using code replacement library (CRL) tables.

memcmp
memcpy
memset
memset2zero

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

  1. Create and save the following CRL table definition file, crl_table_memcpy.m. This file defines a CRL table containing a code 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 = crl_table_memcpy()
    %CRL_TABLE_MEMCPY - Describe memcpy function entry for a CRL 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 = crl_table_memcpy) and by viewing it in the Code Replacement Viewer (>> RTW.viewTfl(crl_table_memcpy)). For more information about validating CRL tables, see Examine and Validate Code Replacement Tables.

  3. Create and save the following CRL registration file, which references the crl_table_memcpy table.

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

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

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

      Tip   To refresh Simulink customizations within the current MATLAB session, use the command sl_refresh_customizations. (To refresh MATLAB Coder CRL registration information within a MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');.)

    For more information about registering CRLs with Simulink or MATLAB Coder software, see Register Code Replacement Libraries.

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

      Note   If you hover over the selected library with the cursor, a tool tip appears. This tip provides information derived from your CRL registration file, such as the CRL description and the list of tables it contains.

    Optionally, you can relaunch the Code Replacement Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered CRLs, 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_crlmath/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 Code Generation pane of the Configuration Parameters dialog box, and select the CRL 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 > Signals and Parameters pane at their default settings, that is, Use memcpy for vector assignment is 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 Code Generation > Report pane of the Configuration Parameters dialog box and select the Create code generation report. Then go to the Code Generation 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.

Map Nonfinite Support Utility Functions to Target-Specific Implementations

The Embedded Coder software supports the following nonfinite support utility functions for replacement with custom library functions using code replacement library (CRL) tables.

GetInf
GetMinusInf
GetNaN
IsInf
IsNan

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

  1. Create and save the following CRL table definition file, crl_table_nonfinite.m. This file defines a CRL table containing code replacement entries for three nonfinite functions.

    For each 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 = crl_table_nonfinite()
    %CRL_TABLE_NONFINITE - Describe function entries for a CRL table.
    
    hTable = RTW.TflTable;
    
    %% Create entries 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 = crl_table_nonfinite) and by viewing it in the Code Replacement Viewer (>> RTW.viewTfl(crl_table_nonfinite)). For more information about validating CRL tables, see Examine and Validate Code Replacement Tables.

  3. Create and save the following CRL registration file, which references the crl_table_nonfinite table.

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

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

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

      Tip   To refresh Simulink customizations within the current MATLAB session, use the command sl_refresh_customizations. (To refresh MATLAB Coder CRL registration information within a MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');.)

    For more information about registering CRLs with Simulink or MATLAB Coder software, see Register Code Replacement Libraries.

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

      Note   If you hover over the selected library with the cursor, a tool tip appears. This tip provides information derived from your CRL registration file, such as the CRL description and the list of tables it contains.

    Optionally, you can relaunch the Code Replacement Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered CRLs, 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. Select the Support: non-finite numbers parameter on the Code Generation > Interface pane of the Configuration Parameters dialog box and configure the Signal Attributes for the In1 and Constant source blocks. For each source block, set Data type to double. Apply the changes. Save the model. In this example, the model is saved to the name nonfinitefcns.mdl.

    Check that the CRL you registered, Nonfinite Functions Example, is selected for this model.

  6. Go to the Code Generation > Report pane of the Configuration Parameters dialog box and select the option Create code generation report. Then go to the Code Generation 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.

Map Scalar Operators to Target-Specific Implementations

The Embedded Coder software supports the following scalar operators for replacement with custom library functions using code replacement library (CRL) tables:

OperatorKey
Addition (+)RTW_OP_ADD
Subtraction (-)RTW_OP_MINUS
Multiplication (*)RTW_OP_MUL
Division (/)RTW_OP_DIV
Data type conversion (cast)RTW_OP_CAST
Shift left (<<)
[integer and fixed-point data types]
RTW_OP_SL
Shift right (>>)
[integer and fixed-point data types]
RTW_OP_SRA (arithmetic)1
RTW_OP_SRL (logical)
Complex conjugationRTW_OP_CONJUGATE
Notes:
1 CRLs that provide arithmetic shift right implementations should also provide logical shift right implementations, because some arithmetic shift rights are converted to logical shift rights during code generation.

Unless otherwise stated, the listed operators are supported for the following input data types:

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

  1. Create and save the following CRL table definition file, crl_table_add_uint8.m. This file defines a CRL 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 = crl_table_add_uint8
    %CRL_TABLE_ADD_UINT8 - Describe operator entry for a Code Replacement 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 operator entry by invoking the table definition file at the MATLAB command line (>> tbl = crl_table_add_uint8) and by viewing it in the Code Replacement Viewer (>> RTW.viewTfl(crl_table_add_uint8)).

    For more information about validating CRL tables, see Examine and Validate Code Replacement Tables.

  3. Create and save the following CRL registration file, which references the crl_table_add_uint8 table.

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

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

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

      Tip   To refresh Simulink customizations within the current MATLAB session, use the command sl_refresh_customizations. (To refresh MATLAB Coder CRL registration information within a MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');.)

    For more information about registering CRLs with Simulink or MATLAB Coder software, see Register Code Replacement Libraries.

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

      Note   If you hover over the selected library with the cursor, a tool tip appears. This tip provides information derived from your CRL registration file, such as the CRL description and the list of tables it contains.

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

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

    Check that the CRL you registered, Addition Operator Example, is selected for this model.

  6. Go to the Code Generation > Report pane of the Configuration Parameters dialog box and select the options Create code generation report and Model-to-code. Then go to the Code Generation 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 CRL entry. For example, right-click the Add block and select Code Generation > 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.

Map Nonscalar Operators to Target-Specific Implementations

The Embedded Coder software supports the following nonscalar operators for replacement with custom library functions using code replacement library (CRL) tables:

OperatorKey
Addition (+)RTW_OP_ADD
Subtraction (-)RTW_OP_MINUS
Multiplication (*)RTW_OP_MUL
Element-wise matrix multiplication (.*)RTW_OP_ELEM_MUL1
Matrix right division (/)RTW_OP_RDIV2
Matrix left division (/)RTW_OP_LDIV2
Matrix inversion (inv)RTW_OP_INV2
Complex conjugationRTW_OP_CONJUGATE
Transposition (.')RTW_OP_TRANS
Hermitian (complex conjugate) transposition (')RTW_OP_HERMITIAN
Multiplication with transpositionRTW_OP_TRMUL
Multiplication with Hermitian transpositionRTW_OP_HMMUL
Notes:
1 For scalar multiplication, use RTW_OP_MUL.
2 Matrix division and inversion are supported for Simulink code generation (not for Stateflow or MATLAB Coder code generation).

These operators are supported for the following input data types:

Map Small Matrix Operations to Processor-Specific Intrinsic Functions.  You can efficiently implement small matrix operations by invoking processor-specific intrinsic functions. The following example uses the method described in General Method for Creating Function and Operator Entries to create a CRL table entry mapping small matrix sum operations to implementation functions that could invoke processor-specific intrinsic functions.

  1. Create and save the following CRL table definition file, crl_table_matrix_add_double.m. This file defines a CRL table containing two matrix operator replacement entries for the + (addition) operator and the double data type.

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

    To specify a matrix argument to createAndAddConceptualArg, use the CRL argument class RTW.TflArgMatrix and specify the base type and the dimensions for which the argument is valid. In this example, the first table entry specifies [2 2] and the second table entry specifies [3 3].

    function hTable = crl_table_matrix_add_double
    %CRL_TABLE_MATRIX_ADD_DOUBLE - Describe two matrix operator entries for a CRL table.
    
    hTable = RTW.TflTable;
    
    LibPath = fullfile(matlabroot, 'toolbox', 'rtw', 'rtwdemos', 'crl_demo');
    
    % Create table entry for matrix_sum_2x2_double
    op_entry = RTW.TflCOperationEntry;
    setTflCOperationEntryParameters(op_entry, ...
        'Key',                      'RTW_OP_ADD', ...
        'Priority',                 30, ...
        'SaturationMode',           'RTW_WRAP_ON_OVERFLOW', ...
        'ImplementationName',       'matrix_sum_2x2_double', ...
        'ImplementationHeaderFile', 'MatrixMath.h', ...
        'ImplementationSourceFile', 'MatrixMath.c', ...
        'ImplementationHeaderPath', LibPath, ...
        'ImplementationSourcePath', LibPath, ...
        'AdditionalIncludePaths',   {LibPath}, ...
        'GenCallback',              'RTW.copyFileToBuildDir', ...
        'SideEffects',              true);
    
    % Specify operands and result
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'y1', ...
                              'IOType',       'RTW_IO_OUTPUT', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 2]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
                              'Name',         'u1', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 2]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
                              'Name',         'u2', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 2]);
    
    % Specify replacement function signature
    arg = getTflArgFromString(hTable, 'y2', 'void');
    arg.IOType = 'RTW_IO_OUTPUT';
    op_entry.Implementation.setReturn(arg);
    arg = getTflArgFromString(hTable, 'u1', ['double' '*']);
    op_entry.Implementation.addArgument(arg);
    arg = getTflArgFromString(hTable, 'u2', ['double' '*']);
    op_entry.Implementation.addArgument(arg);
    arg = getTflArgFromString(hTable, 'y1', ['double' '*']);
    arg.IOType = 'RTW_IO_OUTPUT';
    op_entry.Implementation.addArgument(arg);
    
    addEntry(hTable, op_entry);
    
    % Create table entry for matrix_sum_3x3_double
    op_entry = RTW.TflCOperationEntry;
    setTflCOperationEntryParameters(op_entry, ...
        'Key',                      'RTW_OP_ADD', ...
        'Priority',                 30, ...
        'SaturationMode',           'RTW_WRAP_ON_OVERFLOW', ...
        'ImplementationName',       'matrix_sum_3x3_double', ...
        'ImplementationHeaderFile', 'MatrixMath.h', ...
        'ImplementationSourceFile', 'MatrixMath.c', ...
        'ImplementationHeaderPath', LibPath, ...
        'ImplementationSourcePath', LibPath, ...
        'AdditionalIncludePaths',   {LibPath}, ...
        'GenCallback',              'RTW.copyFileToBuildDir', ...
        'SideEffects',              true);
    
    % Specify operands and result
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'y1', ...
                              'IOType',       'RTW_IO_OUTPUT', ...
                              'BaseType',     'double', ...
                              'DimRange',     [3 3]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
                              'Name',         'u1', ...
                              'BaseType',     'double', ...
                              'DimRange',     [3 3]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
                              'Name',         'u2', ...
                              'BaseType',     'double', ...
                              'DimRange',     [3 3]);
    
    % Specify replacement function signature
    arg = getTflArgFromString(hTable, 'y2', 'void');
    arg.IOType = 'RTW_IO_OUTPUT';
    op_entry.Implementation.setReturn(arg);
    arg = getTflArgFromString(hTable, 'u1', ['double' '*']);
    op_entry.Implementation.addArgument(arg);
    arg = getTflArgFromString(hTable, 'u2', ['double' '*']);
    op_entry.Implementation.addArgument(arg);
    arg = getTflArgFromString(hTable, 'y1', ['double' '*']);
    arg.IOType = 'RTW_IO_OUTPUT';
    op_entry.Implementation.addArgument(arg);
    
    addEntry(hTable, op_entry);
  2. Optionally, perform a quick check of the validity of the operator entries by invoking the table definition file at the MATLAB command line (>> tbl = crl_table_matrix_add_double) and by viewing it in the Code Replacement Viewer (>> RTW.viewTfl(crl_table_matrix_add_double)).

    For more information about validating CRL tables, see Examine and Validate Code Replacement Tables.

  3. Create and save the following CRL registration file, which references the crl_table_matrix_add_double table.

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

    function sl_customization(cm)
    % sl_customization function to register a code replacement library (CRL)
    
      % Register the CRL defined in local function locCrlRegFcn
      cm.registerTargetInfo(@locCrlRegFcn);
    
    end % End of SL_CUSTOMIZATION
    
    
    % Local function to define a CRL containing crl_table_matrix_add_double
    function thisCrl = locCrlRegFcn
    
      % Instantiate a CRL registry entry
      thisCrl = RTW.TflRegistry;
    
      % Define the CRL properties
      thisCrl.Name = 'Matrix Addition Operator Example'; 
      thisCrl.Description = 'Demonstration of matrix addition operator replacement';
      thisCrl.TableList = {'crl_table_matrix_add_double'};
      thisCrl.BaseTfl = 'C89/C90 (ANSI)';
      thisCrl.TargetHWDeviceType = {'*'};
    
    end % End of LOCCRLREGFCN

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

      Tip   To refresh Simulink customizations within the current MATLAB session, use the command sl_refresh_customizations. (To refresh MATLAB Coder CRL registration information within a MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');.)

    For more information about registering CRLs with Simulink or MATLAB Coder software, see Register Code Replacement Libraries.

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

      Note   If you hover over the selected library with the cursor, a tool tip appears. This tip provides information derived from your CRL registration file, such as the CRL description and the list of tables it contains.

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

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

    Configure the Signal Attributes for the In1 and In2 source blocks. For each source block, set Port dimensions to [3 3] and set the Data type to double. Also, go to the Solver pane of the Configuration Parameters dialog box and select a fixed-step, discrete solver with a fixed-step size such as 0.1. Apply the changes. Save the model. In this example, the model is saved to the name matrixadd.mdl.

    Check that the CRL you registered, Matrix Addition Operator Example, is selected for this model.

  6. Go to the Code Generation > Report pane of the Configuration Parameters dialog box and select the options Create code generation report and Model-to-code. Then go to the Code Generation 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 CRL entry. For example, right-click the Add block and select Code Generation > Navigate to Code. This selection highlights the Sum block code within the model step function in matrixadd.c. In this case, code containing the + operator has been replaced with matrix_sum_3x3_double in the generated code.

      Note   Optionally, you can reconfigure the In1 and In2 block Port dimensions to [2 2], regenerate code, and observe that code containing the + operator is replaced with matrix_sum_2x2_double.

Map Matrix Multiplication to MathWorks BLAS Functions.  You can use CRL tables to map nonscalar multiplication operations to the Basic Linear Algebra Subroutine (BLAS) multiplication functions xgemm and xgemv. The following example uses the method described in General Method for Creating Function and Operator Entries to create a CRL table entry mapping floating-point matrix/matrix and matrix/vector multiplication operations to MathWorks BLAS library multiplication functions.

BLAS libraries support matrix/matrix multiplication in the form of , where means X, transposition of X, or Hermitian transposition of X. However, CRLs support only the limited case of . Correspondingly, although BLAS libraries support matrix/vector multiplication in the form of , CRLs support only the limited case of .

  1. Create and save the following CRL table definition file, crl_table_tmwblas_mmult_double.m. This file defines a CRL table containing dgemm and dgemv replacement entries for the matrix multiplication operator and the double data type.

    For each entry, the function body sets selected matrix multiplication operator entry parameters, creates the y1, u1, and u2 conceptual arguments individually, and then configures special implementation arguments that are required for dgemm and dgemv replacements. Finally, each operator entry is added to the table.

    To specify a matrix argument to createAndAddConceptualArg, use the CRL argument class RTW.TflArgMatrix and specify the base type and the dimensions for which the argument is valid. This type of table entry supports a range of dimensions specified in the format [Dim1Min Dim2Min ... DimNMin; Dim1Max Dim2Max ... DimNMax]. For example, [2 2; inf inf] means any two-dimensional matrix of size 2x2 or larger. In this example, the conceptual output argument for the dgemm32 entry for matrix/matrix multiplication replacement specifies dimensions [2 2; inf inf], while the conceptual output argument for the dgemv32 entry for matrix/vector multiplication replacement specifies dimensions [2 1; inf 1].

    function hTable = crl_table_tmwblas_mmult_double
    %CRL_TABLE_TMWBLAS_MMULT_DOUBLE - Describe two mmult operator entries for CRL table.
    
    hTable = RTW.TflTable;
    
    % Define library path for Windows or UNIX
    arch = computer('arch');
    if ~ispc
        LibPath = fullfile('$(MATLAB_ROOT)', 'bin', arch);
    else
        % Use Stateflow to get the compiler info
        compilerInfo = sf('Private','compilerman','get_compiler_info');
        compilerName = compilerInfo.compilerName;
        if strcmp(compilerName, 'msvc90') || ...
                strcmp(compilerName, 'msvc80') || ...
                strcmp(compilerName, 'msvc71') || ...
                strcmp(compilerName, 'msvc60'), ...
                compilerName = 'microsoft';
        end
        LibPath = fullfile('$(MATLAB_ROOT)', 'extern', 'lib', arch, compilerName);
    end
    
    % Create table entry for dgemm32
    op_entry = RTW.TflBlasEntryGenerator;
    if ispc
        libExt = 'lib';
    elseif ismac
        libExt = 'dylib';
    else
        libExt = 'so';
    end
    setTflCOperationEntryParameters(op_entry, ...
        'Key',                      'RTW_OP_MUL', ...
        'Priority',                 100, ...
        'ImplementationName',       'dgemm32', ...
        'ImplementationHeaderFile', 'blascompat32.h', ...
        'ImplementationHeaderPath', fullfile('$(MATLAB_ROOT)','extern','include'), ...
        'AdditionalLinkObjs',       {['libmwblascompat32.' libExt]}, ...
        'AdditionalLinkObjsPaths',  {LibPath}, ...
        'SideEffects',              true);
    
    % Specify operands and result
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'y1', ...
                              'IOType',       'RTW_IO_OUTPUT', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 2; inf inf]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'u1', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 2; inf inf]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'u2', ...
                              'BaseType',     'double', ...
                              'DimRange',     [1 1; inf inf]);
    
    % Using RTW.TflBlasEntryGenerator for xgemm requires the following
    % implementation signature:
    %
    % void f(char* TRANSA, char* TRANSB, int* M, int* N, int* K,
    %        type* ALPHA, type* u1, int* LDA, type* u2, int* LDB,
    %        type* BETA, type* y, int* LDC)
    %
    % Upon a match, the CRL entry will compute the 
    % values for M, N, K, LDA, LDB, and LDC and insert them into the
    % generated code. TRANSA and TRANSB both will be set to 'N'.
    
    % Specify replacement function signature
    
    arg = getTflArgFromString(hTable, 'y2', 'void');
    arg.IOType = 'RTW_IO_OUTPUT';
    op_entry.Implementation.setReturn(arg);
    
    arg = RTW.TflArgCharConstant('TRANSA');
    % Possible values for PassByType property are
    %  RTW_PASSBY_AUTO, RTW_PASSBY_POINTER,
    %  RTW_PASSBY_VOID_POINTER, RTW_PASSBY_BASE_POINTER
    arg.PassByType = 'RTW_PASSBY_POINTER';
    op_entry.Implementation.addArgument(arg);
    
    arg = RTW.TflArgCharConstant('TRANSB');
    arg.PassByType = 'RTW_PASSBY_POINTER';
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'M', 'integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'N', 'integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'K', 'integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'ALPHA', 'double', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'u1', ['double' '*']);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'u2', ['double' '*']);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'LDB', 'integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'BETA', 'double', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'y1', ['double' '*']);
    arg.IOType = 'RTW_IO_OUTPUT';
    arg.PassByType = 'RTW_PASSBY_POINTER';
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'LDC', 'integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);  
    
    addEntry(hTable, op_entry);
    
    % Create table entry for dgemv32
    op_entry = RTW.TflBlasEntryGenerator;
    if ispc
        libExt = 'lib';
    elseif ismac
        libExt = 'dylib';
    else
        libExt = 'so';
    end
    setTflCOperationEntryParameters(op_entry, ...
        'Key',                      'RTW_OP_MUL', ...
        'Priority',                 100, ...
        'ImplementationName',       'dgemv32', ...
        'ImplementationHeaderFile', 'blascompat32.h', ...
        'ImplementationHeaderPath', fullfile('$(MATLAB_ROOT)','extern','include'), ...
        'AdditionalLinkObjs',       {['libmwblascompat32.' libExt]}, ...
        'AdditionalLinkObjsPaths',  {LibPath},...
        'SideEffects',              true);
    
    % Specify operands and result
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'y1', ...
                              'IOType',       'RTW_IO_OUTPUT', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 1; inf 1]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'u1', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 2; inf inf]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
                              'Name',         'u2', ...
                              'BaseType',     'double', ...
                              'DimRange',     [1 1; inf 1]);
    
    % Using RTW.TflBlasEntryGenerator for xgemv requires the following
    % implementation signature:
    %
    % void f(char* TRANS, int* M, int* N,
    %        type* ALPHA, type* u1, int* LDA, type* u2, int* INCX,
    %        type* BETA, type* y, int* INCY)
    %
    % Upon a match, the CRL entry will compute the 
    % values for M, N, LDA, INCX, and INCY, and insert them into the
    % generated code. TRANS will be set to 'N'.
    
    % Specify replacement function signature
    
    arg = getTflArgFromString(hTable, 'y2', 'void');
    arg.IOType = 'RTW_IO_OUTPUT';
    op_entry.Implementation.setReturn(arg);
    
    arg = RTW.TflArgCharConstant('TRANS');
    arg.PassByType = 'RTW_PASSBY_POINTER';
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'M', 'integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'N', 'integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'ALPHA', 'double', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'u1', ['double' '*']);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'u2', ['double' '*']);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'INCX','integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'BETA', 'double', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'y1', ['double' '*']);
    arg.IOType = 'RTW_IO_OUTPUT';
    arg.PassByType = 'RTW_PASSBY_POINTER';
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'INCY', 'integer', 0);
    arg.PassByType = 'RTW_PASSBY_POINTER';
    arg.Type.ReadOnly = true;
    op_entry.Implementation.addArgument(arg); 
    
    addEntry(hTable, op_entry);
  2. Optionally, perform a quick check of the validity of the operator entries by invoking the table definition file at the MATLAB command line (>> tbl = crl_table_tmwblas_mmult_double) and by viewing it in the Code Replacement Viewer (>> RTW.viewTfl(crl_table_tmwblas_mmult_double)).

    For more information about validating CRL tables, see Examine and Validate Code Replacement Tables.

  3. Create and save the following CRL registration file, which references the crl_table_tmwblas_mmult_double table.

    The file specifies that the CRL to be registered is named 'MathWorks BLAS Matrix Multiplication Operator Example' and consists of crl_table_tmwblas_mmult_double, with the default ANSI math library as the base CRL table.

    function sl_customization(cm)
    % sl_customization function to register a code replacement library (CRL)
    
      % Register the CRL defined in local function locCrlRegFcn
      cm.registerTargetInfo(@locCrlRegFcn);
    
    end % End of SL_CUSTOMIZATION
    
    
    % Local function to define a CRL containing crl_table_tmwblas_mmult_double
    function thisCrl = locCrlRegFcn
    
      % Instantiate a CRL registry entry
      thisCrl = RTW.TflRegistry;
    
      % Define the CRL properties
      thisCrl.Name = 'MathWorks BLAS Matrix Multiplication Operator Example'; 
      thisCrl.Description = 'Demonstration of MathWorks BLAS mmult operator replacement';
      thisCrl.TableList = {'crl_table_tmwblas_mmult_double'};
      thisCrl.BaseTfl = 'C89/C90 (ANSI)';
      thisCrl.TargetHWDeviceType = {'*'};
    
    end % End of LOCCRLREGFCN

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

      Tip   To refresh Simulink customizations within the current MATLAB session, use the command sl_refresh_customizations. (To refresh MATLAB Coder CRL registration information within a MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');.)

    For more information about registering CRLs with Simulink or MATLAB Coder software, see Register Code Replacement Libraries.

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

      Note   If you hover over the selected library with the cursor, a tool tip appears. This tip provides information derived from your CRL registration file, such as the CRL description and the list of tables it contains.

    Optionally, you can relaunch the Code Replacement Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered CRLs, including MathWorks BLAS Matrix Multiplication Operator Example.

  5. Create an ERT-based model with two Product blocks, such as the following:

    1. For each Product block, set the block parameter Multiplication to the value Matrix(*).

    2. Configure the Signal Attributes for the In1, In2, and In3 source blocks. For In1 and In2, set Port dimensions to [3 3] and set the Data type to double. For In3, set Port dimensions to [3 1] and set the Data type to double.

    3. Also, go to the Solver pane of the Configuration Parameters dialog box and select a fixed-step, discrete solver with a fixed-step size such as 0.1. Apply the changes.

    4. Save the model. In this example, the model is saved to the name tmwblas_mmult.mdl.

    5. Check that the CRL you registered, MathWorks BLAS Matrix Multiplication Operator Example, is selected for this model.

  6. Go to the Code Generation > Report pane of the Configuration Parameters dialog box and select the options Create code generation report and Model-to-code. Then go to the Code Generation 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 CRL entry. For example, right-click the top Product block and select Code Generation > Navigate to Code. This selection highlights the Product block code within the model step function in tmwblas_mmult.c. In this case, code containing the matrix multiplication operator has been replaced with a call to dgemm32 in the generated code.

Map Matrix Multiplication to ANSI/ISO C BLAS Functions.  You can use CRL tables to map nonscalar multiplication operations to the ANSI/ISO C BLAS multiplication functions xgemm and xgemv. The following example uses the method described in General Method for Creating Function and Operator Entries to create a CRL table entry mapping floating-point matrix/matrix and matrix/vector multiplication operations to ANSI/ISO C BLAS library multiplication functions.

BLAS libraries support matrix/matrix multiplication in the form of , where means X, transposition of X, or Hermitian transposition of X. However, CRLs support only the limited case of . Correspondingly, although BLAS libraries support matrix/vector multiplication in the form of , CRLs support only the limited case of .

  1. Create and save the following CRL table definition file, crl_table_cblas_mmult_double.m. This file defines a CRL table containing dgemm and dgemv replacement entries for the matrix multiplication operator and the double data type.

    For each entry, the function body sets selected matrix multiplication operator entry parameters, creates the y1, u1, and u2 conceptual arguments individually, and then configures special implementation arguments that are required for dgemm and dgemv replacements. Finally, each operator entry is added to the table.

    To specify a matrix argument to createAndAddConceptualArg, use the CRL argument class RTW.TflArgMatrix and specify the base type and the dimensions for which the argument is valid. This type of table entry supports a range of dimensions specified in the format [Dim1Min Dim2Min ... DimNMin; Dim1Max Dim2Max ... DimNMax]. For example, [2 2; inf inf] means any two-dimensional matrix of size 2x2 or larger. In this example, the conceptual output argument for the cblas_dgemm entry for matrix/matrix multiplication replacement specifies dimensions [2 2; inf inf], while the conceptual output argument for the cblas_dgemv entry for matrix/vector multiplication replacement specifies dimensions [2 1; inf 1].

    function hTable = crl_table_cblas_mmult_double
    %CRL_TABLE_CBLAS_MMULT_DOUBLE - Describe two mmult operator entries for CRL table.
    
    hTable = RTW.TflTable;
    
    LibPath = fullfile(matlabroot, 'toolbox', 'rtw', 'rtwdemos', 'crl_demo');
    
    % Create table entry for cblas_dgemm
    op_entry = RTW.TflCBlasEntryGenerator;
    setTflCOperationEntryParameters(op_entry, ...
        'Key',                      'RTW_OP_MUL', ...
        'Priority',                 100, ...
        'ImplementationName',       'cblas_dgemm', ...
        'ImplementationHeaderFile', 'cblas.h', ...
        'ImplementationHeaderPath', LibPath, ...
        'AdditionalIncludePaths',   {LibPath}, ...
        'GenCallback',              'RTW.copyFileToBuildDir', ...
        'SideEffects',              true);
    
    % Specify operands and result
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'y1', ...
                              'IOType',       'RTW_IO_OUTPUT', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 2; inf inf]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'u1', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 2; inf inf]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'u2', ...
                              'BaseType',     'double', ...
                              'DimRange',     [1 1; inf inf]);
    
    % Using RTW.TflCBlasEntryGenerator for xgemm requires the following
    % implementation signature:
    %
    % void f(enum ORDER, enum TRANSA, enum TRANSB, int M, int N, int K,
    %        type ALPHA, type* u1, int LDA, type* u2, int LDB,
    %        type BETA, type* y, int LDC)
    %
    % Since CRLs do not have the ability to specify enums, you must
    % use integer.  (This will cause problems with C++ code generation,
    % so for C++, use a wrapper function to cast each int to the
    % corresponding enumeration type.)
    %
    % Upon a match, the CRL entry will compute the
    % values for M, N, K, LDA, LDB, and LDC and insert them into the
    % generated code.
    
    % Specify replacement function signature
    
    arg = getTflArgFromString(hTable, 'y2', 'void');
    arg.IOType = 'RTW_IO_OUTPUT';
    op_entry.Implementation.setReturn(arg);
    
    arg = getTflArgFromString(hTable, 'ORDER', 'integer', 102);
    %arg.Type.ReadOnly=true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'TRANSA', 'integer', 111);
    %arg.Type.ReadOnly=true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'TRANSB', 'integer', 111);
    %arg.Type.ReadOnly=true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'M', 'integer', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'N', 'integer', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'K', 'integer', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'ALPHA', 'double', 1);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'u1', ['double' '*']);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'u2', ['double' '*']);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'LDB', 'integer', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'BETA', 'double', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'y1', ['double' '*']);
    arg.IOType = 'RTW_IO_OUTPUT';
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'LDC', 'integer', 0);
    op_entry.Implementation.addArgument(arg);
    
    addEntry(hTable, op_entry);
    
    % Create table entry for cblas_dgemv
    op_entry = RTW.TflCBlasEntryGenerator;
    setTflCOperationEntryParameters(op_entry, ...
        'Key',                      'RTW_OP_MUL', ...
        'Priority',                 100, ...
        'ImplementationName',       'cblas_dgemv', ...
        'ImplementationHeaderFile', 'cblas.h', ...
        'ImplementationHeaderPath', LibPath, ...
        'AdditionalIncludePaths',   {LibPath}, ...
        'GenCallback',              'RTW.copyFileToBuildDir', ...
        'SideEffects',              true);
    
    % Specify operands and result
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'y1', ...
                              'IOType',       'RTW_IO_OUTPUT', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 1; inf 1]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix', ...
                              'Name',         'u1', ...
                              'BaseType',     'double', ...
                              'DimRange',     [2 2; inf inf]);
    createAndAddConceptualArg(op_entry, 'RTW.TflArgMatrix',...
                              'Name',         'u2', ...
                              'BaseType',     'double', ...
                              'DimRange',     [1 1; inf 1]);
    
    % Using RTW.TflCBlasEntryGenerator for xgemv requires the following
    % implementation signature:
    %
    % void f(enum ORDER, enum TRANSA, int M, int N,
    %        type ALPHA, type* u1, int LDA, type* u2, int INCX,
    %        type BETA, type* y, int INCY)
    %
    % Since CRLs do not have the ability to specify enums, you must
    % use integer.  (This will cause problems with C++ code generation,
    % so for C++, use a wrapper function to cast each int to the
    % corresponding enumeration type.)
    %
    % Upon a match, the CRL entry will compute the 
    % values for M, N, LDA, INCX, and INCY and insert them into the
    % generated code.
    
    % Specify replacement function signature
    
    arg = getTflArgFromString(hTable, 'y2', 'void');
    arg.IOType = 'RTW_IO_OUTPUT';
    op_entry.Implementation.setReturn(arg);
    
    arg = getTflArgFromString(hTable, 'ORDER', 'integer', 102);
    %arg.Type.ReadOnly=true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'TRANSA', 'integer', 111);
    %arg.Type.ReadOnly=true;
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'M','integer', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'N', 'integer', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'ALPHA', 'double', 1);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'u1', ['double' '*']);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'LDA', 'integer', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'u2', ['double' '*']);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'INCX', 'integer', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'BETA', 'double', 0);
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'y1', ['double' '*']);
    arg.IOType = 'RTW_IO_OUTPUT';
    op_entry.Implementation.addArgument(arg);
    
    arg = getTflArgFromString(hTable, 'INCY', 'integer', 0);
    op_entry.Implementation.addArgument(arg); 
    
    addEntry(hTable, op_entry);
  2. Optionally, perform a quick check of the validity of the operator entries by invoking the table definition file at the MATLAB command line (>> tbl = crl_table_cblas_mmult_double) and by viewing it in the Code Replacement Viewer (>> RTW.viewTFL(crl_table_cblas_mmult_double)).

    For more information about validating CRL tables, see Examine and Validate Code Replacement Tables.

  3. Create and save the following CRL registration file, which references the crl_table_cblas_mmult_double table.

    The file specifies that the CRL to be registered is named 'ANSI/ISO C BLAS Matrix Multiplication Operator Example' and consists of crl_table_cblas_mmult_double, with the default ANSI math library as the base CRL table.

    function sl_customization(cm)
    % sl_customization function to register a code replacement library (CRL)
    
      % Register the CRL defined in local function locCrlRegFcn
      cm.registerTargetInfo(@locCrlRegFcn);
    
    end % End of SL_CUSTOMIZATION
    
    
    % Local function to define a CRL containing crl_table_cblas_mmult_double
    function thisCrl = locCrlRegFcn
    
      % Instantiate a CRL registry entry
      thisCrl = RTW.TflRegistry;
    
      % Define the CRL properties
      thisCrl.Name = 'ANSI/ISO C BLAS Matrix Multiplication Operator Example'; 
      thisCrl.Description = 'Demonstration of C BLAS mmult operator replacement';
      thisCrl.TableList = {'crl_table_cblas_mmult_double'};
      thisCrl.BaseTfl = 'C89/C90 (ANSI)';
      thisCrl.TargetHWDeviceType = {'*'};
    
    end % End of LOCCRLREGFCN

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

      Tip   To refresh Simulink customizations within the current MATLAB session, use the command sl_refresh_customizations. (To refresh MATLAB Coder CRL registration information within a MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');.)

    For more information about registering CRLs with Simulink or MATLAB Coder software, see Register Code Replacement Libraries.

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

      Note   If you hover over the selected library with the cursor, a tool tip appears. This tip provides information derived from your CRL registration file, such as the CRL description and the list of tables it contains.

    Optionally, you can relaunch the Code Replacement Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered CRLs, including ANSI/ISO C BLAS Matrix Multiplication Operator Example.

  5. Create an ERT-based model with two Product blocks, such as the following:

    1. For each Product block, set the block parameter Multiplication to the value Matrix(*).

    2. Configure the Signal Attributes for the In1, In2, and In3 source blocks. For In1 and In2, set Port dimensions to [3 3] and set the Data type to double. For In3, set Port dimensions to [3 1] and set the Data type to double.

    3. Also, go to the Solver pane of the Configuration Parameters dialog box and select a fixed-step, discrete solver with a fixed-step size such as 0.1. Apply the changes.

    4. Save the model. In this example, the model is saved to the name cblas_mmult.mdl.

    5. Check that the CRL you registered, ANSI/ISO C BLAS Matrix Multiplication Operator Example, is selected for this model.

  6. Go to the Code Generation > Report pane of the Configuration Parameters dialog box and select the options Create code generation report and Model-to-code. Then go to the Code Generation 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 CRL entry. For example, right-click the top Product block and select Code Generation > Navigate to Code. This selection highlights the Product block code within the model step function in cblas_mmult.c. In this case, code containing the matrix multiplication operator has been replaced with a call to cblas_dgemm in the generated code.

Map Fixed-Point Operators to Target-Specific Implementations

Overview of Fixed-Point Operator Replacement.  The Embedded Coder software supports CRL-based code replacement for the following scalar operations on fixed-point data types:

OperatorKey
Addition (+)RTW_OP_ADD
Subtraction (-)RTW_OP_MINUS
Multiplication (*)RTW_OP_MUL
Division (/)RTW_OP_DIV
Data type conversion (cast)RTW_OP_CAST
Shift left (<<)RTW_OP_SL
Shift right (>>)RTW_OP_SRA (arithmetic)1
RTW_OP_SRL (logical)
Notes:
1 CRLs that provide arithmetic shift right implementations should also provide logical shift right implementations, because some arithmetic shift rights are converted to logical shift rights during code generation.

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 CRL 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 CRL 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 CRL 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 CRL 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 CRL entry. For this, use a relative scaling factor (RSF) entry or a net slope entry:

Data Type Conversion (Cast).  

The data type conversion operation V0 = V1 implies, for binary-point-only scaling, that

where Sn is the net slope.

Shift.  

The shift left or shift right operation V0 = (V1 / 2n) implies, for binary-point-only scaling, that

where Sn is the net slope.

Create Fixed-Point Operator Entries.  To create CRL 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 CRL table entry
createAndAddImplementationArgCreate implementation argument from specified properties and add to implementation arguments for CRL table entry
createAndSetCImplementationReturnCreate implementation return argument from specified properties and add to implementation for CRL table entry
setTflCOperationEntryParametersSet specified parameters for operator entry in CRL table

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

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


See Create 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 Create 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 equivalent): 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 Create 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 Create 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).

  • NetFixedExponent: 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 Create 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.

Create Fixed-Point Operator Entries for Binary-Point-Only Scaling.  CRL 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 CRL 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 Map Scalar Operators to Target-Specific Implementations, substituting in the code above and an ERT-based model such as the following:

For this model,

Create Fixed-Point Operator Entries for [Slope Bias] Scaling.  CRL 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 CRL 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 Map Scalar Operators to Target-Specific Implementations, substituting in the code above and an ERT-based model such as the following:

For this model,

Create Fixed-Point Operator Entries for Relative Scaling (Multiplication and Division).  CRL 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 CRL 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 Map Scalar Operators to Target-Specific Implementations, substituting in the code above and an ERT-based model such as the following:

For this model,

Create Fixed-Point Operator Entries for Net Slope (Multiplication and Division).  CRL 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 CRL table entry for division of fixed-point data types using a net slope. In this example:

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);

Create Fixed-Point Operator Entries for Equal Slope and Zero Net Bias (Addition and Subtraction).  CRL 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 CRL 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 Map Scalar Operators to Target-Specific Implementations, substituting in the code above and an ERT-based model such as the following:

For this model,

Map Data Type Conversion (Cast) Operations to Target-Specific Implementations.  

You can use CRL table entries to replace the default generated code for data type conversion (cast) operations with calls to optimized functions.

For details of the arithmetic supported for replacement of data type conversion, see the data type conversion (cast) subsection of Fixed-Point Numbers and Arithmetic.

Create a CRL Entry to Replace Casts From int32 To int16.  

The following example uses the method described in General Method for Creating Function and Operator Entries to create a CRL table entry to replace int32 to int16 data type conversion (cast) operations. In this example:

hTable = RTW.TflTable;

% Create an int16 to int32 cast replacement
op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
    'Key',                      'RTW_OP_CAST', ...
    'Priority',                 50, ...
    'ImplementationName',       'my_sat_cast', ...
    'SaturationMode',           'RTW_SATURATE_ON_OVERFLOW', ...
    'RoundingMode',             'RTW_ROUND_FLOOR', ...
    'ImplementationHeaderFile', 'some_hdr.h', ...
    'ImplementationSourceFile', 'some_hdr.c');

% Create int16 arg as conceptual arg 1 and implementation return
arg = getTflArgFromString(hTable, 'y1', 'int16');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(op_entry, arg);
op_entry.Implementation.setReturn(arg);

% Create int32 arg as conceptual arg 2 and implementation input arg 1
arg = getTflArgFromString(hTable, 'u1', 'int32');
addConceptualArg(op_entry, arg);
op_entry.Implementation.addArgument(arg);

addEntry(hTable, op_entry);
Create a CRL Entry to Replace Fixed-Point Casts Using Net Slope.  

The following example uses the method described in General Method for Creating Function and Operator Entries to create a CRL table entry to replace data type conversions (casts) of fixed-point data types using a net slope. In this example:

hTable = RTW.TflTable;

% Create a fixed-point cast replacement using a NetSlope entry
op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
InFL = 2;
InWL = 16;
InSgn = true;
OutFL = 4;
OutWL = 32;
OutSgn = true;
setTflCOperationEntryParameters(op_entry, ...
   'Key',                       'RTW_OP_CAST', ...
   'Priority',                  50, ...
   'SaturationMode',            'RTW_SATURATE_ON_OVERFLOW', ...
   'RoundingMode',              'RTW_ROUND_FLOOR', ...
   'NetSlopeAdjustmentFactor',  1.0, ...
   'NetFixedExponent',          (OutFL - InFL), ...
   'SaturationMode',            'RTW_SATURATE_ON_OVERFLOW', ...
   'RoundingMode',              'RTW_ROUND_FLOOR', ...
   'ImplementationName',        'my_fxp_cast', ...
   'ImplementationHeaderFile',  'some_hdr.h', ...
   'ImplementationSourceFile',  'some_hdr.c');

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',         'y1', ...
                          'IOType',       'RTW_IO_OUTPUT', ...
                          'CheckSlope',   false, ...
                          'CheckBias',    false, ...
                          'DataTypeMode', 'Fixed-point: binary point scaling', ...
                          'IsSigned',     OutSgn, ...
                          'WordLength',   OutWL, ...
                          'FractionLength',OutFL);

createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',         'u1', ...
                          'IOType',       'RTW_IO_INPUT', ...
                          'CheckSlope',   false, ...
                          'CheckBias',    false, ...
                          'DataTypeMode', 'Fixed-point: binary point scaling', ...
                          'IsSigned',     InSgn, ...
                          'WordLength',   InWL, ...
                          'FractionLength',InFL);

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

createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric',...
                          'Name',           'u1', ...
                          'IOType',         'RTW_IO_INPUT', ... 
                          'IsSigned',       InSgn, ...
                          'WordLength',     InWL, ...
                          'FractionLength', 0);

addEntry(hTable, op_entry);

Map Fixed-Point Shift Left Operations to Target-Specific Implementations.  

You can use CRL table entries to replace the default generated code for << (shift left) operations with calls to optimized functions.

For details of the arithmetic supported for replacement of shift-left operations, see the shift left subsection of Fixed-Point Numbers and Arithmetic.

Create a CRL Entry to Replace Shift Lefts for int16 Data.  

The following example uses the method described in General Method for Creating Function and Operator Entries to create a CRL table entry to replace << (shift left) operations for int16 data. In this example:

hTable = RTW.TflTable;

% Create a shift left replacement for int16 data
op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
    'Key',                      'RTW_OP_SL', ...
    'Priority',                 50, ...
    'ImplementationName',       'my_shift_left', ...
    'ImplementationHeaderFile', 'some_hdr.h', ...
    'ImplementationSourceFile', 'some_hdr.c');

% Create int16 arg as conceptual arg 1 and implementation return
arg = getTflArgFromString(hTable, 'y1', 'int16');
arg.IOType = 'RTW_IO_OUTPUT';
addConceptualArg(op_entry, arg);
op_entry.Implementation.setReturn(arg);

% Create int16 arg as conceptual arg 2 and implementation input arg 1
arg = getTflArgFromString(hTable, 'u1', 'int16');
addConceptualArg(op_entry, arg);
op_entry.Implementation.addArgument(arg);

% Create int8 arg as conceptual arg 3 and implementation input arg 2
% Turn off type checking for number of bits to shift argument
arg = getTflArgFromString(hTable, 'u2', 'int8');
arg.CheckType = false;
addConceptualArg(op_entry, arg);
op_entry.Implementation.addArgument(arg);

addEntry(hTable, op_entry);
Create a CRL Entry to Replace Fixed-Point Shift Lefts Using Net Slope.  

The following example uses the method described in General Method for Creating Function and Operator Entries to create a CRL table entry to replace << (shift left) operations for fixed-point data using a net slope. In this example:

hTable = RTW.TflTable;

% Create a fixed-point shift left replacement using a NetSlope entry
op_entry = RTW.TflCOperationEntryGenerator_NetSlope;
InFL = 2;
InWL = 16;
InSgn = true;
OutFL = 4;
OutWL = 32;
OutSgn = true;
setTflCOperationEntryParameters(op_entry, ...
   'Key',                       'RTW_OP_SL', ...
   'Priority',                  50, ...
   'SaturationMode',            'RTW_SATURATE_ON_OVERFLOW', ...
   'RoundingMode',              'RTW_ROUND_FLOOR', ...
   'NetSlopeAdjustmentFactor',  1.0, ...
   'NetFixedExponent',          (OutFL - InFL),...
   'SaturationMode',            'RTW_SATURATE_ON_OVERFLOW', ...
   'RoundingMode',              'RTW_ROUND_FLOOR', ...
   'ImplementationName',        'my_fxp_shift_left', ...
   'ImplementationHeaderFile',  'some_hdr.h', ...
   'ImplementationSourceFile',  'some_hdr.c');

% Create fixed-point arg as conceptual arg 1
createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',         'y1', ...
                          'IOType',       'RTW_IO_OUTPUT', ...
                          'CheckSlope',   false, ...
                          'CheckBias',    false, ...
                          'DataTypeMode', 'Fixed-point: binary point scaling', ...
                          'IsSigned',     OutSgn, ...
                          'WordLength',   OutWL, ...
                          'FractionLength',OutFL);

% Create fixed-point arg as conceptual arg 2
createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',         'u1', ...
                          'IOType',       'RTW_IO_INPUT', ...
                          'CheckSlope',   false, ...
                          'CheckBias',    false, ...
                          'DataTypeMode', 'Fixed-point: binary point scaling', ...
                          'IsSigned',     InSgn, ...
                          'WordLength',   InWL, ...
                          'FractionLength',InFL);

% Create implementation return arg
createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'y1', ...
                          'IOType',         'RTW_IO_OUTPUT', ...
                          'IsSigned',       OutSgn, ...
                          'WordLength',     OutWL, ...
                          'FractionLength', 0);

% Create implementation input arg 1
createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric', ...
                          'Name',           'u1', ...
                          'IOType',         'RTW_IO_INPUT', ...
                          'IsSigned',       InSgn, ...
                          'WordLength',     InWL, ...
                          'FractionLength', 0);

% Create uint8 arg as conceptual arg 3 and implementation input arg 2
% Turn off type checking for number of bits to shift argument
arg = getTflArgFromString(hTable, 'u2', 'uint8');
arg.CheckType = false;
addConceptualArg(op_entry, arg);
op_entry.Implementation.addArgument(arg);

addEntry(hTable, op_entry);

Remap Operator Outputs to Implementation Function Input Positions

If you need your generated code to meet a specific coding pattern or you want more flexibility, for example, to further improve performance, you have the option of remapping operator outputs to input positions in an implementation function argument list.

For example, for a sum operation, the build process might generate code similar to the following:

rtY.Out1 = u8_add_u8_u8(rtU.In1, rtU.In2);

If you remap the output to the first input, the build process generates code similar to the following:

uint8_T rtb_Add8;

u8_add_u8_u8(&rtb_Add8, rtU.In1, rtU.In2);
rtY.Out1 = rtb_Add8;

To remap an operator output to an implementation function input for an existing CRL operator replacement entry, you modify the CRL table definition file as follows:

  1. In the setTflCOperationEntryParameters function call for the operator replacement, specify the SideEffects parameter as true.

  2. When defining the implementation function return, create a new void output argument, for example, y2.

  3. When defining the implementation function arguments, set the operator output argument (for example, y1) as an additional input argument, marking its IOType as output, and make its type a pointer type.

For example, the following CRL table definition file for a sum operation has been modified to remap operator output y1 as the first function input argument. The modified lines of code are shown in bold type. (This definition file generated the example remap code shown above.)

function hTable = crl_table_add_uint8
%CRL_TABLE_ADD_UINT8 - Describe operator entry for a Code Replacement Library table.

hTable = RTW.TflTable;

% Create entry for addition of built-in uint8 data type
op_entry = RTW.TflCOperationEntry;
setTflCOperationEntryParameters(op_entry, ...
                    'Key',                      'RTW_OP_ADD', ...
                    'Priority',                 90, ...
                    'ImplementationName',       'u8_add_u8_u8', ...
                    'ImplementationHeaderFile', 'u8_add_u8_u8.h', ...
                    'ImplementationSourceFile', 'u8_add_u8_u8.c', ...
                    'SideEffects',              true );

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 );

% Create new void output y2
arg = getTflArgFromString(hTable, 'y2', 'void');
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.setReturn(arg);

% Set y1 as first input arg, mark IOType as output, and use pointer type
arg=getTflArgFromString(hTable, 'y1', 'uint8*');
arg.IOType = 'RTW_IO_OUTPUT';
op_entry.Implementation.addArgument(arg);

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

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

addEntry(hTable, op_entry);

Configure Data Alignment for Function Implementations

About CRL-Specified Data Alignment.  CRLs provide the ability to align data objects passed into a replacement function to a specified boundary. This allows you to take advantage of target-specific function implementations that require data to be aligned in order to optimize application performance. To configure data alignment for a function implementation:

  1. Specify the data alignment requirements in a CRL table entry. Alignment can be specified separately for each implementation function argument or collectively for all function arguments. For more information, see Specify Data Alignment Requirements for Function Arguments.

  2. Specify the data alignment capabilities and syntax for one or more compilers, and include the alignment specifications in a CRL registry entry in an sl_customization.m or rtwTargetInfo.m file. For more information, see Provide Data Alignment Specifications for Compilers.

  3. Register the CRL containing the table entry and the alignment specification object.

You can then select the CRL for your model, generate code, and observe the results.

For examples, see Basic Example of CRL-Specified Data Alignment and the data alignment examples in the demo rtwdemo_crl_script.

Specify Data Alignment Requirements for Function Arguments.  To specify the data alignment requirement for an argument in a CRL replacement entry:

The AlignmentBoundary property (or Alignment value parameter) specifies the alignment boundary for data passed to a function argument, in number of bytes. The AlignmentBoundary property is valid only for addressable objects, including matrix and pointer arguments. It has no meaning for value arguments. Valid values are:

For example, the following code specifies the AlignmentBoundary for an argument as 16 bytes.

hLib = RTW.TflTable;
entry = RTW.TflCOperationEntry;
arg = hLib.getTflArgFromString('u1','single*');
desc = RTW.ArgumentDescriptor;
desc.AlignmentBoundary = 16;
arg.Descriptor = desc;
entry.Implementation.addArgument(arg);

Here is the equivalent alignment boundary specification in the Code Replacement Tool dialog box:

Provide Data Alignment Specifications for Compilers.  To support data alignment in generated code, you must describe the data alignment capabilities and syntax for your compiler(s) to the CRL registry. To do this, you provide one or more alignment specifications for each compiler in a CRL registry entry. For more information about CRL registry entries, see Register Code Replacement Libraries.

To describe the data alignment capabilities and syntax for a compiler:

For each data alignment specification, you provide the following information:

AlignmentSpecification PropertyDialog Box ParameterDescription
AlignmentTypeAlignment type

Cell array of predefined enumerated strings, specifying which types of alignment are supported by this specification:

  • DATA_ALIGNMENT_LOCAL_VAR — Local variables.

  • DATA_ALIGNMENT_GLOBAL_VAR — Global variables.

  • DATA_ALIGNMENT_STRUCT_FIELD — Individual structure fields.

  • DATA_ALIGNMENT_WHOLE_STRUCT — Whole structure, with padding (individual structure field alignment, if specified, is favored and takes precedence over whole structure alignment).

Each alignment specification must specify at least DATA_ALIGNMENT_GLOBAL_VAR and DATA_ALIGNMENT_STRUCT_FIELD.

AlignmentPositionAlignment position

Predefined enumerated string specifying the position in which the compiler alignment directive should be placed for alignment type DATA_ALIGNMENT_WHOLE_STRUCT:

  • DATA_ALIGNMENT_PREDIRECTIVE — The alignment directive is emitted before struct st_tag{…}, as part of the type definition statement (for example, MSVC).

  • DATA_ALIGNMENT_POSTDIRECTIVE — The alignment directive is emitted after struct st_tag{…}, as part of the type definition statement (for example, gcc).

  • DATA_ALIGNMENT_PRECEDING_STATEMENT — The alignment directive is emitted as a stand alone statement immediately preceding the definition of the structure type. The registered alignment syntax must be terminated by a semicolon (;).

  • DATA_ALIGNMENT_FOLLOWING_STATEMENT — The alignment directive is emitted as a stand alone statement immediately following the definition of the structure type. The registered alignment syntax must be terminated by a semicolon (;).

For alignment types other than DATA_ALIGNMENT_WHOLE_STRUCT, code generation uses alignment position DATA_ALIGNMENT_PREDIRECTIVE.

AlignmentSyntaxTemplateAlignment syntax

Specifies the alignment directive string that the compiler supports. The string is registered as a syntax template that has placeholders in it. The following placeholders are supported:

  • %n — Replaced by the alignment boundary for the replacement function argument.

  • %s — Replaced by the symbol that will be aligned, usually the identifier of a variable.

For example, for the gcc compiler, you might specify __attribute__((aligned(%n))), or for the MSVC compiler, __declspec(align(%n)).

SupportedLanguagesSupported languages

Cell array specifying the language(s) to which this alignment specification applies, among c and c++. Sometimes alignment syntax and position differ between languages for a compiler.

.

For example, here is a data alignment specification for the GCC compiler:

da = RTW.DataAlignment;

as = RTW.AlignmentSpecification;
as.AlignmentType = {'DATA_ALIGNMENT_LOCAL_VAR', ...
                    'DATA_ALIGNMENT_STRUCT_FIELD', ...
                    'DATA_ALIGNMENT_GLOBAL_VAR'};
as.AlignmentSyntaxTemplate = '__attribute__((aligned(%n)))';
as.AlignmentPosition = 'DATA_ALIGNMENT_PREDIRECTIVE';
as.SupportedLanguages = {'c', 'c++'};
da.addAlignmentSpecification(as);

tc = RTW.TargetCharacteristics;
tc.DataAlignment = da;

Here is the corresponding specification in the Generate customization dialog box of the Code Replacement Tool:

Basic Example of CRL-Specified Data Alignment.  This section steps you through a simple example of the complete workflow for CRL-specified data alignment.

  1. Create and save the following CRL table definition file, crl_table_mmul_4x4_single_align.m. This CRL table defines a replacement entry for the * (multiplication) operator, the single data type, and input dimensions [4,4]. The entry also specifies a data alignment boundary of 16 bytes for each replacement function argument. This expresses the requirement that the starting memory address for the data allocated for the function arguments during code generation will be a multiple of 16.

    function hLib = crl_table_mmul_4x4_single_align
    %CRL_TABLE_MMUL_4x4_SINGLE_ALIGN - Describe matrix operator entry with data alignment
     
    hLib = RTW.TflTable;
    entry = RTW.TflCOperationEntry;
    entry.setTflCOperationEntryParameters(... 
        'Key',                   'RTW_OP_MUL', ...
        'Priority',              90, ...
        'ImplementationName',    'matrix_mul_4x4_s');
     
    % conceptual arguments
    entry.createAndAddConceptualArg('RTW.TflArgMatrix',...
                                    'Name',         'y1', ...
                                    'IOType',       'RTW_IO_OUTPUT', ...
                                    'BaseType',     'single', ...
                                    'DimRange',     [4 4]);
     
    entry.createAndAddConceptualArg('RTW.TflArgMatrix',...
                                    'Name',         'u1', ...
                                    'BaseType',     'single', ...
                                    'DimRange',     [4 4]);
     
    entry.createAndAddConceptualArg('RTW.TflArgMatrix',...
                                    'Name',         'u2', ...
                                    'BaseType',     'single', ...
                                    'DimRange',     [4 4]);
     
    % implementation arguments
    arg = hLib.getTflArgFromString('y2', 'void');
    arg.IOType = 'RTW_IO_OUTPUT';
    entry.Implementation.Return=arg;
     
    arg = hLib.getTflArgFromString('y1','single*');
    desc = RTW.ArgumentDescriptor;
    desc.AlignmentBoundary = 16;
    arg.Descriptor = desc;
    entry.Implementation.addArgument(arg);
     
    arg = hLib.getTflArgFromString('u1','single*');
    desc = RTW.ArgumentDescriptor;
    desc.AlignmentBoundary = 16;
    arg.Descriptor = desc;
    entry.Implementation.addArgument(arg);
     
    arg = hLib.getTflArgFromString('u2','single*');
    desc = RTW.ArgumentDescriptor;
    desc.AlignmentBoundary = 16;
    arg.Descriptor = desc;
    entry.Implementation.addArgument(arg);
     
    hLib.addEntry(entry);
  2. Create and save the following CRL registration file, rtwTargetInfo.m. If you intend to compile the code generated in this example, you can modify the AlignmentSyntaxTemplate property for the compiler you intend to use. For example, for the MSVC compiler, replace the gcc template string __attribute__((aligned(%n))) with __declspec(align(%n)).

    function rtwTargetInfo(cm)
    % rtwTargetInfo function to register a code replacement library (CRL) 
    % for use with  code generation
    
      % Register the CRL defined in local function locCrlRegFcn
      cm.registerTargetInfo(@locCrlRegFcn);
    
    end % End of RTWTARGETINFO
    
    % Local function to define a CRL containing crl_table_mmul_4x4_single_align
    function thisCrl = locCrlRegFcn
    
      % create an alignment specification object, assume gcc
      as = RTW.AlignmentSpecification;
      as.AlignmentType = {'DATA_ALIGNMENT_LOCAL_VAR', ...
                          'DATA_ALIGNMENT_GLOBAL_VAR', ...
                          'DATA_ALIGNMENT_STRUCT_FIELD'};
      as.AlignmentSyntaxTemplate = '__attribute__((aligned(%n)))';
      as.SupportedLanguages={'c', 'c++'};
    
      % add the alignment specification object
      da = RTW.DataAlignment; 
      da.addAlignmentSpecification(as); 
    
      % add the data alignment object to target characteristics
      tc = RTW.TargetCharacteristics;
      tc.DataAlignment = da;
    
      % Instantiate a CRL registry entry
      thisCrl = RTW.TflRegistry;
    
      % Define the CRL properties
      thisCrl.Name = 'Data Alignment Example'; 
      thisCrl.Description = 'Demonstration of replacement with data alignment';
      thisCrl.TableList = {'crl_table_mmul_4x4_single_align'};
      thisCrl.BaseTfl = 'C89/C90 (ANSI)';
      thisCrl.TargetCharacteristics = tc;
    
    end % End of LOCCRLREGFCN
  3. To register your CRL with code generation software without having to restart MATLAB, enter the following command in the MATLAB Command Window:

    >> RTW.TargetRegistry.getInstance('reset');
  4. Open an ERT-based Simulink model and navigate to the Interface pane of the Configuration Parameters dialog box. Verify that the Code replacement library option lists the CRL name you specified and select it.

  5. Create an ERT-based model with a Product block and configure the Product block for [4,4] matrix multiplication.

    Check that the CRL you registered, Data Alignment Example, is selected for this model.

  6. Go to the Code Generation > Report pane of the Configuration Parameters dialog box and select the options Create code generation report and Model-to-code. Then go to the Code Generation 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 CRL entry. For example, right-click the Product block and select Code Generation > Navigate to Code. This selection highlights the Product function code within the model step function in mmalign.c. In this case, a multiplication operation has been replaced with a matrix_mul_4x4_s function call in the generated code.

    Also, in mmalign.h, the gcc alignment directive __attribute__((aligned(16))) has been generated to align the function variables.

Data Alignment Limitations.  CRL data alignment has the following limitations:

Refine CRL Matching and Replacement Using Custom CRL Table Entries

During code generation for your model, the CRL replacement capability uses

However, preset match criteria and preset replacement function signatures might not meet all function and operator replacement needs. For example,

When you need to add extra logic into the CRL matching and replacement process, you can create custom CRL table entries. Custom entries allow you to specify additional match criteria and/or modify the replacement function signature to meet your application needs.

To create a custom CRL table entry, you perform the following steps:

  1. Create a custom CRL entry class, derived from either RTW.TflCOperationEntryML (for operator replacement) or RTW.TflCFunctionEntryML (for function replacement).

  2. In your derived class, implement a do_match method with a fixed preset signature as a MATLAB function. In your do_match method, you can provide either or both of the following customizations for use by CRL table entries that instantiate the class:

    1. Add any additional match criteria not provided by the base class. The base class provides a match based on argument number, argument name, signedness, word size, slope (if not wildcarded), bias (if not wildcarded), math modes such as saturation and rounding, and operator or function key. For example, you can accept a match only when additional size or range conditions are met.

    2. Modify the implementation signature by adding additional arguments or setting constant input argument values. For example, you can inject a constant value, such as an input's scaling value, as an additional argument to the replacement function.

  3. Create CRL table entries that instantiate your custom CRL entry class.

  4. Register a CRL containing the CRL table entries. The registered CRL is then available for selection in the Interface pane of the Simulink Configuration Parameters dialog box.

During code generation, the CRL matching process first tries to match function or operator call sites with the base class of your derived entry class. If a match is found, the software calls your do_match method to execute your additional match logic (if any) and your replacement function customizations (if any).

The following sections provide examples of creating custom CRL table entries to refine matching and replacement for operators and functions. For more examples, see the CRL demos page, including the demo model rtwdemo_crlcustomentry.

Customize CRL Matching and Replacement for Operators.  This example demonstrates how to use custom CRL table entries to refine the matching and replacement logic for operators. In this example, a fixed-point addition replacement needs to be modified such that the implementation function passes in the fraction lengths of the input and output data types as arguments.

  1. To exercise the custom CRL table entries created in this example, create an ERT-based model with one or more unsigned 32-bit fixed-point addition operations, such as the following:

    For the purposes of this example, in the block parameters for both Add blocks, set Integer rounding mode to Floor and select the option Saturate on integer overflow.

  2. Create a class folder using the name of your derived class, such as @TflCustomOperationEntry. Check that the class folder is in the MATLAB search path or in the current working folder.

  3. In the class folder, create and save the following class definition file, TflCustomOperationEntry.m. This file defines the class TflCustomOperationEntry, which is derived from the base class RTW.TflCOperationEntryML

    The derived class defines a do_match method . In the do_match method signature,

    • ent is the return handle, which is returned either as empty (indicating that the match failed) or as a TflCOperationEntry handle.

    • hThis is the handle to this object.

    • hCSO is a handle to an object created by the code generator for the purpose of querying the CRL for a replacement.

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

    The purpose of the do_match method is to add any additional match criteria not provided by the base class and make any desired modifications to the implementation signature. In this case, the do_match method can rely on the base class for checking word size and signedness, and additionally only needs to match the number of conceptual arguments to the value 3 (two inputs and one output) and the bias for each argument to the value 0. If a match is made, the method sets the return handle, removes slope and bias wildcarding from the conceptual arguments (since the match is for specific slope and bias values), and writes fraction-length values for the inputs and output into replacement function arguments 3, 4, and 5.

      Note   The three additional implementation function arguments for passing fraction lengths can be created and added either here in the class definition or in each CRL table entry definition that instantiates this class. In this example, the arguments are created and added in a CRL table definition file and set to specific values in the class definition code. For an example of creating and adding additional implementation function arguments in a class definition, see Customize CRL Matching and Replacement for Functions.

    classdef TflCustomOperationEntry < RTW.TflCOperationEntryML
      methods
        function ent = do_match(hThis, ...
            hCSO, ... %#ok
            targetBitPerChar, ... %#ok
            targetBitPerShort, ... %#ok
            targetBitPerInt, ... %#ok
            targetBitPerLong) %#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.
    
          % 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 the necessary information, and you no longer need
            % a custom match function.
            ent = RTW.TflCOperationEntry(hThis);
    
            % Since this entry is modifying the implementation for specific
            % fraction-length values (arguments 3, 4, and 5), the conceptual argument
            % wildcards must be removed (the wildcards were inherited from the
            % generator when it was used as a template for the concrete entry).
            % This concrete entry is now for a specific slope and bias
            % (not for any slope and bias). The hCSO holds the 
            % slope and bias values (created by the code generator).
            for idx=1:3
              ent.ConceptualArgs(idx).CheckSlope = true;
              ent.ConceptualArgs(idx).CheckBias = true;
    
              % Set the specific Slope and Biases
              ent.ConceptualArgs(idx).Type.Slope = hCSO.ConceptualArgs(idx).Type.Slope;
              ent.ConceptualArgs(idx).Type.Bias = 0;
            end
    
            % 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

    Exit the class folder and return to the previous working folder.

  4. Create and save the following CRL table definition file, crl_table_custom_add_ufix32.m. This file defines a CRL table containing a single operator entry, a CRL entry generator for unsigned 32-bit fixed-point addition operations, with arbitrary fraction-length values on the inputs and the output. This entry instantiates the derived class from the previous step, TflCustomOperationEntry.

      Note  

      • If you want to replace all word sizes and signedness attributes (not just 32-bit and unsigned), you can use the same derived class, but not the same CRL entry, because the WordLength and IsSigned arguments cannot be wildcarded. For example, to support uint8, int8, uint16, int16, and int32, you would need to add five other distinct CRL entries. Similarly, if you wanted to use different implementation functions for saturation and rounding modes other than overflow and round to floor, you would need to add CRL entries for those match permutations.

      • This table entry creates and adds three implementation arguments to hold the fraction-length values for the inputs and output. Alternatively, this table entry could omit those argument definitions and instead the do_match method of the derived class TflCustomOperationEntry could create and add the three implementation arguments. In particular, you should use the alternative approach when the number of additional implementation arguments required might vary based on compile-time information.

    function hTable = crl_table_custom_add_ufix32
    
    hTable = RTW.TflTable;
     
    %% Add TflCustomOperationEntry
    op_entry = TflCustomOperationEntry;
    setTflCOperationEntryParameters(op_entry, ...
                    'Key',                      'RTW_OP_ADD', ...
                    'Priority',                 30, ...
                    'SaturationMode',           'RTW_SATURATE_ON_OVERFLOW', ...
                    'RoundingMode',             'RTW_ROUND_FLOOR', ...
                    'ImplementationName',       'myFixptAdd', ...
                    'ImplementationHeaderFile', 'myFixptAdd.h', ...
                    'ImplementationSourceFile', 'myFixptAdd.c');
    
    createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                              'Name',       'y1', ... 
                              'IOType',     'RTW_IO_OUTPUT', ...
                              'CheckSlope', false, ...
                              'CheckBias',  false, ...
                              'DataType',   'Fixed', ...
                              'Scaling',    'BinaryPoint', ...
                              'IsSigned',   false, ...
                              'WordLength', 32);
    
    createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                              'Name',       'u1', ...
                              'IOType',     'RTW_IO_INPUT', ...
                              'CheckSlope', false, ...
                              'CheckBias',  false, ...
                              'DataType',   'Fixed', ...
                              'Scaling',    'BinaryPoint', ...
                              'IsSigned',   false, ...
                              'WordLength', 32);
    
    createAndAddConceptualArg(op_entry, 'RTW.TflArgNumeric', ...
                              'Name',       'u2', ...
                              'IOType',     'RTW_IO_INPUT', ...
                              'CheckSlope', false, ...
                              'CheckBias',  false, ...
                              'DataType',   'Fixed', ...
                              'Scaling',    'BinaryPoint', ...
                              'IsSigned',   false, ...
                              'WordLength', 32);
    
    % Specify replacement function signature
    createAndSetCImplementationReturn(op_entry, 'RTW.TflArgNumeric', ...
                                  'Name',       'y1', ...
                                  'IOType',     'RTW_IO_OUTPUT', ...
                                  'IsSigned',   false, ...
                                  'WordLength', 32, ...
                                  'FractionLength', 0);
    
    createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric', ...
                                  'Name',       'u1', ...
                                  'IOType',     'RTW_IO_INPUT', ...
                                  'IsSigned',   false, ...
                                  'WordLength', 32, ...
                                  'FractionLength', 0);
    
    createAndAddImplementationArg(op_entry, 'RTW.TflArgNumeric', ...
                                  'Name',       'u2', ...
                                  'IOType',     'RTW_IO_INPUT', ...
                                  'IsSigned',   false, ...
                                  'WordLength', 32, ...
                                  'FractionLength', 0);
    
    % Add 3 fraction-length args. Actual values will be set during code generation.
    createAndAddImplementationArg(op_entry, 'RTW.TflArgNumericConstant', ...
                                  'Name',       'fl_in1', ...
                                  'IOType',     'RTW_IO_INPUT', ...
                                  'IsSigned',   false, ...
                                  'WordLength', 32, ...
                                  'FractionLength', 0, ...
                                  'Value',       0);
    
    createAndAddImplementationArg(op_entry, 'RTW.TflArgNumericConstant', ...
                                  'Name',       'fl_in2', ...
                                  'IOType',     'RTW_IO_INPUT', ...
                                  'IsSigned',   false, ...
                                  'WordLength', 32, ...
                                  'FractionLength', 0, ...
                                  'Value',       0);
     
    createAndAddImplementationArg(op_entry, 'RTW.TflArgNumericConstant', ...
                                  'Name',       'fl_out', ...
                                  'IOType',     'RTW_IO_INPUT', ...
                                  'IsSigned',   false, ...
                                  'WordLength', 32, ...
                                  'FractionLength', 0, ...
                                  'Value',       0);
    
    addEntry(hTable, op_entry);
  5. Optionally, perform a quick check of the validity of the function entry by invoking the table definition file at the MATLAB command line (>> tbl = crl_table_custom_add_ufix32) and by viewing it in the Code Replacement Viewer (>> RTW.viewTfl(crl_table_custom_add_ufix32)). For more information about validating CRL tables, see Examine and Validate Code Replacement Tables.

  6. Create and save the following CRL registration file, which references the crl_table_custom_add_ufix32 table.

    The file specifies that the CRL to be registered is named 'Custom CRL Operator Entry Example' and consists of crl_table_custom_add_ufix32, with the default ANSI math library as the base CRL table.

    function sl_customization(cm)
    % sl_customization function to register a code replacement library (CRL)
    
      % Register the CRL defined in local function locCrlRegFcn
      cm.registerTargetInfo(@locCrlRegFcn);
    
    end % End of SL_CUSTOMIZATION
    
    
    % Local function to define a CRL containing crl_table_custom_add_ufix32
    function thisCrl = locCrlRegFcn
    
      % Instantiate a CRL registry entry
      thisCrl = RTW.TflRegistry;
    
      % Define the CRL properties
      thisCrl.Name = 'Custom CRL Operator Entry Example'; 
      thisCrl.Description = 'Demonstration of custom match for operator replacement';
      thisCrl.TableList = {'crl_table_custom_add_ufix32'};
      thisCrl.BaseTfl = 'C89/C90 (ANSI)';
      thisCrl.TargetHWDeviceType = {'*'};
    
    end % End of LOCCRLREGFCN

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

      Tip   To refresh Simulink customizations within the current MATLAB session, use the command sl_refresh_customizations. (To refresh MATLAB Coder CRL registration information within a MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');.)

    For more information about registering CRLs with Simulink or MATLAB Coder software, see Register Code Replacement Libraries.

  7. With your sl_customization.m file in the MATLAB search path or in the current working folder, open the model you created in step 1 and navigate to the Code Generation > Interface pane of the Configuration Parameters dialog box. Verify that the Code replacement library option lists the CRL name you specified and select it.

    Optionally, you can relaunch the Code Replacement Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered CRLs, including Custom CRL Operator Entry Example.

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

  9. Go to the model window and use model-to-code highlighting to trace the code generated using your CRL entry. For example, right-click either Add block and select Code Generation > Navigate to Code. This selection highlights the Sum block code within the model step function in the model.c file. As shown below, the default implementation code for the unsigned 32-bit fixed-point addition operation has been replaced with myFixptAdd, and the three additional fraction-length arguments are present.

    /* Model step function */
    void ufix32_add_step(void)
    {
      /* Outport: '<Root>/Out1' incorporates:
       *  Inport: '<Root>/In1'
       *  Inport: '<Root>/In2'
       *  Sum: '<Root>/Add'
       */
      ufix32_add_Y.Out1 = myFixptAdd(ufix32_add_U.In1, ufix32_add_U.In2, 9U, 7U, 6U);
    
      /* Outport: '<Root>/Out2' incorporates:
       *  Inport: '<Root>/In3'
       *  Inport: '<Root>/In4'
       *  Sum: '<Root>/Add1'
       */
      ufix32_add_Y.Out2 = myFixptAdd(ufix32_add_U.In3, ufix32_add_U.In4, 10U, 9U, 7U);
    }

Customize CRL Matching and Replacement for Functions.  This example demonstrates how to use custom CRL table entries to refine the matching and replacement logic for functions. In this example, a sine function replacement needs to be modified, only if the integer size on the current target platform is 32 bits, such that the implementation function passes in a degrees-versus-radians flag as an input argument.

  1. To exercise the custom CRL table entries created in this example, create an ERT-based model with a sine function block, such as the following:

    For the purposes of this example, in the import block parameters, set the signal Data type to double. Also, if the target platform selected for your model on the Hardware Implementation pane of the Configuration Parameters dialog box supports an integer size other than 32, you should either temporarily select a target platform with a 32-bit integer size, or modify the code in this example to match the integer size of your target platform.

  2. Create a class folder using the name of your derived class, such as @TflCustomFunctionEntry. Check that the class folder is in the MATLAB search path or in the current working folder.

  3. In the class folder, create and save the following class definition file, TflCustomFunctionEntry.m. This file defines the class TflCustomFunctionEntry, which is derived from the base class RTW.TflCFunctionEntryML

    The derived class defines a do_match method . In the do_match method signature,

    • ent is the return handle, which is returned either as empty (indicating that the match failed) or as a TflCFunctionEntry handle.

    • hThis is the handle to this object.

    • hCSO is a handle to an object created by the code generator for the purpose of querying the CRL for a replacement.

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

    The purpose of the do_match method is to add any additional match criteria not provided by the base class and make any desired modifications to the implementation signature. In this case, the do_match method only needs to match targetBitPerInt, representing the number of bits in the C int data type for the current target, to the value 32. If a match is made, the method sets the return handle and creates and adds an input argument, representing whether units are expressed as degrees or radians, to the replacement function signature.

      Note   Alternatively, the additional implementation function argument for passing a units flag could be created and added in each CRL table definition file that instantiates this class. In that case, this class definition code would not create the argument and would only set its value. For an example of creating and adding additional implementation function arguments in a table definition file, see Customize CRL Matching and Replacement for Operators.

    classdef TflCustomFunctionEntry < RTW.TflCFunctionEntryML
      methods
        function ent = do_match(hThis, ...
            hCSO, ... %#ok
            targetBitPerChar, ... %#ok
            targetBitPerShort, ... %#ok
            targetBitPerInt, ... %#ok
            targetBitPerLong) %#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);
          end
        end
      end
    end

    Exit the class folder and return to the previous working folder.

  4. Create and save the following CRL table definition file, crl_table_custom_sinfcn_double.m. This file defines a CRL table containing 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
    
    hTable = RTW.TflTable;
     
    %% Add TflCustomFunctionEntry
    fcn_entry = TflCustomFunctionEntry;
    setTflCFunctionEntryParameters(fcn_entry, ...
                    'Key',                      'sin', ...
                    'Priority',                 30, ...
                    'ImplementationName',       'mySin', ...
                    'ImplementationHeaderFile', 'mySin.h', ...
                    'ImplementationSourceFile', 'mySin.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');
    
    % TflCustomFunctionEntry class do_match method will create and add
    % an implementation function argument during code generation if
    % the supported integer size on the current target is 32 bits.
    copyConceptualArgsToImplementation(fcn_entry);
    
    addEntry(hTable, fcn_entry);
  5. Optionally, perform a quick check of the validity of the function entry by invoking the table definition file at the MATLAB command line (>> tbl = crl_table_custom_sinfcn_double) and by viewing it in the Code Replacement Viewer (>> RTW.viewTfl(crl_table_custom_sinfcn_double)). For more information about validating CRL tables, see Examine and Validate Code Replacement Tables.

  6. Create and save the following CRL registration file, which references the crl_table_custom_sinfcn_double table.

    The file specifies that the CRL to be registered is named 'Custom CRL Function Entry Example' and consists of crl_table_custom_sinfcn_double, with the default ANSI math library as the base CRL table.

    function sl_customization(cm)
    % sl_customization function to register a code replacement library (CRL)
    
      % Register the CRL defined in local function locCrlRegFcn
      cm.registerTargetInfo(@locCrlRegFcn);
    
    end % End of SL_CUSTOMIZATION
    
    
    % Local function to define a CRL containing crl_table_custom_sinfcn_double
    function thisCrl = locCrlRegFcn
    
      % Instantiate a CRL registry entry
      thisCrl = RTW.TflRegistry;
    
      % Define the CRL properties
      thisCrl.Name = 'Custom CRL Function Entry Example'; 
      thisCrl.Description = 'Demonstration of custom match for function replacement';
      thisCrl.TableList = {'crl_table_custom_sinfcn_double'};
      thisCrl.BaseTfl = 'C89/C90 (ANSI)';
      thisCrl.TargetHWDeviceType = {'*'};
    
    end % End of LOCCRLREGFCN

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

      Tip   To refresh Simulink customizations within the current MATLAB session, use the command sl_refresh_customizations. (To refresh MATLAB Coder CRL registration information within a MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');.)

    For more information about registering CRLs with Simulink or MATLAB Coder software, see Register Code Replacement Libraries.

  7. With your sl_customization.m file in the MATLAB search path or in the current working folder, open the model you created in step 1 and navigate to the Code Generation > Interface pane of the Configuration Parameters dialog box. Verify that the Code replacement library option lists the CRL name you specified and select it.

    Optionally, you can relaunch the Code Replacement Viewer, using the MATLAB command RTW.viewTFL with no argument, to examine all registered CRLs, including Custom CRL Function Entry Example.

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

  9. Go to the model window and use model-to-code highlighting to trace the code generated using your CRL entry. For example, right-click the sine block and select Code Generation > Navigate to Code. This selection highlights the sine block code within the model step function in the model.c file. As shown below, the default implementation code for the sine function has been replaced with mySin, and the additional units flag input argument is present.

    /* Model step function */
    void sine_double_step(void)
    {
      /* Outport: '<Root>/Out1' incorporates:
       *  Inport: '<Root>/In1'
       *  Trigonometry: '<Root>/Trigonometric Function'
       */
      sine_double_Y.Out1 = mySin(sine_double_U.In1, 1);
    }
    

      Note   Optionally, you can change the current target for the model such that the supported integer size is not 32 bits, and then regenerate code. In that case, the custom match is not made, and the additional input argument does not appear in the generated code for the sine block.

Replace Math Functions Based on Computation Method

Certain math function blocks are configured with computation or approximation methods that you can use as distinguishing attributes to control CRL-based code replacement. For example,

You can define CRL table entries to replace these functions for one or all of the available computation methods. For example, you could provide a table entry to replace only Newton-Raphson instances of the rSqrt function.

To distinguish between computation methods for a given function, use the EntryInfoAlgorithm property of CRL function entries in a call to the setTflCFunctionEntryParameters function. The arguments for specifying the computation method to match during code generation are:

For example, to replace only Newton-Raphson instances of the rSqrt function, you can create a table entry similar to the following:

hLib = RTW.TflTable;

%
% real_T rsqrt(real_T)
%

e = RTW.TflCFunctionEntry;
setTflCFunctionEntryParameters(e, ...
  'Key', 'rSqrt', ...
  'Priority', 80, ...
  'ImplementationName', 'rsqrt_newton', ...
  'ImplementationHeaderFile', 'rsqrt.h', ...
  'EntryInfoAlgorithm', 'RTW_NEWTON_RAPHSON'); 
createAndAddConceptualArg(e, 'RTW.TflArgNumeric', ...
  'Name', 'y1', ...
  'IOType', 'RTW_IO_OUTPUT', ... 
  'DataTypeMode', 'double'); 
createAndAddConceptualArg(e, 'RTW.TflArgNumeric', ...
  'Name', 'u1', ...
  'DataTypeMode', 'double');
copyConceptualArgsToImplementation(e);
addEntry(hLib, e);

The generated code for a Newton-Raphson instance of the rSqrt function resembles the following:

/* Model step function */
void mrsqrt_step(void)
{
  /* Outport: '<Root>/Out1' incorporates:
   *  Inport: '<Root>/In1'
   *  Sqrt: '<Root>/rSqrtBlk'
   */
  mrsqrt_Y.Out1 = rsqrt_newton(mrsqrt_U.In1);
}

Specify Build Information for Code Replacements

Functions and Properties for Specifying Table Entry Build Information.  As you create CRL table entries for function or operator replacement, you specify the header and source file information for each function implementation using one of the following:

Each table entry can specify additional header files, source files, and object files to be included in model builds whenever the CRL 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 CRL table creation functions.

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

Also, each table entry can specify additional compile flags, additional link flags, or other files to be included in model builds whenever the CRL table entry is matched and used to replace a function or operator in generated code. To add additional compile or link flags or other files, use the following CRL table entry properties.

PropertyDescription
AdditionalCompileFlagsAdd additional compile flags, specified as cell array of strings, for CRL table entry
AdditionalLinkFlagsAdd additional link flags, specified as cell array of strings, for CRL table entry
OtherFilesAdd other files, specified as cell array of strings, for CRL table entry (for example, a DLL file or README file to be copied to the build folder)

For example, the following code provides an additional compile flag for a function entry:

fcn_entry = RTW.TflCFunctionEntry;
fcn_entry.AdditionalCompileFlags = {'-O3'}

Use RTW.copyFileToBuildDir to Copy Files to the Build Folder.  If a CRL 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 folder 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 folder. 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 folder after code generation, specify the argument 'RTW.copyFileToBuildDir' to the genCallback parameter of the CRL 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 folder and must be copied into the build folder 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 folder.

function hTable = make_my_crl_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)','crl')}, ...
                'ImplementationSourcePath', {fullfile('$(MATLAB_ROOT)','crl')}, ...
                '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');
addAdditionalLinkObjPath(op_entry, fullfile(libdir, 'bin'));
.
.
.
addEntry(hTable, op_entry);

Add Code Replacement Library Reserved Identifiers

The Simulink Coder software reserves certain words for its own use as keywords of the generated code language. Reserved keywords for code generation are for use internal to the Simulink Coder software or C programming and should not be used in Simulink models as identifiers or function names. Reserved keywords for code generation include many CRL identifiers, the majority of which are function names, such as acos. To view a list of reserved identifiers for the CRL that you are using to generate code, call the MATLAB function RTW.TargetRegistry.getInstance.getTflReservedIdentifiers, passing the name of the CRL as displayed in the Code replacement library menu on the Interface pane of the Configuration Parameters dialog box. For example,

crl_ids = RTW.TargetRegistry.getInstance.getTflReservedIdentifiers('GNU99 (GNU)')

For more information, see Simulink Coder Code Replacement Library Keywords in the Simulink Coder documentation.

In a CRL 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 CRL reserved identifiers, use the following function.

FunctionDescription
setReservedIdentifiersRegister specified reserved identifiers to be associated with CRL table

You can register up to four reserved identifier structures in a CRL table. One set of reserved identifiers can be associated with an arbitrary CRL, while the other three (if present) must be associated with ANSI, ISO[6] , or GNU[7] libraries. The following example shows a reserved identifier structure that specifies two identifiers and the associated header file.

d{1}.LibraryName = 'ANSI';
d{1}.HeaderInfos{1}.HeaderName = 'math.h';
d{1}.HeaderInfos{1}.ReservedIds = {'y0', 'y1'};

The specified identifiers are added to the reserved identifiers collection and honored during the build procedure. For more information and examples, see setReservedIdentifiers.

Create and Manage Code Replacement Tables Using the Code Replacement Tool

About the Code Replacement Tool

The Code Replacement Tool provides a graphical interface for creating and managing the code replacement tables that make up a code replacement library (CRL). You can:

Each code replacement table contains one or more table entries. Each table entry represents a potential replacement, during code generation, of a single function or operator by a custom implementation. For each table entry, you provide:

For detailed information about the Code Replacement Tool workflow, see Create and Modify Code Replacement Tables, Validate Code Replacement Tables and Table Entries, and Generate a Code Replacement Registration File. For an introductory exercise, see Code Replacement Tool Quick-Start Example. Tool limitations are addressed in Code Replacement Tool Limitations.

Code Replacement Tool Quick-Start Example

This section steps you through a simple example of the complete Code Replacement Tool workflow.

  1. Start a new MATLAB session, and navigate (cd) to a folder that has no artifacts from previous code replacement library (CRL) work, such as CRL table definition files or CRL registration files.

  2. Open the Code Replacement Tool by entering the MATLAB command crtool.

  3. Create a new code replacement table using File > New table or its keyboard shortcut, Ctrl+T. This table will define one or more entries for replacing generated code for the math function sin with a custom C implementation. In the right-most pane, in the Name field, enter a name for the code replacement table, crl_table_sinfcn, and click Apply. Later, when you save this table to a MATLAB file, the tool will save it to the name crl_table_sinfcn.m.

  4. Create a table entry using File > New entry > Math Function or its keyboard shortcut, Ctrl+2. The new table entry appears in the middle pane, initially without a name.

  5. This table entry will map a sin function with double input and double output to a custom implementation function named sin_dbl, defined in header file sin_dbl.h. Select the table entry in the middle pane, go to the Mapping Information tab in the right pane, and configure the mapping information as follows:

    1. In the Function parameter drop-down list, select sin. Leave the Algorithm parameter set to Unspecified, and leave the parameters in the Conceptual function group at their default values.

    2. In the Replacement function group, for the Name parameter, enter sin_dbl. Click Apply, and notice that the Function signature preview automatically updates to reflect the specified replacement function name. Leave the remaining parameters in the Replacement function group at their default values.

    3. To validate the table entry so far, go to the bottom of the tab and click Validate entry. The completed mapping information is shown below.

  6. Go to the Build Information tab in the right pane, and configure the build information as follows. In the Implementation Header File parameter field, enter the header file specification sin_dbl.h. Click Apply. For this example, you can leave the other Build Information parameters at their default values. The completed build information is shown below.

    Optionally, you can revalidate the modified table entry, by returning to Mapping Information and clicking Validate entry button, or defer in favor of subsequent table-level validation.

  7. Optionally, you can create a second table entry that maps a sin function with single input and double output to a custom implementation function named sin_sgl. An easy way to accomplish this is to copy and paste the first entry to create a second entry. Then, in the second entry, simply modify the input specifications (conceptual and replacement) from double to single and modify the replacement function name and header file from sin_dbl to sin_sgl.

  8. Validate the code replacement table, using Actions > Validate table, the equivalent keyboard shortcut Ctrl+T, or the Validate icon. If any errors are reported, fix the errors, and retry the validation. Repeat until there are no errors reported.

  9. Save the table to a MATLAB file in your working folder, using File > Save table, the equivalent keyboard shortcut Ctrl+S, or the Save icon. The name of the saved file is the table name, crl_table_sinfcn, with an .m extension. Optionally, you can open the saved file in a text editor and examine the MATLAB code for the CRL table definition.

  10. Create a CRL registration file that includes your code replacement table. Select File > Generate customization file to open the Generate customization file dialog box. Edit the dialog box fields to match the following:

    Click OK, which provides feedback and includes the location and name of the registration file. The location should be on the MATLAB path or in the current working folder.

    Optionally, you can open the generated file in a text editor and examine the MATLAB code for the CRL registry entry.

  11. To register your CRL with code generation software without having to restart MATLAB, enter the following command in the MATLAB Command Window:

    >> RTW.TargetRegistry.getInstance('reset');
  12. Open an ERT-based Simulink model and navigate to the Interface pane of the Configuration Parameters dialog box. Verify that the Code replacement library option lists the CRL name you specified and select it.

      Note   If you hover over the selected library with the cursor, a tool tip appears. This tip contains information derived from your CRL registration file, such as the CRL description and the list of tables it contains.

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

    Check that the CRL you registered, Sine Function Example, is selected for this model.

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

  15. Go to the model window and use model-to-code highlighting to trace the code generated using your CRL entry. For example, right-click the Trigonometric Function block and select Code Generation > Navigate to Code. This selection highlights the sin function code within the model step function in sine_double.c. In this case, sin has been replaced with sin_dbl in the generated code.

Create and Modify Code Replacement Tables

Open the Code Replacement Tool.  You can open the Code Replacement Tool in the following ways:

When first used, the Code Replacement Tool dialog box appears as follows:

You can access table operations in the following ways:

Open and Save Code Replacement Tables.  To open an existing code replacement table, use File > Open table or the Open table icon to launch the Import file dialog box, and browse to the MATLAB file to be opened. Optionally, you can repeat the sequence to open additional tables, and potentially work on multiple tables together. Here is a sample display with two tables opened:

Controls for manipulating the display include the following:

If you open multiple tables, you can manage the tables together. Use the available menu entries and icons to create new table entries, delete table entries, and copy and paste or cut and paste information between tables.

To create a new code replacement table and add it to the Tables List in the left-most dialog pane, use File > New table or the New table icon, or right-click Tables List and select New table. The new table initially is empty.

Next, you add one or more table entries, each representing a potential function or operator replacement. The Code Replacement Tool provides several types of table entries for replacing math operators and functions, and also provides a specialized type known as a custom CRL table entry, described in Refine CRL Matching and Replacement Using Custom CRL Table Entries. After you add each table entry, you configure its displayed attributes. Each entry relates a conceptual view of the function or operator to be replaced (similar to the Simulink block view of the function or operator) to a custom implementation of that function or operator. For more information, see Configure Code Replacement Tables.

To save each table to a MATLAB file, use File > Save table, the Save table icon, or right-click/Save table to launch the Browse For Folder dialog box, and browse to the location to which the table file should be stored. Typically, you should select a location on the MATLAB path. The name for the saved file is the table name specified in the Name field of the dialog pane, with the extension .m. You cannot rename a table during the save operation.

Configure Code Replacement Tables.  

About Code Replacement Configuration.  

To configure a code replacement table, you open or create the table as described in Open and Save Code Replacement Tables, and then add, modify, and delete table entries. Each table entry represents a potential code replacement, during code generation, for a single function or operator by a custom implementation. You can configure multiple tables together and copy and paste entries between tables. Before saving a configured table, you validate it, as described in Validate Code Replacement Tables and Table Entries. You can also use the Code Replacement Tool to generate the registration file to register your tables with the code generation software, as described in Generate a Code Replacement Registration File.

To configure a table entry, select the table in the left pane, select the table entry in the middle pane, then examine and modify its attributes in the right-most, dialog pane. For most types of table entries, the attributes are grouped in two tabs, Mapping Information and Build Information, within the dialog pane.

For a basic example of creating a new code replacement table, configuring it, validating it, registering it, and using it for code generation, see Code Replacement Tool Quick-Start Example.

Mapping Information.  

The Mapping Information tab for a code replacement table entry relates a conceptual view of the function or operator (similar to the Simulink block view of the function or operator) to a custom implementation of that function or operator.

Build Information.  

The Build Information tab for a code replacement table entry provides any header, source, or link information required for building the custom implementation.

Validate Code Replacement Tables and Table Entries

The Code Replacement Tool allows you to validate the syntactic correctness of code replacement tables and table entries as you configure them. If validation finds errors, you can address the errors and retry the validation. Repeat until there are no errors reported. You can run validation in the following ways:

Generate a Code Replacement Registration File

In order to register a code replacement library containing your code replacement tables with the code generation software, you need to create a registration file, as described in Register Code Replacement Libraries. The Code Replacement tool provides a graphical interface for creating the registration file. After you have validated and saved your code replacement tables, use File > Generate customization file to open the Generate customization file dialog box:

The dialog box fields correspond to the CRL registry entry properties described in Register Code Replacement Libraries. For an example of registering a custom CRL using the Code Replacement Tool, see Code Replacement Tool Quick-Start Example.

Code Replacement Tool Limitations

The Code Replacement Tool has the following limitations:

Examine and Validate Code Replacement Tables

Overview of Code Replacement Table Validation

After you create a code replacement library (CRL) table containing your code replacement entries, but before you deploy production CRLs containing your table for general use in building models, you can use various techniques to examine and validate the CRL table entries. These include:

Invoke the Table Definition File

Immediately after creating or modifying a table definition file (as described in Create Code Replacement Tables), you should invoke it at the MATLAB command line. This invocation serves as a check of the validity of your table entries. For example,

>> tbl = crl_table_sinfcn
 
tbl =
 
RTW.TflTable
                Version: '1.0'
             AllEntries: [2x1 RTW.TflCFunctionEntry]
        ReservedSymbols: []
    StringResolutionMap: []
>> 

Any errors found during the invocation are displayed. In the following example, a typo in a data type name is detected and displayed.

>> tbl = crl_table_sinfcn
??? RTW_CORE:tfl:TflTable: Unsupported data type, 'dooble'.

Error in ==> crl_table_sinfcn at 7
hTable.registerCFunctionEntry(100, 1, 'sin', 'dooble', 'sin_dbl', ...

>> 

Use the Code Replacement Viewer to Examine Your Table

After creating or modifying a table definition file, as a further check of your table entries, you should use the Code Replacement Viewer to display and examine your table. Invoke the Code Replacement Viewer using the following form of the MATLAB command RTW.viewTfl:

RTW.viewTfl(table-name)

For example,

>> RTW.viewTfl(crl_table_sinfcn)

Select entries in your table and verify that the graphical display of the contents of your table meets your expectations. Common problems that can be detected at this stage include:

For more information about the Code Replacement Viewer, see Using the Code Replacement Viewer in the Simulink Coder documentation.

Use the Code Replacement Viewer to Examine Registered CRLs

After you register a CRL that includes your code replacement table (as described in Register Code Replacement Libraries), you should use the Code Replacement Viewer to verify that your CRL was properly registered and to examine the CRL and the tables it contains. Invoke the Code Replacement Viewer using the MATLAB command RTW.viewTfl with no arguments. This command displays all CRLs registered in the current Simulink session. For example:

>> RTW.viewTfl

If your CRL is not displayed,

If your CRL is displayed, select the CRL and examine and compare its tables, including their relative order. Common problems that can be detected at this stage include

For more information about the Code Replacement Viewer, see Using the Code Replacement Viewer in the Simulink Coder documentation.

Trace Code Replacements Generated Using Your Code Replacement Library

After you register a CRL that includes your code replacement tables, you should use the CRL to generate code and verify that you are obtaining the function or operator replacement that you expect. The following example illustrates two complementary approaches:

  1. Open an ERT-based model for which you anticipate that a function or operator replacement should occur. This example uses the demo model .rtwdemo_crladdsub.

  2. Select your CRL in the Code replacement library drop-down list on the Interface pane of the Configuration Parameters dialog box.

  3. Go to the Code Generation > Report pane of the Configuration Parameters dialog box and select the options Create code generation report, Open report automatically, Model-to-code, and Summarize which blocks triggered code replacements.

  4. Go to the Code Generation pane, select the Generate code only option, and generate code for the model.

  5. Go to the Code Replacements Report section of the HTML code generation report. This report section lists the replacement functions that were used during code generation, and provides a mapping between each replacement instance and the Simulink block that triggered the replacement. Inspect the report to see if the function or operator replacement occurred as you expected. If the replacement function is listed, you can click on each instance of its use to highlight the Simulink block that triggered the replacement.

  6. Go to the model window and use model-to-code highlighting to trace the code generated using your CRL. For example, right-click a block that you expect to have generated a function or operator replacement and select Code Generation > Navigate to Code. This selection highlights the applicable generated function code within the HTML code generation report display of rtwdemo_crladdsub.c.

    Inspect the generated code and see if the function or operator replacement occurred as you expected.

Determine Why Code Replacement Functions Were Not Used

About Code Replacement Hits and Misses.  Code replacement library (CRL) replacement may behave differently than you expect in some cases. To verify that you are obtaining the function or operator replacement that you expect, you first inspect the generated code, as described in Trace Code Replacements Generated Using Your Code Replacement Library.

To analyze replacement behavior, in addition to referencing the HTML code generation report and examining your CRL tables in the Code Replacement Viewer, you can view the CRL cache hits and misses logged during the most recent code generation session. This approach provides information on what data types and attributes should be registered in order to achieve the desired replacement. The following techniques can help you determine why code replacement functions were not used:

Debugging a CRL Table Entry Using Code Replacement Viewer Trace Information.  When debugging a CRL table entry, you can use hits and misses information in the Code Replacement Viewer to help determine why a replacement function was not used in the generated code.

To display the CRL cache hits and misses logged for a CRL table entry during the most recent code generation session:

  1. Open the Code Replacement Viewer using the following commands:

    >> crl=get_param('model', 'TargetFcnLibHandle')
    >> RTW.viewTfl(crl)
  2. In the left pane, select the CRL table to examine. In the middle pane, the viewer lists every entry in the table, with general information for each, including a usage count, which is the number of times the table entry was matched and its replacement function was used during code generation.

  3. In the middle pane, select the table entry to examine. In the right pane, the viewer displays General Information and Trace Information about the table entry.

  4. In the right pane, select the Trace Information tab.

The figure below shows the Trace Information display for the demo model rtwdemo_crladdsub, with the crl_table_addsub table selected in the left pane, and the int16 addition table entry selected in the middle pane.

The Trace Information tab lists Hit Source Locations and Miss Source Locations. Notice that the usage count for the entry is 2, and that the Trace Information tab lists 2 hits and 2 misses in the most recent code generation. The display provides links to each source location (the source block for which code replacement was considered) and, for misses, lists a Miss Reason. In the display above, in one case a saturation mode setting did not match between the CRL entry and the source block, and in another case the signedness attribute did not match. If an expected replacement did not occur, you can use the hit and miss information to modify the match criteria in the CRL table entry.

View Cache Hits and Misses Using the Command-Line Interface.  To display the CRL cache hits and misses logged during the most recent code generation session in the MATLAB Command Window, use the following command:

>> crl=get_param('model', 'TargetFcnLibHandle')

The resulting display includes the following fields:

FieldDescription
HitCacheTable containing function entries that were matched during a code generation session. These entries represent function implementations that should appear in the generated code.
MissCacheTable containing function entries that failed to match during a code generation session. These entries are created by the code generation process for the purpose of querying the CRL to locate a registered implementation. If there is a registered implementation that you feel should have been used in the generated code and was not, examining the MissCache for entries that are similar but did not match can help you locate discrepancies in a conceptual argument list or in table entry attributes.

In the following example, the most recent code generation session logged one cache hit and zero cache misses. You can examine the logged HitCache entry using its table index.

>> a=get_param('sinefcn','TargetFcnLibHandle')
 
a =
 
RTW.TflControl
        Version: '1.0'
       HitCache: [1x1 RTW.TflCFunctionEntry]
      MissCache: [0x1 handle]
    TLCCallList: [0x1 handle]
      TflTables: [2x1 RTW.TflTable]

>> a.HitCache(1)
 
ans =
 
RTW.TflCFunctionEntry
                        Key: 'sin'
                   Priority: 100
             ConceptualArgs: [2x1 RTW.TflArgNumeric]
             Implementation: [1x1 RTW.CImplementation]
          RTWmakecfgLibName: ''
                GenCallback: ''
                GenFileName: ''
             SaturationMode: 'RTW_SATURATE_UNSPECIFIED'
               RoundingMode: 'RTW_ROUND_UNSPECIFIED'
            AcceptExprInput: 1
                SideEffects: 0
                 UsageCount: 2
           SharedUsageCount: 0
                Description: ''
                   ImplType: 'FCN_IMPL_FUNCT'
      AdditionalHeaderFiles: {0x1 cell}
     AdditionalIncludePaths: {0x1 cell}
      AdditionalSourceFiles: {0x1 cell}
      AdditionalSourcePaths: {0x1 cell}
         AdditionalLinkObjs: {0x1 cell}
    AdditionalLinkObjsPaths: {0x1 cell}

>> 

Register Code Replacement Libraries

Overview of CRL Registration

After you define function and operator replacements in a code replacement library (CRL) table definition file, your table can be included in a CRL that you register either with Simulink software or with MATLAB Coder software. When a CRL is registered, it appears in the Code replacement library drop-down list on the Interface pane of the Simulink Configuration Parameters dialog box or on the Hardware pane of the MATLAB Coder Project Settings dialog box. You can select it from the Code replacement library drop-down list for use in code generation.

To register CRLs with Simulink software, use the Simulink customization file sl_customization.m. This file is a mechanism that allows you to use MATLAB code to perform customizations of the standard Simulink user interface. The Simulink software reads the sl_customization.m file, if present on the MATLAB path, when it starts and the customizations specified in the file are applied to the Simulink session. For more information on the sl_customization.m customization file, see Customizing the Simulink User Interface in the Simulink documentation.

To register CRLs with MATLAB Coder software, use the MATLAB Coder customization file rtwTargetInfo.m. This file is a mechanism that allows you to use MATLAB code to perform customizations of the standard MATLAB Coder project settings. The MATLAB Coder software reads the rtwTargetInfo.m file, if present on the MATLAB path, when it starts and the customizations specified in the file are applied to the MATLAB Coder session.

Use the sl_customization API to Register a CRL with Simulink Software

To register a CRL, you create an instance of sl_customization.m and include it on the MATLAB path of the Simulink installation that you want to customize. The sl_customization function accepts one argument: a handle to a customization manager object. The function is declared as follows:

function sl_customization(cm)

The body of the sl_customization function invokes the registerTargetInfo(crl) method to register one or more CRLs with the Simulink software. Typically, the registerTargetInfo function call references a local function that defines the CRLs to be registered. For example:

  % Register the CRL defined in local function locCrlRegFcn
  cm.registerTargetInfo(@locCrlRegFcn);

end % End of SL_CUSTOMIZATION

Below the sl_customization function, the referenced local function describes one or more CRLs to be registered. For example, you can declare the local function as follows:

% Local function to define a CRL
function thisCrl = locCrlRegFcn

In the local function body, for each CRL to be registered, you instantiate a CRL registry entry using crl = RTW.TflRegistry. For example,

  thisCrl = RTW.TflRegistry;

Then, you define the CRL properties shown in the following table within the registry entry.

CRL PropertyDescription
NameString specifying the name of the CRL, as it should be displayed in the Code replacement library drop-down list on the Interface pane of the Configuration Parameters dialog box.
DescriptionString specifying a text description of the CRL, as it should be displayed in the tool tip for the CRL in the Configuration Parameters dialog box.
TableList

Cell array of strings specifying the tables that make up the CRL, in descending priority order. Tables can be specified in any of the following ways:

  • Name of a CRL table file on the MATLAB search path

  • Absolute path to a table file

  • Path to a table file relative to $(MATLAB_ROOT)

See Register Multiple CRLs for examples of each type of table specification.

BaseTfl

String specifying the name of the CRL on which this CRL is based.

    Note   You must specify one of the default MathWorks libraries as the base CRL: 'C89/C90 (ANSI)', 'C99 (ISO)', 'GNU99 (GNU)', 'C++ (ISO)', or an equivalent alias. Doing this provides coverage of the functions, macros, and constants used by built-in blocks in your CRL, and supports compatibility between releases.

TargetHWDeviceTypeAlways specify {'*'}.
LanguageConstraintCell array of strings specifying language constraint keywords. You must specify {'C++'} if your CRL includes C++ function entries or a mix of C and C++ function entries. Otherwise you can omit the field or specify it as empty.
TargetCharacteristicsContains properties that can be used to describe target characteristics, including the DataAlignment property. You can use the DataAlignment property to provide compiler information to support data alignment for function implementations in your CRL. For more information, see Configure Data Alignment for Function Implementations. If you are not configuring data alignment for your CRL, you can omit this field.

For example:

  thisCrl.Name = 'Sine Function Example'; 
  thisCrl.Description = 'Demonstration of sine function replacement';
  thisCrl.TableList = {'crl_table_sinfcn'};
  thisCrl.BaseTfl = 'C89/C90 (ANSI)';
  thisCrl.TargetHWDeviceType = {'*'};

end % End of LOCCRLREGFCN

Combining the elements described in this section, the complete sl_customization function for the 'Sine Function Example' CRL would appear as follows:

function sl_customization(cm)
% sl_customization function to register a code replacement library (CRL)
% for use with Simulink

  % Register the CRL defined in local function locCrlRegFcn
  cm.registerTargetInfo(@locCrlRegFcn);

end % End of SL_CUSTOMIZATION


% Local function to define a CRL containing crl_table_sinfcn
function thisCrl = locCrlRegFcn

  % Instantiate a CRL registry entry
  thisCrl = RTW.TflRegistry;

  % Define the CRL properties
  thisCrl.Name = 'Sine Function Example'; 
  thisCrl.Description = 'Demonstration of sine function replacement';
  thisCrl.TableList = {'crl_table_sinfcn'};
  thisCrl.BaseTfl = 'C89/C90 (ANSI)';
  thisCrl.TargetHWDeviceType = {'*'};

end % End of LOCCRLREGFCN

If you place the sl_customization.m file containing this function in the MATLAB search path or in the current working folder, the CRL is registered at each Simulink startup. The Simulink software will display the CRL in the Code replacement library drop-down list on the Interface pane of the Configuration Parameters dialog box. For example, the following figure shows the Configuration Parameters dialog box display, including tool tip, for the 'Sine Function Example' CRL.

Use the rtwTargetInfo API to Register a CRL with MATLAB Coder Software

To register a CRL for use with MATLAB Coder software, you create an instance of rtwTargetInfo.m and include it on the MATLAB path of the MATLAB Coder installation that you want to customize. The rtwTargetInfo function accepts one argument: a handle to a target registration object. The function is declared as follows:

function rtwTargetInfo(tr)

The body of the rtwTargetInfo function invokes the registerTargetInfo(crl) method provided by the target registry object to register one or more CRLs with the MATLAB Coder software. Typically, the registerTargetInfo function call references a local function that defines the CRLs to be registered. For example:

  % Register the CRL defined in local function locCrlRegFcn
  tr.registerTargetInfo(@locCrlRegFcn);

end % End of RTWTARGETINFO

Below the rtwTargetInfo function, the referenced local function describes one or more CRLs to be registered. The format exactly matches the CRL description format previously described for Simulink use. For example, here is the MATLAB Coder equivalent of the complete CRL registration file displayed in Use the sl_customization API to Register a CRL with Simulink Software.

function rtwTargetInfo(tr)
% rtwTargetInfo function to register a code replacement library (CRL) 
% for use with codegen

  % Register the CRL defined in local function locCrlRegFcn
  tr.registerTargetInfo(@locCrlRegFcn);

end % End of RTWTARGETINFO


% Local function to define a CRL containing crl_table_sinfcn
function thisCrl = locCrlRegFcn

  % Instantiate a CRL registry entry
  thisCrl = RTW.TflRegistry;

  % Define the CRL properties
  thisCrl.Name = 'Sine Function Example'; 
  thisCrl.Description = 'Demonstration of sine function replacement';
  thisCrl.TableList = {'crl_table_sinfcn'};
  thisCrl.BaseTfl = 'C89/C90 (ANSI)';
  thisCrl.TargetHWDeviceType = {'*'};

end % End of LOCCRLREGFCN

If you place the rtwTargetInfo.m file containing this function in the MATLAB search path or in the current working folder, the CRL is registered at each MATLAB Coder startup. The MATLAB Coder software will display the CRL in the Code replacement library drop-down list on the Code Generation > Interface pane of the Configuration Parameter dialog box.

Register Multiple CRLs

For an example of a CRL registration file that registers multiple CRLs, see the sl_customization.m file used in the CRL demo, rtwdemo_crl_script. The following example illustrates the general approach, which applies equally to Simulink and MATLAB Coder CRL registration files. In this example, the three CRL tables referenced in the TableList fields reside at different locations, either on the MATLAB search path or at locations specified using path strings.

function sl_customization(cm)

  cm.registerTargetInfo(@locCrlRegFcn);

end % End of SL_CUSTOMIZATION

% Local function(s)
function thisCrl = locCrlRegFcn
  % Register a Code Replacement Library for use with model: rtwdemo_crladdsub.mdl
  thisCrl(1) = RTW.TflRegistry;
  thisCrl(1).Name = 'Addition & Subtraction Examples'; 
  thisCrl(1).Description = 'Demonstration of addition/subtraction op replacement';
  thisCrl(1).TableList = {'crl_table_addsub'};
  thisCrl(1).BaseTfl = 'C89/C90 (ANSI)';
  thisCrl(1).TargetHWDeviceType = {'*'};

  % Register a Code Replacement Library for use with model: rtwdemo_crlmuldiv.mdl
  thisCrl(2) = RTW.TflRegistry;
  thisCrl(2).Name = 'Multiplication & Division Examples'; 
  thisCrl(2).Description = 'Demonstration of mult/div op repl for built-in integers';
  thisCrl(2).TableList = {'c:/work_crl/crl_table_muldiv'};
  thisCrl(2).BaseTfl = 'C89/C90 (ANSI)';
  thisCrl(2).TargetHWDeviceType = {'*'};

  % Register a Code Replacement Library for use with model: rtwdemo_crlfixpt.mdl
  thisCrl(3) = RTW.TflRegistry;
  thisCrl(3).Name = 'Fixed-Point Examples'; 
  thisCrl(3).Description = 'Demonstration of fixed-point operator replacement';
  thisCrl(3).TableList = ...
{fullfile('$(MATLAB_ROOT)','toolbox','rtw','rtwdemos','crl_demo','crl_table_fixpt')};
  thisCrl(3).BaseTfl = 'C89/C90 (ANSI)';
  thisCrl(3).TargetHWDeviceType = {'*'};

end % End of LOCCRLREGFCN

Code Replacement Library Limitations


[a] GNU is a registered trademark of the Free Software Foundation.

[2] ANSI is a registered trademark of the American National Standards Institute, Inc.

[3] ANSI is a registered trademark of the American National Standards Institute, Inc.

[4] ANSI is a registered trademark of the American National Standards Institute, Inc.

[5] ANSI is a registered trademark of the American National Standards Institute, Inc.

[6] ISO is a registered trademark of the International Organization for Standardization.

[7] GNU is a registered trademark of the Free Software Foundation.

  


Related Products & Applications

Learn more about Simulink through this collection of videos, articles, technical literature and the Getting Started with Simulink Guide.

 © 1984-2012- The MathWorks, Inc.    -   Site Help   -   Patents   -   Trademarks   -   Privacy Policy   -   Preventing Piracy   -   RSS