44# LICENSE file in the root directory of this source tree.
55
66import numpy as np
7+
8+ # noinspection PyUnusedImports
79import pytest
810import torch
11+
912from executorch .backends .nxp .backend .ir .conversion_config import ConversionConfig
13+ from executorch .backends .nxp .backend .ir .converter .builder .model_builder import (
14+ ModelBuilder ,
15+ )
1016from executorch .backends .nxp .backend .ir .converter .node_converters .ops_converters .constant_pad_nd_converter import (
1117 ConstantPadNDConverter ,
1218)
1723from executorch .backends .nxp .tests .executors import (
1824 convert_run_compare ,
1925 graph_contains_any_of_ops ,
26+ OverrideTargetSupportCheck ,
2027 ToNCHWPreprocess ,
2128 ToNHWCPreprocess ,
2229)
30+ from executorch .backends .nxp .tests .graph_verifier import DetailedGraphVerifier
2331from executorch .backends .nxp .tests .models import (
2432 ConstantPadNDConvModule ,
2533 ConstantPadNDModule ,
2634)
35+ from executorch .backends .nxp .tests .nsys_testing import lower_run_compare
36+ from executorch .backends .nxp .tests .ops_aliases import ConstantPadND , Convolution
2737from executorch .backends .nxp .tests .use_qat import * # noqa F403
28- from executorch .backends .nxp .tests .executors import OverrideTargetSupportCheck
29- from executorch .exir .dialects ._ops import ops as exir_ops
3038
3139
3240@pytest .fixture (autouse = True )
@@ -158,9 +166,8 @@ def test_constant_pad_nd__unsupported_paddings(input_shape, paddings, use_qat):
158166 model , input_shape , use_qat = use_qat
159167 ).exported_program ()
160168
161- nodes = list (exec_program .graph .nodes )
162169 # There is at least one non-delegated Pad node
163- assert any ( node . name == "aten_constant_pad_nd_default" for node in nodes )
170+ assert graph_contains_any_of_ops ( exec_program . graph , [ ConstantPadND ] )
164171
165172
166173@pytest .mark .xfail (reason = "EIEX=855" )
@@ -173,9 +180,7 @@ def test_constant_pad_nd__delegation__formatless__supported_padding(use_qat):
173180 ).exported_program ()
174181
175182 # Make sure the `pad` was delegated.
176- assert not graph_contains_any_of_ops (
177- exec_program .graph , [exir_ops .edge .aten .constant_pad_nd .default ]
178- )
183+ assert not graph_contains_any_of_ops (exec_program .graph , [ConstantPadND ])
179184
180185
181186def test_constant_pad_nd__delegation__formatless__unsupported_padding (use_qat ):
@@ -187,9 +192,7 @@ def test_constant_pad_nd__delegation__formatless__unsupported_padding(use_qat):
187192 ).exported_program ()
188193
189194 # Make sure the `pad` was NOT delegated.
190- assert graph_contains_any_of_ops (
191- exec_program .graph , [exir_ops .edge .aten .constant_pad_nd .default ]
192- )
195+ assert graph_contains_any_of_ops (exec_program .graph , [ConstantPadND ])
193196
194197
195198@pytest .mark .xfail (reason = "Regression in Neutron SW 3.0.1 (AIR-14264)" , strict = True )
@@ -202,9 +205,7 @@ def test_constant_pad_nd__delegation__channels_first__supported_padding(use_qat)
202205 ).exported_program ()
203206
204207 # Make sure the `pad` was delegated.
205- assert not graph_contains_any_of_ops (
206- exec_program .graph , [exir_ops .edge .aten .constant_pad_nd .default ]
207- )
208+ assert not graph_contains_any_of_ops (exec_program .graph , [ConstantPadND ])
208209
209210
210211def test_constant_pad_nd__delegation__channels_first__unsupported_padding (use_qat ):
@@ -216,6 +217,118 @@ def test_constant_pad_nd__delegation__channels_first__unsupported_padding(use_qa
216217 ).exported_program ()
217218
218219 # Make sure the `pad` was NOT delegated.
219- assert graph_contains_any_of_ops (
220- exec_program .graph , [exir_ops .edge .aten .constant_pad_nd .default ]
220+ assert graph_contains_any_of_ops (exec_program .graph , [ConstantPadND ])
221+
222+
223+ class TestConstantPadNDNewNeutronFlow :
224+ # noinspection PyMethodMayBeStatic
225+ def assert_delegated (self , model , input_shape , mocker , use_qat = False ):
226+ graph_verifier = DetailedGraphVerifier (
227+ mocker ,
228+ expected_delegated_ops = {ConstantPadND : 1 },
229+ expected_non_delegated_ops = {},
230+ )
231+
232+ lower_run_compare (
233+ model ,
234+ input_shape ,
235+ graph_verifier ,
236+ use_qat = use_qat ,
237+ use_new_flow_neutron_c = True ,
238+ )
239+
240+ def assert_delegated_and_output_shape_equals (
241+ self , model , input_shape , expected_output_shape , mocker
242+ ):
243+ model_builder_spy = mocker .spy (ModelBuilder , "finish" )
244+
245+ self .assert_delegated (model , input_shape , mocker )
246+
247+ neutron_ir_subgraph = model_builder_spy .call_args [0 ][0 ].get_sub_graph ()
248+ assert neutron_ir_subgraph .outputs .tmp_outputs [0 ].shape .vector == list (
249+ expected_output_shape
250+ )
251+
252+ @pytest .mark .parametrize (
253+ "input_shape, paddings" ,
254+ [
255+ pytest .param ((2 ,), tuple (range (2 )), id = "1D, padding H" ),
256+ pytest .param ((2 , 4 ), tuple (range (2 )), id = "2D, padding H" ),
257+ pytest .param ((2 , 4 ), tuple (range (4 )), id = "2D, padding N, H" ),
258+ pytest .param ((2 , 4 , 6 ), tuple (range (2 )), id = "3D, padding H" ),
259+ pytest .param ((2 , 4 , 6 ), tuple (range (4 )), id = "3D, padding C, H" ),
260+ pytest .param ((2 , 4 , 6 , 8 ), tuple (range (2 )), id = "4D, padding W" ),
261+ pytest .param ((2 , 4 , 6 , 8 ), tuple (range (4 )), id = "4D, padding H, W" ),
262+ pytest .param ((1 , 2 , 3 , 4 , 5 ), tuple (range (2 )), id = "5D, padding D" ),
263+ pytest .param ((1 , 2 , 3 , 4 , 5 ), tuple (range (4 )), id = "5D, padding W, D" ),
264+ ],
265+ )
266+ def test__basic_nsys_inference (self , mocker , input_shape , paddings , use_qat ):
267+ # These test cases are also supported by the old flow.
268+ model = ConstantPadNDModule (paddings )
269+ self .assert_delegated (model , input_shape , mocker , use_qat )
270+
271+ def test__channels_padding (self , mocker ):
272+ input_shape = (2 , 4 , 6 )
273+ # These paddings will be applied to the last dimension, which is the channels as the input is formatless.
274+ paddings = (1 , 1 )
275+ expected_output_shape = (2 , 4 , 8 ) # Padded channels.
276+ model = ConstantPadNDModule (paddings )
277+
278+ self .assert_delegated_and_output_shape_equals (
279+ model , input_shape , expected_output_shape , mocker
280+ )
281+
282+ def test__batch_padding (self , mocker ):
283+ input_shape = (2 , 4 , 6 )
284+ paddings = (0 , 0 , 0 , 0 , 1 , 1 ) # Padding applied to the batch dimension.
285+ expected_output_shape = (4 , 4 , 6 ) # Padded batch.
286+ model = ConstantPadNDModule (paddings )
287+
288+ self .assert_delegated_and_output_shape_equals (
289+ model , input_shape , expected_output_shape , mocker
290+ )
291+
292+ @pytest .mark .parametrize ("constant" , [0.0 , - 13.37 ])
293+ def test__specific_constant (self , mocker , constant ):
294+ input_shape = (2 , 4 , 6 )
295+ paddings = (1 , 1 )
296+ model = ConstantPadNDModule (paddings , constant )
297+ self .assert_delegated (model , input_shape , mocker )
298+
299+ @pytest .mark .parametrize (
300+ "input_shape, paddings" ,
301+ [
302+ pytest .param ((1 , 4 , 6 , 8 ), tuple (range (2 )), id = "4D, padding W" ),
303+ pytest .param ((1 , 4 , 6 , 8 ), tuple (range (4 )), id = "4D, padding H, W" ),
304+ ],
221305 )
306+ def test__channels_first (self , mocker , input_shape , paddings ):
307+ model = ConstantPadNDConvModule (paddings )
308+ graph_verifier = DetailedGraphVerifier (
309+ mocker ,
310+ expected_delegated_ops = {ConstantPadND : 1 , Convolution : 1 },
311+ expected_non_delegated_ops = {},
312+ )
313+
314+ lower_run_compare (
315+ model , input_shape , graph_verifier , use_new_flow_neutron_c = True
316+ )
317+
318+ @pytest .mark .xfail (
319+ strict = True ,
320+ raises = RuntimeError ,
321+ reason = "Known issue in Neutron: https://jira.sw.nxp.com/browse/AIR-14624" , # @lint-ignore
322+ )
323+ def test__bugged_channels_first_case (self , mocker ):
324+ input_shape , paddings = (1 , 2 , 6 , 8 ), (0 , 1 , 2 , 3 , 1 , 1 )
325+ model = ConstantPadNDConvModule (paddings )
326+ graph_verifier = DetailedGraphVerifier (
327+ mocker ,
328+ expected_delegated_ops = {ConstantPadND : 1 , Convolution : 1 },
329+ expected_non_delegated_ops = {},
330+ )
331+
332+ lower_run_compare (
333+ model , input_shape , graph_verifier , use_new_flow_neutron_c = True
334+ )
0 commit comments