Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
4 changes: 4 additions & 0 deletions hls4ml/backends/catapult/catapult_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def create_initial_config(
fifo=None,
clock_period=5,
io_type='io_parallel',
write_tar=False,
):
config = {}

Expand All @@ -206,6 +207,9 @@ def create_initial_config(
config['ClockPeriod'] = clock_period
config['FIFO'] = fifo
config['IOType'] = io_type
config['WriterConfig'] = {
'WriteTar': write_tar,
}
config['HLSConfig'] = {}

return config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ def create_initial_config(
clock_period=5,
clock_uncertainty='12.5%',
io_type='io_parallel',
write_tar=False,
interface='axi_stream',
driver='python',
input_type='float',
Expand Down Expand Up @@ -131,7 +132,13 @@ def create_initial_config(
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 = super().create_initial_config(
part=part,
clock_period=clock_period,
clock_uncertainty=clock_uncertainty,
io_type=io_type,
write_tar=write_tar,
)
config['AcceleratorConfig'] = {}
config['AcceleratorConfig']['Board'] = board
config['AcceleratorConfig']['Interface'] = interface # axi_stream, axi_master, axi_lite
Expand Down
15 changes: 8 additions & 7 deletions hls4ml/writer/catapult_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -892,12 +892,11 @@ def write_tar(self, model):
Args:
model (ModelGraph): the hls4ml model.
"""

if not os.path.exists(model.config.get_output_dir() + '.tar.gz'):
with tarfile.open(model.config.get_output_dir() + '.tar.gz', mode='w:gz') as archive:
archive.add(model.config.get_output_dir(), recursive=True)
else:
print('Project .tar.gz archive already exists')
tar_path = model.config.get_output_dir() + '.tar.gz'
if os.path.exists(tar_path):
os.remove(tar_path)
with tarfile.open(tar_path, mode='w:gz') as archive:
archive.add(model.config.get_output_dir(), recursive=True, arcname='')

def write_hls(self, model):
self.write_output_dir(model)
Expand All @@ -912,4 +911,6 @@ def write_hls(self, model):
self.write_nnet_utils(model)
self.write_generated_code(model)
self.write_yml(model)
self.write_tar(model)
write_tar = model.config.get_writer_config().get('WriteTar', False)
if write_tar:
self.write_tar(model)
15 changes: 7 additions & 8 deletions hls4ml/writer/libero_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -884,13 +884,10 @@ def write_tar(self, model):
Args:
model (ModelGraph): the hls4ml model.
"""

write_tar = model.config.get_writer_config().get('WriteTar', False)
if write_tar:
tar_path = Path(model.config.get_output_dir() + '.tar.gz')
tar_path.unlink(missing_ok=True)
with tarfile.open(tar_path, mode='w:gz') as archive:
archive.add(model.config.get_output_dir(), recursive=True, arcname='')
tar_path = Path(model.config.get_output_dir() + '.tar.gz')
tar_path.unlink(missing_ok=True)
with tarfile.open(tar_path, mode='w:gz') as archive:
archive.add(model.config.get_output_dir(), recursive=True, arcname='')

def write_hls(self, model):
print('Writing HLS project')
Expand All @@ -906,5 +903,7 @@ def write_hls(self, model):
self.write_nnet_utils(model)
self.write_generated_code(model)
self.write_yml(model)
self.write_tar(model)
write_tar = model.config.get_writer_config().get('WriteTar', False)
if write_tar:
self.write_tar(model)
print('Done')
16 changes: 8 additions & 8 deletions hls4ml/writer/oneapi_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -971,13 +971,11 @@ def write_tar(self, model):
Args:
model (ModelGraph): the hls4ml model.
"""

if model.config.get_writer_config().get('WriteTar', False):
tar_path = model.config.get_output_dir() + '.tar.gz'
if os.path.exists(tar_path):
os.remove(tar_path)
with tarfile.open(model.config.get_output_dir() + '.tar.gz', mode='w:gz') as archive:
archive.add(model.config.get_output_dir(), recursive=True)
tar_path = model.config.get_output_dir() + '.tar.gz'
if os.path.exists(tar_path):
os.remove(tar_path)
with tarfile.open(tar_path, mode='w:gz') as archive:
archive.add(model.config.get_output_dir(), recursive=True)

def write_hls(self, model):
self.write_project_dir(model)
Expand All @@ -993,4 +991,6 @@ def write_hls(self, model):
self.write_activation_tables(model)
self.write_generated_code(model)
self.write_yml(model)
self.write_tar(model)
write_tar = model.config.get_writer_config().get('WriteTar', False)
if write_tar:
self.write_tar(model)
16 changes: 8 additions & 8 deletions hls4ml/writer/quartus_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1330,13 +1330,11 @@ def write_tar(self, model):
Args:
model (ModelGraph): the hls4ml model.
"""

if model.config.get_writer_config().get('WriteTar', False):
tar_path = model.config.get_output_dir() + '.tar.gz'
if os.path.exists(tar_path):
os.remove(tar_path)
with tarfile.open(model.config.get_output_dir() + '.tar.gz', mode='w:gz') as archive:
archive.add(model.config.get_output_dir(), recursive=True)
tar_path = model.config.get_output_dir() + '.tar.gz'
if os.path.exists(tar_path):
os.remove(tar_path)
with tarfile.open(tar_path, mode='w:gz') as archive:
archive.add(model.config.get_output_dir(), recursive=True)

def write_hls(self, model):
self.write_project_dir(model)
Expand All @@ -1351,4 +1349,6 @@ def write_hls(self, model):
self.write_nnet_utils(model)
self.write_activation_tables(model)
self.write_yml(model)
self.write_tar(model)
write_tar = model.config.get_writer_config().get('WriteTar', False)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why should we move the check outside of the write_tar() function? It was deliberately placed inside so we have a clean set of steps for the writer. Also it is easier to log (we're not doing it now, but could do in the future)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Because right now if you don't set 'WriteTar' field in the writer config, the behaviour of write_tar() is not the one expected, i.e. it doesn't create the tarball archive. To my understanding, that field this is mainly leveraged for local testing, in which you don't want to have the test folder filled with tarball files.
I think a different and cleaner solution would be to set an environment variable that prevents the tar files to be generated (basically moving back the check inside write_tar(), but checking if the env variable is set this time). This solution has the advantage of being set only once before running the tests and it is applied to all the tests.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The check is identical, it is just outside of the function now. The idea of the writer is that it follows a set of steps. The tar writer function may or may not write the tar, depending on the config, just like all the other functions write contents based on the provided config. Using env vars to change the behavior of the conversion process while you also have the conversion config itself that controls all other aspects of conversion would be splitting control and introducing inconsistency that will likely be a burden later on.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, this makes sense. I moved the WriteTar check outside write_tar() following earlier discussion, but I agree that keeping that logic inside write_tar() can preserve the writer-step semantics and original design.
If preferred, I can restore that behavior (move the check back inside write_tar()) while keeping the backend config fixes for Catapult and VivadoAccelerator, plus the related test coverage updates.

if write_tar:
self.write_tar(model)
4 changes: 3 additions & 1 deletion hls4ml/writer/symbolic_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,6 @@ def write_hls(self, model):
self.write_nnet_utils(model)
self.write_generated_code(model)
self.write_yml(model)
self.write_tar(model)
write_tar = model.config.get_writer_config().get('WriteTar', False)
if write_tar:
self.write_tar(model)
4 changes: 3 additions & 1 deletion hls4ml/writer/vitis_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,6 @@ def write_hls(self, model):
self.write_board_script_override(model)
self.write_build_prj_override(model)
self.write_build_opts(model)
self.write_tar(model)
write_tar = model.config.get_writer_config().get('WriteTar', False)
if write_tar:
self.write_tar(model)
4 changes: 3 additions & 1 deletion hls4ml/writer/vivado_accelerator_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,4 +426,6 @@ def write_hls(self, model):
self.write_wrapper_test(model)
self.write_axi_wrapper(model)
self.modify_build_script(model)
self.write_new_tar(model)
write_tar = model.config.get_writer_config().get('WriteTar', False)
if write_tar:
self.write_new_tar(model)
17 changes: 8 additions & 9 deletions hls4ml/writer/vivado_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1112,14 +1112,11 @@ def write_tar(self, model):
Args:
model (ModelGraph): the hls4ml model.
"""

write_tar = model.config.get_writer_config().get('WriteTar', False)
if write_tar:
tar_path = model.config.get_output_dir() + '.tar.gz'
if os.path.exists(tar_path):
os.remove(tar_path)
with tarfile.open(tar_path, mode='w:gz') as archive:
archive.add(model.config.get_output_dir(), recursive=True, arcname='')
tar_path = model.config.get_output_dir() + '.tar.gz'
if os.path.exists(tar_path):
os.remove(tar_path)
with tarfile.open(tar_path, mode='w:gz') as archive:
archive.add(model.config.get_output_dir(), recursive=True, arcname='')

def write_hls(self, model, is_multigraph=False):
if not is_multigraph:
Expand All @@ -1135,7 +1132,9 @@ def write_hls(self, model, is_multigraph=False):
self.write_nnet_utils(model)
self.write_generated_code(model)
self.write_yml(model)
self.write_tar(model)
write_tar = model.config.get_writer_config().get('WriteTar', False)
if write_tar:
self.write_tar(model)
else:
self.write_project_dir(model)
self.write_build_script_multigraph(model)
Expand Down
2 changes: 1 addition & 1 deletion test/pytest/test_writer_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def test_emulator(test_case_id, keras_model, io_type, backend):
hls_model.compile() # It's enough that the model compiles


@pytest.mark.parametrize('backend', ['Vivado', 'Vitis']) # No Quartus for now
@pytest.mark.parametrize('backend', ['Vivado', 'Vitis', 'Catapult', 'VivadoAccelerator']) # No Quartus for now
@pytest.mark.parametrize('write_tar', [True, False])
def test_write_tar(test_case_id, keras_model, write_tar, backend):
config = hls4ml.utils.config_from_keras_model(keras_model, granularity='name')
Expand Down
Loading