| Contents | Index |
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.
| CRL | Description | Contains 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:
A function or operator key (a function name such as 'cos' or an operator ID string such as 'RTW_OP_ADD')
A set of conceptual arguments that observe a Simulink naming scheme ('y1', 'u1', 'u2', ...), along with their I/O types (output or input) and data types
Other attributes, such as fixed-point saturation and rounding characteristics for operators, to identify the function or operator to the code generation process as exactly as you require for matching purposes
The target-specific implementation of a function or operator is represented in a CRL table entry by the following elements:
The name of your implementation function (such as 'cos_dbl' or 'u8_add_u8_u8')
A set of implementation arguments that you define (the order of which must correspond to the conceptual arguments), along with their I/O types (output or input) and data types
Parameters providing the build information for your implementation function, including header file and source file names and paths
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:
Note Function replacement supports only scalar inputs. (Operation replacement supports nonscalar inputs for some matrix operations.) |
Math Functions
| ||||
| abs | acos | acosh | asin | |
| asinh | atan | atan2 | atanh | |
| ceil | cos | cosh | exactrSqrt | |
| exp | fix | floor | frexp | |
| hypot | ldexp | ln | log | |
| log10 | max | min | mod/fmod | |
| pow | rem | round | rSqrt | |
| saturate | sign | sin | sincos | |
| sinh | sqrt | round | tanh | |
| Memory Utility Functions | ||||
| memcmp | memcpy | memset | memset2zero1 | |
| Nonfinite Support Utility Functions2 | ||||
| getInf | getMinusInf | getNaN | isInf3 | |
| 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:
Note Unless otherwise stated, the listed operators are supported for the following input data types:
|
| Operator | Key | Scalar Inputs | Nonscalar Inputs |
|---|---|---|---|
| Addition (+) | RTW_OP_ADD | Yes | Yes |
| Subtraction (-) | RTW_OP_MINUS | Yes | Yes |
| Multiplication (*) | RTW_OP_MUL | Yes | Yes, including the ability to map to Basic Linear Algebra Subroutine (BLAS) multiplication functions |
| Division (/) | RTW_OP_DIV | Yes | — |
| Data type conversion (cast) | RTW_OP_CAST | Yes | — |
| Shift left (<<) | RTW_OP_SL | Yes, 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_MUL2 | — | Yes |
| Matrix right division (/) | RTW_OP_RDIV3 | — | Yes |
| Matrix left division (\) | RTW_OP_LDIV3 | — | Yes |
| Matrix inversion (inv) | RTW_OP_INV3 | — | Yes |
| Complex conjugation | RTW_OP_CONJUGATE | Yes | Yes |
| Transposition (.') | RTW_OP_TRANS | — | Yes |
| Hermitian (complex conjugate) transposition (') | RTW_OP_HERMITIAN | — | Yes |
| Multiplication with transposition | RTW_OP_TRMUL | — | Yes, including the ability to map to BLAS multiplication functions |
| Multiplication with Hermitian transposition | RTW_OP_HMMUL | — | Yes, 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). | |||
The general steps for creating and using a code replacement library are as follows:
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.)

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.
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};

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.
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.)
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','','');Note See Map Math Functions to Target-Specific Implementations for another example of sin function replacement, in which function arguments are created individually. |
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.
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.)
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 LOCCRLREGFCNIf 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.
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.
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.
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.
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.

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]
.
.
.
>> Map Nonfinite Support Utility Functions to Target-Specific Implementations
Map Fixed-Point Operators to Target-Specific Implementations
Remap Operator Outputs to Implementation Function Input Positions
Refine CRL Matching and Replacement Using Custom CRL Table Entries
To create a CRL table containing replacement information for supported functions and operators, you perform the following steps:
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. . . .
Within the function body, instantiate a CRL table with a command such as the following:
hTable = RTW.TflTable;
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
Instantiate a table entry.
Add conceptual arguments, implementation arguments, and other attributes to the entry.
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','','');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:
Examine and validate the table, as described in Examine and Validate Code Replacement Tables.
Register a CRL containing the table with the Simulink software, as described in Register Code Replacement Libraries.
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.
| Function | Description |
|---|---|
| Table entry creation | |
| addEntry | Add table entry to collection of table entries registered in CRL table |
| copyConceptualArgsToImplementation | Copy conceptual argument specifications to matching implementation arguments for CRL table entry |
| createAndAddConceptualArg | Create conceptual argument from specified properties and add to conceptual arguments for CRL table entry |
| createAndAddImplementationArg | Create implementation argument from specified properties and add to implementation arguments for CRL table entry |
| createAndSetCImplementationReturn | Create implementation return argument from specified properties and add to implementation for CRL table entry |
| enableCPP | Enable C++ support for function entry in CRL table |
| setNameSpace | Set name space for C++ function entry in CRL table |
| setTflCFunctionEntryParameters | Set specified parameters for function entry in CRL table |
| setTflCOperationEntryParameters | Set specified parameters for operator entry in CRL table |
| Alternative method for conceptual argument creation | |
| addConceptualArg | Add conceptual argument to array of conceptual arguments for CRL table entry |
| getTflArgFromString | Create CRL argument based on specified name and built-in data type |
| Alternative method for function entry creation | |
| registerCFunctionEntry | Create CRL function entry based on specified parameters and register in CRL table |
| registerCPPFunctionEntry | Create CRL C++ function entry based on specified parameters and register in CRL table |
| registerCPromotableMacroEntry | Create CRL promotable macro entry based on specified parameters and register in CRL table (for abs function replacement only) |
| Build information | |
| addAdditionalHeaderFile | Add additional header file to array of additional header files for CRL table entry |
| addAdditionalIncludePath | Add additional include path to array of additional include paths for CRL table entry |
| addAdditionalLinkObj | Add additional link object to array of additional link objects for CRL table entry |
| addAdditionalLinkObjPath | Add additional link object path to array of additional link object paths for CRL table entry |
| addAdditionalSourceFile | Add additional source file to array of additional source files for CRL table entry |
| addAdditionalSourcePath | Add additional source path to array of additional source paths for CRL table entry |
| Reserved identifiers | |
| setReservedIdentifiers | Register specified reserved identifiers to be associated with CRL table |
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
Instantiate a table entry.
Add conceptual arguments, implementation arguments, and other attributes to the entry.
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.
| Function | Description |
|---|---|
| Table entry creation | |
| addEntry | Add table entry to collection of table entries registered in CRL table |
| copyConceptualArgsToImplementation | Copy conceptual argument specifications to matching implementation arguments for CRL table entry |
| createAndAddConceptualArg | Create conceptual argument from specified properties and add to conceptual arguments for CRL table entry |
| createAndAddImplementationArg | Create implementation argument from specified properties and add to implementation arguments for CRL table entry |
| createAndSetCImplementationReturn | Create implementation return argument from specified properties and add to implementation for CRL table entry |
| enableCPP | Enable C++ support for function entry in CRL table |
| setNameSpace | Set name space for C++ function entry in CRL table |
| setTflCFunctionEntryParameters | Set specified parameters for function entry in CRL table |
| setTflCOperationEntryParameters | Set specified parameters for operator entry in CRL table |
| Alternative method for conceptual argument creation | |
| addConceptualArg | Add conceptual argument to array of conceptual arguments for CRL table entry |
| getTflArgFromString | Create 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.
| Function | Description |
|---|---|
| Alternative method for function entry creation | |
| registerCFunctionEntry | Create CRL function entry based on specified parameters and register in CRL table |
| registerCPPFunctionEntry | Create CRL C++ function entry based on specified parameters and register in CRL table |
| registerCPromotableMacroEntry | Create 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.
Note
|
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 |
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.
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);
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 );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 implementation argument order matches the conceptual argument order.
All input arguments are of the same type.
The return argument name and all input argument names follow the default Simulink naming convention:
For the return argument, y1
For input argument names, u1, u2, ..., un
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:
registerCPromotableMacroEntry (use only for the abs function)
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.
The Embedded Coder software supports the following math functions for replacement with custom library functions using code replacement library (CRL) tables.
Note Function replacement supports only scalar inputs. (Operation replacement supports nonscalar inputs for some matrix operations.) |
| Math Function | Simulink Support | Stateflow Support | MATLAB functions and MATLAB Coder Support |
|---|---|---|---|
| abs1 |
|
| Floating-point |
| acos2 | Floating-point | Floating-point | Floating-point |
| acosh2 | Floating-point | Not available (NA) | Not replaceable (NR) |
| asin2 | Floating-point | Floating-point | Floating-point |
| asinh2 | Floating-point | NA | NR |
| atan2 | Floating-point | Floating-point | Floating-point |
| atan2 | Floating-point | Floating-point | Floating-point |
| atanh2 | Floating-point | NA | NR |
| ceil | Floating-point | Floating-point | Floating-point |
| cos2,3 | Floating-point | Floating-point | Floating-point |
| cosh2 | Floating-point | Floating-point | Floating-point |
| exactrSqrt |
| NA | NA |
| exp | Floating-point | Floating-point | Floating-point |
| fix | Floating-point | NA | Floating-point |
| floor | Floating-point | Floating-point | Floating-point |
| frexp | Floating-point | NA | NA |
| hypot | Floating-point | NA | Floating-point |
| ldexp | Floating-point | Floating-point | Floating-point |
| ln | Floating-point | NA | NA |
| log | Floating-point | Floating-point | Floating-point |
| log10 | Floating-point | Floating-point | Floating-point |
| max |
|
|
|
| min |
|
|
|
| mod/fmod |
| Floating-point (fmod) | NR |
| pow | Floating-point | Floating-point | Floating-point |
| rem | Floating-point | NA | Floating-point |
| round | Floating-point | NA | Floating-point |
| rSqrt |
| NA | NA |
| saturate |
| NA | NA |
| sign |
| NA | Floating-point |
| sin2,3 | Floating-point | Floating-point | Floating-point |
| sincos2,3 | Floating-point | NA | NA |
| sinh2 | Floating-point | Floating-point | Floating-point |
| sqrt |
| Floating-point | Floating-point |
| tan2 | Floating-point | Floating-point | Floating-point |
| tanh2 | Floating-point | Floating-point | Floating-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.
Note See Code Replacement Libraries Quick-Start Example for another example of sin function replacement, in which function arguments are created using the simpler method described in Alternative Method for Creating Function Entries. |
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);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.
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 LOCCRLREGFCNPlace 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.
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.
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.
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.
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.

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.
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);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.
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 LOCCRLREGFCNPlace 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.
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.
Create an ERT-based model that uses memcpy for vector assignments. For example,
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.)

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

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.
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.
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.
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.

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 |
Note
|
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.
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);
%EOFOptionally, 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.
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 LOCCRLREGFCNPlace 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.
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.
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.
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.
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.

The Embedded Coder software supports the following scalar operators for replacement with custom library functions using code replacement library (CRL) tables:
| Operator | Key |
|---|---|
| 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 conjugation | RTW_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:
single, double, and their complex equivalents
int8, int16, int32, and their complex equivalents
uint8, uint16, uint32, and their complex equivalents
Fixed-point data types
Mixed data types (different types for different inputs)
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.
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);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.
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 LOCCRLREGFCNPlace 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.
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.
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.
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.
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.

The Embedded Coder software supports the following nonscalar operators for replacement with custom library functions using code replacement library (CRL) tables:
| Operator | Key |
|---|---|
| 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 conjugation | RTW_OP_CONJUGATE |
| Transposition (.') | RTW_OP_TRANS |
| Hermitian (complex conjugate) transposition (') | RTW_OP_HERMITIAN |
| Multiplication with transposition | RTW_OP_TRMUL |
| Multiplication with Hermitian transposition | RTW_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:
single, double, and their complex equivalents
int8, int16, int32, and their complex equivalents
uint8, uint16, uint32, and their complex equivalents
Fixed-point data types
Mixed data types (different types for different inputs)
Note Saturation and rounding modes are ignored for floating-point nonscalar addition and subtraction. In CRL table entries for nonscalar addition and subtraction, if the argument data types are all floating-point, the setTflCOperationEntryParameters function call should register 'RTW_SATURATE_UNSPECIFIED' for the SaturationMode parameter and 'RTW_ROUND_UNSPECIFIED' for the RoundingMode parameter. |
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.
Note For examples of replacing other matrix operations and handling other data types, see the Matrix Operator Replacement section of the CRL demos page rtwdemo_crl_script, including the demo model rtwdemo_crlmatops and its associated files. |
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);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.
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 LOCCRLREGFCNPlace 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.
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.
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.
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.
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.

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.
Note For examples of handling other data types, see the BLAS Support section of the CRL demos page rtwdemo_crl_script, including the demo model rtwdemo_crlblas and its associated files. |
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
.
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);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.
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 LOCCRLREGFCNPlace 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.
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.
Create an ERT-based model with two Product blocks, such as the following:

For each Product block, set the block parameter Multiplication to the value Matrix(*).
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.
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 tmwblas_mmult.mdl.
Check that the CRL you registered, MathWorks BLAS Matrix Multiplication Operator Example, is selected for this model.
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.
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.
Note For examples of handling other data types, see the BLAS Support section of the CRL demos page rtwdemo_crl_script, including the demo model rtwdemo_crlblas and its associated files. |
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
.
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);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.
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 LOCCRLREGFCNPlace 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.
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.
Create an ERT-based model with two Product blocks, such as the following:

For each Product block, set the block parameter Multiplication to the value Matrix(*).
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.
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 cblas_mmult.mdl.
Check that the CRL you registered, ANSI/ISO C BLAS Matrix Multiplication Operator Example, is selected for this model.
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.
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.

Create Fixed-Point Operator Entries for Binary-Point-Only Scaling
Create Fixed-Point Operator Entries for [Slope Bias] Scaling
Create Fixed-Point Operator Entries for Relative Scaling (Multiplication and Division)
Create Fixed-Point Operator Entries for Net Slope (Multiplication and Division)
Create Fixed-Point Operator Entries for Equal Slope and Zero Net Bias (Addition and Subtraction)
Map Data Type Conversion (Cast) Operations to Target-Specific Implementations
Map Fixed-Point Shift Left Operations 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:
| Operator | Key |
|---|---|
| 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:
A specific binary-point-only scaling combination on the operator inputs and output.
A specific [slope bias] scaling combination on the operator inputs and output.
Relative scaling or net slope between multiplication or division operator inputs and output.
Use these methods to map a range of slope and bias values to a replacement function for multiplication or division.
Equal slope and zero net bias across addition or subtraction operator inputs and output.
Use this method to disregard specific slope and bias values and map relative slope and bias values to a replacement function for addition or subtraction.
Note
|
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
is an arbitrarily
precise real-world value.
is the approximate
real-world value that results from fixed-point representation.
is an integer
that encodes
, referred to as
the quantized integer.
is a coefficient
of
, referred to as the slope.
is an additive
correction, referred to as the bias.
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:
Relative scaling factor (RSF) entry:
The operation V0 = V1 * V2 implies, for binary-point-only scaling, that

where Sn is the net slope.
Multiplication replacement functions may be defined such that all scaling is contained by a single operand. For example, a replacement function s8_mul_s8_u8_rsf0p125 can multiply a signed 8-bit value by a factor of [0 ... 0.1245] and produce a signed 8-bit result. The following discussion describes how to convert the slope on each operand into a net factor.
To match a multiplication operation to the s8_mul_s8_u8_rsf0p125 replacement function, 0 <= SnQ2 <= 2 − 3. Substituting the maximum integer value for Q2 results in the following match criteria: When Sn28 = 2 − 3, or Sn = 2 − 11, CRL replacement processing maps the multiplication operation to the s8_mul_s8_u8_rsf0p125 function.
To accomplish this mapping, the CRL operator entry must define a relative scaling factor, F2E, where the values for F and E are provided using operator entry parameters RelativeScalingFactorF and RelativeScalingFactorE. (For parameter descriptions, see the reference page for the function setTflCOperationEntryParameters.) For the s8_mul_s8_u8_rsf0p125 function, the RelativeScalingFactorF would be set to 1 and the RelativeScalingFactorE would be set to -3.
Net slope entry:
Net slope entries are similar to the relative scaling factor entry described above. The difference is the match criteria. For a net slope entry, the net slope of the call-site operation, Sn, must match the specified net slope, Sn = F2E, without regard to the maximum integer value. Specify the desired net slope F and E values using operator entry parameters NetSlopeAdjustmentFactor and NetFixedExponent. (For parameter descriptions, see the reference page for the function setTflCOperationEntryParameters.)
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:
Relative scaling factor (RSF) entry:
The operation V0 = (V1 / V2) implies, for binary-point-only scaling, that

where Sn is the net slope.
As with multiplication, division replacement functions may be defined such that all scaling is contained by a single operand. For example, a replacement function s16_rsf0p5_div_s16_s16 can divide a signed 16<<16 value by a signed 16-bit value and produce a signed 16-bit result. The following discussion describes how to convert the slope on each operand into a net factor.
To match a division operation to the s16_rsf0p5_div_s16_s16 replacement function, 0 <= SnQ1 <= 2 − 1. Substituting the maximum integer value for Q1 results in the following match criteria: When Sn215 = 2 − 1, or Sn = 2 − 16, CRL replacement processing maps the division operation to the s8_mul_s8_u8_rsf0p125 function.
To accomplish this mapping, the CRL operator entry must define a relative scaling factor, F2E, where the values for F and E are provided using operator entry parameters RelativeScalingFactorF and RelativeScalingFactorE. (For parameter descriptions, see the reference page for the function setTflCOperationEntryParameters.) For the s16_rsf0p5_div_s16_s16 function, the RelativeScalingFactorF would be set to 1 and the RelativeScalingFactorE would be set to -1.
Net slope entry:
Net slope entries are similar to the relative scaling factor entry described above. The difference is the match criteria. For a net slope entry, the net slope of the call-site operation, Sn, must match the specified net slope, Sn = F2E, without regard to the maximum integer value. Specify the desired net slope F and E values using operator entry parameters NetSlopeAdjustmentFactor and NetFixedExponent. (For parameter descriptions, see the reference page for the function setTflCOperationEntryParameters.)
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.
| Function | Description |
|---|---|
| createAndAddConceptualArg | Create conceptual argument from specified properties and add to conceptual arguments for CRL table entry |
| createAndAddImplementationArg | Create implementation argument from specified properties and add to implementation arguments for CRL table entry |
| createAndSetCImplementationReturn | Create implementation return argument from specified properties and add to implementation for CRL table entry |
| setTflCOperationEntryParameters | Set 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.TflCOperationEntry | createAndAddConceptualArg function:
|
| A specific [slope bias] scaling combination on the operator
inputs and output See Create Fixed-Point Operator Entries for [Slope Bias] Scaling. | RTW.TflCOperationEntry | createAndAddConceptualArg function:
|
| Relative scaling between operator inputs and output (multiplication
and division) See Create Fixed-Point Operator Entries for Relative Scaling (Multiplication and Division). | RTW.TflCOperationEntryGenerator | setTflCOperationEntryParameters function:
createAndAddConceptualArg function:
|
| Net slope between operator inputs and output (multiplication
and division) See Create Fixed-Point Operator Entries for Net Slope (Multiplication and Division). | RTW.TflCOperationEntryGenerator_NetSlope | setTflCOperationEntryParameters function:
createAndAddConceptualArg function:
|
| 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.TflCOperationEntryGenerator | setTflCOperationEntryParameters function:
createAndAddConceptualArg function:
|
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:
The CRL operator entry is instantiated using the RTW.TflCOperationEntry class.
The function setTflCOperationEntryParameters is called to set operator entry parameters. These parameters include the type of operation (multiplication), the saturation mode (saturate on overflow), the rounding mode (unspecified), and the name of the replacement function (s32_mul_s16_s16_binarypoint).
The function createAndAddConceptualArg is called to create and add conceptual output and input arguments to the operator entry. Each argument specifies that the data type is fixed-point, the mode is binary-point-only scaling, and its derived slope and bias values must exactly match the call-site slope and bias values. The output argument is 32 bits, signed, with a fraction length of 28, while the input arguments are 16 bits, signed, with fraction lengths of 15 and 13.
The functions createAndSetCImplementationReturn and createAndAddImplementationArg are called to create and add implementation output and input arguments to the operator entry. Implementation arguments must describe fundamental numeric data types (not fixed-point data types). In this case, the output argument is 32 bits and signed (int32) and the input arguments are 16 bits and signed (int16).
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,
Set the Inport 1 Data type to fixdt(1,16,15)
Set the Inport 2 Data type to fixdt(1,16,13)
In the Product block:
Set Output data type to fixdt(1,32,28)
Select the option Saturate on integer overflow
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:
The CRL operator entry is instantiated using the RTW.TflCOperationEntry class.
The function setTflCOperationEntryParameters is called to set operator entry parameters. These parameters include the type of operation (division), the saturation mode (saturate on overflow), the rounding mode (round to ceiling), and the name of the replacement function (s16_div_s16_s16_slopebias).
The function createAndAddConceptualArg is called to create and add conceptual output and input arguments to the operator entry. Each argument specifies that the data type is fixed-point, the mode is [slope bias] scaling, and its specified slope and bias values must exactly match the call-site slope and bias values. The output argument and input arguments are 16 bits, signed, each with specific [slope bias] specifications.
The functions createAndSetCImplementationReturn and createAndAddImplementationArg are called to create and add implementation output and input arguments to the operator entry. Implementation arguments must describe fundamental numeric data types (not fixed-point data types). In this case, the output and input arguments are 16 bits and signed (int16).
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,
Set the Inport 1 Data type to fixdt(1,16,15,2)
Set the Inport 2 Data type to fixdt(1,16,13,5)
In the Divide block:
Set Output data type to Inherit: Inherit via back propagation
Set Integer rounding mode to Ceiling
Select the option Saturate on integer overflow
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:
The CRL operator entry is instantiated using the RTW.TflCOperationEntryGenerator class, which provides access to the fixed-point parameters RelativeScalingFactorF and RelativeScalingFactorE.
The function setTflCOperationEntryParameters is called to set operator entry parameters. These parameters include the type of operation (division), the saturation mode (saturation off), the rounding mode (round to ceiling), and the name of the replacement function (s16_div_s16_s16_rsf0p125). Additionally, RelativeScalingFactorF and RelativeScalingFactorE are used to specify the F and E parts of the relative scaling factor F2E.
The function createAndAddConceptualArg is called to create and add conceptual output and input arguments to the operator entry. Each argument is specified as fixed-point, 16 bits, and signed. Also, each argument specifies that CRL replacement request processing should not check for an exact match to the call-site slope and bias values.
The functions createAndSetCImplementationReturn and createAndAddImplementationArg are called to create and add implementation output and input arguments to the operator entry. Implementation arguments must describe fundamental numeric data types (not fixed-point data types). In this case, the output and input arguments are 16 bits and signed (int16).
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,
Set the Inport 1 Data type to int16
Set the Inport 2 Data type to fixdt(1,16,-5)
In the Divide block:
Set Output data type to fixdt(1,16,-13)
Set Integer rounding mode to Ceiling
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:
The CRL operator entry is instantiated using the RTW.TflCOperationEntryGenerator_NetSlope class, which provides access to the fixed-point parameters NetSlopeAdjustmentFactor and NetFixedExponent.
The function setTflCOperationEntryParameters is called to set operator entry parameters. These parameters include the type of operation (division), the saturation mode (wrap on overflow), the rounding mode (unspecified), and the name of the replacement function (user_div_*). Additionally, NetSlopeAdjustmentFactor and NetFixedExponent are used to specify the F and E parts of the net slope F2E.
The function createAndAddConceptualArg is called to create and add conceptual output and input arguments to the operator entry. Each argument is specified as fixed-point and signed. Also, each argument specifies that CRL replacement request processing should not check for an exact match to the call-site slope and bias values.
The function getTflArgFromString is called to create implementation output and input arguments that are added to the operator entry. Implementation arguments must describe fundamental numeric data types (not fixed-point data types).
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:
The CRL operator entry is instantiated using the RTW.TflCOperationEntryGenerator class, which provides access to the fixed-point parameters SlopesMustBeTheSame and MustHaveZeroNetBias.
The function setTflCOperationEntryParameters is called to set operator entry parameters. These parameters include the type of operation (addition), the saturation mode (saturation off), the rounding mode (unspecified), and the name of the replacement function (u16_add_SameSlopeZeroBias). Additionally, SlopesMustBeTheSame and MustHaveZeroNetBias are set to true to indicate that slopes must be equal and net bias must be zero across the addition inputs and output.
The function createAndAddConceptualArg is called to create and add conceptual output and input arguments to the operator entry. Each argument is specified as 16 bits and unsigned. Also, each argument specifies that CRL replacement request processing should not check for an exact match to the call-site slope and bias values.
The functions createAndSetCImplementationReturn and createAndAddImplementationArg are called to create and add implementation output and input arguments to the operator entry. Implementation arguments must describe fundamental numeric data types (not fixed-point data types). In this case, the output and input arguments are 16 bits and unsigned (uint16).
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,
Set the Inport 1 Data type to fixdt(0,16,13)
Set the Inport 2 Data type to fixdt(0,16,13)
In the Add block:
Verify that Output data type is set to its default, Inherit via internal rule
Set Integer rounding mode to Zero
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:
The CRL operator entry is instantiated using the RTW.TflCOperationEntry class.
The function setTflCOperationEntryParameters is called to set operator entry parameters. These parameters include the type of operation (cast), the saturation mode (saturate on overflow), the rounding mode (toward negative infinity), and the name of the replacement function (my_sat_cast).
The function getTflArgFromString is called to create an int16 output argument, which is then added to the operator entry both as the first conceptual argument and the implementation return argument.
The function getTflArgFromString is called to create an int32 input argument, which is then added to the operator entry both as the second conceptual argument and the sole implementation input argument.
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:
The CRL operator entry is instantiated using the RTW.TflCOperationEntryGenerator_NetSlope class, which provides access to the fixed-point parameters NetSlopeAdjustmentFactor and NetFixedExponent.
The function setTflCOperationEntryParameters is called to set operator entry parameters. These parameters include the type of operation (cast), the saturation mode (saturate on overflow), the rounding mode (toward negative infinity), and the name of the replacement function (my_fxp_cast). Additionally, NetSlopeAdjustmentFactor and NetFixedExponent are used to specify the F and E parts of the net slope F2E.
The function createAndAddConceptualArg is called to create conceptual output and input arguments that are added to the operator entry. Each argument is specified as fixed-point and signed. Also, each argument specifies that CRL replacement request processing should not check for an exact match to the call-site slope and bias values.
The functions createAndSetCImplementationReturn and createAndAddImplementationArg are called to create implementation return and input arguments that are added to the operator entry. Implementation arguments must describe fundamental numeric data types (not fixed-point data types).
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:
The CRL operator entry is instantiated using the RTW.TflCOperationEntry class.
The function setTflCOperationEntryParameters is called to set operator entry parameters. These parameters include the type of operation (shift left) and the name of the replacement function (my_shift_left).
The function getTflArgFromString is called to create an int16 output argument, which is then added to the operator entry both as the first conceptual argument and the implementation return argument.
The function getTflArgFromString is called to create an int16 input argument, which is then added to the operator entry both as the second conceptual argument and the first implementation input argument.
The function getTflArgFromString is called to create an int8 input argument, which is then added to the operator entry both as the third conceptual argument and the second implementation input argument. This argument specifies the number of bits to shift the previous input argument. Since the argument type is not relevant, type checking is disabled by setting the CheckType property to false.
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:
The CRL operator entry is instantiated using the RTW.TflCOperationEntryGenerator_NetSlope class, which provides access to the fixed-point parameters NetSlopeAdjustmentFactor and NetFixedExponent.
The function setTflCOperationEntryParameters is called to set operator entry parameters. These parameters include the type of operation (shift left), the saturation mode (saturate on overflow), the rounding mode (toward negative infinity), and the name of the replacement function (my_fxp_shift_left). Additionally, NetSlopeAdjustmentFactor and NetFixedExponent are used to specify the F and E parts of the net slope F2E.
The function createAndAddConceptualArg is called to create conceptual output and input arguments that are added to the operator entry. Each argument is specified as fixed-point and signed. Also, each argument specifies that CRL replacement request processing should not check for an exact match to the call-site slope and bias values.
The functions createAndSetCImplementationReturn and createAndAddImplementationArg are called to create implementation return and input arguments that are added to the operator entry. Implementation arguments must describe fundamental numeric data types (not fixed-point data types).
The function getTflArgFromString is called to create a uint8 input argument, which is then added to the operator entry both as the third conceptual argument and the second implementation input argument. This argument specifies the number of bits to shift the previous input argument. Since the argument type is not relevant, type checking is disabled by setting the CheckType property to false.
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);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.
Note Remapping outputs to implementation function inputs is supported only for operator replacement. |
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:
In the setTflCOperationEntryParameters function call for the operator replacement, specify the SideEffects parameter as true.
When defining the implementation function return, create a new void output argument, for example, y2.
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);
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:
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.
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.
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:
If you are defining a replacement function in a CRL table definition file, you instantiate an object of class RTW.ArgumentDescriptor, use its AlignmentBoundary property to specify the required alignment boundary, and assign the RTW.ArgumentDescriptor object to the Descriptor property of the argument.
If you are defining a replacement function using the Code Replacement Tool, you enter a value in the Alignment value parameter, which is located on the Mapping Information tab, within the Argument properties for the replacement function.

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:
-1 (default) — If the data is a Simulink.Bus, Simulink.Signal, or Simulink.Parameter object, specifies that the code generator should determine an optimal alignment based on usage. Otherwise, specifies that there is no alignment requirement for this argument.
Positive integer that is a power of 2, not exceeding 128 — Specifies number of bytes in the boundary. The starting memory address for the data allocated for the function argument will be a multiple of the specified value. If you specify an alignment boundary that is less than the natural alignment of the argument data type, the alignment directive is emitted in the generated code, but is silently ignored by the target compiler.
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:

Note If your model imports Simulink.Bus, Simulink.Parameter, or Simulink.Signal objects, you can specify an alignment boundary in the object properties, using the Alignment property. For more information, see the reference pages for Simulink.Bus, Simulink.Parameter, and Simulink.Signal. |
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:
If you are defining a CRL registry entry in a sl_customization.m or rtwTargetInfo.m customization file, you add one or more AlignmentSpecification objects to an RTW.DataAlignment object, and attach the RTW.DataAlignment object to the TargetCharacteristics object of the CRL registry entry.
The RTW.DataAlignment object also has the property DefaultMallocAlignment, which specifies the default alignment boundary, in bytes, that the compiler uses for dynamically-allocated memory. During code generation, if dynamic memory allocation is used for a data object involved in a code replacement, this value is used to determine if the dynamically allocated memory satisfies the alignment requirement of the replacement. If not, the replacement is disallowed. The default value for DefaultMallocAlignment is -1, indicating that the default alignment boundary used for dynamically-allocated memory is unknown. In this case, code generation uses the natural alignment of the data type to determine whether to allow a replacement.
If you are generating a customization file function using the Code Replacement Tool, you fill out the following fields for each compiler:

Click the plus (+) symbol to add additional compiler specifications.
For each data alignment specification, you provide the following information:
| AlignmentSpecification Property | Dialog Box Parameter | Description |
|---|---|---|
| AlignmentType | Alignment type | Cell array of predefined enumerated strings, specifying which types of alignment are supported by this specification:
Each alignment specification must specify at least DATA_ALIGNMENT_GLOBAL_VAR and DATA_ALIGNMENT_STRUCT_FIELD. |
| AlignmentPosition | Alignment position | Predefined enumerated string specifying the position in which the compiler alignment directive should be placed for alignment type DATA_ALIGNMENT_WHOLE_STRUCT:
For alignment types other than DATA_ALIGNMENT_WHOLE_STRUCT, code generation uses alignment position DATA_ALIGNMENT_PREDIRECTIVE. |
| AlignmentSyntaxTemplate | Alignment 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:
For example, for the gcc compiler, you might specify __attribute__((aligned(%n))), or for the MSVC compiler, __declspec(align(%n)). |
| SupportedLanguages | Supported 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.
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);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 LOCCRLREGFCNTo 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');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.

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.
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.
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:
Complex data types are not supported.
Software-in-the-loop (SIL) and Processor-in-the-loop (PIL) are not supported.
Model reference parameters are not supported.
For Simulink.Bus:
If structure field alignment is not supported by user registered alignment specifications, aligning Simulink.Bus objects is not supported unless the Simulink.Bus is imported.
When aligning a Simulink.Bus data object, all elements in the bus object will be aligned on the same boundary, which is the lowest common multiple of the alignment requirements for each individual bus element.
When using the CRL data alignment feature for MATLAB Coder code generation, local variables in a MATLAB function will not be promoted to structure fields if the registered data alignment type specification does not support alignment of local variables. If a desired replacement of an operation on local variables cannot be aligned as required, the replacement does not occur, and code is generated as if the CRL replacement was not registered.
Data alignment is not honored in code generation for shared utilities if the replacement would impose alignment requirements on the shared utility interface arguments. Under these conditions, replacement does not occur. Replacement is allowed if the registered data alignment type specification supports alignment of local variables, and the replacement involves only local variables.
Data alignment is not honored in code generation for a Stateflow graphical function if the function is exported; replacement does not occur.
When alignment is specified for functions that occur in a model reference hierarchy, and the same function data is operated on by multiple models in the hierarchy, the bottommost model dictates the alignment for the rest of the hierarchy. If the alignment requirement for a function in a model higher in the hierarchy cannot be honored due to the alignment set by a model lower in the hierarchy, the replacement in the higher model does not occur (in some cases, an error message is generated). To work around this issue, if the shared data is represented by a bus or signal object, you can manually set the alignment property on the shared data by setting the alignment property of the Simulink.Bus or Simulink.Signal object.
During code generation for your model, the CRL replacement capability uses
Preset match criteria to identify math functions and operators for which target-specific implementations should replace default implementations
Preset replacement function signatures
However, preset match criteria and preset replacement function signatures might not meet all function and operator replacement needs. For example,
You might want to replace an operator with a particular fixed-point implementation function only when fraction lengths are within a particular range.
When a match is made, you might want to modify your replacement function signature based on compile-time information, such as passing fraction-length values into the function.
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:
Create a custom CRL entry class, derived from either RTW.TflCOperationEntryML (for operator replacement) or RTW.TflCFunctionEntryML (for function replacement).
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:
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.
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.
Create CRL table entries that instantiate your custom CRL entry class.
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.
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.
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.
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
endExit the class folder and return to the previous working folder.
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
|
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);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.
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 LOCCRLREGFCNPlace 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.
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.
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.
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.
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.
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.
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
endExit the class folder and return to the previous working folder.
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);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.
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 LOCCRLREGFCNPlace 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.
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.
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.
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);
}
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 configure the Reciprocal Sqrt block to use either of two computation methods, Newton-Raphson or Exact.
You can configure the Trigonometric Function block, with Function set to sin, cos, or sincos, to use either of two approximation methods, CORDIC or None.
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 rSqrt:
'RTW_DEFAULT' (match the default computation method, Exact)
'RTW_NEWTON_RAPHSON'
'RTW_UNSPECIFIED' (match any computation method)
For sin, cos, or sincos:
'RTW_CORDIC'
'RTW_DEFAULT' (match the default approximation method, None)
'RTW_UNSPECIFIED' (match any approximation method)
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);
}Functions and Properties for Specifying Table Entry Build Information
Use RTW.copyFileToBuildDir to Copy Files to the Build Folder
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:
The arguments ImplementationHeaderFile, ImplementationHeaderPath, ImplementationSourceFile, and ImplementationSourcePath to setTflCFunctionEntryParameters or setTflCOperationEntryParameters
The headerFile argument to registerCFunctionEntry, registerCPPFunctionEntry, or registerCPromotableMacroEntry
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.
| Function | Description |
|---|---|
| addAdditionalHeaderFile | Add additional header file to array of additional header files for CRL table entry |
| addAdditionalIncludePath | Add additional include path to array of additional include paths for CRL table entry |
| addAdditionalLinkObj | Add additional link object to array of additional link objects for CRL table entry |
| addAdditionalLinkObjPath | Add additional link object path to array of additional link object paths for CRL table entry |
| addAdditionalSourceFile | Add additional source file to array of additional source files for CRL table entry |
| addAdditionalSourcePath | Add 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.
| Property | Description |
|---|---|
| AdditionalCompileFlags | Add additional compile flags, specified as cell array of strings, for CRL table entry |
| AdditionalLinkFlags | Add additional link flags, specified as cell array of strings, for CRL table entry |
| OtherFiles | Add 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);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.
| Function | Description |
|---|---|
| setReservedIdentifiers | Register 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.
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:
Create a new code replacement table or import existing tables.
Add, modify, and delete table entries. Each table entry represents a potential code replacement for a single function or operator. You can manage multiple tables together and copy and paste entries between tables.
Validate tables and table entries.
Save code replacement tables as MATLAB files.
Generate the customization file to register your code replacement tables with code generation software.
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:
Mapping Information, which 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, which provides any header, source, or link information required for building the custom implementation.
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.
This section steps you through a simple example of the complete Code Replacement Tool workflow.
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.
Open the Code Replacement Tool by entering the MATLAB command crtool.
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.

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.
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:
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.
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.
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.

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.
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.

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

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.
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.
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.

Open the Code Replacement Tool. You can open the Code Replacement Tool in the following ways:
From a Simulink model window, open the Configuration Parameters dialog box, go to the Code Generation > Interface pane, and click the Custom button, which is located to the right of the Code replacement library parameter.

In the MATLAB Command Window, enter the command crtool.
Note The Custom button appears only for ERT-based targets. Creating custom code replacement tables requires an Embedded Coder license. |
When first used, the Code Replacement Tool dialog box appears as follows:

You can access table operations in the following ways:
Available actions are provided through menus, including File, Edit, View, Actions, and Help. You can also right-click in most areas to open context-specific menus. Additionally, many menu items list equivalent keyboard shortcuts.
Common actions additionally are available through icons. You can hover over each icon to see a description.
Keyboard shortcuts are provided for most operations.
Cut, copy, paste, and delete operations are provided by Edit menu entries and by icons. You can copy and paste many types of information. The Edit menu additionally provides specialized Copy Build information and Paste Build information operations.
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:
You can drag boundaries to widen, narrow, shorten, or lengthen dialog panes, and to resize table columns.
By default, the tool displays, left to right, a root panel, a list panel, and a dialog panel. You can use View > Show dialog pane to hide or display the right-most, dialog pane. (The View menu also contains the option Prompt if dialog has unapplied changes, which is selected by default.)
You can click a table column heading to sort the table according to the contents of the selected column.
You can right-click a table column heading and select Hide to remove the column from the display. (You cannot hide the Name column.)
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.
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:
To validate a table entry, select the entry, navigate to the bottom of the Mapping Information tab, and press the Validate entry button. Alternatively, you can select one or more entries and use right-click to select validation on the context menu, or use the equivalent keyboard shortcut.
To validate a table, select the table, and use Actions > Validate table, the equivalent keyboard shortcut, or the Validate icon.
When you save a table, validation is run on any unvalidated content in the table.
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.
The Code Replacement Tool has the following limitations:
Multiple rounding modes are not supported.
The CRL entry property AdditionalCompileFlags is missing from the Build Information tab. To specify additional compile flags, you can edit the generated MATLAB table definition file. For more information, see Specify Build Information for Code Replacements.
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:
Invoking the table definition file
Using the Code Replacement Viewer at various stages of CRL development to examine CRLs, tables, and entries
Tracing code generated from models for which your CRL is selected
Examining CRL cache hits and misses logged during code generation
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', ... >>
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:
Incorrect argument order
Conceptual argument naming that does not match the naming convention used by the code generation process
Incorrect relative priority of entries within the table (highest priority is 0, and lowest priority is 100).
For more information about the Code Replacement Viewer, see Using the Code Replacement Viewer in the Simulink Coder documentation.
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,
There may be an error in your CRL registration file.
You may need to refresh the CRL registration information by issuing the MATLAB command sl_refresh_customizations or, for a MATLAB Coder CRL registration, using the command RTW.TargetRegistry.getInstance('reset').
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
Incorrect relative order of tables in the library (tables are displayed in search order)
Table entry problems as listed in the previous section
For more information about the Code Replacement Viewer, see Using the Code Replacement Viewer in the Simulink Coder documentation.
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:
Check the Code Replacement Report section of the HTML code generation report for a specific expected replacement
Using model-to-code highlighting to trace a specific expected replacement
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.
Select your CRL in the Code replacement library drop-down list on the Interface pane of the Configuration Parameters dialog box.
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.
Go to the Code Generation pane, select the Generate code only option, and generate code for the model.
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.

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.
Note If a function or operator was not replaced as you expected, it means that a call site request was not matched as you intended by your table entry attributes. Either a higher-priority (lower priority value) match was used or no match was found. You can analyze the CRL table entry matching behavior by using the following resources together:
|
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.
Note To generate code replacement trace information for viewing in the Code Replacement Viewer, you must select the Code Generation > Report option Summarize which blocks triggered code replacements before generating code. |
To display the CRL cache hits and misses logged for a CRL table entry during the most recent code generation session:
Open the Code Replacement Viewer using the following commands:
>> crl=get_param('model', 'TargetFcnLibHandle')
>> RTW.viewTfl(crl)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.
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.
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:
| Field | Description |
|---|---|
| HitCache | Table containing function entries that were matched during a code generation session. These entries represent function implementations that should appear in the generated code. |
| MissCache | Table 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}
>> Use the sl_customization API to Register a CRL with Simulink Software
Use the rtwTargetInfo API to Register a CRL with MATLAB Coder Software
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.
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 Property | Description | |
|---|---|---|
| Name | String 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. | |
| Description | String 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:
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.
| |
| TargetHWDeviceType | Always specify {'*'}. | |
| LanguageConstraint | Cell 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. | |
| TargetCharacteristics | Contains 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 LOCCRLREGFCNCombining 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 LOCCRLREGFCNIf 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.

Tip
|
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 LOCCRLREGFCNIf 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.
Tip To refresh MATLAB Coder CRL registration information within the current MATLAB session, use the command RTW.TargetRegistry.getInstance('reset');. |
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 LOCCRLREGFCNCode replacement library (CRL) replacement may behave differently than you expect in some cases. For example, data types that you observe in a model do not necessarily match what the code generator determines to use as intermediate data types in an operation. To verify whether you are obtaining the function or operator replacement that you expect, inspect the generated code.
To analyze replacement behavior, in addition to referencing the generated code and examining your CRL tables in the Code Replacement Viewer, view the CRL cache hits and misses logged during the most recent code generation session. This approach provides information on what data types should be registered in order to achieve the desired replacement. For more information on analyzing CRL table entries, see Examine and Validate Code Replacement Tables.
You must register a CRL in either an sl_customization.m file or an rtwTargetInfo file, but not in both files.
[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.
![]() | Export Code Generated from Model to External Application | Performance | ![]() |

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 |