Skip to content

Commit 679c32e

Browse files
Merge branch 'main' into tosa_dialect_pad
2 parents ceed279 + 6b5283c commit 679c32e

6 files changed

Lines changed: 164 additions & 89 deletions

File tree

backends/arm/operator_support/ethos_u55_support.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,11 @@ def __init__(self, reporter: WhyNoPartitionReporter):
8686
exir_ops.edge.aten.permute_copy.default,
8787
]
8888

89-
target_ops_i8_i16 = (*TableOps.included_ops(), exir_ops.edge.aten.amax.default)
89+
target_ops_i8_i16 = (
90+
*TableOps.included_ops(),
91+
exir_ops.edge.aten.amax.default,
92+
exir_ops.edge.aten.amin.default,
93+
)
9094

9195
def is_node_supported( # noqa: C901
9296
self, submodules: typing.Mapping[str, torch.nn.Module], node: fx.Node

backends/arm/operators/op_amax.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,20 @@ def define_node(
3636
) -> None:
3737
validate_num_inputs(self.target, inputs, 3)
3838
validate_same_dtype(self.target, [inputs[0], output], ts)
39+
valid_dtypes = [
40+
ts.DType.INT8,
41+
ts.DType.INT16,
42+
ts.DType.INT32,
43+
ts.DType.FP16,
44+
ts.DType.FP32,
45+
ts.DType.BF16,
46+
]
47+
if self.tosa_spec.is_U55_subset:
48+
valid_dtypes.remove(ts.DType.INT32)
3949
validate_valid_dtype(
4050
self.target,
4151
[inputs[0], output],
42-
[
43-
ts.DType.INT8,
44-
ts.DType.INT16,
45-
ts.DType.INT32,
46-
ts.DType.FP16,
47-
ts.DType.FP32,
48-
ts.DType.BF16,
49-
],
52+
valid_dtypes,
5053
self.tosa_spec,
5154
)
5255

backends/arm/operators/op_amin.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,20 @@ def define_node(
3636
) -> None:
3737
validate_num_inputs(self.target, inputs, 3)
3838
validate_same_dtype(self.target, [inputs[0], output], ts)
39+
valid_dtypes = [
40+
ts.DType.INT8,
41+
ts.DType.INT16,
42+
ts.DType.INT32,
43+
ts.DType.FP16,
44+
ts.DType.FP32,
45+
ts.DType.BF16,
46+
]
47+
if self.tosa_spec.is_U55_subset:
48+
valid_dtypes.remove(ts.DType.INT32)
3949
validate_valid_dtype(
4050
self.target,
4151
[inputs[0], output],
42-
[
43-
ts.DType.INT8,
44-
ts.DType.INT16,
45-
ts.DType.INT32,
46-
ts.DType.FP16,
47-
ts.DType.FP32,
48-
ts.DType.BF16,
49-
],
52+
valid_dtypes,
5053
self.tosa_spec,
5154
)
5255

backends/arm/test/ops/test_amin.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,18 @@ def test_amin_u55_INT_not_delegated():
156156
pipeline.run()
157157

158158

159+
def test_amin_u55_INT_int32_not_delegated():
160+
data, dim, keep_dims = ((torch.ones([2, 2], dtype=torch.int32),), 1, False)
161+
pipeline = OpNotSupportedPipeline[Amin.input_t](
162+
Amin(dim, keep_dims),
163+
data,
164+
{"executorch_exir_dialects_edge__ops_aten_amin_default": 1},
165+
quantize=True,
166+
u55_subset=True,
167+
)
168+
pipeline.run()
169+
170+
159171
@common.parametrize("test_data", Amin.test_data)
160172
@common.XfailIfNoCorstone320
161173
def test_amin_u85_INT(test_data: Amin.input_t):

backends/nxp/tests/ir/converter/node_converter/test_slice_tensor_converter.py

Lines changed: 117 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from executorch.backends.nxp.tests.executorch_pipeline import to_quantized_edge_program
1212
from executorch.backends.nxp.tests.executors import (
1313
convert_run_compare,
14+
graph_contains_any_of_ops,
1415
ToChannelFirstPreprocess,
1516
ToChannelLastPreprocess,
1617
)
@@ -29,72 +30,112 @@ def reseed_model_per_test_run():
2930
np.random.seed(23)
3031

3132

32-
@pytest.mark.parametrize(
33-
"x_input_shape, dims, starts, ends",
34-
[
35-
pytest.param((24, 32), (0, 1), (0, 16), (24, 32), id="2D, no transpose"),
36-
pytest.param(
37-
(24, 32, 64), (0, 1, 2), (0, 0, 8), (24, 32, 64), id="3D, no transpose"
38-
),
39-
pytest.param(
40-
(24, 32, 64, 48),
41-
(0, 1, 2, 3),
42-
(0, 0, 0, 8),
43-
(24, 32, 64, 48),
44-
id="4D, no transpose",
45-
),
46-
pytest.param(
47-
(24, 32),
48-
(0, 1),
49-
(8, 0),
50-
(24, 32),
51-
id="2D, one transpose",
52-
marks=pytest.mark.xfail(reason="EIEX-649", strict=True),
33+
ExecutorchDelegateCall = torch.ops.higher_order.executorch_call_delegate
34+
Slice = exir_ops.edge.aten.slice.Tensor
35+
SliceCopy = exir_ops.edge.aten.slice_copy.Tensor
36+
37+
38+
passing_cases = [
39+
pytest.param((24, 32), (0, 1), (0, 16), (24, 32), id="2D, no transpose"),
40+
pytest.param(
41+
(24, 32, 64), (0, 1, 2), (0, 0, 8), (24, 32, 64), id="3D, no transpose"
42+
),
43+
pytest.param(
44+
(24, 32, 64, 48),
45+
(0, 1, 2, 3),
46+
(0, 0, 0, 8),
47+
(24, 32, 64, 48),
48+
id="4D, no transpose",
49+
),
50+
pytest.param(
51+
(24, 32),
52+
(0, 1),
53+
(0, 13),
54+
(24, 32),
55+
id="2D, start arg not divisible by num_macs",
56+
),
57+
pytest.param(
58+
(24, 32),
59+
(0, 1),
60+
(0, 0),
61+
(24, 31),
62+
id="2D, end arg not divisible by num_macs",
63+
),
64+
pytest.param((24, 32), (1, 0), (16, 0), (32, 24), id="2D, mixed dim args"),
65+
pytest.param((24, 32), (0, -1), (0, 16), (24, 32), id="2D, negative dim arg"),
66+
]
67+
68+
xfail_cases = [
69+
pytest.param(
70+
(24, 32),
71+
(0, 1),
72+
(8, 0),
73+
(24, 32),
74+
id="2D, one transpose",
75+
marks=pytest.mark.xfail(
76+
reason="Neutron-converter now only supports transpose in 4D, ticket: AIR-13446",
77+
strict=True,
5378
),
54-
pytest.param(
55-
(24, 32, 64),
56-
(0, 1, 2),
57-
(0, 8, 0),
58-
(24, 32, 64),
59-
id="3D, one transpose",
60-
marks=pytest.mark.xfail(reason="EIEX-649", strict=True),
79+
),
80+
pytest.param(
81+
(24, 32, 64),
82+
(0, 1, 2),
83+
(0, 8, 0),
84+
(24, 32, 64),
85+
id="3D, one transpose",
86+
marks=pytest.mark.xfail(
87+
reason="Neutron-converter now only supports transpose in 4D, ticket: AIR-13446",
88+
strict=True,
6189
),
62-
pytest.param(
63-
(24, 32, 64, 48),
64-
(0, 1, 2, 3),
65-
(0, 0, 8, 0),
66-
(24, 32, 64, 48),
67-
id="4D, one transpose",
68-
marks=pytest.mark.xfail(reason="EIEX-649", strict=True),
90+
),
91+
pytest.param(
92+
(24, 32, 64, 48),
93+
(0, 1, 2, 3),
94+
(0, 0, 8, 0),
95+
(24, 32, 64, 48),
96+
id="4D, one transpose",
97+
marks=pytest.mark.xfail(
98+
reason="Neutron-converter now only supports transpose of NHWC -> NCHW and vice versa, ticket: AIR-13446",
99+
strict=True,
69100
),
70-
pytest.param(
71-
(24, 32, 64),
72-
(0, 1, 2),
73-
(8, 8, 0),
74-
(24, 32, 64),
75-
id="3D, two transposes",
76-
marks=pytest.mark.xfail(reason="EIEX-649", strict=True),
101+
),
102+
pytest.param(
103+
(24, 32, 64),
104+
(0, 1, 2),
105+
(8, 8, 0),
106+
(24, 32, 64),
107+
id="3D, two transposes",
108+
marks=pytest.mark.xfail(
109+
reason="Neutron-converter now only supports transpose in 4D, ticket: AIR-13446",
110+
strict=True,
77111
),
78-
# bug in neutron-converter will not properly convert models in these test cases
79-
# pytest.param((24, 32, 64, 48), (0, 1, 2, 3), (16, 0, 8, 0), (24, 32, 64, 48), id="4D, two transposes"),
80-
# pytest.param((24, 32, 64, 48), (0, 1, 2, 3), (16, 0, 8, 0), (24, 24, 56, 48), id="4D, three transposes"),
81-
pytest.param(
82-
(24, 32),
83-
(0, 1),
84-
(0, 13),
85-
(24, 32),
86-
id="2D, start arg not divisible by num_macs",
112+
),
113+
pytest.param(
114+
(24, 32, 64, 48),
115+
(0, 1, 2, 3),
116+
(16, 0, 8, 0),
117+
(24, 32, 64, 48),
118+
id="4D, two transposes",
119+
marks=pytest.mark.xfail(
120+
reason="Bug in neutron-converter, ticket: AIR-13665", strict=True
87121
),
88-
pytest.param(
89-
(24, 32),
90-
(0, 1),
91-
(0, 0),
92-
(24, 31),
93-
id="2D, end arg not divisible by num_macs",
122+
),
123+
pytest.param(
124+
(24, 32, 64, 48),
125+
(0, 1, 2, 3),
126+
(16, 0, 8, 0),
127+
(24, 24, 56, 48),
128+
id="4D, three transposes",
129+
marks=pytest.mark.xfail(
130+
reason="Bug in neutron-converter, ticket: AIR-13665", strict=True
94131
),
95-
pytest.param((24, 32), (1, 0), (16, 0), (32, 24), id="2D, mixed dim args"),
96-
pytest.param((24, 32), (0, -1), (0, 16), (24, 32), id="2D, negative dim arg"),
97-
],
132+
),
133+
]
134+
135+
136+
@pytest.mark.parametrize(
137+
"x_input_shape, dims, starts, ends",
138+
passing_cases + xfail_cases,
98139
)
99140
def test_slice_tensor_quant_conversion(mocker, x_input_shape, dims, starts, ends):
100141
model = SliceTensorModule(
@@ -106,10 +147,10 @@ def test_slice_tensor_quant_conversion(mocker, x_input_shape, dims, starts, ends
106147

107148
# Run conversion
108149
edge_program = to_quantized_edge_program(model, x_input_shape).exported_program()
109-
edge_nodes = list(edge_program.graph.nodes)
110150

111151
# Check if slices were delegated
112-
assert not any("slice" in n.name for n in edge_nodes)
152+
assert not graph_contains_any_of_ops(edge_program.graph, [Slice, SliceCopy])
153+
assert graph_contains_any_of_ops(edge_program.graph, [ExecutorchDelegateCall])
113154

114155
# Capture generated model
115156
tflite_flatbuffers_model, _ = converter_spy.spy_return
@@ -133,30 +174,36 @@ def test_slice_tensor_quant_conversion(mocker, x_input_shape, dims, starts, ends
133174
"x_input_shape, dims, starts, ends",
134175
[
135176
pytest.param(
136-
(1, 4, 34, 50),
177+
(1, 16, 32, 48),
137178
(0, 1, 2, 3),
138-
(0, 0, 8, 0),
139-
(1, 8, 32, 32),
179+
(0, 8, 0, 0),
180+
(1, 16, 32, 48),
140181
id="4D, handle channel order swap",
141-
marks=pytest.mark.xfail(reason="EIEX-649", strict=True),
142182
)
143183
],
144184
)
145185
def test_slice_tensor_w_conv_quant_conversion(
146186
mocker, x_input_shape, dims, starts, ends
147187
):
148-
model = SliceTensorConvModule(dims=dims, starts=starts, ends=ends)
188+
in_channels = out_channels = x_input_shape[1]
189+
model = SliceTensorConvModule(
190+
dims=dims,
191+
starts=starts,
192+
ends=ends,
193+
in_channels=in_channels,
194+
out_channels=out_channels,
195+
)
149196

150197
converter_spy = mocker.spy(EdgeProgramToIRConverter, "convert_program")
151198

152199
# Run conversion
153200
edge_program = to_quantized_edge_program(
154201
model, x_input_shape, use_neutron_for_format_conversion=False
155202
).exported_program()
156-
edge_nodes = list(edge_program.graph.nodes)
157203

158204
# Check if slices were delegated
159-
assert not any("slice" in n.name for n in edge_nodes)
205+
assert not graph_contains_any_of_ops(edge_program.graph, [Slice, SliceCopy])
206+
assert graph_contains_any_of_ops(edge_program.graph, [ExecutorchDelegateCall])
160207

161208
# Capture generated model
162209
tflite_flatbuffers_model, _ = converter_spy.spy_return
@@ -250,4 +297,4 @@ def test_slice_not_delegated(mocker, x_input_shape, dims, starts, ends):
250297

251298
for i in range(0, num_slice_ops):
252299
slice_idx = (i + 1) * 3
253-
assert nodes[slice_idx].target == exir_ops.edge.aten.slice_copy.Tensor
300+
assert nodes[slice_idx].target in [Slice, SliceCopy]

backends/nxp/tests/models.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,15 @@ def forward(self, x):
192192

193193

194194
class SliceTensorConvModule(torch.nn.Module):
195-
def __init__(self, dims, starts, ends):
195+
def __init__(self, dims, starts, ends, in_channels, out_channels):
196196
super().__init__()
197-
self.conv = Conv2dModule(in_channels=4, out_channels=8, kernel_size=3, stride=1)
197+
self.conv = Conv2dModule(
198+
in_channels=in_channels,
199+
out_channels=out_channels,
200+
kernel_size=3,
201+
stride=1,
202+
padding=1,
203+
)
198204
self.slice = SliceTensorModule(dims, starts, ends)
199205

200206
def forward(self, x):

0 commit comments

Comments
 (0)