Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
3922260
add vitisUnified backend and its writer
Tanawin1701d Jul 12, 2025
6ac2b71
add vitis unified template
Tanawin1701d Aug 14, 2025
cfc92d5
add dma wrapper access
Tanawin1701d Aug 15, 2025
f570c3f
extract writer class + add gmem wrapper
Tanawin1701d Aug 15, 2025
1169bf4
extract writer class + add gmem wrapper
Tanawin1701d Aug 15, 2025
a772aeb
fix store value override
Tanawin1701d Aug 15, 2025
235bc2d
draft write_hls initialization
Tanawin1701d Aug 15, 2025
2c5a6e8
fix import bug at VitisUnifiedwriter
Tanawin1701d Aug 15, 2025
fd4f3d6
add project generation and .h file generation
Tanawin1701d Aug 15, 2025
5913c9c
fix generation bug in unified workspace
Tanawin1701d Aug 16, 2025
8304a20
fix new gmem wrapper to get data and send data at wrong index
Tanawin1701d Aug 16, 2025
b979ec0
add auto platform linker script
Tanawin1701d Aug 16, 2025
926f412
add initiat config parameter for io buffer and platform path
Tanawin1701d Aug 16, 2025
b516a96
modifying build function for vitis unified
Tanawin1701d Aug 16, 2025
3f6d224
update build function for vitis unified
Tanawin1701d Aug 17, 2025
19e0af9
add bridge simulation
Tanawin1701d Aug 17, 2025
32d079b
add bridge script and move a bit bridge generator
Tanawin1701d Aug 17, 2025
9237af5
change build script permission and refactoring cosim writing
Tanawin1701d Aug 17, 2025
bd6a384
add cosim testbench + fix namming in gmem
Tanawin1701d Aug 17, 2025
c1b95c9
fix wrapper mismatch io bug and testing the bridge simulation
Tanawin1701d Aug 17, 2025
6e37f3c
add .bit file for full flow
Tanawin1701d Aug 18, 2025
f64b50d
add python generator for the system
Tanawin1701d Aug 18, 2025
3f465ab
clean some code
Tanawin1701d Aug 19, 2025
86d64d5
add base ip for magic architecture and add axi warpper
Tanawin1701d Aug 19, 2025
c69fcf6
convert meta gen into class
Tanawin1701d Aug 19, 2025
b508473
refractor vitisUnified backend to be a multiple subclass and build ax…
Tanawin1701d Aug 19, 2025
548a8f0
divert tot use mg and add mgs group generator
Tanawin1701d Aug 20, 2025
abf830f
add sub-writer override for vitis unified/unified partial
Tanawin1701d Aug 20, 2025
485c1c8
register backend and writer
Tanawin1701d Aug 20, 2025
d78a50d
fix minor missing syntax
Tanawin1701d Aug 20, 2025
d23e591
fix wrap_gen syntax bug + add include ap_axi_sdata.h for wrapgen + ad…
Tanawin1701d Aug 20, 2025
6cce4ea
add magic streamer generator and auto invoker
Tanawin1701d Aug 20, 2025
7d99de6
add icap wraper and magic seq
Tanawin1701d Aug 21, 2025
c1e2419
add project builder tcl file copy
Tanawin1701d Aug 22, 2025
ccd3d2a
integrating the zcu102 synthesis code
Tanawin1701d Aug 23, 2025
b982b21
add connection between block
Tanawin1701d Aug 23, 2025
0b3debc
drafting the automatically magic streamer linker
Tanawin1701d Aug 24, 2025
d4220c4
add new refactor magic streamer controller
Tanawin1701d Aug 25, 2025
e81078a
add start converter for class MgsModel
Tanawin1701d Aug 25, 2025
05cc849
fix mgs model syntax bug
Tanawin1701d Aug 25, 2025
fe9fe8b
fix syntax generation for vitisUnified partialbackend
Tanawin1701d Aug 25, 2025
7b1b12b
send magic streamer manager to writer
Tanawin1701d Aug 25, 2025
b2f2238
specify io signal meta-data to tcl file for each configuration
Tanawin1701d Aug 25, 2025
654724a
add build for stitcher
Tanawin1701d Aug 25, 2025
95148d8
update vivado project stitcher script
Tanawin1701d Aug 25, 2025
3de0444
delete vitis Unified partial after merge the co-reactor
Tanawin1701d Aug 26, 2025
3e1314c
delete vitis Unified partial template
Tanawin1701d Aug 26, 2025
e367146
fix bridge gen top function name change
Tanawin1701d Aug 26, 2025
ac04d40
clean vitis config: test using bridge test and it pass
Tanawin1701d Aug 26, 2025
dfbbc3d
add to check accept only io stream
Tanawin1701d Aug 26, 2025
04d0e6d
add bridge gen to support both float and double input
Tanawin1701d Aug 26, 2025
b77e22f
fix size getting bug in cosim
Tanawin1701d Aug 26, 2025
e14f2c6
fix config to gen two kernel hardware cfg for csim and csim
Tanawin1701d Aug 26, 2025
6a357cb
fix cosimulation bug from segment fault buffer size and invalid resul…
Tanawin1701d Aug 27, 2025
5e87503
add fifo-flag in hls compile kernel
Tanawin1701d Aug 27, 2025
0525079
push fifo
Tanawin1701d Aug 28, 2025
671c1ae
upgrade new wrapper
Tanawin1701d Aug 28, 2025
f5189b9
upgrade the parameter of cosim and bridge sim
Tanawin1701d Aug 28, 2025
2d83c57
fix missing wrap problem
Tanawin1701d Aug 28, 2025
fbf1dee
fix missing wrap problem
Tanawin1701d Aug 29, 2025
1ece84e
update the driver and testing
Tanawin1701d Aug 29, 2025
143ae14
push ready to test code and its example driver
Tanawin1701d Aug 29, 2025
7097f63
delete polute file and unconment the compile
Tanawin1701d Aug 29, 2025
48e49d4
remove debug print on multigraph
Tanawin1701d Aug 29, 2025
d588181
change xpfm default Path
Tanawin1701d Aug 29, 2025
b2ee0e3
revert the multigraph modification because it is not relate to this b…
Tanawin1701d Aug 29, 2025
b17d2b2
get the code out that not related to vitisUnified backend
Tanawin1701d Aug 29, 2025
3f6a37e
update code to precommit style
Tanawin1701d Sep 2, 2025
48d7500
fix vitisConfig missign (after refactor) add comment
Tanawin1701d Sep 2, 2025
0feaf32
fix ciricular import again
Tanawin1701d Sep 2, 2025
c2e5209
add bridge sim for axi stream
Tanawin1701d Feb 10, 2026
3970b21
fix support fifo-op, driver_gen, auto_link for axi stream
Tanawin1701d Feb 12, 2026
ac34e21
update driver template for both axis and axim
Tanawin1701d Feb 13, 2026
a62044f
refactor the generated file naming
Tanawin1701d Feb 13, 2026
611b8d8
pass test both axi_stream and axi_master/ add dedicated example ipynb
Tanawin1701d Feb 13, 2026
e22ac46
clean code/ cut out unused argument/ use pytest
Tanawin1701d Feb 14, 2026
e982ed1
Merge upstream main into VitisUnifiedClean
nghielme Feb 17, 2026
5bdf2c1
Finalize Vitis Unified backend cleanup and naming alignment after syn…
nghielme Feb 17, 2026
0ebb669
pre-commit changes
nghielme Feb 17, 2026
8347f39
pre-commit changes
nghielme Feb 17, 2026
c858411
Enhance Vitis Unified backend with support for new board configuratio…
nghielme Feb 19, 2026
98a67b1
pre-commit changes
nghielme Feb 19, 2026
cec7297
pre-commit changes
nghielme Feb 19, 2026
7f7d32c
Minor fix on .gitignore
nghielme Feb 19, 2026
e540553
Merge pull request #1 from nghielme/vitis-unified-pr
Tanawin1701d Feb 21, 2026
28dc178
Merge branch 'main' into VitisUnifiedClean
nghielme Feb 23, 2026
f70d574
add main driver to wrap the IP's driver and make the IP's driver shared
Tanawin1701d Feb 25, 2026
a8b736f
Merge remote-tracking branch 'origin/VitisUnifiedClean' into VitisUni…
Tanawin1701d Feb 25, 2026
86e7211
restructure the template repository
Tanawin1701d Feb 26, 2026
d69d15e
restructure a supported_boards.json
Tanawin1701d Feb 26, 2026
4dbc6b3
fix return execution's profile
Tanawin1701d Feb 26, 2026
0e9a32c
fix axi master driver variable mismatch and precomit for wrapper fix
Tanawin1701d Feb 27, 2026
b52af9c
add last packet checking to axi_stream
Tanawin1701d Feb 27, 2026
8fcae7a
fix axi_stream bug from missing tkeep
Tanawin1701d Feb 27, 2026
193508b
fix tlast signal tracking bug
Tanawin1701d Feb 27, 2026
bd5951a
update tlast stream and stream driver
Tanawin1701d Feb 28, 2026
36b4947
fix axi stream driver performance bug
Tanawin1701d Feb 28, 2026
a45f5e4
unified the IP driver and NN driver wrapper
Tanawin1701d Mar 1, 2026
4a27208
fix vitis unified driver generation error
Tanawin1701d Mar 2, 2026
57ce9c4
modify axi_stream wrapper to support multiple queries without tlast s…
Tanawin1701d Mar 2, 2026
74302f5
copy driver for zcu102
Tanawin1701d Mar 2, 2026
5978625
aggreagate the axi_stream loop to ensure there is no bubble time from…
Tanawin1701d Mar 2, 2026
0a8c6d3
fix vitis unified compute bug and add performance tracker to the system
Tanawin1701d Mar 5, 2026
ad7c66f
delete tlast stream parameter
Tanawin1701d Mar 5, 2026
f1f1c76
Merge branch 'main' into VitisUnifiedClean
nghielme Mar 10, 2026
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
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ 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_unified/supported_boards.json
3 changes: 3 additions & 0 deletions hls4ml/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@

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

from hls4ml.backends.vitis_unified.vitis_unified_backend import VitisUnifiedBackend # isort: skip


def _register_builtin_backends():
register_backend('Vivado', VivadoBackend)
register_backend('VivadoAccelerator', VivadoAcceleratorBackend)
register_backend('Vitis', VitisBackend)
register_backend('VitisUnified', VitisUnifiedBackend)
register_backend('Quartus', QuartusBackend)
register_backend('Catapult', CatapultBackend)
register_backend('SymbolicExpression', SymbolicExpressionBackend)
Expand Down
114 changes: 114 additions & 0 deletions hls4ml/backends/vitis_unified/passes/fifo_depth_optimization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# we inherit it from vitis
import re
import zipfile

from hls4ml.backends.vitis.passes.fifo_depth_optimization import (
generate_depths_file,
initialize_large_fifos,
set_optimized_fifo_depths,
)
from hls4ml.model.optimizer.optimizer import ConfigurableOptimizerPass, ModelOptimizerPass


def get_vitis_optimized_fifo_depths(model, cus_hls_prj_path=None):
"""Parse the files generated by the co-simulation to retrieve the optimized depths for the FIFOs.
Attention, only the FIFOs between the layers are profiled!

Args:
model (ModelGraph): The model to which FIFO depth optimization is applied.

Returns:
Dict[str, int]: A dictionary that contains the FIFO names as keys and the optimized depths as values.
"""
# channel.zip is generated after the co-simulation and contains the chan_status*.csv files
# in the chan_status*.csv files the max depth achieved during co-simulation can be found at the last (4th) line

if cus_hls_prj_path is None:
cus_hls_prj_path = model.config.get_output_dir() + '/' + model.config.get_project_name() + '/_prj/solution1'

path_to_zip_file = cus_hls_prj_path + '/.autopilot/db/channel_depth_info/'

with zipfile.ZipFile(f'{path_to_zip_file}channel.zip', 'r') as zip_ref:
zip_ref.extractall(path_to_zip_file)

# the channel_info.csv file contains the mapping of each fifo name (i.e layer4_out_U) to the respective
# chan_status*.csv file
names_file_path = cus_hls_prj_path + '/.autopilot/db/channel_info.csv'

csv_fifo_depth_files = {}
with open(names_file_path) as names_file:
for line in names_file:
slitted_line = line.split(',')
if len(slitted_line[0]) == 0:
continue
layer_name = slitted_line[1]
csv_file_name = slitted_line[3][:-1]
csv_fifo_depth_files[layer_name] = csv_file_name

optmized_fifo_depths = {}
for layer_name, file_name in csv_fifo_depth_files.items():
with open(path_to_zip_file + file_name) as chan_status_file:
lines = chan_status_file.readlines()
cleaned_layer_name = re.sub(r'(_i)?_U$', '', layer_name)
optmized_fifo_depths[cleaned_layer_name] = int(
lines[-1]
) # remove "_i_U" (axis) or "_U" (axim) from the layer name
# string and keep the last line of the file that contains the max depth

return optmized_fifo_depths


def execute_cosim_to_profile_fifos(model):
model.write()
model.build(
reset=False,
csim=False,
synth=True,
cosim=False,
vsynth=False,
fifo_opt=True,
bitfile=False,
log_to_stdout=False,
)


class FifoDepthOptimization(ConfigurableOptimizerPass, ModelOptimizerPass):
def __init__(self):
self.profiling_fifo_depth = 100_000

def transform(self, model):
"""Perform FIFO depth optimization between the FIFOs of all layers to reduce resource utilization as the
initial FIFOs set by hls4ml might be larger than required. At the end of the optimization the FIFOs will
have the largest depths achieved during co-simulation without causing any deadlocks between the layers
(producer-consumer), thus no additional delays between the layers. In some cases, this optimization
might lead to bigger FIFOs than initially set by the hls4ml tool in order to prevent deadlocks.

Args:
model (ModelGraph): The model to which FIFO depth optimization is applied.

Raises:
ValueError: If the FIFO depth for profiling provided by the user is not a non-negative integer.
RuntimeError: If the IO type is not set to "io_stream".

Returns:
bool: The execution state of the Optimizer Pass
"""

if not isinstance(self.profiling_fifo_depth, int) or self.profiling_fifo_depth <= 0:
raise ValueError('The FIFO depth for profiling (profiling_fifo_depth variable) must be a non-negative integer.')

# check axi-stream or io-stream
if not (model.config.get_config_value('IOType') == 'io_stream'):
raise RuntimeError('To use this optimization you have to set `IOType` field to `io_stream` in the HLS config.')

hlsPrjPath = model.config.backend.writer.get_vitis_hls_exec_dir(model)

initial_fifo_depths = initialize_large_fifos(model, self.profiling_fifo_depth)
execute_cosim_to_profile_fifos(model)
optimized_fifo_depths = get_vitis_optimized_fifo_depths(model, cus_hls_prj_path=hlsPrjPath + '/hls')
generate_depths_file(model, initial_fifo_depths, optimized_fifo_depths)
set_optimized_fifo_depths(model, optimized_fifo_depths)

print('FIFO optimization completed')

return False
33 changes: 33 additions & 0 deletions hls4ml/backends/vitis_unified/supported_boards.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"zcu102": {
"part": "xczu9eg-ffvb1156-2-e",
"axi_master": {
"platform_file": "base_platforms/xilinx_zcu102_base_202320_1/xilinx_zcu102_base_202320_1.xpfm",
"python_driver": "axi_master_driver.py",
"c_drivers": ""
},
"axi_stream": {
"platform_generator_tcl": "zcu102/tcl_scripts/create_xsa.tcl",
"platform_output": "zcu102/tcl_scripts/output/zcu102_axi_stream_platform.xsa",
"python_driver": "axi_stream_driver.py",
"c_drivers": ""
}
},

"kv260": {
"part": "sk-kv260-g",
"axi_master": {
"platform_generator_tcl": "kv260/tcl_scripts/create_xsa.tcl",
"platform_output": "kv260/tcl_scripts/output/kv260_axi_all_platform.xsa",
"python_driver": "axi_master_driver.py",
"c_drivers": ""
},
"axi_stream": {
"platform_generator_tcl": "kv260/tcl_scripts/create_xsa.tcl",
"platform_output": "kv260/tcl_scripts/output/kv260_axi_all_platform.xsa",
"python_driver": "axi_stream_driver.py",
"c_drivers": ""
}
}

}
162 changes: 162 additions & 0 deletions hls4ml/backends/vitis_unified/vitis_unified_backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import os
import subprocess
import sys
from shutil import copy2

from hls4ml.backends import VitisBackend, VivadoBackend
from hls4ml.model.flow import register_flow


class VitisUnifiedBackend(VitisBackend):
def __init__(self):
super(VivadoBackend, self).__init__(name='VitisUnified')
self._register_layer_attributes()
self._register_flows()

def build(
self,
model,
reset=False,
csim=False,
synth=False,
cosim=False,
vsynth=False,
fifo_opt=False,
bitfile=False,
log_to_stdout=True,
):
# it builds and return vivado reports
if 'linux' in sys.platform:
found = os.system('command -v v++ > /dev/null')
if found != 0:
raise Exception('Vitis installation not found. Make sure "vitis" is on PATH.')

found = os.system('command -v vitis-run > /dev/null')
if found != 0:
raise Exception('Vitis installation not found. Make sure "vitis-run" is on PATH.')

output_dir = model.config.get_output_dir()

hls_config_file = os.path.join(output_dir, 'hls_kernel_config.cfg')
# build command
csynth_cmd = ('v++ -c --mode hls --config {configPath} --work_dir vitis_unified_project').format(
configPath=hls_config_file
)
# util template (used in csim/cosim/package)
util_command = 'vitis-run --mode hls --{op} --config {configPath} --work_dir vitis_unified_project'

# command for each configuration
vitis_hls_dir = model.config.backend.writer.get_vitis_hls_dir(model)
package_cmd = util_command.format(op='package', configPath=hls_config_file)
cosim_cmd = util_command.format(op='cosim', configPath=hls_config_file)
csim_cmd = util_command.format(op='csim', configPath=hls_config_file)

kerlink_cmd = './link_system.sh'
kerlink_cwd = model.config.backend.writer.get_vitis_linker_dir(model)

commands = []
if synth:
self.prepare_sim_config_file(model, True)
commands.append(('csynth', csynth_cmd, vitis_hls_dir))
commands.append(('package', package_cmd, vitis_hls_dir))

if csim:
self.prepare_sim_config_file(model, True)
commands.append(('csim', csim_cmd, vitis_hls_dir))

if cosim or fifo_opt:
self.prepare_sim_config_file(model, False)
commands.append(('cosim', cosim_cmd, vitis_hls_dir))

if bitfile:
commands.append(('kerlink', kerlink_cmd, kerlink_cwd))

for task_name, command, cwd in commands:
stdout_log = os.path.join(output_dir, f'{task_name}_stdout.log')
stderr_log = os.path.join(output_dir, f'{task_name}_stderr.log')
stdout_target = None if log_to_stdout else open(stdout_log, 'w')
stderr_target = None if log_to_stdout else open(stderr_log, 'w')

try:
process = subprocess.Popen(
command, shell=True, cwd=cwd, stdout=stdout_target, stderr=stderr_target, text=True
)
process.communicate()

if process.returncode != 0:
raise Exception(f'Build failed for {model.config.get_project_name()} during task "{task_name}".')
finally:
if not log_to_stdout:
stdout_target.close()
stderr_target.close()

def prepare_sim_config_file(self, model, is_csim):
suffix = 'csim' if is_csim else 'cosim'
src = f'{model.config.get_output_dir()}/hls_kernel_config_{suffix}.cfg'
des = f'{model.config.get_output_dir()}/hls_kernel_config.cfg'
copy2(src, des)
return des

def create_initial_config(
self,
board='zcu102',
part=None,
clock_period=5,
clock_uncertainty='12.5%',
io_type='io_stream',
driver='python',
input_type='float',
output_type='float',
in_stream_buf_size=128,
out_stream_buf_size=128,
axi_mode='axi_master',
**_,
):
supported_boards_path = os.path.join(os.path.dirname(__file__), 'supported_boards.json')
if os.path.exists(supported_boards_path):
import json

with open(supported_boards_path) as f:
supported_boards = json.load(f)
if board in supported_boards:
part = part or supported_boards[board]['part']
if part is None:
part = 'xczu9eg-ffvb1156-2-e'

config = super().create_initial_config(part, clock_period, clock_uncertainty, io_type)

config['VitisUnifiedConfig'] = {}
config['VitisUnifiedConfig']['Board'] = board
config['VitisUnifiedConfig']['axi_mode'] = axi_mode
config['VitisUnifiedConfig']['in_stream_buf_size'] = in_stream_buf_size
config['VitisUnifiedConfig']['out_stream_buf_size'] = out_stream_buf_size

config['VitisUnifiedConfig']['Driver'] = driver
config['VitisUnifiedConfig']['InputDtype'] = input_type # float, double or ap_fixed<a,b>
config['VitisUnifiedConfig']['OutputDtype'] = output_type # float, double or ap_fixed<a,b>

if io_type != 'io_stream':
raise Exception('io_type must be io_stream')
if input_type not in ['double', 'float']:
raise Exception('input_type must be float or double')
if output_type not in ['double', 'float']:
raise Exception('output_type must be float or double')

return config

def get_default_flow(self):
return self._default_flow

def get_writer_flow(self):
return self._writer_flow

def _register_flows(self):
vitis_ip = 'vitis:ip'
writer_passes = ['make_stamp', 'vitisunified:write_hls']
self._writer_flow = register_flow('write', writer_passes, requires=['vitis:ip'], backend=self.name)
self._default_flow = vitis_ip

# register fifo depth optimization
fifo_depth_opt_passes = ['vitisunified:fifo_depth_optimization'] + writer_passes

register_flow('fifo_depth_optimization', fifo_depth_opt_passes, requires=['vitis:ip'], backend=self.name)
Loading