%% FPGA Floating-Point Library IP Mapping
% This example illustrates the floating-point workflow that integrates IP
% libraries provided by vendors, such as Altera and Xilinx. 
% For more information on how to map designs to 
% floating-point libraries, see <docid:hdlcoder_ug#bun6o0e-1>.

% Copyright 2011-2016 The MathWorks, Inc.

%% Introduction
% Implementing designs with floating-point arithmetic enable you to model
% with higher precision and wider dynamic range and saves 
% time by skipping floating-point to fixed-point conversion.  This is
% particularly beneficial for model-based design, where high-level
% algorithms are modeled with floating-point and does not have implementation timing
% details, such as pipelining and timing constraints. However, they
% are necessary to map operations to floating-point IP modules. HDL Coder
% automatically optimizes and implements your designs with these timing
% details and provides interfaces for you to adjust them.  Floating-point
% math is finally implemented by integrating with floating-point IP modules from
% vendor libraries.
 
%% Mapping designs to floating-point IP libraries
% This Field-Oriented Control (FOC) algorithm
% example demonstrates the basic steps in this workflow to map designs to
% floating-point libraries.
% See the example <docid:hdlcoder_ug#example-hdlcoderFocCurrentFixptScript>
% for details about this application.
%
% This model uses single-precision and
% contains blocks that perform basic math operators, such as adders,
% multipliers, comparators, and complex sin and cos functions. 
%  
% Signal rates in this model are modeled at 20 $\mu s$ or 50 KHz only.
% Notice that this model contains only 
% the numerical implementation, and doesn't have any FPGA implementation timing
% details, such as operation latencies.  All numerical operations,
% including sin and cos functions, compute in a single sample time-step. 
open_system('hdlcoderFocCurrentSingleTargetHdl');
open_system('hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/Sine_Cosine');

%% Choosing an IP library
% In order to map to a vendor floating-point library, set
% the FPGA device.
hdlset_param('hdlcoderFocCurrentSingleTargetHdl', 'SynthesisToolChipFamily', 'Arria 10');
hdlset_param('hdlcoderFocCurrentSingleTargetHdl', 'SynthesisTool', 'Altera Quartus II');

%%
% Setup target library tools.
hdlsetuptoolpath('ToolName', 'Altera Quartus II','ToolPath', quartuspath);
hdlsetuptoolpath('ToolName', 'XILINX ISE','ToolPath', isepath);

%%
% quartuspath and isepath return synthesis tool paths in our
% environment.  Refer to <docid:hdlcoder_ref#burmn3j-1>
% for how to setup tools in your environment.  

%%
% The first step is to choose a vendor library.  For Xilinx devices, you can use
% 'XILINXLOGICORE', and for Altera devices, you can select 'ALTERAFPFUNCTIONS' or 'ALTFP'.
% Check library documentation for their supported devices. 
%
% Create a floating-point target configuration object for ALTERAFPFUNCTIONS.
fc = hdlcoder.createFloatingPointTargetConfig('ALTERAFPFUNCTIONS');

%%
% Set the configuration object on the model
hdlset_param('hdlcoderFocCurrentSingleTargetHdl', 'FloatingPointTargetConfiguration', fc);

%%
% To compile and simulate the generated code with QuestaSim, you have to
% compile Altera simulation library and set its path on model with  
% the SimulationLibPath parameter.  Check <docid:hdlcoder_gs#btbq1zv> for more information.
% alterasimulationlibpath returns the path to the compiled Altera simulation library
% in our environment.
hdlset_param('hdlcoderFocCurrentSingleTargetHdl', 'SimulationLibPath', alterasimulationlibpath);

%% 
% Altera Megafunction (ALTERAFPFUNCTIONS) library allows generating IP modules
% for a given target frequency. In this example, the target frequency is
% set to 250MHz.
hdlset_param('hdlcoderFocCurrentSingleTargetHdl', 'TargetFrequency', 250);

%% Remodeling for IP mapping
% Generate code
try
    makehdl('hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control');
catch me
    disp(me.message);
end

%%
% The error message indicates that the Dynamic Saturation block cannot map to floating-point
% library.
hilite_system('hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control/Saturate_Output/Saturation_Dynamic');

%%
% The blocks supported for floating-point library mapping is a subset of
% all HDL Coder supported blocks.  Saturation dynamic is an example of a
% block that is supported for fixed-point, but not floating-point mapping.  In these cases,
% the block may be described as a sub-graph of the supported subset.
% For a complete list of blocks and modes that can map to floating-point
% libraries, check <docid:hdlcoder_ug#bvehzq4-1>.  
%
% In this example, we will replace the
% Saturate_Output subsystems that contains Dynamic Saturation blocks with
% an alternative implementation.
% 
open_system('floatFocUtils');
blocksToReplace = {'hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control/Saturate_Output', ...
    'hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/DQ_Current_Control/Q_Current_Control/Saturate_Output'...
    };
position1 = get_param(blocksToReplace{1}, 'Position');
delete_block(blocksToReplace{1});
add_block('floatFocUtils/Saturate_Output_Detailed', ...
    blocksToReplace{1}, 'Position', position1);
position2 = get_param(blocksToReplace{2}, 'Position');
delete_block(blocksToReplace{2});
add_block('floatFocUtils/Saturate_Output_Detailed', ...
    blocksToReplace{2}, 'Position', position2);
bdclose('floatFocUtils');
open_system(blocksToReplace{1}, 'force');

%% Applying clock rate pipelining to resolve IP latencies
% Try to generate code again
try
    makehdl('hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control');
catch me
    disp(me.message);
end

%%
% These error messages indicate that HDL Coder cannot replace operations in
% feedback loops with floating-point IP modules, because those loops are modeled
% with fewer delays than the latency of the equivalent floating-point IP modules to be
% replaced with.  Floating-point IP
% modules are implemented as pipelined blocks.  For some modules, there are
% minimum latency requirements.  As changing the latency of the
% feedback loop generates an incorrect implementation, HDL Coder
% prevents the addition of such latency inside feedback loop.  
%
% The error indicates that the adder inside the feedback loop
% requires     
% multiple cycles but the loop has only one delay.
hilite_system('hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control/Add');

%%
% There are a few options available in this situation:
%%
% * Reduce the target frequency may lower the pipelining depth requirement.
% But, this may also slow down all other IP modules in the design.
%%
% * Configure the IP modules used in the loop with a smaller latency.  This also
% slows down the IP modules' operating frequency, but only for specified IP modules.
%%
% * Apply clock rate pipelining.  When the data rate is slower than the
% FPGA clock rate, FPGA has multiple cycles at clock rate to finish
% operations and  
% still retains the numerical consistency.  For more information about clock rate pipelining,
% see <docid:hdlcoder_ug#buktkyk-1>.
%
% Let us apply the clock-rate pipelining option to solve the feedback loop
% problem, since the sample time of 20 $\mu s$ and the FPGA target
% frequency of  
% 250 MHz  (or 4 ns).  Thus, we define the Oversampling factor as the ratio
% of the two values, i.e. 5000, meaning that one unit delay, such as
% the one shown in the loop, with sample time of 20 $\mu s$ in the original model, is equivalent to 5000 clock rate cycles
% at sample time of 4 ns on the FPGA.  They are sufficient for
% floating-point IP modules in the 
% loops.  Clock rate pipelining is an ideal option for this design.  
%
% Set oversampling to 5000.
hdlset_param('hdlcoderFocCurrentSingleTargetHdl', 'Oversampling', 5000);

%%
% Generate code
makehdl('hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control');

%%
% Now, the entire design is mapped to floating-point IP modules.  The target code
% generation report summarizes the floating IP module usage.
%
% Inspect the generated model for implementation details.  For
% example, subsystem gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control/Add
% corresponding to hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control/Add
% in the original model shows that this operation takes 3 cycles.
hilite_system('gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control/Add/Add_pd1');
get_param('gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control/Add/Add_pd1', ...
    'DelayLength')

%%
% Since floating-point IP modules introduce latencies across the design, HDL Coder
% automatically adds necessary matching delays to maintain data
% synchronization.  See <docid:hdlcoder_ug#bsohw7e-2> for more details.

%% Share Floating-point IPs
% Floating-point IP modules are suitable to share, because they are usually
% identical for the same kind.  Floating point IPs are typically expensive
% operations and it is desirable to share these resources, if possible, to
% reduce the area footprint. HDL Coder shares  
% resources in the same subsystem.  In order to 
% allow more resources to share, we flatten the subsystem hierarchy and
% set resource sharing factor on the top network.
hdlset_param('hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control', 'FlattenHierarchy', 'on');
hdlset_param('hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control', 'SharingFactor', 4);

%%
% Generate code
makehdl('hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control');


%%
% We can confirm that fewer IP modules are inferred from the Floating-point resource
% report now.
%
% We can also observe the resource sharing results by inspecting the generated
% model.
%
open_system('gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control');
set_param('gm_hdlcoderFocCurrentSingleTargetHdl', 'SimulationCommand', 'update');
set_param('gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control', 'ZoomFactor', 'FitSystem');
hilite_system('gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/crp_temp_shared');
hilite_system('gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/crp_temp_shared1');
hilite_system('gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/crp_temp_shared2');
hilite_system('gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/crp_temp_shared3');
hilite_system('gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/crp_temp_shared4');
hilite_system('gm_hdlcoderFocCurrentSingleTargetHdl/FOC_Current_Control/crp_temp_shared5');

%% IP Library Configuration
% Floating point IP libraries provide some customization options for their
% IP modules. In this section, we illustrate how to control this
% configuration in the HDL Coder workflow.
%
% We will use XILINX LOGICORE and a simple model containing one add block
% for this section.

%%
% Create a
% floating-point target configuration object for XILINX LOGICORE.
fc = hdlcoder.createFloatingPointTargetConfig('XILINXLOGICORE');

%%
% In addition to library name, the configuration object has two other fields for
% library settings and individual IP module settings, respectively.
fc

%%
% LibrarySettings contains library-wide settings.  Check the setting for
% XILINX LOGICORE library.
fc.LibrarySettings

%%
% These are the settings applicable to all IP modules from this library.  For
% example Objective specifies the c_optimization parameter to XILINX
% LOGICORE.  We can switch it to 'AREA'.
fc.LibrarySettings.Objective = 'AREA';
fc.LibrarySettings

%%
% Library settings are library specific.  See <docid:hdlcoder_ug#bun6o0e-1>
% for all settings for specific libraries.
%
% IPConfig provides settings, such as Latency and
% ExtraArgs, for individual IP modules.
%
% As shown in the previous section, latency is a critical property
% for IP mapping.  HDL Coder infers latency based on library settings and
% target frequency, if applicable.  We can also specify latency for
% individual IP module with the configuration object and HDL Coder uses them for
% code generation and optimizations.
fc.IPConfig.customize('ADDSUB', 'SINGLE', 'Latency', 11);
fc.IPConfig

%%
% The latency for the ADDSUB IP becomes 11 instead of the default value 12.
%
% Other IP specific settings are specified with ExtraArgs.  For example,
% HDL Coder calls XILINX LOGICORE to generate floating-point IP modules without using
% any DSP blocks by default.  XILINX LOGICORE provides a parameter
% c_mult_usage to control DSP usage.  In order to use DSP blocks, we can
% pass a different setting with ExtraArgs to override the default behavior.
% Because the ExtraArgs string is appended to the default IP module generation
% parameters, it must comply with library setting syntax.  Check IP
% library documents for parameter usage and syntax.
fc.IPConfig.customize('ADDSUB', 'SINGLE', 'ExtraArgs', 'CSET c_mult_usage=Full_Usage');
fc.IPConfig

%%
% Open the model and set the configuration object on it.
open_system('hdlcoder_targetIP_configuration');
hdlset_param('hdlcoder_targetIP_configuration', 'FloatingPointTargetConfiguration', fc);

%%
% Run synthesis and mapping to confirm the DSP block usage.
%
%    hWC = hdlcoder.WorkflowConfig('SynthesisTool','Xilinx ISE', ...
%        'TargetWorkflow','Generic ASIC/FPGA');
%    hWC.SkipPreRouteTimingAnalysis = true;
%    hWC.RunTaskAnnotateModelWithSynthesisResult = false;
%    hWC.GenerateRTLCode = true;
%    hWC.validate;
%    hdlcoder.runWorkflow('hdlcoder_targetIP_configuration/Add_Subsystem', hWC);

%% Summary
% HDL Coder bridges the gap between high level algorithms modeled with
% floating-point and low level FPGA implementation details.  It not only automates
% the process for fast prototyping, but also allows you to explore high
% level algorithm design choices efficiently.  This example demonstrates the necessary
% steps to generate synthesizable floating-point HDL code.  The
% command-line APIs used in this example helps to automate your entire
% code generation process and design space exploration.  All the APIs have
% corresponding GUI settings for ease of usage.  For more information about the
% APIs and GUI options, check <docid:hdlcoder_ug#bun6o0e-1>.
 
displayEndOfDemoMessage(mfilename)
 



