Skip to content

Vitis accelerator #991

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

Open
wants to merge 66 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
de5d4d3
Initial version of VitisAccelerator backend:
axiotisk Jun 1, 2023
54fa480
fixing discrepancies post-merge
alex-yang-upenn May 16, 2024
b4dd93d
reverting unnecessary changes
alex-yang-upenn May 16, 2024
b477cce
final adjustments
alex-yang-upenn May 16, 2024
be71a58
minor fixes and testing notebook
alex-yang-upenn May 17, 2024
7163096
minor fixes
alex-yang-upenn May 17, 2024
1e6fa24
Updated host code and added more board support
alex-yang-upenn May 17, 2024
6e0bb8a
cleaned up c++ code generation and added build functionality
alex-yang-upenn May 19, 2024
ea95210
Added ability to use numpy array as I/O + CNN fixes
alex-yang-upenn May 24, 2024
17ef012
Optimizations for reading dat + copytree bugfix
alex-yang-upenn May 25, 2024
6e0cb47
updated testing notebook
alex-yang-upenn May 25, 2024
0e0185a
Cleaned-up host code + improved .dat generation
alex-yang-upenn May 28, 2024
6eccfb1
fixed testing notebook
alex-yang-upenn May 28, 2024
c1de99b
build() signature alignment + xcl update + write_host() overwrite
alex-yang-upenn Jun 3, 2024
fa01fa1
Fix VCK5000 part definition
Jun 13, 2024
2165127
Documentation draft
axiotisk Jun 14, 2024
f1300f4
Default directives + HLS Clock control
alex-yang-upenn Jun 19, 2024
713781a
implementing hw quant option
alex-yang-upenn Jun 28, 2024
680aa29
Update makefile
Jun 13, 2024
21b4d92
Fix vck5000 detection in makefile
Jun 13, 2024
eb9ddf5
Remove messageDb from config file now that it is handled in makefile
Jun 13, 2024
4b5925b
build dir name + versal packaging + ultraclean
alex-yang-upenn Jun 21, 2024
9ae3705
minor fixes
alex-yang-upenn Jun 28, 2024
a63fe52
Fix Makefile template and Makefile generation
Jul 1, 2024
c73114c
Python black formating
Jul 1, 2024
49cf2e8
Apply pre-commit suggested changes (formating)
Jul 1, 2024
76520d8
Update manifest and remove developpement requirement.txt
Jul 1, 2024
55400fa
Update documentation.
Jul 1, 2024
17a2dde
Documentation update
alex-yang-upenn Jul 1, 2024
a04e1f3
fixing build() behavior + documentation
alex-yang-upenn Jul 1, 2024
631d13d
Whitespace cleanup
Jul 2, 2024
2f23026
Fix missing parameter in create_initial_config() (due to rebase)
Jul 2, 2024
75584bf
Remove duplication in documentation
axiotisk Jul 4, 2024
e209bfb
Fix pre-commit
axiotisk Jul 5, 2024
7e08a31
fixing spacing in generated code
alex-yang-upenn Jul 6, 2024
673fbab
Fix typo
Jul 9, 2024
0ee67bc
Update bulild():
Jul 9, 2024
b4df872
Add a target parameter to hardware_predict()
Jul 9, 2024
81aaa27
Update documentation.
Jul 10, 2024
0c1c6aa
Setup emu in Makefile and edit tb_input_features in host
axiotisk Jul 19, 2024
3071549
Backend and Makefile fixes for emulation
axiotisk Jul 23, 2024
9cccde2
Update host code for clarity & better data handling
alex-yang-upenn Aug 2, 2024
901dc64
Allowing flexibility with platforms
alex-yang-upenn Aug 7, 2024
109b331
VitisAccelerator Host code refactor:
Jan 12, 2025
766c07d
fix(vitis_backend.py): command variable not initialized on hardware_p…
Djokzer Jun 4, 2025
3630148
feat[shared_library]: started a predict function in host code
Djokzer Jun 18, 2025
c31bbbe
feat[shared_library]: Can load test data from python to the host code
Djokzer Jun 19, 2025
1716eff
feat[shared_library]: shared library works in python but not with jup…
Djokzer Jun 19, 2025
6230d70
feat[hardware_predict]: add shared lib way in the hardware predict fu…
Djokzer Jun 19, 2025
667cf53
fix[hardware_predict]: Check if shared lib exists
Djokzer Jun 23, 2025
8407bb0
fix[hardware_predict]: Fixed hardcoded output directory
Djokzer Jun 23, 2025
f840df8
feat[hardware_predict] : add debug print
Djokzer Jun 23, 2025
3a0c43d
fix[debug]: fixed a print error
Djokzer Jun 23, 2025
2492ce9
fix[shared_library] : Print on a file, because print don't work with …
Djokzer Jun 25, 2025
0902ba6
fix[hardware_predict]: Force x array to float64
Djokzer Jun 25, 2025
d9c0370
Fix[hardware_predict]: Fixed working directory changing
Djokzer Jun 25, 2025
9448b12
feat[shared_lib]: small opti for input buffer to vector
Djokzer Jun 25, 2025
6032ee7
fix[hardware_predict]: file based makefile, fix make run
Djokzer Jun 25, 2025
5aaaf47
feat[platforms]: more user friendly platform selection
Djokzer Jul 15, 2025
6df5b93
fix[platforms] : fixed typo on print
Djokzer Jul 15, 2025
33d85dc
fix[hardware_predict]: Fixed rebuild when hardware predict, changed d…
Djokzer Jul 22, 2025
1340296
fix[hardware_predict]: fixed x input for file based
Djokzer Jul 22, 2025
12ad2d2
Improves commande line help message
Jul 29, 2025
fe60c69
Enable dynamic batch size for io_stream wrapper
Jul 29, 2025
172c9a5
Enable dynmamic batch size for io_parallel
Jul 29, 2025
8d218d3
fix[io_parralel]: fixed dynamic batchsize for io_parallel
Djokzer Aug 4, 2025
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
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ recursive-include hls4ml *.py
recursive-include hls4ml/contrib *
global-exclude .git .gitmodules .gitlab-ci.yml *.pyc
include hls4ml/backends/vivado_accelerator/supported_boards.json
include hls4ml/backends/vitis_accelerator/supported_boards.json
include hls4ml/backends/vitis_accelerator/vivado_directives.json
109 changes: 109 additions & 0 deletions docs/backend/accelerator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,112 @@ The ``predict`` method will send the input data to the PL and return the output

nn = NeuralNetworkOverlay('hls4ml_nn.bit', X_test.shape, y_test.shape)
y_hw, latency, throughput = nn.predict(X_test, profile=True)

================
VitisAccelerator
================

The ``VitsAccelerator`` backend leverages the `Vitis System Design Flow <https://www.xilinx.com/products/design-tools/vitis.html#design-flows>`_ to automate and simplify the creation of an hls4ml project targeting `AMD Alveo PCIe accelerators <https://www.amd.com/en/products/accelerators/alveo.html>`_.
The Vitis accelerator backend has been tested with the following boards:

* `Alveo u50 <https://www.xilinx.com/products/boards-and-kits/alveo/u50.html>`_
* `Alveo u55c <https://www.xilinx.com/products/boards-and-kits/alveo/u55c.html>`_
* `Alveo u250 <https://www.xilinx.com/products/boards-and-kits/alveo/u250.html>`_
* `Versal vck5000 <https://www.xilinx.com/products/boards-and-kits/vck5000.html>`_

Kernel wrapper
==============

To integrate with the Vitis System Design Flow and run on an accelerator, the generated ``hls4ml`` model must be encapsulated and built as a Vitis kernel (``.xo`` file) and linked into a binary file (``.xclbin``) during the implementation step. On the host side, standard C++ code using either `OpenCL <https://xilinx.github.io/XRT/master/html/opencl_extension.html>`_ or `XRT API <https://xilinx.github.io/XRT/master/html/xrt_native_apis.html>`_ can be used to download the ``.xclbin`` file to the accelerator card and use any kernel it contains.

The ``VitisAccelerator`` backend automatically generates a kernel wrapper, an host code example, and a Makefile to build the project.

**Note:** The current implementation of the kernel wrapper code is oriented toward throughput benchmarking and not general inference uses (See :ref:`here<hardware_predict-method>`). It can nonetheless be further customized to fit specific applications.

Options
=======

As PCIe accelerators are not suitable for ultra-low latency applications, it is assumed that they are used for high-throughput applications. To accommodate this, the backend supports the following options to optimize the kernel for throughput:

* ``num_kernel``: Number of kernel instance to implement in the hardware architecture.
* ``num_thread``: Number of host threads used to exercise the kernels in the host application.
* ``batchsize``: Number of samples to be processed in a single kernel execution.

Additionaly, the backend proposes the following options to customize the implementation:

* ``board``: The target board, must match one entry in ``supported_boards.json``.
* ``clock_period``: The target clock period in ns.
* ``hw_quant``: Is arbitrary precision quantization performed in hardware or not. If True, the quantization is performed in hardware and float are used at the kernel interface, otherwise it is performed in software and arbitrary precision types are used at the interface. (Defaults to ``False``).
* ``vivado_directives``: A list of strings to be added under the ``[Vivado]`` section of the generated ``accelerator_card.cfg`` link configuration file. Can be used to add custom directives to the Vivado project.

Build workflow
==============

At the call of the ``build`` method, the following option affect the build process:

* ``reset``: If True, clears files generated during previous build processes (Equivalent to ``make clean`` in build folder).
* ``target``: Can be one of ``hw``, ``hw_emu``, ``sw_emu``, to define which build target to use (Default is ``hw``).
* ``debug``: If True, compiles the c++ host code and the HLS in debug mode.

Once the project is generated, it possible to run manually the build steps by using one of the following ``make`` targets in the generated project directory:

* ``host``: Compiles the host application.
* ``hls``: Produces only the kernel's object file.
* ``xclbin``: Produces only the kernel's .xclbin file.
* ``clean``: Removes all generated files.
* ``run``: Run the host application using the .xclbin file and the input data present in ``tb_data/tb_input_features.dat``.

It is also possible to run the full build process by calling ``make`` without any target. Modifications to the ``accelerator_card.cfg`` file can be done manually before running the build process (e.g., to change the clock period, or add addition ``.xo`` kernel to the build).

Host code
=========

Once built, the host program can be run to load the board and perform inferences:

.. code-block:: Bash

./host

By defaut, all Computing Unit (CU) on all compatible devices will be used, with 3 worker thread per CU.

The generated host code application support the following options to tweak the execution:

* ``-d``: device BDF to use (can be specified multiple times)
* ``-x``: XCLBIN path
* ``-i``: input feature file
* ``-o``: output feature file
* ``-c``: maximum computing units count to use
* ``-n``: number of worker threads to use
* ``-r``: number of repeatition of the input feature file (For artificially increasing the data size for benchmarking purpose)
* ``-v``: enable verbose output
* ``-h``: print help

The following example shows how to limit on only one device, one CU, and on worker thread:

.. code-block:: Bash

./host -d 0000:c1:00.1 -c 1 -n 1

Example
=======

The following example is a modified version of `hsl4ml example 7 <https://github.com/fastmachinelearning/hls4ml-tutorial/blob/master/part7_deployment.ipynb>`_.

.. code-block:: Python

import hls4ml
hls_model = hls4ml.converters.convert_from_keras_model(
model,
hls_config=config,
output_dir='model_3/hls4ml_prj_vitis_accel',
backend='VitisAccelerator',
board='alveo-u55c',
num_kernel=4,
num_thread=8,
batchsize=8192,
hw_quant=False,
vivado_directives=["prop=run.impl_1.STEPS.PLACE_DESIGN.ARGS.DIRECTIVE=Explore"]
)
hls_model.compile()
hls_model.build()
y = hls_model.predict_hardware(y) # Limited to batchsize * num_kernel * num_thread for now
21 changes: 21 additions & 0 deletions docs/ir/modelgraph.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,24 @@ The trace method is an advanced version of the ``predict`` method. It's used to

#We also support a similar function for keras
keras_trace = hls4ml.model.profiling.get_ymodel_keras(keras_model, X)

----

.. _hardware_predict-method:

``hardware_predict`` method
===========================

A specialized version of the ``predict`` method, for the VitisAccelerator backend after a successful build. Runs the project on the FPGA and obtains prediction for the supplied numpy array.

**Note:** The host code being run under the hood is an example written for generic benchmarking purposes, helpful for validating projects and gauging maximum throughput. It should be further adapted for more specific applications. Currently, the maximum number of input samples that can be processed is ``batchsize * num_cu * num_buffer``. If the input array exceeds that size, the additional samples will be ignored.

An optional ``target`` argument can be used to specify the target emulation mode (``hw``, ``sw_emu``, ``hw_emu``) to run the project on. The default is ``hw``.

.. code-block:: python

# Suppose that you already have input array X
# Note that you have to do both hls_model.compile() and hls_model.build(), ensuring the
# .xclbin file is successfully created, before using hardware_predict

y = hls_model.hardware_predict(X)
4 changes: 4 additions & 0 deletions hls4ml/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
from hls4ml.backends.oneapi.oneapi_backend import OneAPIBackend
from hls4ml.backends.quartus.quartus_backend import QuartusBackend
from hls4ml.backends.symbolic.symbolic_backend import SymbolicExpressionBackend
from hls4ml.backends.vitis_accelerator.vitis_accelerator_config import VitisAcceleratorConfig # noqa: F401
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.catapult.catapult_backend import CatapultBackend # isort: skip

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


register_backend('Vivado', VivadoBackend)
register_backend('VivadoAccelerator', VivadoAcceleratorBackend)
register_backend('Vitis', VitisBackend)
register_backend('VitisAccelerator', VitisAcceleratorBackend)
register_backend('Quartus', QuartusBackend)
register_backend('Catapult', CatapultBackend)
register_backend('SymbolicExpression', SymbolicExpressionBackend)
Expand Down
Empty file.
Empty file.
34 changes: 34 additions & 0 deletions hls4ml/backends/vitis_accelerator/passes/feature_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from hls4ml.model.optimizer import OptimizerPass


class ValidateConvImplementation(OptimizerPass):
def match(self, node):
return 'Conv' in node.class_name

def transform(self, model, node):
if node.get_attr('implementation', 'linebuffer') == 'encoded':
print(
f'WARNING: "Encoded" implementation in "{node.name}" ({node.class_name}) is not supported in Vitis backend. '
'Switching to "LineBuffer" implementation.'
)
node.set_attr('implementation', 'linebuffer')


class ValidateStrategy(OptimizerPass):
_resource_layer_cls = ['Conv1D', 'Conv2D', 'Dense']

def match(self, node):
is_resource_layer = len([layer_cls for layer_cls in self._resource_layer_cls if layer_cls in node.class_name]) > 0
is_resource_strategy = node.model.config.is_resource_strategy(node)

return is_resource_layer and is_resource_strategy

def transform(self, model, node):
n_in, _ = model.config.backend.get_layer_mult_size(node)
rf = node.get_attr('reuse_factor')
if rf > n_in and rf % n_in > 0:
print(
f'WARNING: "Resource" strategy in "{node.name}" ({node.class_name}) may have suboptimal QoR in Vitis '
'backend due to use of "urem" cores.\n'
'Consider using a different ReuseFactor or switching to "Latency" strategy.'
)
26 changes: 26 additions & 0 deletions hls4ml/backends/vitis_accelerator/supported_boards.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"alveo-u55c": {
"board_type": "alveo",
"part": "xcu55c-fsvh2892-2L-e",
"platform": ["xilinx_u55c_gen3x16_xdma_3_202210_1"],
"memory": {"type": "hbm", "channels": 32, "capacity": 16}
},
"alveo-u50": {
"board_type": "alveo",
"part": "xcu50-fsvh2104-2-e",
"platform": ["xilinx_u50_gen3x16_xdma_5_202210_1"],
"memory": {"type": "hbm", "channels": 32, "capacity": 8}
},
"alveo-u250": {
"board_type": "alveo",
"part": "xcu250-figd2104-2L-e",
"platform": ["xilinx_u250_xdma_201830_2"],
"memory": {"type": "ddr", "channels": 4, "capacity": 64}
},
"vck5000": {
"board_type": "versal",
"part": "xcvc1902-vsvd1760-2MP-e-S",
"platform": ["xilinx_vck5000_gen4x8_qdma_2_202220_1"],
"memory":{"type": "ddr", "channels": 3, "capacity": 12}
}
}
Loading