%% Generate Custom Bitstream to Meet Custom Deep Learning Network Requirements
% Deploy your custom network that only has layers with the convolution module output format or only layers with the fully connected module output format by generating a resource optimized custom bitstream that satisfies your performance and resource requirements. Bitstream generated using the default deep learning processor configuration consists of the convolution (conv), fully connected (fc), and adder modules. The generated default bitstreams could exceed your resource utilization requirements which could drive up costs. To generate a bitstream that consists of only the layers in your custom deep learning network, modify the deep learning processor configuration by using the setModuleProperty function of the dlhdl.ProcessorConfig object.
% In this example, you have a network that has only layers that have the fully connected module output format. Generate a custom bitstream that consists of the fully connected module only by removing the convolution and adder modules from the deep learning processor configuration. To remove the convolution and adder modules:
% Turn off the ModuleGeneration property for the individual modules in the deep learning processor configuration.
% Use the optimizeConfigurationForNetwork function. The function takes the deep learning network object as the input and returns an optimized custom deep learning processor configuration.
% Rapidly verify the resource utilization of the optimized deep learning processor configuration by using the estimateResources function.
%
%
%% Prerequisites
% Deep Learning HDL Toolbox™ Support Package for Xilinx™ FPGA and SoC
% Deep Learning Toolbox™
% Deep Learning HDL Toolbox™
%
%% Create Custom Processor Configuration
% Create a custom processor configuration. Save the configuration to hPC.

hPC = dlhdl.ProcessorConfig

%
%
%% Optimize Processor Configuration for a Custom Fully Connected (FC) Layer only Network
%
%  To optimize your processor configuration, create a custom fully connected layer only network. Call the custom network fcnet.

layers = [ ...
    imageInputLayer([28 28 3],'Normalization','none','Name','input')
    fullyConnectedLayer(10,'Name','fc')
    regressionLayer('Name','output')];
layers(2).Weights = rand(10,28*28*3);
layers(2).Bias = rand(10,1);
fcnet = assembleNetwork(layers);
plot(fcnet);

% Retrieve the resource utilization for the default custom processor configuration by using estimateResources. Retrieve the performance for the custom network fcnet by using estimatePerformance.

hPC.estimateResources
hPC.estimatePerformance(fcnet)

% The target device resource counts are:
% Digital signal processor (DSP) slice count —  240
% Block random access memory (BRAM) count — 128
% The estimated performance is 1454 frames per second (FPS). The estimated resource use counts are:
% Digital signal processor (DSP) slice count — 368
% Block random access memory (BRAM) count — 508
% The estimated DSP slice count and BRAM count use exceeds the target device resource budget. Customize the bitstream configuration to reduce resource use by customizing the processor configuration.
%
%% Customize Processor Configuration by Using ModuleGeneration Property
% Create a deep learning network processor configuration object. Save it to hPC_moduleoff. Turn off the convolution and adder modules in the custom deep learning processor configuration.

hPC_moduleoff = dlhdl.ProcessorConfig;
hPC_moduleoff.setModuleProperty('conv','ModuleGeneration','off');
hPC_moduleoff.setModuleProperty('adder','ModuleGeneration','off');

% Retrieve the resource utilization for the default custom processor configuration by using estimateResources. Retrieve the performance for the custom network fcnet by using estimatePerformance.

hPC_moduleoff.estimateResources
hPC_moduleoff.estimatePerformance(fcnet)

% The target device resource counts are:
% Digital signal processor (DSP) slice count — 240
% Block random access memory (BRAM) count — 128
% The estimated performance is 1454 frames per second (FPS). The estimated resource use counts are:
% Digital signal processor (DSP) slice count — 17
% Block random access memory (BRAM) count — 44
% The estimated resources of the customized bitstream match the user target device resource budget. The estimated performance matches the target network performance.
%
%% Customize Processor Configuration by Using optimizeConfigurationForNetwork
% Create a deep learning network processor configuration object. Save it to hPC_optimized. Generate an optimized deep learning processor configuration by using the optimizeConfigurationForNetwork function.

hPC_optimized = dlhdl.ProcessorConfig;
hPC_optimized.optimizeConfigurationForNetwork(fcnet);

% Retrieve the resource utilization for the default custom processor configuration by using estimateResources. Retrieve the performance for the custom network fcnet by using estimatePerformance.

hPC_optimized.estimateResources
hPC_optimized.estimatePerformance(fcnet)

% The target device resource counts are:
% Digital signal processor (DSP) slice count — 240
% Block random access memory (BRAM) count — 128
% The estimated performance is 1454 frames per second (FPS). The estimated resource use counts are:
% Digital signal processor (DSP) slice count — 17
% Block random access memory (BRAM) count — 20
% The estimated resources of the customized bitstream match the user target device resource budget. The estimated performance matches the target network performance.
%
%% Generate Custom Bitstream
% Generate a custom bitstream using the processor configuration that matches your performance and resource requirements.
% To deploy fcnet using the bitstream generated by using the ModuleOff property, uncomment this line of code:

%   dlhdl.buildProcessor(hPC_moduleoff)

% To deploy fcnet using the bitstream generated by using the optimizeConfigurationForNetwork function, uncomment this line of code:

%   dlhdl.buildProcessor(hPC_optimized)

%
% Copyright 2021 The MathWorks, Inc.