Skip to content

Commit a68a884

Browse files
committed
[Backend Tester] Add ARM TOSA flow
ghstack-source-id: e4ce243 ghstack-comment-id: 3277010040 Pull-Request: #14190
1 parent 074b942 commit a68a884

File tree

6 files changed

+88
-5
lines changed

6 files changed

+88
-5
lines changed

.ci/scripts/test_backend_linux.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,17 @@ if [[ "$FLOW" == *qnn* ]]; then
3939
fi
4040

4141
if [[ "$FLOW" == *vulkan* ]]; then
42-
# Setup swiftshader and Vulkan SDK which are required to build the Vulkan delegate
42+
# Setup swiftshader and Vulkan SDK which are required to build the Vulkan delegate.
4343
source .ci/scripts/setup-vulkan-linux-deps.sh
4444

4545
EXTRA_BUILD_ARGS+=" -DEXECUTORCH_BUILD_VULKAN=ON"
4646
fi
4747

48+
if [[ "$FLOW" == *arm* ]]; then
49+
# Setup ARM deps.
50+
.ci/scripts/setup-arm-baremetal-tools.sh
51+
fi
52+
4853
# We need the runner to test the built library.
4954
PYTHON_EXECUTABLE=python CMAKE_ARGS="$EXTRA_BUILD_ARGS" .ci/scripts/setup-linux.sh --build-tool cmake --build-mode Release --editable true
5055

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Test ARM Backend
2+
3+
on:
4+
schedule:
5+
- cron: 0 2 * * *
6+
push:
7+
tags:
8+
- ciflow/nightly/*
9+
pull_request:
10+
paths:
11+
- .github/workflows/test-backend-arm.yml
12+
- .github/workflows/_test_backend.yml
13+
workflow_dispatch:
14+
15+
concurrency:
16+
group: ${{ github.workflow }}--${{ github.event.pull_request.number || github.sha }}-${{ github.event_name == 'workflow_dispatch' }}
17+
cancel-in-progress: true
18+
19+
jobs:
20+
test-arm:
21+
uses: ./.github/workflows/_test_backend.yml
22+
with:
23+
backend: arm
24+
flows: '["arm_tosa"]'
25+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
26+
timeout: 120
27+
run-linux: true

backends/arm/test/tester/arm_tester.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060

6161
from executorch.backends.arm.vgf import VgfCompileSpec, VgfPartitioner
6262

63+
from executorch.backends.test.harness.error_statistics import ErrorStatistics
6364
from executorch.backends.test.harness.stages import Stage, StageType
6465
from executorch.backends.xnnpack.test.tester import Tester
6566
from executorch.devtools.backend_debug import get_delegation_info
@@ -374,6 +375,7 @@ def to_edge_transform_and_lower(
374375
transform_passes: Optional[
375376
Union[Sequence[PassType], Dict[str, Sequence[PassType]]]
376377
] = None,
378+
generate_etrecord: bool = False,
377379
):
378380
if transform_passes is not None:
379381
raise RuntimeError(
@@ -408,7 +410,9 @@ def to_edge_transform_and_lower(
408410
to_edge_and_lower_stage.partitioners = partitioners
409411
if edge_compile_config is not None:
410412
to_edge_and_lower_stage.edge_compile_conf = edge_compile_config
411-
return super().to_edge_transform_and_lower(to_edge_and_lower_stage)
413+
return super().to_edge_transform_and_lower(
414+
to_edge_and_lower_stage, generate_etrecord=generate_etrecord
415+
)
412416

413417
def to_executorch(self, to_executorch_stage: Optional[ToExecutorch] | None = None):
414418
if to_executorch_stage is None:
@@ -439,6 +443,7 @@ def run_method_and_compare_outputs(
439443
qtol=0,
440444
error_callbacks=None,
441445
run_eager_mode=False,
446+
statistics_callback: Callable[[ErrorStatistics], None] | None = None,
442447
):
443448
"""
444449
Compares the run_artifact output of 'stage' with the output of a reference stage.
@@ -694,10 +699,17 @@ def _compare_outputs(
694699
rtol=1e-03,
695700
qtol=0,
696701
error_callbacks=None,
702+
statistics_callback: Callable[[ErrorStatistics], None] | None = None,
697703
):
698704
try:
699705
super()._compare_outputs(
700-
reference_output, stage_output, quantization_scale, atol, rtol, qtol
706+
reference_output,
707+
stage_output,
708+
quantization_scale,
709+
atol,
710+
rtol,
711+
qtol,
712+
statistics_callback=statistics_callback,
701713
)
702714
except AssertionError as e:
703715
if error_callbacks is None:

backends/test/suite/flow.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class TestFlow:
3838
skip_patterns: list[str] = field(default_factory=lambda: [])
3939
""" Tests with names containing any substrings in this list are skipped. """
4040

41+
supports_serialize: bool = True
42+
""" True if the test flow supports the Serialize stage. """
43+
4144
def should_skip_test(self, test_name: str) -> bool:
4245
return any(pattern in test_name for pattern in self.skip_patterns)
4346

@@ -115,4 +118,13 @@ def all_flows() -> dict[str, TestFlow]:
115118
except Exception as e:
116119
logger.info(f"Skipping QNN flow registration: {e}")
117120

121+
try:
122+
from executorch.backends.test.suite.flows.arm import ARM_TOSA_FLOW
123+
124+
flows += [
125+
ARM_TOSA_FLOW,
126+
]
127+
except Exception as e:
128+
logger.info(f"Skipping ARM flow registration: {e}")
129+
118130
return {f.name: f for f in flows if f is not None}

backends/test/suite/flows/arm.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from executorch.backends.arm.test import common
2+
from executorch.backends.arm.test.tester.arm_tester import ArmTester
3+
from executorch.backends.test.suite.flow import TestFlow
4+
5+
6+
def _create_arm_tester_tosa_fp(*args, **kwargs) -> ArmTester:
7+
kwargs["compile_spec"] = common.get_tosa_compile_spec(tosa_spec="TOSA-1.0+FP")
8+
9+
return ArmTester(
10+
*args,
11+
**kwargs,
12+
)
13+
14+
15+
def _create_tosa_flow() -> TestFlow:
16+
return TestFlow(
17+
"arm_tosa",
18+
backend="arm",
19+
tester_factory=_create_arm_tester_tosa_fp,
20+
supports_serialize=False,
21+
)
22+
23+
24+
ARM_TOSA_FLOW = _create_tosa_flow()

backends/test/suite/runner.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,11 @@ def build_result(
191191
# Only run the runtime portion if something was delegated (or the flow doesn't delegate)
192192
if is_delegated or not flow.is_delegated:
193193
try:
194-
tester.to_executorch().serialize()
195-
extra_stats["pte_size_bytes"] = len(tester.get_artifact())
194+
tester.to_executorch()
195+
196+
if flow.supports_serialize:
197+
tester.serialize()
198+
extra_stats["pte_size_bytes"] = len(tester.get_artifact())
196199
except Exception as e:
197200
# We could introduce a result value for this, but I'm not sure it's necessary.
198201
# We can do this if we ever see to_executorch() or serialize() fail due a backend issue.

0 commit comments

Comments
 (0)