%% Optimize Generate Code by Using Multiple Code Replacement Libraries
%
% You can generate code that has code replacements enabled by multiple code replacement libraries.
% You can select multiple Code Replacement libraries in a unified workflow
% so that the generated code contains optimizations from varied code
% replacement libraries such as |AUTOSAR 4.0| and |Intel SSE|. 
% You can also select your own custom code replacement libraries along with libraries included with Embedded Coder to further optimize the generated code.
% You can select and use a combination of libraries and achieve the requisite functionalities, and need not author separate libraries.
% In instances where there are multiple custom code replacement libraries and you need functionalities from all of them, individually select the libraries.
%
%   Copyright 2020 The MathWorks, Inc.
%% Example Model
% This example shows how to replace the generated code with a model containing an Add and an Abs block by using multiple code replacement libraries.
% You replace the Abs block using a code replacement customization that replaces the regular |fabs| function with the custom implementation |CRL_abs_d| from the |ScalarFcn| library. 
% The Add block has inputs of size |[50 50]|. The loops in the generated code are vectorized with SIMD capabilities supported by the |Intel AVX| library.
%
% Open the model |mMultiLibrary_abs| that has an Add block and an Abs block.
model = 'mMultiLibrary_abs';
open_system(model);

copyfile multipleFnRtwTargetInfo.txt rtwTargetInfo.m

%% 
% The MATLAB customization files |hcrl_make_abs| and |hcrl_sum_float| have already been executed.   
% Run the sl_refresh_customizations function to register the library |ScalarFcn|.
sl_refresh_customizations;

%% Enable Code Replacement Library
% # Open the Configuration Parameters dialog box.  
% # In the Configuration Parameters dialog box, set the correct *Device Vendor* and *Device
% Type* depending on the hardware target. In this example |Intel| is the
% *Device Vendor* and
% |x86-64(Windows64)| is the *Device
% Type*.
% # On the *Interface* pane, set  *Code Replacement Library* parameter by clicking *Select* and adding the code replacement libraries to the *Selected code replacement libraries - prioritized* list pane.
% # Order the code replacement libraries according to the priority in which you want to see them replaced in the generated code. Code replacement libraries at the top of order have a higher priority during code replacement.

%%
% <<../multicrlselect.png>>
%
% 
% Alternatively, use the command-line API to enable the code replacement:
set_param('mMultiLibrary_abs','CodeReplacementLibrary','Intel SSE (Windows),ScalarFcn')
evalc('rtwbuild(model)');
%%
% *NOTE:* When registering a code replacement library, you cannot use a comma in the code replacement library name.

%%
% View the generated code with the replacements. Here is a portion of |mMultiLibrary_abs.c|.
cfile = fullfile('mMultiLibrary_abs_ert_rtw','mMultiLibrary_abs.c');
rtwdemodbtype(cfile,'/* Model step function ','/* Model initialize function',1, 1);
%%
% The generated code contains the |CRL_abs_d| function enabled by the custom code replacement library |ScalarFcn|. 
% The for-loop utilizes SIMD functionality through the function |_mm_add_pd| enabled by the |Intel SSE (Windows)| code replacement library.
% Selecting multiple code replacement libraries enables multiple optimizations in the generated code. 

%%
% Close the model and code generation report.
delete ./rtwTargetInfo.m
bdclose(model)
rtwdemoclean;

%%
% *Limitations:* 
%
% * When you use multiple Intel SIMD code replacement libraries, the priority ordering is ignored. Intel AVX512 has a higher priority than AVX, which has higher priority over SSE, regardless of the order specified by the code replacement library.
% * When you use different argument types such as matrix and scalar, the priority ordering is ignored. A matrix code replacement library has a higher priority than a scalar code replacement library, regardless of the order specified by the code replacement library.
% * When the code replacement library parameter specifies a Standard Math Library, for instance through its BaseTfl, and it does not match the *Standard Math Library* parameter, the library specified by the *Standard Math Library* parameter is used.

