Skip to content

Commit d0b1cfc

Browse files
committed
Follow up with Quartus and Catapult
1 parent 21a7e7b commit d0b1cfc

File tree

4 files changed

+66
-67
lines changed

4 files changed

+66
-67
lines changed

hls4ml/templates/quartus/build_lib.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/bin/bash
2+
set -e
23

34
CC=g++
45
if [[ "$OSTYPE" == "linux-gnu" ]]; then

hls4ml/templates/vivado/build_lib.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ LDFLAGS=
1111
INCFLAGS="-Ifirmware/ap_types/"
1212
PROJECT=myproject
1313
LIB_STAMP=mystamp
14+
WEIGHTS_DIR="\"weights\""
1415

15-
${CC} ${CFLAGS} ${INCFLAGS} -c firmware/${PROJECT}.cpp -o ${PROJECT}.o
16-
${CC} ${CFLAGS} ${INCFLAGS} -c ${PROJECT}_bridge.cpp -o ${PROJECT}_bridge.o
16+
${CC} ${CFLAGS} ${INCFLAGS} -D WEIGHTS_DIR=${WEIGHTS_DIR} -c firmware/${PROJECT}.cpp -o ${PROJECT}.o
17+
${CC} ${CFLAGS} ${INCFLAGS} -D WEIGHTS_DIR=${WEIGHTS_DIR} -c ${PROJECT}_bridge.cpp -o ${PROJECT}_bridge.o
1718
${CC} ${CFLAGS} ${INCFLAGS} -shared ${PROJECT}.o ${PROJECT}_bridge.o -o firmware/${PROJECT}-${LIB_STAMP}.so
1819
rm -f *.o

hls4ml/writer/catapult_writer.py

Lines changed: 41 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import glob
22
import os
3+
import stat
34
import tarfile
45
from collections import OrderedDict
6+
from pathlib import Path
57
from shutil import copyfile, copytree, rmtree
68

79
import numpy as np
@@ -749,55 +751,50 @@ def write_build_script(self, model):
749751
model (ModelGraph): the hls4ml model.
750752
"""
751753

752-
filedir = os.path.dirname(os.path.abspath(__file__))
754+
filedir = Path(__file__).parent
753755

754756
# build_prj.tcl
755-
srcpath = os.path.join(filedir, '../templates/catapult/build_prj.tcl')
756-
dstpath = f'{model.config.get_output_dir()}/build_prj.tcl'
757-
# copyfile(srcpath, dstpath)
758-
f = open(srcpath)
759-
fout = open(dstpath, 'w')
760-
for line in f.readlines():
761-
indent = line[: len(line) - len(line.lstrip())]
762-
line = line.replace('myproject', model.config.get_project_name())
763-
line = line.replace('CATAPULT_DIR', model.config.get_project_dir())
764-
if '#hls-fpga-machine-learning insert techlibs' in line:
765-
if model.config.get_config_value('Technology') is None:
766-
if model.config.get_config_value('Part') is not None:
767-
line = indent + 'setup_xilinx_part {{{}}}\n'.format(model.config.get_config_value('Part'))
768-
elif model.config.get_config_value('ASICLibs') is not None:
769-
line = indent + 'setup_asic_libs {{{}}}\n'.format(model.config.get_config_value('ASICLibs'))
770-
else:
771-
if model.config.get_config_value('Technology') == 'asic':
772-
line = indent + 'setup_asic_libs {{{}}}\n'.format(model.config.get_config_value('ASICLibs'))
757+
srcpath = (filedir / '../templates/catapult/build_prj.tcl').resolve()
758+
dstpath = Path(f'{model.config.get_output_dir()}/build_prj.tcl').resolve()
759+
with open(srcpath) as src, open(dstpath, 'w') as dst:
760+
for line in src.readlines():
761+
indent = line[: len(line) - len(line.lstrip())]
762+
line = line.replace('myproject', model.config.get_project_name())
763+
line = line.replace('CATAPULT_DIR', model.config.get_project_dir())
764+
if '#hls-fpga-machine-learning insert techlibs' in line:
765+
if model.config.get_config_value('Technology') is None:
766+
if model.config.get_config_value('Part') is not None:
767+
line = indent + 'setup_xilinx_part {{{}}}\n'.format(model.config.get_config_value('Part'))
768+
elif model.config.get_config_value('ASICLibs') is not None:
769+
line = indent + 'setup_asic_libs {{{}}}\n'.format(model.config.get_config_value('ASICLibs'))
773770
else:
774-
line = indent + 'setup_xilinx_part {{{}}}\n'.format(model.config.get_config_value('Part'))
775-
elif '#hls-fpga-machine-learning insert invoke_args' in line:
776-
tb_in_file = model.config.get_config_value('InputData')
777-
tb_out_file = model.config.get_config_value('OutputPredictions')
778-
invoke_args = '$sfd/firmware/weights'
779-
if tb_in_file is not None:
780-
invoke_args = invoke_args + f' $sfd/tb_data/{tb_in_file}'
781-
if tb_out_file is not None:
782-
invoke_args = invoke_args + f' $sfd/tb_data/{tb_out_file}'
783-
line = indent + f'flow package option set /SCVerify/INVOKE_ARGS "{invoke_args}"\n'
784-
elif 'set hls_clock_period 5' in line:
785-
line = indent + 'set hls_clock_period {}\n'.format(model.config.get_config_value('ClockPeriod'))
786-
fout.write(line)
787-
f.close()
788-
fout.close()
771+
if model.config.get_config_value('Technology') == 'asic':
772+
line = indent + 'setup_asic_libs {{{}}}\n'.format(model.config.get_config_value('ASICLibs'))
773+
else:
774+
line = indent + 'setup_xilinx_part {{{}}}\n'.format(model.config.get_config_value('Part'))
775+
elif '#hls-fpga-machine-learning insert invoke_args' in line:
776+
tb_in_file = model.config.get_config_value('InputData')
777+
tb_out_file = model.config.get_config_value('OutputPredictions')
778+
invoke_args = '$sfd/firmware/weights'
779+
if tb_in_file is not None:
780+
invoke_args = invoke_args + f' $sfd/tb_data/{tb_in_file}'
781+
if tb_out_file is not None:
782+
invoke_args = invoke_args + f' $sfd/tb_data/{tb_out_file}'
783+
line = indent + f'flow package option set /SCVerify/INVOKE_ARGS "{invoke_args}"\n'
784+
elif 'set hls_clock_period 5' in line:
785+
line = indent + 'set hls_clock_period {}\n'.format(model.config.get_config_value('ClockPeriod'))
786+
dst.write(line)
789787

790788
# build_lib.sh
791-
f = open(os.path.join(filedir, '../templates/catapult/build_lib.sh'))
792-
fout = open(f'{model.config.get_output_dir()}/build_lib.sh', 'w')
793-
794-
for line in f.readlines():
795-
line = line.replace('myproject', model.config.get_project_name())
796-
line = line.replace('mystamp', model.config.get_config_value('Stamp'))
797-
798-
fout.write(line)
799-
f.close()
800-
fout.close()
789+
build_lib_src = (filedir / '../templates/catapult/build_lib.sh').resolve()
790+
build_lib_dst = Path(f'{model.config.get_output_dir()}/build_lib.sh').resolve()
791+
with open(build_lib_src) as src, open(build_lib_dst, 'w') as dst:
792+
for line in src.readlines():
793+
line = line.replace('myproject', model.config.get_project_name())
794+
line = line.replace('mystamp', model.config.get_config_value('Stamp'))
795+
796+
dst.write(line)
797+
build_lib_dst.chmod(build_lib_dst.stat().st_mode | stat.S_IEXEC)
801798

802799
def write_nnet_utils(self, model):
803800
"""Copy the nnet_utils, AP types headers and any custom source to the project output directory

hls4ml/writer/quartus_writer.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import glob
22
import os
3+
import stat
34
import tarfile
45
from collections import OrderedDict
6+
from pathlib import Path
57
from shutil import copyfile, copytree, rmtree
68

79
import numpy as np
@@ -877,32 +879,30 @@ def write_build_script(self, model):
877879
model (ModelGraph): the hls4ml model.
878880
"""
879881

880-
# Makefile
881-
filedir = os.path.dirname(os.path.abspath(__file__))
882-
f = open(os.path.join(filedir, '../templates/quartus/Makefile'))
883-
fout = open(f'{model.config.get_output_dir()}/Makefile', 'w')
882+
filedir = Path(__file__).parent
884883

885-
for line in f.readlines():
886-
line = line.replace('myproject', model.config.get_project_name())
884+
# Makefile
885+
makefile_src = (filedir / '../templates/quartus/Makefile').resolve()
886+
makefile_dst = Path(f'{model.config.get_output_dir()}/Makefile').resolve()
887+
with open(makefile_src) as src, open(makefile_dst, 'w') as dst:
888+
for line in src.readlines():
889+
line = line.replace('myproject', model.config.get_project_name())
887890

888-
if 'DEVICE :=' in line:
889-
line = 'DEVICE := {}\n'.format(model.config.get_config_value('Part'))
891+
if 'DEVICE :=' in line:
892+
line = 'DEVICE := {}\n'.format(model.config.get_config_value('Part'))
890893

891-
fout.write(line)
892-
f.close()
893-
fout.close()
894+
dst.write(line)
894895

895896
# build_lib.sh
896-
f = open(os.path.join(filedir, '../templates/quartus/build_lib.sh'))
897-
fout = open(f'{model.config.get_output_dir()}/build_lib.sh', 'w')
898-
899-
for line in f.readlines():
900-
line = line.replace('myproject', model.config.get_project_name())
901-
line = line.replace('mystamp', model.config.get_config_value('Stamp'))
902-
903-
fout.write(line)
904-
f.close()
905-
fout.close()
897+
build_lib_src = (filedir / '../templates/quartus/build_lib.sh').resolve()
898+
build_lib_dst = Path(f'{model.config.get_output_dir()}/build_lib.sh').resolve()
899+
with open(build_lib_src) as src, open(build_lib_dst, 'w') as dst:
900+
for line in src.readlines():
901+
line = line.replace('myproject', model.config.get_project_name())
902+
line = line.replace('mystamp', model.config.get_config_value('Stamp'))
903+
904+
dst.write(line)
905+
build_lib_dst.chmod(build_lib_dst.stat().st_mode | stat.S_IEXEC)
906906

907907
def write_nnet_utils(self, model):
908908
"""Copy the nnet_utils, AP types headers and any custom source to the project output directory

0 commit comments

Comments
 (0)