diff --git a/backends/qualcomm/tests/TARGETS b/backends/qualcomm/tests/TARGETS index 8078ca611f8..cb6bfa21b25 100644 --- a/backends/qualcomm/tests/TARGETS +++ b/backends/qualcomm/tests/TARGETS @@ -37,3 +37,13 @@ python_library( "//executorch/backends/qualcomm/debugger:utils", ], ) + +python_library( + name = "tester", + srcs = [ + "tester.py", + ], + deps = [ + ":test_qnn_delegate" + ] +) diff --git a/backends/qualcomm/tests/tester.py b/backends/qualcomm/tests/tester.py new file mode 100644 index 00000000000..58dda07ef46 --- /dev/null +++ b/backends/qualcomm/tests/tester.py @@ -0,0 +1,88 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Any, List, Optional, Tuple + +import executorch +import executorch.backends.test.harness.stages as BaseStages + +import torch +from executorch.backends.qualcomm._passes.qnn_pass_manager import QnnPassManager +from executorch.backends.qualcomm.partition.qnn_partitioner import QnnPartitioner +from executorch.backends.qualcomm.utils.utils import ( + generate_htp_compiler_spec, + generate_qnn_executorch_compiler_spec, + get_soc_to_chipset_map, +) +from executorch.backends.test.harness import Tester as TesterBase +from executorch.backends.test.harness.stages import StageType +from executorch.exir import EdgeCompileConfig, to_edge_transform_and_lower +from executorch.exir.backend.partitioner import Partitioner +from torch.export import ExportedProgram + + +class Partition(BaseStages.Partition): + def __init__(self, partitioner: Optional[Partitioner] = None): + super().__init__( + partitioner=partitioner or QnnPartitioner, + ) + + +class ToEdgeTransformAndLower(BaseStages.ToEdgeTransformAndLower): + def __init__( + self, + partitioners: Optional[List[Partitioner]] = None, + edge_compile_config: Optional[EdgeCompileConfig] = None, + soc_model: str = "SM8650", + ): + backend_options = generate_htp_compiler_spec(use_fp16=True) + self.chipset = get_soc_to_chipset_map()[soc_model] + self.compiler_specs = generate_qnn_executorch_compiler_spec( + soc_model=self.chipset, + backend_options=backend_options, + ) + + super().__init__( + partitioners=partitioners or [QnnPartitioner(self.compiler_specs)], + edge_compile_config=edge_compile_config + or EdgeCompileConfig(_check_ir_validity=False), + default_partitioner_cls=QnnPartitioner, + ) + + def run(self, artifact: ExportedProgram, inputs=None) -> None: + ep = QnnPassManager().transform_for_export_pipeline(artifact) + transform_passes = QnnPassManager().get_to_edge_transform_passes(ep) + + self.edge_dialect_program = to_edge_transform_and_lower( + ep, + transform_passes=transform_passes, + partitioner=self.partitioners, + compile_config=self.edge_compile_conf, + ) + + +class QualcommTester(TesterBase): + def __init__( + self, + module: torch.nn.Module, + example_inputs: Tuple[torch.Tensor], + dynamic_shapes: Optional[Tuple[Any]] = None, + ): + # Specialize for Qualcomm + stage_classes = ( + executorch.backends.test.harness.Tester.default_stage_classes() + | { + StageType.PARTITION: Partition, + StageType.TO_EDGE_TRANSFORM_AND_LOWER: ToEdgeTransformAndLower, + } + ) + + super().__init__( + module=module, + stage_classes=stage_classes, + example_inputs=example_inputs, + dynamic_shapes=dynamic_shapes, + ) diff --git a/backends/test/suite/flow.py b/backends/test/suite/flow.py index 2e2c2bf9391..124891fc541 100644 --- a/backends/test/suite/flow.py +++ b/backends/test/suite/flow.py @@ -71,4 +71,13 @@ def all_flows() -> dict[str, TestFlow]: except Exception as e: logger.info(f"Skipping Vulkan flow registration: {e}") + try: + from executorch.backends.test.suite.flows.qualcomm import QUALCOMM_TEST_FLOW + + flows += [ + QUALCOMM_TEST_FLOW, + ] + except Exception as e: + logger.info(f"Skipping Qualcomm flow registration: {e}") + return {f.name: f for f in flows if f is not None} diff --git a/backends/test/suite/flows/qualcomm.py b/backends/test/suite/flows/qualcomm.py new file mode 100644 index 00000000000..bf17061597b --- /dev/null +++ b/backends/test/suite/flows/qualcomm.py @@ -0,0 +1,17 @@ +from executorch.backends.qualcomm.tests.tester import QualcommTester +from executorch.backends.test.suite.flow import TestFlow + + +def _create_qualcomm_flow( + name: str, + quantize: bool = False, +) -> TestFlow: + return TestFlow( + name, + backend="qualcomm", + tester_factory=QualcommTester, + quantize=quantize, + ) + + +QUALCOMM_TEST_FLOW = _create_qualcomm_flow("qualcomm")