|
3 | 3 | # This source code is licensed under the BSD-style license found in the |
4 | 4 | # LICENSE file in the root directory of this source tree. |
5 | 5 |
|
6 | | -import torch |
7 | | - |
8 | | -from executorch.backends.nxp.backend.edge_program_converter import ( |
9 | | - EdgeProgramToIRConverter, |
10 | | -) |
11 | | -from executorch.backends.nxp.backend.ir.lib.tflite.BuiltinOptions import BuiltinOptions |
12 | | -from executorch.backends.nxp.backend.ir.lib.tflite.Model import Model |
13 | | -from executorch.backends.nxp.backend.neutron_target_spec import NeutronTargetSpec |
14 | | -from executorch.backends.nxp.nxp_backend import PayloadComposer |
15 | 6 | from executorch.backends.nxp.tests.executorch_pipeline import to_quantized_edge_program |
16 | | -from executorch.backends.nxp.tests.executors import graph_contains_any_of_ops |
17 | 7 | from executorch.backends.nxp.tests.models import Conv2dModule, LinearSoftmaxModule |
18 | 8 |
|
19 | 9 |
|
@@ -65,217 +55,3 @@ def test_neutron_backend__linear_softmax_model__payload_header_formatless(): |
65 | 55 | assert payload[6] == 0x0 # Map 0-th Neutron output to 0-th model output |
66 | 56 | assert all(byte == 0x0 for byte in payload[7:16]) # Aligned to 16 bytes |
67 | 57 | assert payload[17] != 0x0 # Followed by non-zero content |
68 | | - |
69 | | - |
70 | | -def test_delegating_format_related_transpose_operators__unsupported_shapes(mocker): |
71 | | - # This test focuses on the case when Neutron would not support the inserted Transpose operators, so they are not |
72 | | - # inserted, so the runtime will permute the data. |
73 | | - |
74 | | - # Make sure none of the dimensions are multiples of `num_macs` (8), for proper testing. |
75 | | - model = Conv2dModule(in_channels=3, out_channels=3, padding=1, stride=1) |
76 | | - input_shape = (1, 3, 3, 3) |
77 | | - |
78 | | - converter_spy = mocker.spy(EdgeProgramToIRConverter, "convert_program") |
79 | | - payload_header_spy = mocker.spy(PayloadComposer, "_create_payload_header") |
80 | | - edge_program = to_quantized_edge_program( |
81 | | - model, |
82 | | - input_shape, |
83 | | - use_neutron_for_format_conversion=True, # Make sure the IR converter inserts the extra `Transpose` operators. |
84 | | - ).exported_program() |
85 | | - |
86 | | - # Make sure the edge_program only contains the 1 delegate call. |
87 | | - nodes = list(edge_program.graph.nodes) |
88 | | - assert len(nodes) == 7 |
89 | | - assert "call_delegate" in nodes[3].name |
90 | | - assert not graph_contains_any_of_ops( |
91 | | - edge_program.graph, [torch.ops.aten.convolution.default] |
92 | | - ) |
93 | | - assert not graph_contains_any_of_ops( |
94 | | - edge_program.graph, [torch.ops.aten.permute_copy.default] |
95 | | - ) |
96 | | - |
97 | | - # Capture the converted IR model. |
98 | | - tflite_flatbuffers_model, _ = converter_spy.spy_return |
99 | | - |
100 | | - # Make sure the `Transpose` ops are NOT in the IR model. |
101 | | - tflite_subgraph = Model.GetRootAs(tflite_flatbuffers_model).Subgraphs(0) |
102 | | - assert tflite_subgraph.OperatorsLength() == 2 |
103 | | - assert ( |
104 | | - tflite_subgraph.Operators(0).BuiltinOptionsType() == BuiltinOptions.PadV2Options |
105 | | - ) |
106 | | - assert ( |
107 | | - tflite_subgraph.Operators(1).BuiltinOptionsType() |
108 | | - == BuiltinOptions.Conv2DOptions |
109 | | - ) |
110 | | - |
111 | | - # Get the header of the payload for the delegated partition. |
112 | | - payload_header = payload_header_spy.spy_return |
113 | | - assert payload_header.size == 7 |
114 | | - # the 4th and 5th bytes indicate the format. `1` means `channels_last`, which means the runtime will transpose the data. |
115 | | - assert all(payload_header[3:5] == [1, 1]) # [<input_byte>, <output_byte>] |
116 | | - |
117 | | - |
118 | | -def test_delegating_format_related_transpose_operators__supported_case(mocker): |
119 | | - # Make sure the output channels (channels for the trailing Transpose), and the last input dimension (channels for |
120 | | - # the leading Transpose) are multiples of `num_macs``. |
121 | | - |
122 | | - num_macs = NeutronTargetSpec("imxrt700", "SDK_25_09").get_num_macs() |
123 | | - model = Conv2dModule( |
124 | | - in_channels=num_macs, out_channels=num_macs, padding=1, stride=1 |
125 | | - ) |
126 | | - input_shape = (1, num_macs, num_macs, num_macs) |
127 | | - |
128 | | - converter_spy = mocker.spy(EdgeProgramToIRConverter, "convert_program") |
129 | | - payload_header_spy = mocker.spy(PayloadComposer, "_create_payload_header") |
130 | | - edge_program = to_quantized_edge_program( |
131 | | - model, |
132 | | - input_shape, |
133 | | - use_neutron_for_format_conversion=True, # Make sure the IR converter inserts the extra `Transpose` operators. |
134 | | - ).exported_program() |
135 | | - |
136 | | - # Make sure the edge_program only contains the 1 delegate call. |
137 | | - nodes = list(edge_program.graph.nodes) |
138 | | - assert len(nodes) == 7 |
139 | | - assert "call_delegate" in nodes[3].name |
140 | | - assert not graph_contains_any_of_ops( |
141 | | - edge_program.graph, [torch.ops.aten.convolution.default] |
142 | | - ) |
143 | | - assert not graph_contains_any_of_ops( |
144 | | - edge_program.graph, [torch.ops.aten.permute_copy.default] |
145 | | - ) |
146 | | - |
147 | | - # Capture the converted IR model. |
148 | | - tflite_flatbuffers_model, _ = converter_spy.spy_return |
149 | | - |
150 | | - # Make sure the `Transpose` ops ARE in the IR model. |
151 | | - tflite_subgraph = Model.GetRootAs(tflite_flatbuffers_model).Subgraphs(0) |
152 | | - assert tflite_subgraph.OperatorsLength() == 4 |
153 | | - assert ( |
154 | | - tflite_subgraph.Operators(0).BuiltinOptionsType() |
155 | | - == BuiltinOptions.TransposeOptions |
156 | | - ) |
157 | | - assert ( |
158 | | - tflite_subgraph.Operators(1).BuiltinOptionsType() == BuiltinOptions.PadV2Options |
159 | | - ) |
160 | | - assert ( |
161 | | - tflite_subgraph.Operators(2).BuiltinOptionsType() |
162 | | - == BuiltinOptions.Conv2DOptions |
163 | | - ) |
164 | | - assert ( |
165 | | - tflite_subgraph.Operators(3).BuiltinOptionsType() |
166 | | - == BuiltinOptions.TransposeOptions |
167 | | - ) |
168 | | - |
169 | | - # Get the header of the payload for the delegated partition. |
170 | | - payload_header = payload_header_spy.spy_return |
171 | | - assert payload_header.size == 7 |
172 | | - # the 4th and 5th bytes indicate the format. `0` means `channels_last`, which means the runtime will NOT transpose the data. |
173 | | - assert all(payload_header[3:5] == [0, 0]) # [<input_byte>, <output_byte>] |
174 | | - |
175 | | - |
176 | | -def test_delegating_format_related_transpose_operators__supported_output__unsupported_input( |
177 | | - mocker, |
178 | | -): |
179 | | - num_macs = NeutronTargetSpec("imxrt700", "SDK_25_09").get_num_macs() |
180 | | - model = Conv2dModule( |
181 | | - in_channels=num_macs, |
182 | | - out_channels=num_macs, # The output `Transpose` will be supported. |
183 | | - padding=1, |
184 | | - stride=1, |
185 | | - ) |
186 | | - input_shape = (1, num_macs, num_macs, 3) # The input `Transpose` is not supported. |
187 | | - |
188 | | - converter_spy = mocker.spy(EdgeProgramToIRConverter, "convert_program") |
189 | | - payload_header_spy = mocker.spy(PayloadComposer, "_create_payload_header") |
190 | | - edge_program = to_quantized_edge_program( |
191 | | - model, |
192 | | - input_shape, |
193 | | - use_neutron_for_format_conversion=True, # Make sure the IR converter inserts the extra `Transpose` operators. |
194 | | - ).exported_program() |
195 | | - |
196 | | - # Make sure the edge_program only contains the 1 delegate call. |
197 | | - nodes = list(edge_program.graph.nodes) |
198 | | - assert len(nodes) == 7 |
199 | | - assert "call_delegate" in nodes[3].name |
200 | | - assert not graph_contains_any_of_ops( |
201 | | - edge_program.graph, [torch.ops.aten.convolution.default] |
202 | | - ) |
203 | | - assert not graph_contains_any_of_ops( |
204 | | - edge_program.graph, [torch.ops.aten.permute_copy.default] |
205 | | - ) |
206 | | - |
207 | | - # Capture the converted IR model. |
208 | | - tflite_flatbuffers_model, _ = converter_spy.spy_return |
209 | | - |
210 | | - # Make sure there is just the 1 `Transpose` in the model. |
211 | | - tflite_subgraph = Model.GetRootAs(tflite_flatbuffers_model).Subgraphs(0) |
212 | | - assert tflite_subgraph.OperatorsLength() == 3 |
213 | | - assert ( |
214 | | - tflite_subgraph.Operators(0).BuiltinOptionsType() == BuiltinOptions.PadV2Options |
215 | | - ) |
216 | | - assert ( |
217 | | - tflite_subgraph.Operators(1).BuiltinOptionsType() |
218 | | - == BuiltinOptions.Conv2DOptions |
219 | | - ) |
220 | | - assert ( |
221 | | - tflite_subgraph.Operators(2).BuiltinOptionsType() |
222 | | - == BuiltinOptions.TransposeOptions |
223 | | - ) |
224 | | - |
225 | | - # Get the header of the payload for the delegated partition. |
226 | | - payload_header = payload_header_spy.spy_return |
227 | | - assert payload_header.size == 7 |
228 | | - # the 4th and 5th bytes indicate the format. `1` means `channels_last`, which means the runtime will transpose the data. |
229 | | - assert all(payload_header[3:5] == [1, 0]) # [<input_byte>, <output_byte>] |
230 | | - |
231 | | - |
232 | | -def test_delegating_format_related_transpose_operators__supported_input__unsupported_output( |
233 | | - mocker, |
234 | | -): |
235 | | - num_macs = NeutronTargetSpec("imxrt700", "SDK_25_09").get_num_macs() |
236 | | - model = Conv2dModule( |
237 | | - in_channels=num_macs, |
238 | | - out_channels=3, # The output `Transpose` will NOT be supported. |
239 | | - stride=1, |
240 | | - ) |
241 | | - input_shape = (1, num_macs, 3, num_macs) # The input `Transpose` is supported. |
242 | | - |
243 | | - converter_spy = mocker.spy(EdgeProgramToIRConverter, "convert_program") |
244 | | - payload_header_spy = mocker.spy(PayloadComposer, "_create_payload_header") |
245 | | - edge_program = to_quantized_edge_program( |
246 | | - model, |
247 | | - input_shape, |
248 | | - use_neutron_for_format_conversion=True, # Make sure the IR converter inserts the extra `Transpose` operators. |
249 | | - ).exported_program() |
250 | | - |
251 | | - # Make sure the edge_program only contains the 1 delegate call. |
252 | | - nodes = list(edge_program.graph.nodes) |
253 | | - assert len(nodes) == 7 |
254 | | - assert "call_delegate" in nodes[3].name |
255 | | - assert not graph_contains_any_of_ops( |
256 | | - edge_program.graph, [torch.ops.aten.convolution.default] |
257 | | - ) |
258 | | - assert not graph_contains_any_of_ops( |
259 | | - edge_program.graph, [torch.ops.aten.permute_copy.default] |
260 | | - ) |
261 | | - |
262 | | - # Capture the converted IR model. |
263 | | - tflite_flatbuffers_model, _ = converter_spy.spy_return |
264 | | - |
265 | | - # Make sure there is just the 1 `Transpose` in the model. |
266 | | - tflite_subgraph = Model.GetRootAs(tflite_flatbuffers_model).Subgraphs(0) |
267 | | - assert tflite_subgraph.OperatorsLength() == 2 |
268 | | - assert ( |
269 | | - tflite_subgraph.Operators(0).BuiltinOptionsType() |
270 | | - == BuiltinOptions.TransposeOptions |
271 | | - ) |
272 | | - assert ( |
273 | | - tflite_subgraph.Operators(1).BuiltinOptionsType() |
274 | | - == BuiltinOptions.Conv2DOptions |
275 | | - ) |
276 | | - |
277 | | - # Get the header of the payload for the delegated partition. |
278 | | - payload_header = payload_header_spy.spy_return |
279 | | - assert payload_header.size == 7 |
280 | | - # the 4th and 5th bytes indicate the format. `1` means `channels_last`, which means the runtime will transpose the data. |
281 | | - assert all(payload_header[3:5] == [0, 1]) # [<input_byte>, <output_byte>] |
0 commit comments