Skip to content
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
wants to merge 90 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 88 commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
312832f
Initial commit
steltze Apr 19, 2024
d2b5a15
Set change the backend
steltze Apr 19, 2024
02659dd
Change the accelerator config script
steltze Apr 19, 2024
56296b6
Set the vitis accelerator template
steltze Apr 19, 2024
7dd0173
Set vitis accelerator writer
steltze Apr 19, 2024
6f181b8
Fix writes init
steltze Apr 19, 2024
bd2e52e
Include separable convolution resource implementation
steltze May 10, 2024
b795240
Separate depthwise resource strategy to 3 cases
steltze May 29, 2024
eeb04d4
Complete vitis accelerator wrapper for io_stream case
steltze May 29, 2024
7e47c85
Fix call to wrong backend writer
steltze May 31, 2024
5a2a38f
Fix vitis accelerator writer
steltze May 31, 2024
99f9429
Fix include in axi wrapper header file writer
steltze Jun 11, 2024
b9609dc
Change python-cpp bridge writer
steltze Jun 11, 2024
4f69c16
Fix tlast handling in axis wrapper writer
steltze Jun 11, 2024
014a7b2
Extend convert_data to handle stream type, use that for the bridge
steltze Jun 11, 2024
723073e
Add zcu102 to the supported boards json
steltze Jun 14, 2024
290896b
Fix some c synthesis warnings
steltze Jun 20, 2024
c9dfcf2
Group more tests per YAML to reduce the number of envs created
vloncar Apr 11, 2024
d3b8e20
Support negative_slope in quantized_relu
vloncar Mar 25, 2024
b32984f
[pre-commit.ci] auto fixes from pre-commit hooks
pre-commit-ci[bot] Mar 28, 2024
98273a0
Fix activation check in profiling
vloncar Apr 16, 2024
1640c4b
Stage initial set of changes for the Catapult backend (#956)
dgburnette Apr 15, 2024
2a71a83
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] Apr 15, 2024
6ac964c
fix unwanted tested file change in #956
calad0i Apr 16, 2024
ec95e01
Fix SR backend synth missing variables
bo3z Apr 10, 2024
5de1bf5
Test for SR backend config
vloncar Apr 16, 2024
a6fec36
Upsampling support for PyTorch models
vloncar Mar 6, 2024
1b72b19
Split Catapult types into separate file
vloncar Apr 15, 2024
28521d0
Split Quartus types into separate file
vloncar Apr 15, 2024
a44707d
Split Vivado types into separate file
vloncar Apr 15, 2024
cefab60
Increase precision of Softsign test
vloncar Apr 18, 2024
440901b
Use quantized input in binary CNN test
vloncar Apr 18, 2024
c351a02
Add UnspecifiedPrecisionType
vloncar Aug 20, 2023
4d9d35a
Rudimentary optimizer to infer 'auto' precision
vloncar Aug 20, 2023
32ae9b6
Auto precision test
vloncar Aug 20, 2023
932b01e
Sepconv fixes
vloncar Aug 20, 2023
6a65fed
update precision propagation for signed, select im2col for quartus pa…
jmitrevs Jan 26, 2024
41b7e98
Make inferring no_bias a configurable option of the optimizer
vloncar Feb 6, 2024
24253e1
updates to infering precision from qonnx branch
jmitrevs Apr 16, 2024
6ee8189
remove count, become more selective on when True is returned
jmitrevs Apr 17, 2024
b5add0c
fix pooling precision
calad0i Apr 17, 2024
665c904
remove typing
calad0i Apr 17, 2024
b366d24
Fix avg pooling op check
vloncar Apr 18, 2024
f0ca865
Optimizer to remove expensive Transpose that serves as Flatten
vloncar Feb 21, 2024
1e416b5
Generalize removal of Transpose after flatten so it works on 1D as well
vloncar Feb 27, 2024
2a5d8de
Remove transpose of input if n_chan=1
vloncar Feb 27, 2024
3969523
SepConv1d/2d for io_parallel w/ Latency strategy
vloncar May 13, 2024
52252ca
Cosmetic parameter config fixes
vloncar May 13, 2024
be56b93
Tests for SepConv io_parallel
vloncar May 13, 2024
b0085a1
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] Apr 29, 2024
44bc8f3
Update pytest docker image to 0.5.4
jmitrevs Apr 26, 2024
a7826e0
bump to 0.5.5
jmitrevs May 1, 2024
41ab6af
fix pre-commit warning
jmitrevs Apr 25, 2024
c0f8d9f
change writing of obsolete ".h5" to ".keras" files
jmitrevs Apr 26, 2024
bcfd685
Fix extension test for Keras v3
vloncar May 1, 2024
8c09595
Support ParallelizationFactor in SepConv1D/2D
vloncar May 15, 2024
11819ac
updated pytest docker image
jmitrevs May 30, 2024
39d9232
Don't test io_parallel for Catapult test and reduce the size of test …
vloncar Jun 3, 2024
68a83d6
Add explicit DepthwiseConv tests and simpligy SepConv tests
vloncar Jun 9, 2024
8a9d556
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] Jun 10, 2024
ad86387
Initial commit
steltze Apr 19, 2024
4ea329b
Stage initial set of changes for the Catapult backend (#956)
dgburnette Apr 15, 2024
992b9b7
Rudimentary optimizer to infer 'auto' precision
vloncar Aug 20, 2023
8174465
Sepconv fixes
vloncar Aug 20, 2023
84ff2c6
Optimizer to remove expensive Transpose that serves as Flatten
vloncar Feb 21, 2024
518796d
Remove transpose of input if n_chan=1
vloncar Feb 27, 2024
238e35c
Optimizer to remove expensive Transpose that serves as Flatten
vloncar Feb 21, 2024
c10dd82
Remove transpose of input if n_chan=1
vloncar Feb 27, 2024
d6fe369
fix up automatic precision inferrence
jmitrevs Jun 13, 2024
7290a29
starting towards being able to split seperable
jmitrevs Jun 11, 2024
13fcf0a
complete implementation of seperable -> dw + pw, untested
jmitrevs Jun 12, 2024
92e7222
make conv_same_pad also trigger on depthwise, varius bug fixes
jmitrevs Jun 12, 2024
f12a7ea
add parsing of depth multiplier for 1D depthwise conv
jmitrevs Jun 13, 2024
4d24e4e
Merge remote-tracking branch 'upstream/main' into vitis_accelerator_i…
Aug 26, 2024
e2d270e
Finish resolving conficts with main
Aug 26, 2024
fa6bd66
Supress removing tar for now
steltze Nov 18, 2024
b42210d
Fix csynth and cosim
steltze Nov 18, 2024
1303bba
Fix tcl script to find cosim report
steltze Nov 18, 2024
8d3a1f2
Correct PYNQ Z2 vivado tcl script, bitstream generated
steltze Nov 18, 2024
a8e0497
Clean pynq tcl script
steltze Nov 19, 2024
48686d3
Fix compatibility of nnet helper functions with vitis axis
steltze Nov 19, 2024
bae450b
Setup vivado tcl script for zcu102
steltze Nov 19, 2024
dde9124
Rename backend to VitisAcceleratorIPFLow to prevent conflicts with ke…
steltze Nov 19, 2024
663181f
Fix compatiblity between axi stream and io parallel
steltze Nov 20, 2024
e32f4d0
Update pynq driver for zcu102
steltze Nov 20, 2024
c52ec75
Run pre-commit
steltze Nov 20, 2024
9d9e645
Remove unused file
steltze Nov 20, 2024
80697c0
Remove unused xclbin generator
steltze Nov 20, 2024
f467829
Clean backends init
steltze Nov 27, 2024
4c74550
Fix backend import sequence
steltze Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions hls4ml/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@
from hls4ml.backends.fpga.fpga_backend import FPGABackend # noqa: F401
from hls4ml.backends.quartus.quartus_backend import QuartusBackend
from hls4ml.backends.symbolic.symbolic_backend import SymbolicExpressionBackend
from hls4ml.backends.vitis_accelerator_ip_flow.vitis_accelerator_ip_flow_config import ( # noqa: F401
VitisAcceleratorIPFlowConfig,
)
from hls4ml.backends.vivado.vivado_backend import VivadoBackend
from hls4ml.backends.vivado_accelerator.vivado_accelerator_backend import VivadoAcceleratorBackend
from hls4ml.backends.vivado_accelerator.vivado_accelerator_config import VivadoAcceleratorConfig # noqa: F401

from hls4ml.backends.vitis_accelerator_ip_flow.vitis_accelerator_ip_flow_backend import ( # isort: skip
VitisAcceleratorIPFlowBackend,
)

from hls4ml.backends.catapult.catapult_backend import CatapultBackend # isort: skip

from hls4ml.backends.vitis.vitis_backend import VitisBackend # isort: skip

register_backend('Vivado', VivadoBackend)
register_backend('VivadoAccelerator', VivadoAcceleratorBackend)
register_backend('Vitis', VitisBackend)
register_backend('VitisAcceleratorIPFlow', VitisAcceleratorIPFlowBackend)
register_backend('Quartus', QuartusBackend)
register_backend('Catapult', CatapultBackend)
register_backend('SymbolicExpression', SymbolicExpressionBackend)
Empty file.
Empty file.
42 changes: 42 additions & 0 deletions hls4ml/backends/vitis_accelerator_ip_flow/supported_boards.json
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": {}
}
}
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)
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
2 changes: 1 addition & 1 deletion hls4ml/templates/vitis/nnet_utils/nnet_sepconv1d_stream.h
Copy link
Contributor

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

Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void separable_conv_1d_cl(hls::stream<data_T> &data, hls::stream<res_T> &res,
#pragma HLS DATAFLOW

hls::stream<dw_res_T> depthwise_res;
unsigned res_depth = CONFIG_T::depthwise_config::out_width;
const unsigned res_depth = CONFIG_T::depthwise_config::out_width;
#pragma HLS STREAM variable=depthwise_res depth=res_depth

depthwise_conv_1d_buffer_cl<data_T, dw_res_T, typename CONFIG_T::depthwise_config>(data, depthwise_res,
Expand Down
2 changes: 1 addition & 1 deletion hls4ml/templates/vitis/nnet_utils/nnet_sepconv2d_stream.h
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, I think this modification shouldn't be part of this PR

Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ void separable_conv_2d_cl(hls::stream<data_T> &data, hls::stream<res_T> &res,
#pragma HLS DATAFLOW

hls::stream<dw_res_T> depthwise_res;
unsigned res_depth = CONFIG_T::depthwise_config::out_height * CONFIG_T::depthwise_config::out_width;
const unsigned res_depth = CONFIG_T::depthwise_config::out_height * CONFIG_T::depthwise_config::out_width;
#pragma HLS STREAM variable=depthwise_res depth=res_depth

depthwise_conv_2d_buffer_cl<data_T, dw_res_T, typename CONFIG_T::depthwise_config>(data, depthwise_res,
Expand Down
Loading