Contents

Replacing Math Functions and Operators

This example shows how to use code replacement libraries to replace operators and functions in the generated code. The models described show the replacement capabilities. With each example model, the example provides separate MATLAB® files to illustrate creation of operator and function replacements using a MATLAB® based APIMATLAB® based API and registrationregistration of the replacements with Simulink®.

Using code replacement libraries enables:

  • Better integration of model code with external and legacy code, to reduce code size and verification efforts.

  • Use of target-specific function implementations, to optimize performance of the embedded application.

Code replacement capabilities include:

  • Replacement of math functions with target-specific function implementations.

  • Replacement of math operations with target-specific function implementations.

  • Specifying build information for compiling and building the replacements with the generated code.

Steps for Using a Code Replacement Library

  • Create a table of replacement function entries.

  • Register a code replacement library consisting of one or more tables using the Simulink sl_customization.m API.

  • From the model, select the code replacement library using the Interface pane under the Code Generation pane in the Configuration Parameters dialog box.

  • Generate code for the model with Embedded Coder®.

For more information on these steps, look herelook here.

Addition and Subtraction Operator Replacement for Built-In Integers

This example code replacement library replaces '+' and '-' for two input, scalar operations on data types that are built-in integers:

  • int8, uint8

  • int16, uint16

  • int32, uint32

The model rtwdemo_crladdsubrtwdemo_crladdsub shows these replacements. For more information on operator replacement, look herelook here.

Note: The default 'EntryInfoAlgorithm' setting for addition/ subtraction code replacement library entries is 'RTW_CAST_BEFORE_OP'.

open_system('rtwdemo_crladdsub')

Addition and Subtraction EntryInfoAlgorithm

This example demonstrates the difference between the two EntryInfoAlgorithm options for addition and subtraction code replacement library entries:

  • RTW_CAST_BEFORE_OP

  • RTW_CAST_AFTER_OP

The model rtwdemo_crl_cbo_caortwdemo_crl_cbo_cao shows the different accumulator type settings on the SUM block to match the corresponding replacement entry. For more information on the EntryInfoAlgorithm options, look herelook here.

open_system('rtwdemo_crl_cbo_cao')

Multiplication and Division Operator Replacement for Built-In Integers

This example code replacement library replaces '*' and '/' for two input, scalar operations on data types that are built-in integers:

  • int8, uint8

  • int16, uint16

  • int32, uint32

The model rtwdemo_crlmuldivrtwdemo_crlmuldiv shows these replacements.

open_system('rtwdemo_crlmuldiv')

Fixed-Point Operator Replacement for Basic Operators

This example code replacement library replaces '+', '-', '*' and '/' for two input, scalar operations on data types that are fixed point. Replacements can be defined as matching:

  • A specific slope/bias scaling combination on the inputs and output.

  • A specific binary point scaling combination on the inputs and output.

  • A relative scaling between the inputs and output.

  • The same slope value and a zero net bias across the inputs and output.

The model rtwdemo_crlfixptrtwdemo_crlfixpt shows these replacements.

Notes:

  • The default 'EntryInfoAlgorithm' setting for addition/ subtraction code replacement library entries is 'RTW_CAST_BEFORE_OP'.

  • Using fixed-point data types in a model requires a Fixed-Point Designer™ license.

open_system('rtwdemo_crlfixpt')

Addition and Subtraction Operator Replacement in MATLAB® Coder™

This example code replacement library replaces '+' and '-' for two input, scalar operations on integer data types when using the codegen command.

For more information on operator replacement, look herelook here. For more information on embeddable C-code generation using MATLAB Coder, look herelook here.

This example requires a MATLAB file named addsub_two_int16.m. Copy the file to a temporary folder. This step requires write access to the temporary folder.

To see the MATLAB file, look herelook here.

Note: The default 'EntryInfoAlgorithm' setting for addition/ subtraction code replacement library entries is 'RTW_CAST_BEFORE_OP'.

coderdir = [tempname filesep 'coderdir'];
if ~exist(coderdir,'dir')
    mkdir(coderdir);
end
codersrc = ...
    fullfile(matlabroot,'toolbox','rtw','rtwdemos','crl_demo','addsub_two_int16.m');
copyfile(codersrc,coderdir,'f');
codercurdir = pwd;
cd(coderdir);

Set MATLAB Coder to Use the Code Replacement Library

Set up the configuration parameters to build and define the operation input type. To see the code replacement table definition file, look herelook here.

addpath(fullfile(matlabroot,'toolbox','rtw','rtwdemos','crl_demo'));
sl_refresh_customizations;
cfg = coder.config('lib','ecoder',true);
cfg.CodeReplacementLibrary = 'Addition & Subtraction Examples';
cfg.GenerateReport = false;
cfg.LaunchReport = false;

t = int16(2); %#ok<NASGU>

Compile the MATLAB program into a C Source File

Compile the MATLAB program. Use the configuration parameters that point to the code replacement library and the example input class defined in the previous step as input parameters to the codegen command.

codegen -config cfg -c addsub_two_int16 -args {t, t};

Inspect the MATLAB Coder Generated Code

After compiling, you might want to explore the generated source code. To see the generated code, look herelook here.

Math Function Replacement

Code replacement supports the replacement of a variety of functions. For a full list of supported functions, look herelook here.

The model rtwdemo_crlmathrtwdemo_crlmath shows these replacements. For more information on math function replacement, look herelook here.

cd(codercurdir);
open_system('rtwdemo_crlmath')

Matrix Operator Replacement

Code replacement supports replacement of the following matrix operations:

addition, subtraction, multiplication, transposition, conjugate, Hermitian

The model rtwdemo_crlmatopsrtwdemo_crlmatops shows some of these replacements. Supported types include:

  • single, double

  • int8, uint8

  • int16, uint16

  • int32, uint32

  • csingle, cdouble

  • cint8, cuint8

  • cint16, cuint16

  • cint32, cuint32

  • fixed-point integers

  • mixed types (different type on each input)

For more information on matrix operator replacement, look herelook here.

Note: The default 'EntryInfoAlgorithm' setting for addition/ subtraction code replacement library entries is 'RTW_CAST_BEFORE_OP'.

open_system('rtwdemo_crlmatops')

BLAS Support

Matrix multiplication can be mapped to Basic Linear Algebra Subroutines (BLAS).You can map the following operations to a BLAS Subroutine:

  • Matrix multiplication

  • Matrix multiplication with transpose on single or both inputs

  • Matrix multiplication with Hermitian operation on single or both inputs

The model rtwdemo_crlblasrtwdemo_crlblas shows mapping to BLAS xGEMM and xGEMV subroutines.

open_system('rtwdemo_crlblas')

Other Scalar Operator Replacements

Code replacement supports replacement of the following scalar operations:

Complex operations including addition, subtraction, multiplication, division, and complex conjugate. Other scalar operations including data type cast, shift left, arithmetic shift right, and logical shift right.

The model rtwdemo_crlscalaropsrtwdemo_crlscalarops shows some of these replacements. Supported types include:

  • single, double

  • int8, uint8

  • int16, uint16

  • int32, uint32

  • csingle, cdouble

  • cint8, cuint8

  • cint16, cuint16

  • cint32, cuint32

  • fixed-point integers

  • mixed types (different type on each input)

For more information on scalar operator replacement, look herelook here

Note: The default 'EntryInfoAlgorithm' setting for addition/ subtraction code replacement library entries is 'RTW_CAST_BEFORE_OP'.

open_system('rtwdemo_crlscalarops')

Custom Entries

Code replacement supports the creation of custom entries. You can create your own entry by subclassing from either RTW.TflCFunctionEntryML or RTW.TflCOperationEntryML. Your entry class must implement a do_match method that customizes your matching logic or modifies the matched entry. The do_match method must have a fixed preset signature. The model rtwdemo_crlcustomentryrtwdemo_crlcustomentry shows how to use custom entries to create your own matching function. This model shows how to modify the matched entry by injecting constants as additional implementation function arguments.

For more information on custom entries, look herelook here.

open_system('rtwdemo_crlcustomentry')

MATLAB Function Replacement

Code replacement supports the replacement of MATLAB functions specified in the MATLAB function block. The function can be opted for replacement by specifying 'coder.replace' within it. This feature supports replacement of MATLAB functions with the following:

  • single/multiple inputs

  • single/multiple outputs

  • scalar and matrix inputs/outputs

The model rtwdemo_crlcoderreplacertwdemo_crlcoderreplace shows some of these requirements. Supported types include:

  • single, double

  • int8, uint8

  • int16, uint16

  • int32, uint32

  • csingle, cdouble

  • cint8, cuint8

  • cint16, cuint16

  • cint32, cuint32

  • fixed-point integers

  • mixed types (different type on each input)

For more information on MATLAB function replacement, look herelook here

open_system('rtwdemo_crlcoderreplace')

Data Alignment for Function Implementations

This example code replacement library shows how to specify the alignment of nonscalar data passed into a replacement function. Some target- specific function implementations require data to be aligned to optimize application performance. To configure data alignment for a function implementation:

  • Specify the data alignment requirements in a table entry. You can specify alignment for implementation function arguments individually or collectively.

  • Specify the data alignment capabilities and syntax for your compiler. Attach an AlignmentSpecification object to the TargetCharacteristics object of the registry entry specified in your sl_customization.m or rtwTargetInfo.m file.

The model rtwdemo_crlalignrtwdemo_crlalign shows these alignment specifications. For more information on specifying data alignment for function arguments, look herelook here. For more information on specifying compiler alignment attributes, look herelook here.

This example is configured to use either the GCC, Clang, or MSVC compilers.

open_system('rtwdemo_crlalign')

Performance Gain from Data Alignment

This model shows the performance that can be gained by using code replacements to align data that is then used in SIMD instructions. The model rtwdemo_crlalignperfrtwdemo_crlalignperf shows this performance improvement.

This example is configured to use either the GCC, Clang, or MSVC compiler.

open_system('rtwdemo_crlalignperf')

cc = rtwprivate('getMexCompilerInfo');
isDaDemoSupported = strcmpi(cc.comp.Manufacturer,'GNU') || ...
                    strcmpi(cc.comp.Manufacturer,'Apple') || ...
                    strcmpi(cc.comp.Manufacturer,'Microsoft');
if ~isDaDemoSupported
  recMsg = ['Use "mex -setup" to select either GCC, Clang, or MSVC and restart this ' ...
            'example'];
  warning(['The model "%s" is configured to use either GCC, Clang, or MSVC to create ' ...
          'a Data Aligned Executable. %s.'], 'rtwdemo_crlalignperf',recMsg); %#ok<CTPCT>
end

Generate a Baseline

A baseline is generated by selecting the ANSI® library, building the model, and then running the generated executable ten times. This model uses an element-wise matrix multiplication operation as part of an image processing algorithm. The matrix multiplication is executed numerous times as each pixel in the image is processed. Profiling hooks time the execution of the executable.

if (isDaDemoSupported)
  coderdir = [tempname filesep 'coderdir'];
  if ~exist(coderdir,'dir')
      mkdir(coderdir);
  end
  cd(coderdir);
  set_param('rtwdemo_crlalignperf', 'CodeReplacementLibrary','None' ...
                                  , 'TargetLangStandard','C89/C90 (ANSI)');
  rtwbuild('rtwdemo_crlalignperf');
  iterations = 10;
  T1 = zeros(iterations, 1);
  for idx = 1:iterations
      evalc(['!', fullfile('.', 'rtwdemo_crlalignperf')]);
      evalc(['load ', fullfile('.','rtwdemo_crlalignperf.mat')]);
      T1(idx) = rt_yout.signals(1).values;
  end
  if exist('rtwdemo_crlalignperf_ANSI', 'dir')
      rmdir('rtwdemo_crlalignperf_ANSI', 's');
  end
  movefile('rtwdemo_crlalignperf_ert_rtw', 'rtwdemo_crlalignperf_ANSI');
else
  warning('Unable to build model "%s". %s.', 'rtwdemo_crlalignperf',recMsg);
end
### Starting build procedure for model: rtwdemo_crlalignperf
### Successful completion of build procedure for model: rtwdemo_crlalignperf

Generate a Data Aligned Executable

You generate an optimized, data-aligned executable by selecting a library that maps element-wise matrix multiplication operations to SIMD intrinsic calls, and then building the model. The SIMD intrinsic calls impose an alignment requirement on data passed to the intrinsic. The optimized executable is run ten times. Profiling hooks again capture timing data.

if (isDaDemoSupported)
  set_param('rtwdemo_crlalignperf', 'CodeReplacementLibrary', ...
            'SIMD Single 5x5 Element-wise Mul');
  rtwbuild('rtwdemo_crlalignperf');
  T2 = zeros(iterations, 1);
  for idx=1:iterations
      evalc(['!', fullfile('.', 'rtwdemo_crlalignperf')]);
      evalc(['load ', fullfile('.','rtwdemo_crlalignperf.mat')]);
      T2(idx) = rt_yout.signals(1).values;
  end
  if exist('rtwdemo_crlalignperf_SIMD', 'dir')
      rmdir('rtwdemo_crlalignperf_SIMD','s');
  end
  movefile('rtwdemo_crlalignperf_ert_rtw', 'rtwdemo_crlalignperf_SIMD');
else
  warning('The Data Aligned Executable for the model "%s" could not be generated. %s.' ...
          ,'rtwdemo_crlalignperf',recMsg);
end
### Starting build procedure for model: rtwdemo_crlalignperf
### Successful completion of build procedure for model: rtwdemo_crlalignperf

Compare Timing Results Between the Baseline and Data-Aligned Executables

The timing data captured from running the baseline and data-aligned executables is displayed in a graph. The graph illustrates that using SIMD operations with data alignment can effectively speed up execution of data-parallel operations.

if (isDaDemoSupported)
  T1(T1<0) = NaN;    % The profile counter may overflow.
  T2(T2<0) = NaN;
  t = [min(T1), min(T2)];
  h = figure;

  bar([NaN, t(1), NaN, t(2), NaN]);
  set(gca, 'XLim', [0.5, 5.5], 'XTickLabel', {'', 'ANSI Multiply', '', 'SIMD Multiply', ''}, ...
           'TickLength', [0 0], 'YLim', [0, max(t) * 1.3], 'YTick', []);
  ylabel('Execution Time (CPU Cycles)');
  % annotate the plot
  annotation('textbox', get(gca, 'Position'), ...
             'String', ['Execution Speed Increased By: ', num2str((1 - t(2)/t(1))*100, '%2.0f'), '%'], ...
             'LineStyle', 'none', 'FitBoxToText', 'off', 'FitHeightToText', 'on', ...
             'FontWeight', 'bold', 'FontSize', 12, 'HorizontalAlignment', 'center');
  % annotate first bar (simple multiply without alignment)
  text('Position', [2, t(1)], 'String', int2str(t(1)), 'LineStyle', 'none', ...
       'FontSize', 12, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom');

  % annotate second bar (SIMD Multiply without alignment)
  text('Position', [4, t(2)],  'String', int2str(t(2)), 'LineStyle', 'none', ...
       'FontSize', 12, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom');
else
  warning('The Data Alignment Performance Gain example could not be executed. %s.' ...
        , recMsg);
end

Viewer for Code Replacement Libraries

A viewer is provided for examining and validating tables and their entries. For example, to view the table 'crl_tablemuldiv', the commands are:

crl = crl_table_muldiv;
RTW.viewTfl(crl);
daRoot = DAStudio.Root;
me = daRoot.find('-isa', 'DAStudio.Explorer');

For more information on the code replacement viewer, look herelook here.

Build Support

Each entry in a code replacement table can specify build information such as:

  • Header file dependencies

  • Source file dependencies

  • Additional include paths

  • Additional source paths

  • Additional link flags

Additionally, you can use the method RTW.copyFileToBuildDir to locally copy the source and header files specified by an entry. For more information on specifying compilation information, look herelook here.

Note: The models in this example are configured for code generation only because the implementations for the replacement functions are not provided.

Reserved Identifier Support

Each function implementation name defined by a entry is reserved as a unique identifier. You can specify other identifiers with a table on a per-header-file basis. Providing additional reserved identifiers can help prevent duplicate symbols and other identifier related compile and link issues.

For more information on specifying reserved identifiers, look herelook here.

Removing the Example Code Replacement Libraries

Once you are finished using the example models, you can remove the example code replacement libraries and close the example models with these commands:

rmpath(fullfile(matlabroot,'toolbox','rtw','rtwdemos','crl_demo'));
sl_refresh_customizations;

close_system('rtwdemo_crladdsub', 0)
close_system('rtwdemo_crl_cbo_cao', 0)
close_system('rtwdemo_crlmuldiv', 0)
close_system('rtwdemo_crlfixpt', 0)
close_system('rtwdemo_crlmath', 0)
close_system('rtwdemo_crlmatops', 0)
close_system('rtwdemo_crlblas', 0)
close_system('rtwdemo_crlscalarops', 0)
close_system('rtwdemo_crlcustomentry', 0)
close_system('rtwdemo_crlcoderreplace', 0)
close_system('rtwdemo_crlalign', 0)
close_system('rtwdemo_crlalignperf', 0)

drawnow;
if exist('h','var') && ishghandle(h)
  close(h);
end

if ~isempty(me)
    me(end).delete;
end

clear h;
clear crl;
clear coderdir;
clear codersrc;
clear codercurdir;
clear n1;
clear me;
clear cfg;
clear t;
clear cc;
clear recMsg;
clear isDaDemoSupported;
clear T1;
clear T2;
clear idx;
clear iterations;
clear rt_tout;
clear rt_yout;
Was this topic helpful?