%% Specify Buffer Reuse by Using Simulink.Signal Objects
% If your model has the optimal parameter settings for removing data
% copies, you might be able to remove additional data copies by using |Simulink.Signal|
% objects to specify buffer reuse. After studying the generated code and the Static Code Metrics
% Report and identifying areas where you think buffer reuse is possible, you specify signal objects on signal lines.   
% 
% You can specify buffer reuse on signals that include a pair of root
% inport and outport signals. You can also specify buffer reuse on just a pair of
% root inport and outport signals. This optimization reduces ROM and RAM
% consumption because there are less global variables and data copies in
% the generated code. Code execution speed also increases. 
%% Example Model
% The model <matlab:rtwdemo_reusable_csc rtwdemo_reusable_csc> contains the nonreusable
% subsystem |DeltaSubsystem| and the MATLAB Function block |Downsample|.
% |DeltaSubsystem| contains the MATLAB Function blocks |DeltaX| and
% |DeltaY|. 
model ='rtwdemo_reusable_csc';
open_system(model);
%% Specify a Simulink Signal Object for Reuse
% # In the *Apps* gallery, under *Code generation*, click *Embedded Coder* . The *C Code* tab opens.
% # To open the Code Mappings editor, click *Code Interface > Individual*
% *Element Code Mappings* .
% # In the model, select the |RCSC_REAL| signal line. To view this signal or any signal in the
% Code Mappings editor, on the Signals/States tab, click the *Add selected
% signals to code mappings* button.
% # For the row that represents the signal line, inspect the *Storage
% Class* column. The signal object uses the storage class |Reusable|, which
% means the object appears in the generated code as a global variable named
% |RCSC_REAL|.
% # In the model, navigate into the |DeltaSubsystem| subsystem.
% # Select the |RCSC_REAL| signal line in this subsystem. This signal also resolves to the
% signal object in the base workspace. 
%
% With the |Reusable| storage class, the generated code
% can store the output of the |Complex to Real-Imag| block (at the root level
% of the model) and the output of the |DeltaX| block (in the subsystem) in
% the |RCSC_REAL| global variable.
%% Generate Code 
% Build the model.
%%
currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild(model);
%%
% For buffer reuse, the |rtwdemo_reusable_csc.c| file contains these global
% variables:
%
% * |static real_T RCSC_IMAG[1048576];|
% * |static real_T RCSC_IMAG2[262144];|
% * |static real_T RCSC_REAL[1048576];|
% * |static real_T RCSC_REAL2[262144];|
%%
% The |rtwdemo_reusable_csc.c| file contains this code:
cfile = fullfile(cgDir,...
    'rtwdemo_reusable_csc_ert_rtw','rtwdemo_reusable_csc.c');
rtwdemodbtype(cfile,...
    '/* Output and update for atomic system: ''<Root>/DeltaSubsystem'' */',...
    '/* Output and update for atomic system: ''<Root>/Downsample'' */',1,0);
rtwdemodbtype(cfile,...
    '/* Model step function */','/* Model initialize function */',1,0);

%%
% The variables |RCSC_REAL| and |RCSC_IMAG| hold the outputs of the Complex to
% Real-Image block and |DeltaX|. These variables hold the inputs to the |DeltaY| block.
% The variables |RCSC_REAL2| and |RCSC_IMAG2| hold the outputs of |Downsample| and |DeltaY|.
% These variables hold the inputs to the |DeltaX| block. By
% interleaving buffers in this way, you eliminate global variables in the
% generated code.
%%
% To remove the signal objects from the signal lines and regenerate code,
% in the MATLAB Command Window, enter these commands:
portHandles = get_param(...
    'rtwdemo_reusable_csc/Complex to Real-Imag','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');

portHandles = get_param(...
    'rtwdemo_reusable_csc/Downsample','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');

portHandles = get_param(...
    'rtwdemo_reusable_csc/DeltaSubsystem/DeltaX','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');

portHandles = get_param(...
    'rtwdemo_reusable_csc/DeltaSubsystem/DeltaY','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');

rtwbuild(model);
%%
% The |rtwdemo_reusable_csc.c| file now contains this code. 
cfile = fullfile(cgDir,...
    'rtwdemo_reusable_csc_ert_rtw','rtwdemo_reusable_csc.c');
rtwdemodbtype(cfile,...
    '/* Output and update for atomic system: ''<Root>/DeltaSubsystem'' */',...
    '/* Output and update for atomic system: ''<Root>/Downsample'' */',1,0);
rtwdemodbtype(cfile,...
    '/* Model step function */','/* Model initialize function */',1,0);
%%
% The generated code contains two additional global variables for holding
% block inputs and outputs. 
%
% Note: You can specify buffer reuse on signals that the code generator
% cannot implement. For those cases, use two diagnostics to specify the
% message type that the model displays. In the Configuration Parameters
% dialog box, these diagnostics are *Detect non-reused custom storage classes* 
% and *Detect ambiguous custom storage class final values*.

%%
bdclose(model)
rtwdemoclean;
cd(currentDir)

%% Buffer Reuse for Unit Delay and Delay Blocks
% To reuse the signal of a Unit Delay or Delay block, use the same reusable storage class specification for a pair of
% input and state arguments or a pair of output and state arguments of a
% Unit Delay or a Delay block. For Delay blocks, you must set the *Delay length* parameter to |1| and
% *Initial condition > Source* to |Dialog|. To access these parameters, in
% the model, open the Property Inspector and click the block in the model. 

%% Limitations for Root Inport and Outport Signals
% These limitations apply to a model in which you specify buffer
% reuse for a pair of root inport and outport signals:
%
% * The output ports cannot be conditional.
% * If the code generator cannot reuse the same buffer in a top model,
% the generated code contains additional buffers. If the top model is a reference model, the
% code generator reports an error. To resolve the error, remove the
% Simulink.signal specification from the signal that connects to the outport port.
% * When you run the executable that the code generator produces, and you reuse a
% pair of root inport and outport signals, when the root input value is zero, the root output value must also be zero. If the
% output value is nonzero and you reuse the signals, then the results from
% the simulation can differ from the results that the executable produces.
% * There might be a simulation versus code generation mismatch when you
% assign the same Reusable storage class to pair of root inport and
% root outport signals. This mismatch occurs when an Assignment block
% drives the Root Outport block, and the Assignment block does not assign a
% value to every element of the output signal because the Y0 port of the
% Assignment block is not active. This image shows a model in which the
% mismatch occurs:
%
% <<../rooti_o_limitation.png>>
%
% During simulation, the unwritten Assignment block output values are zero.
% During code generation, the unwritten output values are the same as the input.
%
%% Limitations for the Model
% These limitations apply to a model in which you specify buffer
% reuse for signals:
%
% * Signals that you specify for reuse must have the same data types and sampling rates.
% * For user-specified buffer reuse, blocks that modify a signal
% specified for reuse must execute before blocks that use the original
% signal value. Sometimes the code generator has to change the block
% operation order so that buffer reuse can occur. For models in which the
% code generator is unable to reorder block operations, buffer reuse does
% not occur.
% * For models in which the code generator reorders block operations so that
% |Simulink.Signal| reuse can occur, you can observe the difference in the
% sorted order. On the *Debug* tab, in the *Diagnostics* section select the *Information Overlays* drop-down arrow. 
% In the *Blocks* section of the dialog, select *Execution Order*. To
% display the sorted execution order during simulation, on the *Modeling*
% tab, select *Update Model* . To display the execution order in the
% generated code, on the *C Code* tab, select *Build Model*.
% * You can specify buffer reuse for a chain of reusable subsystems as long
% as these subsystems do not get reused anywhere in the model.
%% 
% Copyright 2020 The MathWorks, Inc.