Skip to content

Commit f7ed853

Browse files
committed
Arm backend: Refactor test infra to enable TOSA V1.0 testing (part 3)
Signed-off-by: Saoirse Stewart <[email protected]> Change-Id: I7a1896ba1d40d2bd0e313da0c33ff21ed8c0738c
1 parent 5331790 commit f7ed853

27 files changed

+2108
-2377
lines changed

backends/arm/test/ops/test_lshift.py

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# LICENSE file in the root directory of this source tree.
55

66
import torch
7+
from executorch.backends.arm.test import common
78
from executorch.backends.arm.test.common import (
89
XfailIfNoCorstone300,
910
XfailIfNoCorstone320,
@@ -14,7 +15,6 @@
1415
TosaPipelineBI,
1516
TosaPipelineMI,
1617
)
17-
from parameterized import parameterized
1818

1919
scalar_input_t = tuple[torch.Tensor, int]
2020

@@ -23,11 +23,20 @@ class LshiftScalar(torch.nn.Module):
2323
torch_op_MI = "torch.ops.aten.__lshift__.Scalar"
2424
torch_op_BI = "torch.ops.aten.bitwise_left_shift.Tensor"
2525
exir_op = "executorch_exir_dialects_edge__ops_aten_bitwise_left_shift_Tensor"
26-
test_data = [
27-
((torch.randint(-8, 8, (1, 12, 3, 4), dtype=torch.int8), 1),),
28-
((torch.randint(-100, 100, (1, 5, 3, 4), dtype=torch.int16), 5),),
29-
((torch.randint(-100, 100, (1, 5, 3, 4), dtype=torch.int32), 2),),
30-
]
26+
test_data = {
27+
"randint_neg_8_int8": (
28+
torch.randint(-8, 8, (1, 12, 3, 4), dtype=torch.int8),
29+
1,
30+
),
31+
"randint_neg_100_int16": (
32+
torch.randint(-100, 100, (1, 5, 3, 4), dtype=torch.int16),
33+
5,
34+
),
35+
"randint_neg_100_int32": (
36+
torch.randint(-100, 100, (1, 5, 3, 4), dtype=torch.int32),
37+
2,
38+
),
39+
}
3140

3241
def forward(self, x: torch.Tensor, shift: int):
3342
return x << shift
@@ -39,33 +48,27 @@ def forward(self, x: torch.Tensor, shift: int):
3948
class LshiftTensor(torch.nn.Module):
4049
torch_op = "torch.ops.aten.bitwise_left_shift.Tensor"
4150
exir_op = "executorch_exir_dialects_edge__ops_aten_bitwise_left_shift_Tensor"
42-
test_data = [
43-
(
44-
(
45-
torch.randint(-8, 8, (3, 3), dtype=torch.int8),
46-
torch.randint(0, 4, (3, 3), dtype=torch.int8),
47-
),
51+
test_data = {
52+
"randint_neg_8_tensor_int8": (
53+
torch.randint(-8, 8, (3, 3), dtype=torch.int8),
54+
torch.randint(0, 4, (3, 3), dtype=torch.int8),
4855
),
49-
(
50-
(
51-
torch.randint(-1024, 1024, (3, 3, 3), dtype=torch.int16),
52-
torch.randint(0, 5, (3, 3, 3), dtype=torch.int16),
53-
),
56+
"randint_neg_1024_tensor_int16": (
57+
torch.randint(-1024, 1024, (3, 3, 3), dtype=torch.int16),
58+
torch.randint(0, 5, (3, 3, 3), dtype=torch.int16),
5459
),
55-
(
56-
(
57-
torch.randint(0, 127, (1, 2, 3, 3), dtype=torch.int32),
58-
torch.randint(0, 5, (1, 2, 3, 3), dtype=torch.int32),
59-
),
60+
"randint_0_tensor_int16": (
61+
torch.randint(0, 127, (1, 2, 3, 3), dtype=torch.int32),
62+
torch.randint(0, 5, (1, 2, 3, 3), dtype=torch.int32),
6063
),
61-
]
64+
}
6265

6366
def forward(self, x: torch.Tensor, shift: torch.Tensor):
6467
return x.bitwise_left_shift(shift)
6568

6669

67-
@parameterized.expand(LshiftScalar.test_data)
68-
def test_lshift_scalar_tosa_MI(test_data):
70+
@common.parametrize("test_data", LshiftScalar.test_data)
71+
def test_lshift_scalar_tosa_MI_scalar(test_data):
6972
TosaPipelineMI[scalar_input_t](
7073
LshiftScalar(),
7174
test_data,
@@ -74,18 +77,21 @@ def test_lshift_scalar_tosa_MI(test_data):
7477
).run()
7578

7679

77-
@parameterized.expand(LshiftScalar.test_data)
78-
def test_lshift_scalar_tosa_BI(test_data):
80+
@common.parametrize("test_data", LshiftScalar.test_data)
81+
def test_bitwise_left_shift_tensor_tosa_BI_scalar(test_data):
7982
pipeline = TosaPipelineBI[scalar_input_t](
80-
LshiftScalar(), test_data, LshiftScalar.torch_op_BI, LshiftScalar.exir_op
83+
LshiftScalar(),
84+
test_data,
85+
LshiftScalar.torch_op_BI,
86+
LshiftScalar.exir_op,
8187
)
8288
pipeline.pop_stage("check.quant_nodes")
8389
pipeline.run()
8490

8591

86-
@parameterized.expand(LshiftScalar.test_data)
92+
@common.parametrize("test_data", LshiftScalar.test_data)
8793
@XfailIfNoCorstone300
88-
def test_lshift_scalar_tosa_u55(test_data):
94+
def test_bitwise_left_shift_tensor_u55_BI_scalar(test_data):
8995
pipeline = EthosU55PipelineBI[scalar_input_t](
9096
LshiftScalar(),
9197
test_data,
@@ -97,9 +103,9 @@ def test_lshift_scalar_tosa_u55(test_data):
97103
pipeline.run()
98104

99105

100-
@parameterized.expand(LshiftScalar.test_data)
106+
@common.parametrize("test_data", LshiftScalar.test_data)
101107
@XfailIfNoCorstone320
102-
def test_lshift_scalar_tosa_u85(test_data):
108+
def test_bitwise_left_shift_tensor_u85_BI_scalar(test_data):
103109
pipeline = EthosU85PipelineBI[scalar_input_t](
104110
LshiftScalar(),
105111
test_data,
@@ -111,8 +117,8 @@ def test_lshift_scalar_tosa_u85(test_data):
111117
pipeline.run()
112118

113119

114-
@parameterized.expand(LshiftTensor.test_data)
115-
def test_lshift_tensor_tosa_MI(test_data):
120+
@common.parametrize("test_data", LshiftTensor.test_data)
121+
def test_lshift_scalar_tosa_MI(test_data):
116122
TosaPipelineMI[scalar_input_t](
117123
LshiftTensor(),
118124
test_data,
@@ -121,18 +127,21 @@ def test_lshift_tensor_tosa_MI(test_data):
121127
).run()
122128

123129

124-
@parameterized.expand(LshiftTensor.test_data)
125-
def test_lshift_tensor_tosa_BI(test_data):
130+
@common.parametrize("test_data", LshiftTensor.test_data)
131+
def test_bitwise_left_shift_tensor_tosa_BI(test_data):
126132
pipeline = TosaPipelineBI[scalar_input_t](
127-
LshiftTensor(), test_data, LshiftTensor.torch_op, LshiftTensor.exir_op
133+
LshiftTensor(),
134+
test_data,
135+
LshiftTensor.torch_op,
136+
LshiftTensor.exir_op,
128137
)
129138
pipeline.pop_stage("check.quant_nodes")
130139
pipeline.run()
131140

132141

133-
@parameterized.expand(LshiftTensor.test_data)
142+
@common.parametrize("test_data", LshiftTensor.test_data)
134143
@XfailIfNoCorstone300
135-
def test_lshift_tensor_tosa_u55(test_data):
144+
def test_bitwise_left_shift_tensor_u55_BI(test_data):
136145
pipeline = EthosU55PipelineBI[scalar_input_t](
137146
LshiftTensor(),
138147
test_data,
@@ -144,9 +153,9 @@ def test_lshift_tensor_tosa_u55(test_data):
144153
pipeline.run()
145154

146155

147-
@parameterized.expand(LshiftTensor.test_data)
156+
@common.parametrize("test_data", LshiftTensor.test_data)
148157
@XfailIfNoCorstone320
149-
def test_lshift_tensor_tosa_u85(test_data):
158+
def test_bitwise_left_shift_tensor_u85_BI(test_data):
150159
pipeline = EthosU85PipelineBI[scalar_input_t](
151160
LshiftTensor(),
152161
test_data,
Lines changed: 75 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# Copyright 2024-2025 Arm Limited and/or its affiliates.
2-
# All rights reserved.
32
#
43
# This source code is licensed under the BSD-style license found in the
54
# LICENSE file in the root directory of this source tree.
@@ -8,115 +7,83 @@
87
# Tests the repeat op which copies the data of the input tensor (possibly with new data format)
98
#
109

11-
import unittest
10+
1211
from typing import Sequence, Tuple
1312

1413
import torch
1514

16-
from executorch.backends.arm.quantizer import (
17-
EthosUQuantizer,
18-
get_symmetric_quantization_config,
19-
TOSAQuantizer,
20-
)
2115
from executorch.backends.arm.test import common
22-
from executorch.backends.arm.test.tester.arm_tester import ArmTester
23-
from executorch.backends.arm.tosa_specification import TosaSpecification
24-
25-
from executorch.backends.xnnpack.test.tester.tester import Quantize
26-
from executorch.exir.backend.backend_details import CompileSpec
27-
from parameterized import parameterized
28-
29-
30-
class TestSimpleRepeat(unittest.TestCase):
31-
"""Tests Tensor.repeat for different ranks and dimensions."""
32-
33-
class Repeat(torch.nn.Module):
34-
# (input tensor, multiples)
35-
test_parameters = [
36-
(torch.randn(3), (2,)),
37-
(torch.randn(3, 4), (2, 1)),
38-
(torch.randn(1, 1, 2, 2), (1, 2, 3, 4)),
39-
(torch.randn(3), (2, 2)),
40-
(torch.randn(3), (1, 2, 3)),
41-
(torch.randn((3, 3)), (2, 2, 2)),
42-
(torch.randn((3, 3, 3)), (2, 1, 2, 4)),
43-
]
44-
45-
def forward(self, x: torch.Tensor, multiples: Sequence):
46-
return x.repeat(multiples)
47-
48-
def _test_repeat_tosa_MI_pipeline(self, module: torch.nn.Module, test_data: Tuple):
49-
(
50-
ArmTester(
51-
module,
52-
example_inputs=test_data,
53-
compile_spec=common.get_tosa_compile_spec("TOSA-0.80+MI"),
54-
)
55-
.export()
56-
.check_count({"torch.ops.aten.repeat.default": 1})
57-
.to_edge()
58-
.partition()
59-
.check_not(["torch.ops.aten.repeat.default"])
60-
.check_count({"torch.ops.higher_order.executorch_call_delegate": 1})
61-
.to_executorch()
62-
.run_method_and_compare_outputs(inputs=test_data)
63-
)
64-
65-
def _test_repeat_tosa_BI_pipeline(self, module: torch.nn.Module, test_data: Tuple):
66-
tosa_spec = TosaSpecification.create_from_string("TOSA-0.80+BI")
67-
compile_spec = common.get_tosa_compile_spec(tosa_spec)
68-
quantizer = TOSAQuantizer(tosa_spec).set_io(get_symmetric_quantization_config())
69-
(
70-
ArmTester(module, example_inputs=test_data, compile_spec=compile_spec)
71-
.quantize(Quantize(quantizer, get_symmetric_quantization_config()))
72-
.export()
73-
.check_count({"torch.ops.aten.repeat.default": 1})
74-
.to_edge()
75-
.partition()
76-
.check_not(["torch.ops.aten.repeat.default"])
77-
.check_count({"torch.ops.higher_order.executorch_call_delegate": 1})
78-
.to_executorch()
79-
.run_method_and_compare_outputs(inputs=test_data, qtol=1)
80-
)
81-
82-
def _test_repeat_ethosu_pipeline(
83-
self, compile_spec: CompileSpec, module: torch.nn.Module, test_data: Tuple
84-
):
85-
quantizer = EthosUQuantizer(compile_spec).set_io(
86-
get_symmetric_quantization_config()
87-
)
88-
(
89-
ArmTester(
90-
module,
91-
example_inputs=test_data,
92-
compile_spec=compile_spec,
93-
)
94-
.quantize(Quantize(quantizer, get_symmetric_quantization_config()))
95-
.export()
96-
.check_count({"torch.ops.aten.repeat.default": 1})
97-
.to_edge()
98-
.partition()
99-
.check_not(["torch.ops.aten.repeat.default"])
100-
.check_count({"torch.ops.higher_order.executorch_call_delegate": 1})
101-
.to_executorch()
102-
)
103-
104-
@parameterized.expand(Repeat.test_parameters)
105-
def test_repeat_tosa_MI(self, test_input, multiples):
106-
self._test_repeat_tosa_MI_pipeline(self.Repeat(), (test_input, multiples))
107-
108-
@parameterized.expand(Repeat.test_parameters)
109-
def test_repeat_tosa_BI(self, test_input, multiples):
110-
self._test_repeat_tosa_BI_pipeline(self.Repeat(), (test_input, multiples))
111-
112-
@parameterized.expand(Repeat.test_parameters)
113-
def test_repeat_u55_BI(self, test_input, multiples):
114-
self._test_repeat_ethosu_pipeline(
115-
common.get_u55_compile_spec(), self.Repeat(), (test_input, multiples)
116-
)
117-
118-
@parameterized.expand(Repeat.test_parameters)
119-
def test_repeat_u85_BI(self, test_input, multiples):
120-
self._test_repeat_ethosu_pipeline(
121-
common.get_u85_compile_spec(), self.Repeat(), (test_input, multiples)
122-
)
16+
from executorch.backends.arm.test.tester.test_pipeline import (
17+
EthosU55PipelineBI,
18+
EthosU85PipelineBI,
19+
TosaPipelineBI,
20+
TosaPipelineMI,
21+
)
22+
23+
input_t1 = Tuple[torch.Tensor, torch.Tensor] # Input x, Input y
24+
aten_op = "torch.ops.aten.repeat.default"
25+
26+
27+
"""Tests Tensor.repeat for different ranks and dimensions."""
28+
29+
30+
class Repeat(torch.nn.Module):
31+
# (input tensor, multiples)
32+
test_parameters = {
33+
"1_x_1": lambda: (torch.randn(3), (2,)),
34+
"2_x_2": lambda: (torch.randn(3, 4), (2, 1)),
35+
"4_x_4": lambda: (torch.randn(1, 1, 2, 2), (1, 2, 3, 4)),
36+
"1_x_2": lambda: (torch.randn(3), (2, 2)),
37+
"1_x_3": lambda: (torch.randn(3), (1, 2, 3)),
38+
"2_x_3": lambda: (torch.randn((3, 3)), (2, 2, 2)),
39+
"1_x_4": lambda: (torch.randn((3, 3, 3)), (2, 1, 2, 4)),
40+
}
41+
42+
def forward(self, x: torch.Tensor, multiples: Sequence):
43+
return x.repeat(multiples)
44+
45+
46+
@common.parametrize("test_data", Repeat.test_parameters)
47+
def test_repeat_tosa_MI(test_data: Tuple):
48+
pipeline = TosaPipelineMI[input_t1](
49+
Repeat(),
50+
test_data(),
51+
aten_op,
52+
exir_op=[],
53+
)
54+
pipeline.run()
55+
56+
57+
@common.parametrize("test_data", Repeat.test_parameters)
58+
def test_repeat_tosa_BI(test_data: Tuple):
59+
pipeline = TosaPipelineBI[input_t1](
60+
Repeat(),
61+
test_data(),
62+
aten_op,
63+
exir_op=[],
64+
)
65+
pipeline.run()
66+
67+
68+
@common.parametrize("test_data", Repeat.test_parameters)
69+
def test_repeat_u55_BI(test_data: Tuple):
70+
pipeline = EthosU55PipelineBI[input_t1](
71+
Repeat(),
72+
test_data(),
73+
aten_op,
74+
exir_ops=[],
75+
run_on_fvp=False,
76+
)
77+
pipeline.run()
78+
79+
80+
@common.parametrize("test_data", Repeat.test_parameters)
81+
def test_repeat_u85_BI(test_data: Tuple):
82+
pipeline = EthosU85PipelineBI[input_t1](
83+
Repeat(),
84+
test_data(),
85+
aten_op,
86+
exir_ops=[],
87+
run_on_fvp=False,
88+
)
89+
pipeline.run()

0 commit comments

Comments
 (0)