Skip to content

Commit c7a89d8

Browse files
authored
Merge branch 'main' into initialRecurr
2 parents ebd4de3 + 90ada94 commit c7a89d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+890
-463
lines changed

.pre-commit-config.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,26 @@ exclude: (^hls4ml\/templates\/(vivado|quartus)\/(ap_types|ac_types)\/|^test/pyte
22

33
repos:
44
- repo: https://github.com/psf/black
5-
rev: 24.10.0
5+
rev: 25.1.0
66
hooks:
77
- id: black
88
language_version: python3
99
args: ['--line-length=125',
1010
'--skip-string-normalization']
1111

12+
- repo: https://github.com/tox-dev/pyproject-fmt
13+
rev: v2.5.0
14+
hooks:
15+
- id: pyproject-fmt
16+
1217
- repo: https://github.com/pre-commit/pre-commit-hooks
1318
rev: v5.0.0
1419
hooks:
1520
- id: check-added-large-files
1621
- id: check-case-conflict
1722
- id: check-merge-conflict
1823
- id: check-symlinks
24+
- id: check-toml
1925
- id: check-yaml
2026
- id: debug-statements
2127
- id: end-of-file-fixer
@@ -24,22 +30,16 @@ repos:
2430
- id: trailing-whitespace
2531

2632
- repo: https://github.com/PyCQA/isort
27-
rev: 5.13.2
33+
rev: 6.0.0
2834
hooks:
2935
- id: isort
30-
args: ["--profile", "black", --line-length=125]
3136

3237
- repo: https://github.com/asottile/pyupgrade
3338
rev: v3.19.1
3439
hooks:
3540
- id: pyupgrade
3641
args: ["--py36-plus"]
3742

38-
- repo: https://github.com/asottile/setup-cfg-fmt
39-
rev: v2.7.0
40-
hooks:
41-
- id: setup-cfg-fmt
42-
4343
- repo: https://github.com/pycqa/flake8
4444
rev: 7.1.1
4545
hooks:

MANIFEST.in

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
include LICENSE README.md CONTRIBUTING.md CITATION.cff pyproject.toml setup.py setup.cfg .clang-format
1+
include LICENSE README.md CONTRIBUTING.md CITATION.cff pyproject.toml .clang-format
22
graft example-models
33
graft test
44
graft contrib
55
recursive-include hls4ml/templates *
6-
global-exclude .git .gitmodules .gitlab-ci.yml
6+
recursive-include hls4ml *.py
7+
recursive-include hls4ml/contrib *
8+
global-exclude .git .gitmodules .gitlab-ci.yml *.pyc
79
include hls4ml/backends/vivado_accelerator/supported_boards.json

hls4ml/__init__.py

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,3 @@
1-
# Temporary workaround for QKeras installation requirement, will be removed after 1.0.0
2-
def maybe_install_qkeras():
3-
import subprocess
4-
import sys
5-
6-
QKERAS_PKG_NAME = 'QKeras'
7-
# QKERAS_PKG_SOURCE = QKERAS_PKG_NAME
8-
QKERAS_PKG_SOURCE = 'qkeras@git+https://github.com/fastmachinelearning/qkeras.git'
9-
10-
def pip_list():
11-
p = subprocess.run([sys.executable, '-m', 'pip', 'list'], check=True, capture_output=True)
12-
return p.stdout.decode()
13-
14-
def pip_install(package):
15-
subprocess.check_call([sys.executable, '-m', 'pip', 'install', package])
16-
17-
all_pkgs = pip_list()
18-
if QKERAS_PKG_NAME not in all_pkgs:
19-
print('QKeras installation not found, installing one...')
20-
pip_install(QKERAS_PKG_SOURCE)
21-
print('QKeras installed.')
22-
23-
24-
try:
25-
maybe_install_qkeras()
26-
except Exception:
27-
print('Could not find QKeras installation, make sure you have QKeras installed.')
28-
29-
# End of workaround
30-
311
from hls4ml import converters, report, utils # noqa: F401, E402
322

333
try:

hls4ml/backends/catapult/passes/conv_stream.py

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ class GenerateConvStreamingInstructions(OptimizerPass):
66
'''Generates the instructions for streaming implementation of CNNs'''
77

88
def match(self, node):
9-
return isinstance(node, (Conv1D, SeparableConv1D, Conv2D, SeparableConv2D))
9+
is_match = (
10+
isinstance(node, (Conv1D, SeparableConv1D, Conv2D, SeparableConv2D))
11+
and node.model.config.get_config_value('IOType').lower() == 'io_stream'
12+
and node.get_attr('implementation').lower() == 'encoded'
13+
)
14+
return is_match
1015

1116
def transform(self, model, node):
1217
node_class = node.__class__.__name__
@@ -18,35 +23,25 @@ def transform(self, model, node):
1823
raise Exception(f'Cannot generate instructions for node {node.name} ({node_class})')
1924

2025
def _generate_1d_instructions(self, node):
21-
if node.model.config.get_config_value('IOType') == 'io_stream':
22-
min_w, instructions = node.model.config.backend.compute_conv1d_instructions(
23-
node.get_input_variable().shape[0],
24-
node.get_input_variable().shape[1],
25-
node.get_attr('filt_width'),
26-
node.get_attr('stride_width'),
27-
)
28-
instructions_str = ','.join(str(i) for i in instructions)
29-
node.set_attr('min_width', min_w)
30-
node.set_attr('instructions', instructions_str)
31-
else:
32-
# these are unused; just put dummy values
33-
node.set_attr('min_width', node.get_attr('in_width'))
34-
node.set_attr('instructions', '0')
26+
min_w, instructions = node.model.config.backend.compute_conv1d_instructions(
27+
node.get_input_variable().shape[0],
28+
node.get_input_variable().shape[1],
29+
node.get_attr('filt_width'),
30+
node.get_attr('stride_width'),
31+
)
32+
instructions_str = ','.join(str(i) for i in instructions)
33+
node.set_attr('min_width', min_w)
34+
node.set_attr('instructions', instructions_str)
3535

3636
def _generate_2d_instructions(self, node):
37-
if node.model.config.get_config_value('IOType') == 'io_stream':
38-
min_h, min_w, instructions = node.model.config.backend.compute_conv2d_instructions(
39-
node.get_input_variable().shape[0],
40-
node.get_input_variable().shape[1],
41-
node.get_input_variable().shape[2],
42-
node.get_attr('filt_height'),
43-
node.get_attr('stride_height'),
44-
)
45-
instructions_str = ','.join(str(i) for i in instructions)
46-
node.set_attr('min_height', min_h)
47-
node.set_attr('min_width', min_w)
48-
node.set_attr('instructions', instructions_str)
49-
else:
50-
node.set_attr('min_height', node.get_attr('in_height'))
51-
node.set_attr('min_width', node.get_attr('in_width'))
52-
node.set_attr('instructions', '0')
37+
min_h, min_w, instructions = node.model.config.backend.compute_conv2d_instructions(
38+
node.get_input_variable().shape[0],
39+
node.get_input_variable().shape[1],
40+
node.get_input_variable().shape[2],
41+
node.get_attr('filt_height'),
42+
node.get_attr('stride_height'),
43+
)
44+
instructions_str = ','.join(str(i) for i in instructions)
45+
node.set_attr('min_height', min_h)
46+
node.set_attr('min_width', min_w)
47+
node.set_attr('instructions', instructions_str)

hls4ml/backends/catapult/passes/convolution_templates.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ def format(self, node):
9494
else:
9595
params['fill_fn'] = 'FillConv1DBuffer'
9696

97+
params['min_width'] = node.get_attr('min_width', node.get_attr('in_width'))
98+
params['instructions'] = node.get_attr('instructions', '0')
99+
97100
conv_config = self.template.format(**params)
98101

99102
mult_params = self._default_config_params(node)
@@ -210,6 +213,10 @@ def format(self, node):
210213
else:
211214
params['fill_fn'] = 'FillConv2DBuffer'
212215

216+
params['min_height'] = node.get_attr('min_height', node.get_attr('in_height'))
217+
params['min_width'] = node.get_attr('min_width', node.get_attr('in_width'))
218+
params['instructions'] = node.get_attr('instructions', '0')
219+
213220
conv_config = self.template.format(**params)
214221

215222
mult_params = self._default_config_params(node)

hls4ml/backends/oneapi/passes/clone_templates.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
""" The clone templates in the fpga backend are not enough for oneAPI, so this adds the missing parts
2-
"""
1+
"""The clone templates in the fpga backend are not enough for oneAPI, so this adds the missing parts"""
32

43
from hls4ml.backends.fpga.passes.clone import Clone
54
from hls4ml.backends.oneapi.oneapi_template import StreamFunctionCallTemplate, TaskSequenceTemplate

hls4ml/backends/vivado/passes/conv_stream.py

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ class GenerateConvStreamingInstructions(OptimizerPass):
66
'''Generates the instructions for streaming implementation of CNNs'''
77

88
def match(self, node):
9-
return isinstance(node, (Conv1D, SeparableConv1D, Conv2D, SeparableConv2D))
9+
is_match = (
10+
isinstance(node, (Conv1D, SeparableConv1D, Conv2D, SeparableConv2D))
11+
and node.model.config.get_config_value('IOType').lower() == 'io_stream'
12+
and node.get_attr('implementation').lower() == 'encoded'
13+
)
14+
return is_match
1015

1116
def transform(self, model, node):
1217
node_class = node.__class__.__name__
@@ -18,35 +23,25 @@ def transform(self, model, node):
1823
raise Exception(f'Cannot generate instructions for node {node.name} ({node_class})')
1924

2025
def _generate_1d_instructions(self, node):
21-
if node.model.config.get_config_value('IOType') == 'io_stream':
22-
min_w, instructions = node.model.config.backend.compute_conv1d_instructions(
23-
node.get_input_variable().shape[0],
24-
node.get_input_variable().shape[1],
25-
node.get_attr('filt_width'),
26-
node.get_attr('stride_width'),
27-
)
28-
instructions_str = ','.join(str(i) for i in instructions)
29-
node.set_attr('min_width', min_w)
30-
node.set_attr('instructions', instructions_str)
31-
else:
32-
# these are unused; just put dummy values
33-
node.set_attr('min_width', node.get_attr('in_width'))
34-
node.set_attr('instructions', '0')
26+
min_w, instructions = node.model.config.backend.compute_conv1d_instructions(
27+
node.get_input_variable().shape[0],
28+
node.get_input_variable().shape[1],
29+
node.get_attr('filt_width'),
30+
node.get_attr('stride_width'),
31+
)
32+
instructions_str = ','.join(str(i) for i in instructions)
33+
node.set_attr('min_width', min_w)
34+
node.set_attr('instructions', instructions_str)
3535

3636
def _generate_2d_instructions(self, node):
37-
if node.model.config.get_config_value('IOType') == 'io_stream':
38-
min_h, min_w, instructions = node.model.config.backend.compute_conv2d_instructions(
39-
node.get_input_variable().shape[0],
40-
node.get_input_variable().shape[1],
41-
node.get_input_variable().shape[2],
42-
node.get_attr('filt_height'),
43-
node.get_attr('stride_height'),
44-
)
45-
instructions_str = ','.join(str(i) for i in instructions)
46-
node.set_attr('min_height', min_h)
47-
node.set_attr('min_width', min_w)
48-
node.set_attr('instructions', instructions_str)
49-
else:
50-
node.set_attr('min_height', node.get_attr('in_height'))
51-
node.set_attr('min_width', node.get_attr('in_width'))
52-
node.set_attr('instructions', '0')
37+
min_h, min_w, instructions = node.model.config.backend.compute_conv2d_instructions(
38+
node.get_input_variable().shape[0],
39+
node.get_input_variable().shape[1],
40+
node.get_input_variable().shape[2],
41+
node.get_attr('filt_height'),
42+
node.get_attr('stride_height'),
43+
)
44+
instructions_str = ','.join(str(i) for i in instructions)
45+
node.set_attr('min_height', min_h)
46+
node.set_attr('min_width', min_w)
47+
node.set_attr('instructions', instructions_str)

hls4ml/backends/vivado/passes/convolution_templates.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ def format(self, node):
108108
else:
109109
params['conv_fn'] = 'Conv1DResource'
110110

111+
params['min_width'] = node.get_attr('min_width', node.get_attr('in_width'))
112+
params['instructions'] = node.get_attr('instructions', '0')
113+
111114
conv_config = self.template.format(**params)
112115

113116
mult_params = self._default_config_params(node)
@@ -239,6 +242,10 @@ def format(self, node):
239242
else:
240243
params['fill_fn'] = 'FillConv2DBuffer'
241244

245+
params['min_height'] = node.get_attr('min_height', node.get_attr('in_height'))
246+
params['min_width'] = node.get_attr('min_width', node.get_attr('in_width'))
247+
params['instructions'] = node.get_attr('instructions', '0')
248+
242249
conv_config = self.template.format(**params)
243250

244251
mult_params = self._default_config_params(node)

hls4ml/backends/vivado/passes/recurrent_templates.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
# recurrent multiplication template
66

7-
recr_mult_config_template = """struct config{index} : nnet::dense_config {{
7+
recr_mult_config_template_1 = """struct config{index} : nnet::dense_config {{
88
static const unsigned n_in = {n_in};
99
static const unsigned n_out = {n_out};
1010
static const unsigned strategy = nnet::{strategy};
@@ -22,6 +22,24 @@
2222
using product = nnet::product::{product_type}<x_T, y_T>;
2323
}};\n"""
2424

25+
recr_mult_config_template_2 = """struct config{index} : nnet::dense_config {{
26+
static const unsigned n_in = {n_in};
27+
static const unsigned n_out = {n_out};
28+
static const unsigned strategy = nnet::{strategy};
29+
static const unsigned reuse_factor = {reuse};
30+
static const unsigned n_zeros = {nzeros};
31+
static const unsigned n_nonzeros = {nonzeros};
32+
static const unsigned multiplier_limit = DIV_ROUNDUP(n_in * n_out, reuse_factor) - n_zeros / reuse_factor;
33+
static const bool store_weights_in_bram = false;
34+
typedef {accum_t.name} accum_t;
35+
typedef {recurrent_bias_t.name} bias_t;
36+
typedef {recurrent_weight_t.name} weight_t;
37+
template<class data_T, class res_T, class CONFIG_T>
38+
using kernel = nnet::{dense_function}<data_T, res_T, CONFIG_T>;
39+
template<class x_T, class y_T>
40+
using product = nnet::product::{product_type}<x_T, y_T>;
41+
}};\n"""
42+
2543
# activation templates
2644

2745
activ_config_template = """struct {type}_config{index} : nnet::activ_config {{
@@ -45,7 +63,9 @@
4563
recr_config_template = """struct config{index} : nnet::{recr_type}_config {{
4664
typedef {accum_t.name} accum_t;
4765
typedef {weight_t.name} weight_t; // Matrix
66+
typedef {recurrent_weight_t.name} recurrent_weight_t; // Matrix
4867
typedef {bias_t.name} bias_t; // Vector
68+
typedef {recurrent_bias_t.name} recurrent_bias_t; // Vector
4969
typedef {config_mult_t1} mult_config1;
5070
typedef {config_mult_t2} mult_config2;
5171
typedef {recr_act_t} ACT_CONFIG_{RECR_TYPE};
@@ -79,8 +99,8 @@ def __init__(self):
7999
self.template = recr_config_template
80100
self.act_template = activ_config_template
81101
self.recr_act_template = recr_activ_config_template
82-
self.mult1_template = recr_mult_config_template
83-
self.mult2_template = recr_mult_config_template
102+
self.mult1_template = recr_mult_config_template_1
103+
self.mult2_template = recr_mult_config_template_2
84104

85105
def format(self, node):
86106
params = self._default_config_params(node)

0 commit comments

Comments
 (0)