Skip to content

Commit 1194737

Browse files
authored
Merge branch 'qonnx-1p0' into qonnx-big-fixes
2 parents b594fd1 + ce09665 commit 1194737

40 files changed

+209
-164
lines changed

docs/api/configuration.rst

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@ We currently support two ways of setting hls4ml's model configuration. This page
99

1010
.. contents:: \
1111

12+
The Python API approach is recommended for most users as there are more utilities to help create the configuration dictionaries.
1213

1314
**NOTE:**
1415

1516

1617
*
1718
One important part of ``hls4ml`` to remember is that the user is responsible for the format of the inputs. There is no automatic formatting or normalization so this must be done in the training.
1819

19-
*
20+
..
21+
*
2022
For developers, you might also want to checkout this section: `Detailed configuration in converted hls codes <#detailed-configuration-in-converted-hls-codes>`_.
23+
*Broken link*
2124
2225
----
2326

@@ -31,11 +34,26 @@ Using hls4ml, you can quickly generate a simple configuration dictionary from a
3134
import hls4ml
3235
config = hls4ml.utils.config_from_keras_model(model, granularity='model')
3336
34-
For more advanced and detailed configuration, you can also set them through the created dictionary. For example, to change the reuse factor:
37+
This python dictionary can be edited as needed. A more advanced configuration can be generated by, for example:
38+
39+
.. code-block:: python
40+
41+
import hls4ml
42+
config = hls4ml.utils.config_from_keras_model(
43+
model,
44+
granularity='name',
45+
default_precision='fixed<16,6>',
46+
backend='Vitis')
47+
48+
This will include per-layer configuration based on the model. Including the backend is recommended because some configation options depend on the backend. Note, the precisions at the
49+
higher granularites usually default to 'auto', which means that ``hls4ml`` will try to set it automatically. Note that higher granularity settings take precendence
50+
over model-level settings. See :py:class:`~hls4ml.utils.config.config_from_keras_model` for more information on the various options.
51+
52+
One can override specific values before using the configuration:
3553

3654
.. code-block:: python
3755
38-
config['Model']['ReuseFactor'] = 2
56+
config['LayerName']['fc1']['ReuseFactor'] = 2
3957
4058
Or to set the precision of a specific layer's weight:
4159

@@ -45,6 +63,20 @@ Or to set the precision of a specific layer's weight:
4563
4664
To better understand how the configuration hierachy works, refer to the next section for more details.
4765

66+
Finally, one then uses the configuration to create an hls model:
67+
68+
.. code-block:: python
69+
70+
hls_model = hls4ml.converters.convert_from_keras_model(
71+
model,
72+
hls_config=config,
73+
output_dir="my_project_dir",
74+
io_type='io_stream',
75+
backend='Vitis'
76+
)
77+
78+
See :py:class:`~hls4ml.converters.convert_from_keras_model` for more information on the various options.
79+
4880
----
4981

5082
2. YAML Configuration file

docs/setup.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ To run FPGA synthesis, installation of following tools is required:
5757

5858
* Xilinx Vivado HLS 2018.2 to 2020.1 for synthesis for Xilinx FPGAs
5959

60-
* Vitis HLS 2022.1 or newer is required for synthesis for Xilinx FPGAs using the experimental ``Vitis`` backend.
60+
* Vitis HLS 2022.2 or newer is required for synthesis for Xilinx FPGAs using the ``Vitis`` backend.
6161

6262
* Intel Quartus 20.1 to 21.4 for the synthesis for Intel FPGAs
6363

docs/status.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ Other feature notes:
8181
* ``hls4ml`` is tested on Linux, and supports
8282
* Vivado HLS versions 2018.2 to 2020.1
8383
* Intel HLS versions 20.1 to 21.4
84-
* Vitis HLS versions 2020.2 to 2022.2 (experimentally)
84+
* Vitis HLS versions 2022.2 to 2024.1
8585
* Windows and macOS are not supported
8686
* BDT support has moved to the `Conifer <https://github.com/thesps/conifer>`__ package
8787

hls4ml/backends/catapult/catapult_backend.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ def _register_flows(self):
110110
'catapult:inplace_stream_flatten',
111111
'catapult:skip_softmax',
112112
'catapult:fix_softmax_table_size',
113+
'infer_precision_types',
113114
]
114115
optimization_flow = register_flow('optimize', optimization_passes, requires=[init_flow], backend=self.name)
115116

hls4ml/backends/catapult/passes/conv_same_pad.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ class InsertZeroPaddingBeforeConv1D(OptimizerPass):
66
name = 'insert_zero_padding_before_conv1d'
77

88
def match(self, node):
9-
is_match = (
10-
isinstance(node, (Conv1D, SeparableConv1D))
11-
and ((node.get_attr('padding') == 'same') or (node.get_attr('padding') == 'causal'))
12-
and node.get_attr('filt_width') != 1
9+
is_match = isinstance(node, (Conv1D, SeparableConv1D)) and (
10+
(node.get_attr('pad_left') != 0) or (node.get_attr('pad_right') != 0)
1311
)
1412
return is_match
1513

@@ -37,7 +35,6 @@ def transform(self, model, node):
3735
}
3836

3937
# Switch Conv1D layer padding to 'valid'
40-
node.set_attr('padding', 'valid')
4138
node.set_attr('pad_left', 0)
4239
node.set_attr('pad_right', 0)
4340
node.set_attr('in_width', out_width)
@@ -54,11 +51,11 @@ class InsertZeroPaddingBeforeConv2D(OptimizerPass):
5451
name = 'insert_zero_padding_before_conv2d'
5552

5653
def match(self, node):
57-
is_match = (
58-
isinstance(node, (Conv2D, SeparableConv2D))
59-
and node.get_attr('padding') == 'same'
60-
and node.get_attr('filt_height') != 1
61-
and node.get_attr('filt_width') != 1
54+
is_match = isinstance(node, (Conv2D, SeparableConv2D)) and (
55+
(node.get_attr('pad_left') != 0)
56+
or (node.get_attr('pad_right') != 0)
57+
or (node.get_attr('pad_top') != 0)
58+
or (node.get_attr('pad_bottom') != 0)
6259
)
6360
return is_match
6461

@@ -93,7 +90,6 @@ def transform(self, model, node):
9390
}
9491

9592
# Switch Conv2D layer padding to 'valid'
96-
node.set_attr('padding', 'valid')
9793
node.set_attr('pad_top', 0)
9894
node.set_attr('pad_bottom', 0)
9995
node.set_attr('pad_left', 0)

hls4ml/backends/vivado/passes/conv_same_pad.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ class InsertZeroPaddingBeforeConv1D(OptimizerPass):
66
name = 'insert_zero_padding_before_conv1d'
77

88
def match(self, node):
9-
is_match = (
10-
isinstance(node, (Conv1D, SeparableConv1D))
11-
and ((node.get_attr('padding') == 'same') or (node.get_attr('padding') == 'causal'))
12-
and node.get_attr('filt_width') != 1
9+
is_match = isinstance(node, (Conv1D, SeparableConv1D)) and (
10+
(node.get_attr('pad_left') != 0) or (node.get_attr('pad_right') != 0)
1311
)
1412
return is_match
1513

@@ -37,7 +35,6 @@ def transform(self, model, node):
3735
}
3836

3937
# Switch Conv1D layer padding to 'valid'
40-
node.set_attr('padding', 'valid')
4138
node.set_attr('pad_left', 0)
4239
node.set_attr('pad_right', 0)
4340
node.set_attr('in_width', out_width)
@@ -54,11 +51,11 @@ class InsertZeroPaddingBeforeConv2D(OptimizerPass):
5451
name = 'insert_zero_padding_before_conv2d'
5552

5653
def match(self, node):
57-
is_match = (
58-
isinstance(node, (Conv2D, SeparableConv2D))
59-
and node.get_attr('padding') == 'same'
60-
and node.get_attr('filt_height') != 1
61-
and node.get_attr('filt_width') != 1
54+
is_match = isinstance(node, (Conv2D, SeparableConv2D)) and (
55+
(node.get_attr('pad_left') != 0)
56+
or (node.get_attr('pad_right') != 0)
57+
or (node.get_attr('pad_top') != 0)
58+
or (node.get_attr('pad_bottom') != 0)
6259
)
6360
return is_match
6461

@@ -93,7 +90,6 @@ def transform(self, model, node):
9390
}
9491

9592
# Switch Conv2D layer padding to 'valid'
96-
node.set_attr('padding', 'valid')
9793
node.set_attr('pad_top', 0)
9894
node.set_attr('pad_bottom', 0)
9995
node.set_attr('pad_left', 0)

hls4ml/converters/keras/convolution.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ def parse_conv1d_layer(keras_layer, input_names, input_shapes, data_reader):
3030
layer['n_filt'] = layer['n_chan'] * layer.get('depth_multiplier')
3131
layer['filt_width'] = keras_layer['config']['kernel_size'][0]
3232
layer['stride_width'] = keras_layer['config']['strides'][0]
33-
layer['padding'] = keras_layer['config']['padding']
3433

3534
(layer['out_width'], layer['pad_left'], layer['pad_right']) = compute_padding_1d(
36-
layer['padding'], layer['in_width'], layer['stride_width'], layer['filt_width']
35+
keras_layer['config']['padding'], layer['in_width'], layer['stride_width'], layer['filt_width']
3736
)
3837

3938
if layer['data_format'] == 'channels_last':
@@ -74,7 +73,6 @@ def parse_conv2d_layer(keras_layer, input_names, input_shapes, data_reader):
7473
layer['filt_width'] = keras_layer['config']['kernel_size'][1]
7574
layer['stride_height'] = keras_layer['config']['strides'][0]
7675
layer['stride_width'] = keras_layer['config']['strides'][1]
77-
layer['padding'] = keras_layer['config']['padding']
7876

7977
(
8078
layer['out_height'],
@@ -84,7 +82,7 @@ def parse_conv2d_layer(keras_layer, input_names, input_shapes, data_reader):
8482
layer['pad_left'],
8583
layer['pad_right'],
8684
) = compute_padding_2d(
87-
layer['padding'],
85+
keras_layer['config']['padding'],
8886
layer['in_height'],
8987
layer['in_width'],
9088
layer['stride_height'],

hls4ml/converters/keras/pooling.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ def parse_pooling_layer(keras_layer, input_names, input_shapes, data_reader):
1515

1616
layer['pool_width'] = keras_layer['config']['pool_size'][0]
1717
layer['stride_width'] = keras_layer['config']['strides'][0]
18-
layer['padding'] = keras_layer['config']['padding']
1918

2019
(layer['n_out'], layer['pad_left'], layer['pad_right']) = compute_padding_1d(
21-
layer['padding'], layer['n_in'], layer['stride_width'], layer['pool_width']
20+
keras_layer['config']['padding'], layer['n_in'], layer['stride_width'], layer['pool_width']
2221
)
2322

2423
if layer['data_format'] == 'channels_last':
@@ -32,7 +31,6 @@ def parse_pooling_layer(keras_layer, input_names, input_shapes, data_reader):
3231
layer['stride_width'] = keras_layer['config']['strides'][1]
3332
layer['pool_height'] = keras_layer['config']['pool_size'][0]
3433
layer['pool_width'] = keras_layer['config']['pool_size'][1]
35-
layer['padding'] = keras_layer['config']['padding']
3634

3735
(
3836
layer['out_height'],
@@ -42,7 +40,7 @@ def parse_pooling_layer(keras_layer, input_names, input_shapes, data_reader):
4240
layer['pad_left'],
4341
layer['pad_right'],
4442
) = compute_padding_2d(
45-
layer['padding'],
43+
keras_layer['config']['padding'],
4644
layer['in_height'],
4745
layer['in_width'],
4846
layer['stride_height'],

hls4ml/converters/pytorch/convolution.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,6 @@ def parse_conv1d_layer(operation, layer_name, input_names, input_shapes, node, c
3535
else:
3636
padding = class_object.padding
3737

38-
if padding == 0: # No padding, i.e., 'VALID' padding in Keras/Tensorflow
39-
layer['padding'] = 'valid'
40-
else: # Only 'valid' and 'same' padding are available in Keras
41-
layer['padding'] = 'same'
42-
4338
# Ouput info
4439
(layer['out_width'], pad_left, pad_right) = compute_padding_1d_pytorch(
4540
padding, layer['in_width'], layer['stride_width'], layer['filt_width'], layer['dilation']
@@ -84,11 +79,6 @@ def parse_conv2d_layer(operation, layer_name, input_names, input_shapes, node, c
8479
layer['pad_top'] = layer['pad_bottom'] = class_object.padding[0]
8580
layer['pad_left'] = layer['pad_right'] = class_object.padding[1]
8681

87-
if all(x == 0 for x in class_object.padding): # No padding, i.e., 'VALID' padding in Keras/Tensorflow
88-
layer['padding'] = 'valid'
89-
else: # Only 'valid' and 'same' padding are available in Keras
90-
layer['padding'] = 'same'
91-
9282
# Ouput info
9383
(layer['out_height'], layer['out_width'], _, _, _, _) = compute_padding_2d_pytorch(
9484
class_object.padding,

hls4ml/converters/pytorch/core.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,12 @@ def parse_activation_layer(operation, layer_name, input_names, input_shapes, nod
4343
layer = {}
4444

4545
layer['class_name'] = operation
46-
layer['activation'] = layer['class_name']
46+
layer['activation'] = layer['class_name'].lower()
4747
layer['name'] = layer_name
4848
layer['inputs'] = input_names
4949

50-
# if layer['class_name'] != 'Activation':
51-
# layer['activation'] = layer['class_name']
5250
if node.op == 'call_module':
53-
if layer['class_name'] == 'ReLU' or layer['class_name'] == 'Sigmoid':
51+
if layer['class_name'] in ['ReLU', 'Sigmoid', 'Tanh']:
5452
layer['class_name'] = 'Activation'
5553
if layer['class_name'] == 'LeakyReLU':
5654
layer['activ_param'] = class_object.negative_slope
@@ -68,7 +66,7 @@ def parse_activation_layer(operation, layer_name, input_names, input_shapes, nod
6866
if hasattr(node, 'dim'):
6967
layer['axis'] = class_object.dim
7068
else:
71-
if layer['class_name'] == 'ReLU' or layer['class_name'] == 'Sigmoid':
69+
if layer['class_name'] in ['ReLU', 'Sigmoid', 'Tanh']:
7270
layer['class_name'] = 'Activation'
7371
if layer['class_name'] == 'LeakyReLU':
7472
layer['activ_param'] = node.kwargs['negative_slope']

0 commit comments

Comments
 (0)