finn-plus-tests 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. finn_plus_tests-1.3.0/PKG-INFO +25 -0
  2. finn_plus_tests-1.3.0/__init__.py +0 -0
  3. finn_plus_tests-1.3.0/analysis/test_unsupported_layers.py +301 -0
  4. finn_plus_tests-1.3.0/brevitas/king_charles.jpg +0 -0
  5. finn_plus_tests-1.3.0/brevitas/test_brevitas_avg_pool_export.py +114 -0
  6. finn_plus_tests-1.3.0/brevitas/test_brevitas_cnv.py +82 -0
  7. finn_plus_tests-1.3.0/brevitas/test_brevitas_debug.py +98 -0
  8. finn_plus_tests-1.3.0/brevitas/test_brevitas_deconv.py +82 -0
  9. finn_plus_tests-1.3.0/brevitas/test_brevitas_fc.py +87 -0
  10. finn_plus_tests-1.3.0/brevitas/test_brevitas_mobilenet.py +130 -0
  11. finn_plus_tests-1.3.0/brevitas/test_brevitas_non_scaled_quanthardtanh_export.py +87 -0
  12. finn_plus_tests-1.3.0/brevitas/test_brevitas_qconv2d.py +108 -0
  13. finn_plus_tests-1.3.0/brevitas/test_brevitas_qlinear.py +83 -0
  14. finn_plus_tests-1.3.0/brevitas/test_brevitas_relu_act_export.py +105 -0
  15. finn_plus_tests-1.3.0/brevitas/test_brevitas_scaled_qhardtanh_export.py +123 -0
  16. finn_plus_tests-1.3.0/brevitas/test_brevitas_selu_act_export.py +73 -0
  17. finn_plus_tests-1.3.0/brevitas/test_brevitas_validate_mobilenet.py +214 -0
  18. finn_plus_tests-1.3.0/conftest.py +91 -0
  19. finn_plus_tests-1.3.0/end2end/test_end2end_bnn_pynq.py +834 -0
  20. finn_plus_tests-1.3.0/end2end/test_end2end_cybsec_mlp.py +193 -0
  21. finn_plus_tests-1.3.0/end2end/test_end2end_mobilenet_v1.py +523 -0
  22. finn_plus_tests-1.3.0/end2end/test_ext_weights.py +104 -0
  23. finn_plus_tests-1.3.0/example_data/build_dataflow/build.py +70 -0
  24. finn_plus_tests-1.3.0/example_data/build_dataflow/dataflow_build_config.json +28 -0
  25. finn_plus_tests-1.3.0/example_data/build_dataflow/expected_output.npy +0 -0
  26. finn_plus_tests-1.3.0/example_data/build_dataflow/folding_config.json +29 -0
  27. finn_plus_tests-1.3.0/example_data/build_dataflow/input.npy +0 -0
  28. finn_plus_tests-1.3.0/example_data/build_dataflow/model.onnx +0 -0
  29. finn_plus_tests-1.3.0/example_data/build_dataflow/specialize_layers_config.json +21 -0
  30. finn_plus_tests-1.3.0/example_data/cifar10/cifar10-test-data-class3.npz +0 -0
  31. finn_plus_tests-1.3.0/example_data/cybsec-mlp/state_dict.pth +0 -0
  32. finn_plus_tests-1.3.0/example_data/cybsec-mlp/validate-unsw-nb15.py +105 -0
  33. finn_plus_tests-1.3.0/example_data/test_ext_weights/specialize_layers_config.json +30 -0
  34. finn_plus_tests-1.3.0/example_data/test_ext_weights/tfc-w2a2-extw.json +38 -0
  35. finn_plus_tests-1.3.0/fpgadataflow/test_code_gen_trafo.py +98 -0
  36. finn_plus_tests-1.3.0/fpgadataflow/test_compilation_trafo.py +95 -0
  37. finn_plus_tests-1.3.0/fpgadataflow/test_convert_to_hw_1d_conv_layer.py +196 -0
  38. finn_plus_tests-1.3.0/fpgadataflow/test_convert_to_hw_channelwise_layer.py +143 -0
  39. finn_plus_tests-1.3.0/fpgadataflow/test_convert_to_hw_conv_fc_transition.py +226 -0
  40. finn_plus_tests-1.3.0/fpgadataflow/test_convert_to_hw_conv_layer.py +173 -0
  41. finn_plus_tests-1.3.0/fpgadataflow/test_convert_to_hw_layers_cnv.py +153 -0
  42. finn_plus_tests-1.3.0/fpgadataflow/test_convert_to_hw_layers_fc.py +208 -0
  43. finn_plus_tests-1.3.0/fpgadataflow/test_convert_to_hw_layers_synthetic.py +238 -0
  44. finn_plus_tests-1.3.0/fpgadataflow/test_convert_to_hw_pool_batch.py +244 -0
  45. finn_plus_tests-1.3.0/fpgadataflow/test_depthwise_convolution.py +242 -0
  46. finn_plus_tests-1.3.0/fpgadataflow/test_fifosizing.py +180 -0
  47. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_addstreams.py +148 -0
  48. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_attention.py +537 -0
  49. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_attention_heads.py +411 -0
  50. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_channelwise_ops.py +174 -0
  51. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_checksum.py +230 -0
  52. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_concat.py +176 -0
  53. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_convinputgenerator.py +227 -0
  54. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_convinputgenerator_rtl_dynamic.py +616 -0
  55. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_deconv.py +206 -0
  56. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_downsampler.py +162 -0
  57. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_duplicatestreams.py +159 -0
  58. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_dwc.py +174 -0
  59. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_elementwise_binary.py +329 -0
  60. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_eltwise.py +143 -0
  61. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_fifo.py +111 -0
  62. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_fmpadding.py +160 -0
  63. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_globalaccpool.py +146 -0
  64. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_ipstitch.py +329 -0
  65. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_labelselect.py +138 -0
  66. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_lookup.py +192 -0
  67. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_mvau.py +961 -0
  68. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_replicate_stream.py +222 -0
  69. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_res_estimate.py +145 -0
  70. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_split.py +154 -0
  71. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_thresholding.py +387 -0
  72. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_thresholding_runtime.py +356 -0
  73. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_upsampler.py +217 -0
  74. finn_plus_tests-1.3.0/fpgadataflow/test_fpgadataflow_vvau.py +474 -0
  75. finn_plus_tests-1.3.0/fpgadataflow/test_minimize_bit_width.py +304 -0
  76. finn_plus_tests-1.3.0/fpgadataflow/test_runtime_weights.py +141 -0
  77. finn_plus_tests-1.3.0/fpgadataflow/test_set_folding.py +136 -0
  78. finn_plus_tests-1.3.0/fpgadataflow/test_split_large_fifos.py +123 -0
  79. finn_plus_tests-1.3.0/fpgadataflow/test_squeeze.py +392 -0
  80. finn_plus_tests-1.3.0/fpgadataflow/test_unsqueeze.py +397 -0
  81. finn_plus_tests-1.3.0/infrastructure/custom_steps.py +2 -0
  82. finn_plus_tests-1.3.0/infrastructure/test_custom_step_resolution.py +32 -0
  83. finn_plus_tests-1.3.0/notebooks/test_jupyter_notebooks.py +108 -0
  84. finn_plus_tests-1.3.0/pyproject.toml +47 -0
  85. finn_plus_tests-1.3.0/test_enforce_import_order.py +43 -0
  86. finn_plus_tests-1.3.0/testing_util/__init__.py +34 -0
  87. finn_plus_tests-1.3.0/testing_util/imagenet.py +1146 -0
  88. finn_plus_tests-1.3.0/testing_util/pytorch.py +65 -0
  89. finn_plus_tests-1.3.0/testing_util/test.py +172 -0
  90. finn_plus_tests-1.3.0/transformation/streamline/test_absorb_mul_into_topk.py +108 -0
  91. finn_plus_tests-1.3.0/transformation/streamline/test_absorb_opposite_transposes.py +81 -0
  92. finn_plus_tests-1.3.0/transformation/streamline/test_absorb_transp_into_flatten.py +100 -0
  93. finn_plus_tests-1.3.0/transformation/streamline/test_collapse_repeated_op.py +132 -0
  94. finn_plus_tests-1.3.0/transformation/streamline/test_factor_out_mul_sign_magnitude.py +61 -0
  95. finn_plus_tests-1.3.0/transformation/streamline/test_maxpool_nhwc.py +97 -0
  96. finn_plus_tests-1.3.0/transformation/streamline/test_move_add_past_mul.py +150 -0
  97. finn_plus_tests-1.3.0/transformation/streamline/test_move_chw_add_past_conv.py +107 -0
  98. finn_plus_tests-1.3.0/transformation/streamline/test_move_flatten_past_affine.py +108 -0
  99. finn_plus_tests-1.3.0/transformation/streamline/test_move_flatten_past_topk.py +94 -0
  100. finn_plus_tests-1.3.0/transformation/streamline/test_move_identical_op_past_join_add.py +151 -0
  101. finn_plus_tests-1.3.0/transformation/streamline/test_move_identical_op_past_join_add_broadcast.py +255 -0
  102. finn_plus_tests-1.3.0/transformation/streamline/test_move_identical_op_past_join_concat.py +184 -0
  103. finn_plus_tests-1.3.0/transformation/streamline/test_move_identical_op_past_split.py +140 -0
  104. finn_plus_tests-1.3.0/transformation/streamline/test_move_maxpool_past_multithreshold.py +125 -0
  105. finn_plus_tests-1.3.0/transformation/streamline/test_move_mul_past_dw_conv.py +118 -0
  106. finn_plus_tests-1.3.0/transformation/streamline/test_move_mul_past_maxpool.py +116 -0
  107. finn_plus_tests-1.3.0/transformation/streamline/test_move_past_fork.py +133 -0
  108. finn_plus_tests-1.3.0/transformation/streamline/test_move_scalar_past_conv.py +196 -0
  109. finn_plus_tests-1.3.0/transformation/streamline/test_move_scalar_past_convtranspose.py +106 -0
  110. finn_plus_tests-1.3.0/transformation/streamline/test_move_scalar_past_matmul.py +190 -0
  111. finn_plus_tests-1.3.0/transformation/streamline/test_move_transpose_past_scalar_mul.py +113 -0
  112. finn_plus_tests-1.3.0/transformation/streamline/test_round_thresholds.py +270 -0
  113. finn_plus_tests-1.3.0/transformation/streamline/test_scale_resize_nhwc.py +376 -0
  114. finn_plus_tests-1.3.0/transformation/streamline/test_sign_to_thres.py +66 -0
  115. finn_plus_tests-1.3.0/transformation/streamline/test_streamline_cnv.py +103 -0
  116. finn_plus_tests-1.3.0/transformation/streamline/test_streamline_fc.py +98 -0
  117. finn_plus_tests-1.3.0/transformation/test_batchnorm_to_affine_bnn_pynq.py +96 -0
  118. finn_plus_tests-1.3.0/transformation/test_infer_data_layouts_cnv.py +124 -0
  119. finn_plus_tests-1.3.0/transformation/test_infer_datatypes_lfc.py +68 -0
  120. finn_plus_tests-1.3.0/transformation/test_qonnx_to_finn.py +145 -0
  121. finn_plus_tests-1.3.0/util/test_build_dataflow.py +81 -0
  122. finn_plus_tests-1.3.0/util/test_create.py +67 -0
  123. finn_plus_tests-1.3.0/util/test_data_packing.py +182 -0
  124. finn_plus_tests-1.3.0/util/test_hls_vector.py +117 -0
@@ -0,0 +1,25 @@
1
+ Metadata-Version: 2.4
2
+ Name: finn-plus-tests
3
+ Version: 1.3.0
4
+ Summary: Test suite for finn-plus
5
+ Maintainer: Felix Jentzsch
6
+ Maintainer-email: felix.jentzsch@upb.de
7
+ Requires-Python: >=3.10,<3.12
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Requires-Dist: pytest (>=8.4.1,<8.5.0)
12
+ Requires-Dist: pytest-cov (>=6.2.1,<6.3.0)
13
+ Requires-Dist: pytest-dependency (>=0.6.0,<0.7.0)
14
+ Requires-Dist: pytest-forked (>=1.6.0,<1.7.0)
15
+ Requires-Dist: pytest-html (>=4.1.1,<4.2.0)
16
+ Requires-Dist: pytest-html-merger (>=0.1.0,<0.2.0)
17
+ Requires-Dist: pytest-metadata (>=3.1.1,<3.2.0)
18
+ Requires-Dist: pytest-parallel (>=0.1.1,<0.2.0)
19
+ Requires-Dist: pytest-rerunfailures (>=15.1,<15.2)
20
+ Requires-Dist: pytest-xdist[setproctitle] (>=3.6.1,<3.7.0)
21
+ Requires-Dist: torch (>=2.7.1,<2.8.0)
22
+ Requires-Dist: torchvision (>=0.22.1,<0.23.0)
23
+ Requires-Dist: wget (>=3.2,<3.3)
24
+ Project-URL: EKI Project, https://www.eki-project.tech/
25
+ Project-URL: GitHub, https://github.com/eki-project/finn-plus
File without changes
@@ -0,0 +1,301 @@
1
+ import pytest
2
+
3
+ import random
4
+ import string
5
+ from onnx import TensorProto, helper
6
+ from qonnx.core.modelwrapper import ModelWrapper
7
+ from qonnx.util.basic import qonnx_make_model
8
+
9
+ from finn.analysis.fpgadataflow.unsupported_layers import unsupported_layers
10
+ from finn.builder.build_dataflow_steps import step_create_dataflow_partition
11
+ from finn.util.exception import FINNUserError
12
+
13
+
14
+ def get_random_name():
15
+ return "".join(random.choices(string.ascii_lowercase, k=10))
16
+
17
+
18
+ def create_tensor():
19
+ return helper.make_tensor_value_info(get_random_name(), TensorProto.FLOAT, None)
20
+
21
+
22
+ def create_node(inputs, outputs, fpga=False, name=None):
23
+ if fpga:
24
+ domain = "finn.custom_op.fpgadataflow"
25
+ else:
26
+ domain = "somethingelse"
27
+
28
+ return helper.make_node(
29
+ "CustomOp", [i.name for i in inputs], [o.name for o in outputs], domain=domain, name=name
30
+ )
31
+
32
+
33
+ @pytest.mark.analysis
34
+ def test_unsupported_layers_expected_fail():
35
+ inp1 = create_tensor()
36
+ inp2 = create_tensor()
37
+
38
+ n1n3 = create_tensor()
39
+ n2n3 = create_tensor()
40
+
41
+ n1 = create_node([inp1], [n1n3], fpga=False)
42
+ n2 = create_node([inp2], [n2n3], fpga=False)
43
+
44
+ n3n5 = create_tensor()
45
+ n3n4 = create_tensor()
46
+
47
+ n3 = create_node([n1n3, n2n3], [n3n4, n3n5], fpga=True)
48
+
49
+ n5n6 = create_tensor()
50
+ n4n6 = create_tensor()
51
+
52
+ n5 = create_node([n3n5], [n5n6], fpga=False)
53
+ n4 = create_node([n3n4], [n4n6], fpga=True)
54
+
55
+ n6n7 = create_tensor()
56
+
57
+ n6 = create_node([n5n6, n4n6], [n6n7], fpga=True)
58
+
59
+ out = create_tensor()
60
+
61
+ n7 = create_node([n6n7], [out], fpga=True)
62
+
63
+ mul_graph = helper.make_graph(
64
+ nodes=[n1, n2, n3, n4, n5, n6, n7],
65
+ name="g1",
66
+ inputs=[inp1, inp2],
67
+ outputs=[out],
68
+ value_info=[n1n3, n2n3, n3n4, n3n5, n5n6, n4n6, n6n7],
69
+ )
70
+
71
+ model = qonnx_make_model(mul_graph)
72
+ model = ModelWrapper(model)
73
+
74
+ ret = unsupported_layers(model)
75
+ assert ret[0] is False, "Model should not be supported, but was not detected as such"
76
+
77
+
78
+ @pytest.mark.analysis
79
+ def test_unsupported_layers():
80
+ inp1 = create_tensor()
81
+ inp2 = create_tensor()
82
+
83
+ n1n3 = create_tensor()
84
+ n2n3 = create_tensor()
85
+
86
+ n1 = create_node([inp1], [n1n3], fpga=False)
87
+ n2 = create_node([inp2], [n2n3], fpga=False)
88
+
89
+ n3n5 = create_tensor()
90
+ n3n4 = create_tensor()
91
+
92
+ n3 = create_node([n1n3, n2n3], [n3n4, n3n5], fpga=True)
93
+
94
+ n5n6 = create_tensor()
95
+ n4n6 = create_tensor()
96
+
97
+ n5 = create_node([n3n5], [n5n6], fpga=True)
98
+ n4 = create_node([n3n4], [n4n6], fpga=True)
99
+
100
+ n6n7 = create_tensor()
101
+
102
+ n6 = create_node([n5n6, n4n6], [n6n7], fpga=True)
103
+
104
+ out = create_tensor()
105
+
106
+ n7 = create_node([n6n7], [out], fpga=True)
107
+
108
+ mul_graph = helper.make_graph(
109
+ nodes=[n1, n2, n3, n4, n5, n6, n7],
110
+ name="g1",
111
+ inputs=[inp1, inp2],
112
+ outputs=[out],
113
+ value_info=[n1n3, n2n3, n3n4, n3n5, n5n6, n4n6, n6n7],
114
+ )
115
+
116
+ model = qonnx_make_model(mul_graph)
117
+ model = ModelWrapper(model)
118
+
119
+ ret = unsupported_layers(model)
120
+ assert ret[0] is True, "Model should be supported, but was not detected as such"
121
+
122
+
123
+ @pytest.mark.analysis
124
+ def test_unsupported_layers_loop():
125
+ inp1 = create_tensor()
126
+ inp2 = create_tensor()
127
+
128
+ n1n3 = create_tensor()
129
+ n2n3 = create_tensor()
130
+
131
+ n1 = create_node([inp1], [n1n3], fpga=False)
132
+ n2 = create_node([inp2], [n2n3], fpga=False)
133
+
134
+ n3n5 = create_tensor()
135
+ n3n4 = create_tensor()
136
+
137
+ n3 = create_node([n1n3, n2n3], [n3n4, n3n5], fpga=True)
138
+
139
+ n5n6 = create_tensor()
140
+ n4n6 = create_tensor()
141
+
142
+ n6n5 = create_tensor()
143
+
144
+ n5 = create_node([n3n5, n6n5], [n5n6], fpga=True)
145
+ n4 = create_node([n3n4], [n4n6], fpga=True)
146
+
147
+ n6n7 = create_tensor()
148
+
149
+ n6 = create_node([n5n6, n4n6], [n6n7, n6n5], fpga=True)
150
+
151
+ out = create_tensor()
152
+
153
+ n7 = create_node([n6n7], [out], fpga=True)
154
+
155
+ mul_graph = helper.make_graph(
156
+ nodes=[n1, n2, n3, n4, n5, n6, n7],
157
+ name="g1",
158
+ inputs=[inp1, inp2],
159
+ outputs=[out],
160
+ value_info=[n1n3, n2n3, n3n4, n3n5, n5n6, n4n6, n6n7],
161
+ )
162
+
163
+ model = qonnx_make_model(mul_graph)
164
+ model = ModelWrapper(model)
165
+
166
+ ret = unsupported_layers(model)
167
+ assert ret[0] is True, "Model should be supported, but was not detected as such"
168
+
169
+
170
+ @pytest.mark.analysis
171
+ def test_large_model():
172
+ inp1 = create_tensor()
173
+ inp2 = create_tensor()
174
+
175
+ n1n3 = create_tensor()
176
+ n2n4 = create_tensor()
177
+
178
+ n1 = create_node([inp1], [n1n3], fpga=False)
179
+ n2 = create_node([inp2], [n2n4], fpga=False)
180
+
181
+ n3n5 = create_tensor()
182
+ n4n5 = create_tensor()
183
+ n4n6 = create_tensor()
184
+
185
+ n3 = create_node([n1n3], [n3n5], fpga=True)
186
+ n4 = create_node([n2n4], [n4n5, n4n6], fpga=False)
187
+
188
+ out1 = create_tensor()
189
+
190
+ n6 = create_node([n4n6], [out1], fpga=False)
191
+
192
+ n5n7 = create_tensor()
193
+ n5n8 = create_tensor()
194
+
195
+ n5 = create_node([n3n5, n4n5], [n5n7, n5n8], fpga=True)
196
+
197
+ out2 = create_tensor()
198
+
199
+ n7 = create_node([n5n7], [out2], fpga=True)
200
+
201
+ n8n9 = create_tensor()
202
+
203
+ n8 = create_node([n5n8], [n8n9], fpga=True)
204
+
205
+ n9n10 = create_tensor()
206
+
207
+ n9 = create_node([n8n9], [n9n10], fpga=True, name="n9")
208
+
209
+ n10n11 = create_tensor()
210
+ n10n12 = create_tensor()
211
+
212
+ n10 = create_node([n9n10], [n10n11, n10n12], fpga=False, name="n10")
213
+
214
+ out3 = create_tensor()
215
+
216
+ n11 = create_node([n10n11], [out3], fpga=False, name="n11")
217
+
218
+ out4 = create_tensor()
219
+
220
+ n12 = create_node([n10n12], [out4], fpga=True, name="n12")
221
+
222
+ mul_graph = helper.make_graph(
223
+ nodes=[n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12],
224
+ name="g2",
225
+ inputs=[inp1, inp2],
226
+ outputs=[out1, out2, out3, out4],
227
+ value_info=[n1n3, n2n4, n3n5, n4n5, n4n6, n5n7, n5n8, n8n9, n9n10, n10n11, n10n12],
228
+ )
229
+
230
+ model = qonnx_make_model(mul_graph)
231
+ model = ModelWrapper(model)
232
+
233
+ ret = unsupported_layers(model)
234
+ assert ret[0] is False, "Model should not be supported, but was not detected as such"
235
+
236
+
237
+ @pytest.mark.analysis
238
+ def test_large_model_step():
239
+ inp1 = create_tensor()
240
+ inp2 = create_tensor()
241
+
242
+ n1n3 = create_tensor()
243
+ n2n4 = create_tensor()
244
+
245
+ n1 = create_node([inp1], [n1n3], fpga=False)
246
+ n2 = create_node([inp2], [n2n4], fpga=False)
247
+
248
+ n3n5 = create_tensor()
249
+ n4n5 = create_tensor()
250
+ n4n6 = create_tensor()
251
+
252
+ n3 = create_node([n1n3], [n3n5], fpga=True)
253
+ n4 = create_node([n2n4], [n4n5, n4n6], fpga=False)
254
+
255
+ out1 = create_tensor()
256
+
257
+ n6 = create_node([n4n6], [out1], fpga=False)
258
+
259
+ n5n7 = create_tensor()
260
+ n5n8 = create_tensor()
261
+
262
+ n5 = create_node([n3n5, n4n5], [n5n7, n5n8], fpga=True)
263
+
264
+ out2 = create_tensor()
265
+
266
+ n7 = create_node([n5n7], [out2], fpga=True)
267
+
268
+ n8n9 = create_tensor()
269
+
270
+ n8 = create_node([n5n8], [n8n9], fpga=True)
271
+
272
+ n9n10 = create_tensor()
273
+
274
+ n9 = create_node([n8n9], [n9n10], fpga=True, name="n9")
275
+
276
+ n10n11 = create_tensor()
277
+ n10n12 = create_tensor()
278
+
279
+ n10 = create_node([n9n10], [n10n11, n10n12], fpga=False, name="n10")
280
+
281
+ out3 = create_tensor()
282
+
283
+ n11 = create_node([n10n11], [out3], fpga=False, name="n11")
284
+
285
+ out4 = create_tensor()
286
+
287
+ n12 = create_node([n10n12], [out4], fpga=True, name="n12")
288
+
289
+ mul_graph = helper.make_graph(
290
+ nodes=[n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12],
291
+ name="g2",
292
+ inputs=[inp1, inp2],
293
+ outputs=[out1, out2, out3, out4],
294
+ value_info=[n1n3, n2n4, n3n5, n4n5, n4n6, n5n7, n5n8, n8n9, n9n10, n10n11, n10n12],
295
+ )
296
+
297
+ model = qonnx_make_model(mul_graph)
298
+ model = ModelWrapper(model)
299
+
300
+ with pytest.raises(FINNUserError):
301
+ step_create_dataflow_partition(model, None)
@@ -0,0 +1,114 @@
1
+ # Copyright (c) 2020, Xilinx
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of FINN nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ import pytest
29
+
30
+ import numpy as np
31
+ import os
32
+ import torch
33
+ from brevitas.export import export_qonnx
34
+ from brevitas.nn import QuantIdentity, QuantReLU, TruncAvgPool2d
35
+ from qonnx.core.datatype import DataType
36
+ from qonnx.core.modelwrapper import ModelWrapper
37
+ from qonnx.transformation.infer_datatypes import InferDataTypes
38
+ from qonnx.transformation.infer_shapes import InferShapes
39
+ from qonnx.util.basic import gen_finn_dt_tensor
40
+ from qonnx.util.cleanup import cleanup as qonnx_cleanup
41
+
42
+ import finn.core.onnx_exec as oxe
43
+ from finn.transformation.qonnx.convert_qonnx_to_finn import ConvertQONNXtoFINN
44
+ from finn.util.basic import make_build_dir
45
+
46
+
47
+ @pytest.mark.brevitas_export
48
+ @pytest.mark.parametrize("kernel_size", [2, 3])
49
+ @pytest.mark.parametrize("stride", [1, 2])
50
+ @pytest.mark.parametrize("signed", [True]) # TODO: Add unsigned test case
51
+ @pytest.mark.parametrize("bit_width", [2, 4])
52
+ @pytest.mark.parametrize("input_bit_width", [4, 8, 16])
53
+ @pytest.mark.parametrize("channels", [2, 4])
54
+ @pytest.mark.parametrize("idim", [7, 8])
55
+ def test_brevitas_avg_pool_export(
56
+ kernel_size,
57
+ stride,
58
+ signed,
59
+ bit_width,
60
+ input_bit_width,
61
+ channels,
62
+ idim,
63
+ ):
64
+ build_dir = make_build_dir(prefix="test_brevitas_avg_pool_export")
65
+ export_onnx_path = os.path.join(build_dir, "test.onnx")
66
+ if signed:
67
+ quant_node = QuantIdentity(
68
+ bit_width=input_bit_width,
69
+ return_quant_tensor=True,
70
+ )
71
+ else:
72
+ quant_node = QuantReLU(
73
+ bit_width=input_bit_width,
74
+ return_quant_tensor=True,
75
+ )
76
+ quant_avgpool = TruncAvgPool2d(
77
+ kernel_size=kernel_size,
78
+ stride=stride,
79
+ bit_width=bit_width,
80
+ return_quant_tensor=False,
81
+ float_to_int_impl_type="FLOOR",
82
+ )
83
+ model_brevitas = torch.nn.Sequential(quant_node, quant_avgpool)
84
+ model_brevitas.eval()
85
+
86
+ # determine input
87
+ input_shape = (1, channels, idim, idim)
88
+ input_array = gen_finn_dt_tensor(DataType["FLOAT32"], input_shape)
89
+
90
+ input_tensor = torch.from_numpy(input_array).float()
91
+
92
+ # export
93
+ export_qonnx(
94
+ model_brevitas,
95
+ export_path=export_onnx_path,
96
+ input_t=input_tensor,
97
+ )
98
+ model = ModelWrapper(export_onnx_path)
99
+ model.save(export_onnx_path)
100
+
101
+ qonnx_cleanup(export_onnx_path, out_file=export_onnx_path)
102
+ model = ModelWrapper(export_onnx_path)
103
+ model = model.transform(ConvertQONNXtoFINN())
104
+ model = model.transform(InferShapes())
105
+ model = model.transform(InferDataTypes())
106
+
107
+ # reference brevitas output
108
+ ref_output_array = model_brevitas(input_tensor).detach().numpy()
109
+ # finn output
110
+ idict = {model.graph.input[0].name: input_array}
111
+ odict = oxe.execute_onnx(model, idict, True)
112
+ finn_output = odict[model.graph.output[0].name]
113
+ # compare outputs
114
+ assert np.isclose(ref_output_array, finn_output).all()
@@ -0,0 +1,82 @@
1
+ # Copyright (c) 2020, Xilinx
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of FINN nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ import pytest
30
+
31
+ import numpy as np
32
+ import os
33
+ import torch
34
+ from brevitas.export import export_qonnx
35
+ from pathlib import Path
36
+ from qonnx.core.modelwrapper import ModelWrapper
37
+ from qonnx.transformation.fold_constants import FoldConstants
38
+ from qonnx.transformation.general import GiveUniqueNodeNames, RemoveStaticGraphInputs
39
+ from qonnx.transformation.infer_shapes import InferShapes
40
+ from qonnx.util.cleanup import cleanup as qonnx_cleanup
41
+
42
+ import finn.core.onnx_exec as oxe
43
+ from finn.transformation.qonnx.convert_qonnx_to_finn import ConvertQONNXtoFINN
44
+ from finn.util.basic import make_build_dir
45
+ from tests.testing_util.test import get_test_model_trained
46
+
47
+
48
+ @pytest.mark.brevitas_export
49
+ @pytest.mark.parametrize("abits", [1, 2])
50
+ @pytest.mark.parametrize("wbits", [1, 2])
51
+ def test_brevitas_cnv_export_exec(wbits, abits):
52
+ if wbits > abits:
53
+ pytest.skip("No wbits > abits cases at the moment")
54
+ build_dir = make_build_dir("test_brevitas_cnv_export_exec")
55
+ export_onnx_path = os.path.join(build_dir, "test_brevitas_cnv.onnx")
56
+ cnv = get_test_model_trained("CNV", wbits, abits)
57
+ ishape = (1, 3, 32, 32)
58
+ export_qonnx(cnv, torch.randn(ishape), export_onnx_path)
59
+ qonnx_cleanup(export_onnx_path, out_file=export_onnx_path)
60
+ model = ModelWrapper(export_onnx_path)
61
+ model = model.transform(ConvertQONNXtoFINN())
62
+ model = model.transform(GiveUniqueNodeNames())
63
+ model = model.transform(InferShapes())
64
+ model = model.transform(FoldConstants())
65
+ model = model.transform(RemoveStaticGraphInputs())
66
+ assert len(model.graph.input) == 1
67
+ assert len(model.graph.output) == 1
68
+ cifar_path = (
69
+ Path(__file__).parent.parent / "example_data" / "cifar10" / "cifar10-test-data-class3.npz"
70
+ )
71
+ input_tensor = np.load(cifar_path)["arr_0"].astype(np.float32)
72
+ input_tensor = input_tensor / 255
73
+ assert input_tensor.shape == (1, 3, 32, 32)
74
+ # run using FINN-based execution
75
+ input_dict = {model.graph.input[0].name: input_tensor}
76
+ output_dict = oxe.execute_onnx(model, input_dict, True)
77
+ produced = output_dict[model.graph.output[0].name]
78
+ # do forward pass in PyTorch/Brevitas
79
+ input_tensor = torch.from_numpy(input_tensor).float()
80
+ expected = cnv.forward(input_tensor).detach().numpy()
81
+ assert np.isclose(produced, expected, atol=1e-3).all()
82
+ assert np.argmax(produced) == 3
@@ -0,0 +1,98 @@
1
+ # Copyright (c) 2020, Xilinx
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of FINN nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ import pytest
30
+
31
+ import brevitas.onnx as bo
32
+ import numpy as np
33
+ import onnx
34
+ import onnx.numpy_helper as nph
35
+ import os
36
+ import torch
37
+ from brevitas.export import export_qonnx
38
+ from brevitas.quant_tensor import _unpack_quant_tensor
39
+ from pkgutil import get_data
40
+ from qonnx.core.modelwrapper import ModelWrapper
41
+ from qonnx.util.cleanup import cleanup as qonnx_cleanup
42
+
43
+ import finn.core.onnx_exec as oxe
44
+ from finn.transformation.qonnx.convert_qonnx_to_finn import ConvertQONNXtoFINN
45
+ from finn.util.basic import make_build_dir
46
+ from tests.testing_util.test import get_test_model_trained
47
+
48
+
49
+ @pytest.mark.brevitas_export
50
+ @pytest.mark.parametrize("QONNX_FINN_conversion", [False, True])
51
+ def test_brevitas_debug(QONNX_FINN_conversion):
52
+ build_dir = make_build_dir("test_brevitas_debug")
53
+ finn_onnx = os.path.join(build_dir, "test_brevitas_debug.onnx")
54
+ fc = get_test_model_trained("TFC", 2, 2)
55
+ ishape = (1, 1, 28, 28)
56
+ dbg_hook = bo.enable_debug(fc, proxy_level=True)
57
+ export_qonnx(fc, torch.randn(ishape), finn_onnx)
58
+ # DebugMarkers have the brevitas.onnx domain, so that needs adjusting
59
+ model = ModelWrapper(finn_onnx)
60
+ dbg_nodes = model.get_nodes_by_op_type("DebugMarker")
61
+ for dbg_node in dbg_nodes:
62
+ dbg_node.domain = "qonnx.custom_op.general"
63
+ model.save(finn_onnx)
64
+ qonnx_cleanup(finn_onnx, out_file=finn_onnx)
65
+ if QONNX_FINN_conversion:
66
+ model = ModelWrapper(finn_onnx)
67
+ model = model.transform(ConvertQONNXtoFINN())
68
+ model.save(finn_onnx)
69
+ model = ModelWrapper(finn_onnx)
70
+ assert len(model.graph.input) == 1
71
+ assert len(model.graph.output) == 1
72
+ # load one of the test vectors
73
+ raw_i = get_data("qonnx.data", "onnx/mnist-conv/test_data_set_0/input_0.pb")
74
+ input_tensor = onnx.load_tensor_from_string(raw_i)
75
+ # run using FINN-based execution
76
+ input_dict = {model.graph.input[0].name: nph.to_array(input_tensor)}
77
+ output_dict = oxe.execute_onnx(model, input_dict, return_full_exec_context=True)
78
+ produced = output_dict[model.graph.output[0].name]
79
+ # run using PyTorch/Brevitas
80
+ input_tensor = torch.from_numpy(nph.to_array(input_tensor)).float()
81
+ assert input_tensor.shape == (1, 1, 28, 28)
82
+ # do forward pass in PyTorch/Brevitas
83
+ expected = fc.forward(input_tensor).detach().numpy()
84
+ assert np.isclose(produced, expected, atol=1e-3).all()
85
+ # check all tensors at debug markers
86
+ names_brevitas = set(dbg_hook.values.keys())
87
+ names_finn = set(output_dict.keys())
88
+ names_common = names_brevitas.intersection(names_finn)
89
+ # The different exports return debug markers in different numbers and places
90
+ print(len(names_common))
91
+ if not QONNX_FINN_conversion:
92
+ assert len(names_common) == 12
93
+ else:
94
+ assert len(names_common) == 8
95
+ for dbg_name in names_common:
96
+ tensor_pytorch = _unpack_quant_tensor(dbg_hook.values[dbg_name]).detach().numpy()
97
+ tensor_finn = output_dict[dbg_name]
98
+ assert np.isclose(tensor_finn, tensor_pytorch, atol=1e-5).all()