Skip to content

Commit bf6fe7a

Browse files
committed
cosmatic
1 parent d1a3b75 commit bf6fe7a

File tree

5 files changed

+31
-21
lines changed

5 files changed

+31
-21
lines changed

hls4ml/backends/fpga/passes/clone.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import numpy as np
1+
from math import prod
22

33
from hls4ml.backends.template import FunctionCallTemplate
44
from hls4ml.model.layers import Layer, register_layer
@@ -80,11 +80,12 @@ def transform(self, model, node):
8080
if n_outputs == 1:
8181
continue
8282
if n_outputs > 3:
83-
msg = f'ERROR: Cloning output {output} of {node.__class__.__name__} ({node.name}) more than 3 times not currently supported' # noqa: E501
83+
msg = f'ERROR: Cloning output {output} of {node.class_name}\
84+
({node.name}) more than 3 times not currently supported'
8485
raise ValueError(msg)
8586

8687
out_var = node.get_output_variable(output)
87-
attrs = {'size': np.prod(out_var.shape)}
88+
attrs = {'size': prod(out_var.shape)}
8889

8990
init_stream_idx = 1
9091
if in_output:

hls4ml/backends/fpga/passes/inplace_parallel_reshape.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class InplaceParallelReshape(OptimizerPass):
1212

1313
def match(self, node):
1414
if not isinstance(node, Reshape):
15-
return
15+
return False
1616
return node.model.config.get_config_value('IOType') == 'io_parallel'
1717

1818
def transform(self, model, node):
@@ -24,6 +24,8 @@ def transform(self, model, node):
2424
prev_node = node.get_input_node()
2525
assert (
2626
prev_node.name not in model.outputs
27-
), f"Cannot output node {prev_node.name}: reshape is a no-op in io_parallel. As a result, the previous node {prev_node.name}'s output will be used as the output. However, this node is already an output." # noqa: E501
27+
), f"Cannot output node {prev_node.name}: reshape is a no-op in io_parallel.\
28+
As a result, the previous node {prev_node.name}'s output will be used as the\
29+
output. However, this node is already an output."
2830
model.outputs = [name if name != node.name else prev_node.name for name in model.outputs]
2931
return False

hls4ml/backends/fpga/passes/inplace_stream_flatten.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ def match(self, node):
1515
if not (isinstance(node, Reshape) and len(node.get_output_variable().shape)) == 1:
1616
# Reshape with multiple outputs will be kept as is, or repack cannot handle different shapes
1717
return False
18-
io_type = node.model.config.get_config_value('IOType')
19-
return io_type == 'io_stream'
18+
return node.model.config.get_config_value('IOType') == 'io_stream'
2019

2120
def transform(self, model, node):
2221
outvar = node.get_output_variable()

hls4ml/model/graph.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -524,14 +524,16 @@ def remove_node(self, node, rewire=True):
524524
node to the input of next one. If the removed node has multiple
525525
inputs/outputs tensors, an exception is raised.
526526
527-
Args:
528-
node (Layer): The node to remove rewire (bool, optional):
529-
Deprecated, no effect
527+
:param node: The node to remove.
528+
:type node: Layer
529+
:param rewire: Deprecated, no effect.
530+
:type rewire: bool, optional
530531
531-
Raises:
532-
Exception: If an attempt is made to rewire a node with
533-
multiple inputs/outputs.
534-
"""
532+
:raises Exception: If an attempt is made to rewire a node with
533+
multiple inputs/outputs.
534+
535+
.. deprecated:: 1.0
536+
The `rewire` parameter is deprecated and has no effect."""
535537

536538
inputs = [inp for inp in node.inputs if inp]
537539
outputs = [outp for outp in node.outputs if outp]

test/pytest/test_multiout_network.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def model():
2020

2121

2222
@pytest.fixture(scope='module')
23-
def model2():
23+
def model_corner_cases():
2424
in1 = keras.layers.Input(shape=(24, 8))
2525
in2 = keras.layers.Input(shape=(16))
2626
out1 = keras.layers.Conv1D(1, 3)(in1)
@@ -40,7 +40,7 @@ def data():
4040

4141

4242
@pytest.fixture(scope='module')
43-
def data2():
43+
def data_corner_cases():
4444
X1 = np.random.normal(0, 1, (1000, 24, 8))
4545
X2 = np.random.normal(0, 1, (1000, 16))
4646
X1 = np.clip(X1, -16, 15)
@@ -70,18 +70,24 @@ def test_multi_output_nn(model, data, backend: str, io_type: str):
7070
@pytest.mark.parametrize('backend', ['Vivado', 'Quartus', 'Vitis', 'Catapult', 'OneAPI'])
7171
@pytest.mark.parametrize('io_type', ['io_parallel', 'io_stream'])
7272
@pytest.mark.parametrize('strategy', ['latency', 'resource'])
73-
def test_multi_output_nn_2(model2, data2, backend: str, io_type: str, strategy: str):
74-
"""Cover corner case where a flatten layer is cloned multiple times, and used as model output"""
73+
def test_multi_output_nn_corner_cases(model_corner_cases, data_corner_cases, backend: str, io_type: str, strategy: str):
74+
"""Cover corner cases, when:
75+
- a layer outputs both to the next layer(s) and to the model output
76+
- when an node removal/insertion is triggered internally
77+
- a reshape in io_parallel, or flatten in io_stream layer's output is used multiple times
78+
- and as layer output
79+
- and by layer taking multiple inputs
80+
"""
7581
output_dir = str(test_root_path / f'hls4mlprj_multiout_network_2_{backend}_{io_type}_{strategy}')
7682
hls_config = {'Model': {'Precision': 'fixed<32,5>', 'ReuseFactor': 1}, 'Strategy': strategy}
7783

7884
model_hls = convert_from_keras_model(
79-
model2, backend=backend, output_dir=output_dir, hls_config=hls_config, io_type=io_type
85+
model_corner_cases, backend=backend, output_dir=output_dir, hls_config=hls_config, io_type=io_type
8086
)
8187

8288
model_hls.compile()
83-
r_hls = model_hls.predict(data2)
84-
r_keras = model2.predict(data2, verbose=0, batch_size=1000)
89+
r_hls = model_hls.predict(data_corner_cases)
90+
r_keras = model_corner_cases.predict(data_corner_cases, verbose=0, batch_size=1000)
8591

8692
assert np.allclose(r_hls[0], r_keras[0], atol=1e-5, rtol=0)
8793
assert np.allclose(r_hls[1], r_keras[1], atol=1e-5, rtol=0)

0 commit comments

Comments
 (0)