-
Notifications
You must be signed in to change notification settings - Fork 423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vitis Accelerator IP Flow #1134
Draft
steltze
wants to merge
90
commits into
fastmachinelearning:main
Choose a base branch
from
steltze:vitis_accelerator_ip_flow
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 88 commits
Commits
Show all changes
90 commits
Select commit
Hold shift + click to select a range
312832f
Initial commit
steltze d2b5a15
Set change the backend
steltze 02659dd
Change the accelerator config script
steltze 56296b6
Set the vitis accelerator template
steltze 7dd0173
Set vitis accelerator writer
steltze 6f181b8
Fix writes init
steltze bd2e52e
Include separable convolution resource implementation
steltze b795240
Separate depthwise resource strategy to 3 cases
steltze eeb04d4
Complete vitis accelerator wrapper for io_stream case
steltze 7e47c85
Fix call to wrong backend writer
steltze 5a2a38f
Fix vitis accelerator writer
steltze 99f9429
Fix include in axi wrapper header file writer
steltze b9609dc
Change python-cpp bridge writer
steltze 4f69c16
Fix tlast handling in axis wrapper writer
steltze 014a7b2
Extend convert_data to handle stream type, use that for the bridge
steltze 723073e
Add zcu102 to the supported boards json
steltze 290896b
Fix some c synthesis warnings
steltze c9dfcf2
Group more tests per YAML to reduce the number of envs created
vloncar d3b8e20
Support negative_slope in quantized_relu
vloncar b32984f
[pre-commit.ci] auto fixes from pre-commit hooks
pre-commit-ci[bot] 98273a0
Fix activation check in profiling
vloncar 1640c4b
Stage initial set of changes for the Catapult backend (#956)
dgburnette 2a71a83
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] 6ac964c
fix unwanted tested file change in #956
calad0i ec95e01
Fix SR backend synth missing variables
bo3z 5de1bf5
Test for SR backend config
vloncar a6fec36
Upsampling support for PyTorch models
vloncar 1b72b19
Split Catapult types into separate file
vloncar 28521d0
Split Quartus types into separate file
vloncar a44707d
Split Vivado types into separate file
vloncar cefab60
Increase precision of Softsign test
vloncar 440901b
Use quantized input in binary CNN test
vloncar c351a02
Add UnspecifiedPrecisionType
vloncar 4d9d35a
Rudimentary optimizer to infer 'auto' precision
vloncar 32ae9b6
Auto precision test
vloncar 932b01e
Sepconv fixes
vloncar 6a65fed
update precision propagation for signed, select im2col for quartus pa…
jmitrevs 41b7e98
Make inferring no_bias a configurable option of the optimizer
vloncar 24253e1
updates to infering precision from qonnx branch
jmitrevs 6ee8189
remove count, become more selective on when True is returned
jmitrevs b5add0c
fix pooling precision
calad0i 665c904
remove typing
calad0i b366d24
Fix avg pooling op check
vloncar f0ca865
Optimizer to remove expensive Transpose that serves as Flatten
vloncar 1e416b5
Generalize removal of Transpose after flatten so it works on 1D as well
vloncar 2a5d8de
Remove transpose of input if n_chan=1
vloncar 3969523
SepConv1d/2d for io_parallel w/ Latency strategy
vloncar 52252ca
Cosmetic parameter config fixes
vloncar be56b93
Tests for SepConv io_parallel
vloncar b0085a1
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] 44bc8f3
Update pytest docker image to 0.5.4
jmitrevs a7826e0
bump to 0.5.5
jmitrevs 41ab6af
fix pre-commit warning
jmitrevs c0f8d9f
change writing of obsolete ".h5" to ".keras" files
jmitrevs bcfd685
Fix extension test for Keras v3
vloncar 8c09595
Support ParallelizationFactor in SepConv1D/2D
vloncar 11819ac
updated pytest docker image
jmitrevs 39d9232
Don't test io_parallel for Catapult test and reduce the size of test …
vloncar 68a83d6
Add explicit DepthwiseConv tests and simpligy SepConv tests
vloncar 8a9d556
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] ad86387
Initial commit
steltze 4ea329b
Stage initial set of changes for the Catapult backend (#956)
dgburnette 992b9b7
Rudimentary optimizer to infer 'auto' precision
vloncar 8174465
Sepconv fixes
vloncar 84ff2c6
Optimizer to remove expensive Transpose that serves as Flatten
vloncar 518796d
Remove transpose of input if n_chan=1
vloncar 238e35c
Optimizer to remove expensive Transpose that serves as Flatten
vloncar c10dd82
Remove transpose of input if n_chan=1
vloncar d6fe369
fix up automatic precision inferrence
jmitrevs 7290a29
starting towards being able to split seperable
jmitrevs 13fcf0a
complete implementation of seperable -> dw + pw, untested
jmitrevs 92e7222
make conv_same_pad also trigger on depthwise, varius bug fixes
jmitrevs f12a7ea
add parsing of depth multiplier for 1D depthwise conv
jmitrevs 4d24e4e
Merge remote-tracking branch 'upstream/main' into vitis_accelerator_i…
e2d270e
Finish resolving conficts with main
fa6bd66
Supress removing tar for now
steltze b42210d
Fix csynth and cosim
steltze 1303bba
Fix tcl script to find cosim report
steltze 8d3a1f2
Correct PYNQ Z2 vivado tcl script, bitstream generated
steltze a8e0497
Clean pynq tcl script
steltze 48686d3
Fix compatibility of nnet helper functions with vitis axis
steltze bae450b
Setup vivado tcl script for zcu102
steltze dde9124
Rename backend to VitisAcceleratorIPFLow to prevent conflicts with ke…
steltze 663181f
Fix compatiblity between axi stream and io parallel
steltze e32f4d0
Update pynq driver for zcu102
steltze c52ec75
Run pre-commit
steltze 9d9e645
Remove unused file
steltze 80697c0
Remove unused xclbin generator
steltze f467829
Clean backends init
steltze 4c74550
Fix backend import sequence
steltze File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
42 changes: 42 additions & 0 deletions
42
hls4ml/backends/vitis_accelerator_ip_flow/supported_boards.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"pynq-z2": { | ||
"part": "xc7z020clg400-1", | ||
"tcl_scripts": {"axi_lite": "axi_lite_design.tcl", "axi_stream": "axi_stream_design.tcl"}, | ||
"python_drivers": {"axi_stream": "axi_stream_driver.py"}, | ||
"c_drivers": {} | ||
}, | ||
"zcu102": { | ||
"part": "xczu9eg-ffvb1156-2-e", | ||
"tcl_scripts": { "axi_stream": "axi_stream_design.tcl"}, | ||
"python_drivers": {"axi_stream": "axi_stream_driver.py"}, | ||
"c_drivers": {} | ||
}, | ||
"alveo-u50": { | ||
"part": "xcu50-fsvh2104-2-e", | ||
"tcl_scripts": {"axi_stream": "axi_stream_design.tcl"}, | ||
"python_drivers": {"axi_stream": "axi_stream_driver.py"}, | ||
"krnl_rtl_srcs": {"axi_stream": "krnl_rtl_src"}, | ||
"c_drivers": {} | ||
}, | ||
"alveo-u250": { | ||
"part": "xcu250-figd2104-2L-e", | ||
"tcl_scripts": {"axi_stream": "axi_stream_design.tcl"}, | ||
"python_drivers": {"axi_stream": "axi_stream_driver.py"}, | ||
"krnl_rtl_srcs": {"axi_stream": "krnl_rtl_src"}, | ||
"c_drivers": {} | ||
}, | ||
"alveo-u200": { | ||
"part": "xcu200-fsgd2104-2-e", | ||
"tcl_scripts": {"axi_stream": "axi_stream_design.tcl"}, | ||
"python_drivers": {"axi_stream": "axi_stream_driver.py"}, | ||
"krnl_rtl_srcs": {"axi_stream": "krnl_rtl_src"}, | ||
"c_drivers": {} | ||
}, | ||
"alveo-u280": { | ||
"part": "xcu280-fsvh2892-2L-e", | ||
"tcl_scripts": {"axi_stream": "axi_stream_design.tcl"}, | ||
"python_drivers": {"axi_stream": "axi_stream_driver.py"}, | ||
"krnl_rtl_srcs": {"axi_stream": "krnl_rtl_src"}, | ||
"c_drivers": {} | ||
} | ||
} |
122 changes: 122 additions & 0 deletions
122
hls4ml/backends/vitis_accelerator_ip_flow/vitis_accelerator_ip_flow_backend.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import os | ||
|
||
from hls4ml.backends import VitisBackend, VivadoBackend | ||
from hls4ml.model.flow import register_flow | ||
from hls4ml.report import parse_vivado_report | ||
|
||
|
||
class VitisAcceleratorIPFlowBackend(VitisBackend): | ||
def __init__(self): | ||
super(VivadoBackend, self).__init__(name='VitisAcceleratorIPFlow') | ||
self._register_layer_attributes() | ||
self._register_flows() | ||
|
||
def build( | ||
self, | ||
model, | ||
reset=False, | ||
csim=True, | ||
synth=True, | ||
cosim=False, | ||
validation=False, | ||
export=False, | ||
vsynth=False, | ||
# fifo_opt=False, | ||
bitfile=False, | ||
): | ||
# run the VitisBackend build | ||
super().build( | ||
model, | ||
reset=reset, | ||
csim=csim, | ||
synth=synth, | ||
cosim=cosim, | ||
validation=validation, | ||
export=export, | ||
vsynth=vsynth, | ||
# fifo_opt=fifo_opt, | ||
) | ||
# Get Config to view Board and Platform | ||
# from hls4ml.backends import VitisAcceleratorIPFlowConfig | ||
|
||
# vitis_accelerator_ip_flow_config = VitisAcceleratorIPFlowConfig( | ||
# model.config, model.get_input_variables(), model.get_output_variables() | ||
# ) | ||
# now make a bitfile | ||
if bitfile: | ||
curr_dir = os.getcwd() | ||
os.chdir(model.config.get_output_dir()) | ||
try: | ||
os.system('vivado -mode batch -source design.tcl') # check if this is accepted as a command | ||
except Exception: | ||
print("Something went wrong, check the Vivado logs") | ||
os.chdir(curr_dir) | ||
|
||
return parse_vivado_report(model.config.get_output_dir()) | ||
|
||
def create_initial_config( | ||
self, | ||
board='pynq-z2', | ||
part=None, | ||
clock_period=5, | ||
clock_uncertainty='12.5%', | ||
io_type='io_parallel', | ||
interface='axi_stream', | ||
driver='python', | ||
input_type='float', | ||
output_type='float', | ||
platform='xilinx_u250_xdma_201830_2', | ||
): | ||
''' | ||
Create initial accelerator config with default parameters | ||
|
||
Args: | ||
board: one of the keys defined in supported_boards.json | ||
clock_period: clock period passed to hls project | ||
io_type: io_parallel or io_stream | ||
interface: `axi_stream`: generate hardware designs and drivers which exploit axi stream channels. | ||
`axi_master`: generate hardware designs and drivers which exploit axi master channels. | ||
`axi_lite` : generate hardware designs and drivers which exploit axi lite channels. (Don't use it | ||
to exchange large amount of data) | ||
driver: `python`: generates the python driver to use the accelerator in the PYNQ stack. | ||
`c`: generates the c driver to use the accelerator bare-metal. | ||
input_type: the wrapper input precision. Can be `float` or an `ap_type`. Note: VivadoAcceleratorBackend | ||
will round the number of bits used to the next power-of-2 value. | ||
output_type: the wrapper output precision. Can be `float` or an `ap_type`. Note: | ||
VivadoAcceleratorBackend will round the number of bits used to the next power-of-2 value. | ||
platform: development target platform | ||
|
||
Returns: | ||
populated config | ||
''' | ||
board = board if board is not None else 'pynq-z2' | ||
config = super().create_initial_config(part, clock_period, clock_uncertainty, io_type) | ||
config['AcceleratorConfig'] = {} | ||
config['AcceleratorConfig']['Board'] = board | ||
config['AcceleratorConfig']['Interface'] = interface # axi_stream, axi_master, axi_lite | ||
config['AcceleratorConfig']['Driver'] = driver | ||
config['AcceleratorConfig']['Precision'] = {} | ||
config['AcceleratorConfig']['Precision']['Input'] = {} | ||
config['AcceleratorConfig']['Precision']['Output'] = {} | ||
config['AcceleratorConfig']['Precision']['Input'] = input_type # float, double or ap_fixed<a,b> | ||
config['AcceleratorConfig']['Precision']['Output'] = output_type # float, double or ap_fixed<a,b> | ||
# if board.startswith('alveo'): | ||
# config['AcceleratorConfig']['Platform'] = platform | ||
|
||
return config | ||
|
||
def get_default_flow(self): | ||
return self._default_flow | ||
|
||
def get_writer_flow(self): | ||
return self._writer_flow | ||
|
||
def _register_flows(self): | ||
vivado_ip = 'vivado:ip' | ||
writer_passes = ['make_stamp', 'vitisacceleratoripflow:write_hls'] | ||
self._writer_flow = register_flow('write', writer_passes, requires=[vivado_ip], backend=self.name) | ||
self._default_flow = vivado_ip | ||
|
||
# fifo_depth_opt_passes = ['vivadoaccelerator:fifo_depth_optimization'] + writer_passes | ||
|
||
# register_flow('fifo_depth_optimization', fifo_depth_opt_passes, requires=[vivado_ip], backend=self.name) |
169 changes: 169 additions & 0 deletions
169
hls4ml/backends/vitis_accelerator_ip_flow/vitis_accelerator_ip_flow_config.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import json | ||
import os | ||
|
||
import numpy as np | ||
|
||
from hls4ml.model.layers import FixedPrecisionType, IntegerPrecisionType | ||
|
||
|
||
class VitisAcceleratorIPFlowConfig: | ||
def __init__(self, config, model_inputs, model_outputs): | ||
self.config = config.config | ||
self.board = self.config.get('AcceleratorConfig', {}).get('Board', 'pynq-z2') | ||
self.supported_boards = json.load(open(os.path.dirname(__file__) + '/supported_boards.json')) | ||
if self.board in self.supported_boards.keys(): | ||
board_info = self.supported_boards[self.board] | ||
self.part = board_info['part'] | ||
else: | ||
raise Exception('The board does not appear in supported_boards.json file') | ||
|
||
if self.config.get('Part') is not None: | ||
if self.config.get('Part') != self.part: | ||
print( | ||
'WARNING: You set a Part that does not correspond to the Board you specified. The correct ' | ||
'Part is now set.' | ||
) | ||
self.config['Part'] = self.part | ||
accel_config = self.config.get('AcceleratorConfig', None) | ||
if accel_config is not None: | ||
prec = accel_config.get('Precision') | ||
if prec is None: | ||
raise Exception('Precision must be provided in the AcceleratorConfig') | ||
else: | ||
if prec.get('Input') is None or prec.get('Output') is None: | ||
raise Exception('Input and Output fields must be provided in the AcceleratorConfig->Precision') | ||
else: | ||
accel_config = { | ||
'Precision': {'Input': 'float', 'Output': 'float'}, | ||
'Driver': 'python', | ||
'Interface': 'axi_stream', | ||
} | ||
config.config['AcceleratorConfig'] = accel_config | ||
|
||
self.interface = self.config['AcceleratorConfig'].get('Interface', 'axi_stream') # axi_stream, axi_master, axi_lite | ||
self.driver = self.config['AcceleratorConfig'].get('Driver', 'python') # python or c | ||
self.input_type = self.config['AcceleratorConfig']['Precision'].get( | ||
'Input', 'float' | ||
) # float, double or ap_fixed<a,b> | ||
self.output_type = self.config['AcceleratorConfig']['Precision'].get( | ||
'Output', 'float' | ||
) # float, double or ap_fixed<a,b> | ||
self.platform = self.config['AcceleratorConfig'].get( | ||
'Platform', 'xilinx_u250_xdma_201830_2' | ||
) # Get platform folder name | ||
|
||
assert ( | ||
len(model_inputs) == 1 | ||
), "Only models with one input tensor are currently supported by VitisAcceleratorIPFlowBackend" | ||
assert ( | ||
len(model_outputs) == 1 | ||
), "Only models with one output tensor are currently supported by VitisAcceleratorIPFlowBackend" | ||
self.inp = model_inputs[0] | ||
self.out = model_outputs[0] | ||
inp_axi_t = self.input_type | ||
out_axi_t = self.output_type | ||
|
||
if inp_axi_t not in ['float', 'double']: | ||
self.input_type = self._next_factor8_type(config.backend.convert_precision_string(inp_axi_t)) | ||
if out_axi_t not in ['float', 'double']: | ||
self.output_type = self._next_factor8_type(config.backend.convert_precision_string(out_axi_t)) | ||
|
||
if self.input_type == 'float': | ||
self.input_bitwidth = 32 | ||
elif self.input_type == 'double': | ||
self.input_bitwidth = 64 | ||
else: | ||
self.input_bitwidth = config.backend.convert_precision_string(inp_axi_t).width | ||
|
||
if out_axi_t == 'float': | ||
self.output_bitwidth = 32 | ||
elif out_axi_t == 'double': | ||
self.output_bitwidth = 64 | ||
else: | ||
self.output_bitwidth = config.backend.convert_precision_string(out_axi_t).width | ||
|
||
def _next_factor8_type(self, p): | ||
'''Return a new type with the width rounded to the next factor of 8 up to p's width | ||
Args: | ||
p : IntegerPrecisionType or FixedPrecisionType | ||
Returns: | ||
An IntegerPrecisionType or FixedPrecisionType with the width rounder up to the next factor of 8 | ||
of p's width. Other parameters (fractional bits, extra modes) stay the same. | ||
''' | ||
W = p.width | ||
newW = int(np.ceil(W / 8) * 8) | ||
if isinstance(p, FixedPrecisionType): | ||
return FixedPrecisionType(newW, p.integer, p.signed, p.rounding_mode, p.saturation_mode, p.saturation_bits) | ||
elif isinstance(p, IntegerPrecisionType): | ||
return IntegerPrecisionType(newW, p.signed) | ||
|
||
def get_io_bitwidth(self): | ||
return self.input_bitwidth, self.output_bitwidth | ||
|
||
def get_corrected_types(self): | ||
return self.input_type, self.output_type, self.inp, self.out | ||
|
||
def get_interface(self): | ||
return self.interface | ||
|
||
def get_board_info(self, board=None): | ||
if board is None: | ||
board = self.board | ||
if board in self.supported_boards.keys(): | ||
return self.supported_boards[board] | ||
else: | ||
raise Exception('The board is still not supported') | ||
|
||
def get_part(self): | ||
return self.part | ||
|
||
def get_driver(self): | ||
return self.driver | ||
|
||
def get_board(self): | ||
return self.board | ||
|
||
def get_platform(self): | ||
return self.platform | ||
|
||
def get_clock_period(self): | ||
return self.clock_period | ||
|
||
def get_driver_path(self): | ||
if self.board.startswith('alveo'): | ||
return '../templates/vitis_accelerator_ip_flow/' + 'alveo/' + self.driver + '_drivers/' + self.get_driver_file() | ||
else: | ||
return ( | ||
'../templates/vitis_accelerator_ip_flow/' | ||
+ self.board | ||
+ '/' | ||
+ self.driver | ||
+ '_drivers/' | ||
+ self.get_driver_file() | ||
) | ||
|
||
def get_driver_file(self): | ||
driver_ext = '.py' if self.driver == 'python' else '.h' | ||
return self.interface + '_driver' + driver_ext | ||
|
||
def get_krnl_rtl_src_dir(self): | ||
return '../templates/vitis_accelerator_ip_flow/' + 'alveo/' + '/krnl_rtl_src' | ||
|
||
def get_input_type(self): | ||
return self.input_type | ||
|
||
def get_output_type(self): | ||
return self.output_type | ||
|
||
def get_tcl_file_path(self): | ||
board_info = self.get_board_info(self.board) | ||
tcl_scripts = board_info.get('tcl_scripts', None) | ||
if tcl_scripts is None: | ||
raise Exception('No tcl scripts definition available for the board in supported_board.json') | ||
tcl_script = tcl_scripts.get(self.interface, None) | ||
if tcl_script is None: | ||
raise Exception('No tcl script definition available for the desired interface in supported_board.json') | ||
if self.board.startswith('alveo'): | ||
return '../templates/vitis_accelerator_ip_flow/' + 'alveo/' + '/tcl_scripts/' + tcl_script | ||
else: | ||
return '../templates/vitis_accelerator_ip_flow/' + self.board + '/tcl_scripts/' + tcl_script |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly, I think this modification shouldn't be part of this PR |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this modification shouldn't be part of this PR