xref: /aosp_15_r20/external/executorch/backends/arm/test/common.py (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1*523fa7a6SAndroid Build Coastguard Worker# Copyright 2024 Arm Limited and/or its affiliates.
2*523fa7a6SAndroid Build Coastguard Worker# All rights reserved.
3*523fa7a6SAndroid Build Coastguard Worker#
4*523fa7a6SAndroid Build Coastguard Worker# This source code is licensed under the BSD-style license found in the
5*523fa7a6SAndroid Build Coastguard Worker# LICENSE file in the root directory of this source tree.
6*523fa7a6SAndroid Build Coastguard Worker
7*523fa7a6SAndroid Build Coastguard Workerimport logging
8*523fa7a6SAndroid Build Coastguard Workerimport os
9*523fa7a6SAndroid Build Coastguard Workerimport platform
10*523fa7a6SAndroid Build Coastguard Workerimport shutil
11*523fa7a6SAndroid Build Coastguard Workerimport subprocess
12*523fa7a6SAndroid Build Coastguard Workerimport sys
13*523fa7a6SAndroid Build Coastguard Workerimport tempfile
14*523fa7a6SAndroid Build Coastguard Workerfrom datetime import datetime
15*523fa7a6SAndroid Build Coastguard Workerfrom enum import auto, Enum
16*523fa7a6SAndroid Build Coastguard Workerfrom pathlib import Path
17*523fa7a6SAndroid Build Coastguard Workerfrom typing import Any
18*523fa7a6SAndroid Build Coastguard Worker
19*523fa7a6SAndroid Build Coastguard Workerimport pytest
20*523fa7a6SAndroid Build Coastguard Worker
21*523fa7a6SAndroid Build Coastguard Workerimport torch
22*523fa7a6SAndroid Build Coastguard Worker
23*523fa7a6SAndroid Build Coastguard Workerfrom executorch.backends.arm.arm_backend import ArmCompileSpecBuilder
24*523fa7a6SAndroid Build Coastguard Workerfrom executorch.exir.backend.compile_spec_schema import CompileSpec
25*523fa7a6SAndroid Build Coastguard Worker
26*523fa7a6SAndroid Build Coastguard Worker
27*523fa7a6SAndroid Build Coastguard Workerclass arm_test_options(Enum):
28*523fa7a6SAndroid Build Coastguard Worker    quantize_io = auto()
29*523fa7a6SAndroid Build Coastguard Worker    corstone300 = auto()
30*523fa7a6SAndroid Build Coastguard Worker    dump_path = auto()
31*523fa7a6SAndroid Build Coastguard Worker    date_format = auto()
32*523fa7a6SAndroid Build Coastguard Worker    fast_fvp = auto()
33*523fa7a6SAndroid Build Coastguard Worker
34*523fa7a6SAndroid Build Coastguard Worker
35*523fa7a6SAndroid Build Coastguard Worker_test_options: dict[arm_test_options, Any] = {}
36*523fa7a6SAndroid Build Coastguard Worker
37*523fa7a6SAndroid Build Coastguard Worker# ==== Pytest hooks ====
38*523fa7a6SAndroid Build Coastguard Worker
39*523fa7a6SAndroid Build Coastguard Worker
40*523fa7a6SAndroid Build Coastguard Workerdef pytest_addoption(parser):
41*523fa7a6SAndroid Build Coastguard Worker    parser.addoption("--arm_quantize_io", action="store_true")
42*523fa7a6SAndroid Build Coastguard Worker    parser.addoption("--arm_run_corstone300", action="store_true")
43*523fa7a6SAndroid Build Coastguard Worker    parser.addoption("--default_dump_path", default=None)
44*523fa7a6SAndroid Build Coastguard Worker    parser.addoption("--date_format", default="%d-%b-%H:%M:%S")
45*523fa7a6SAndroid Build Coastguard Worker    parser.addoption("--fast_fvp", action="store_true")
46*523fa7a6SAndroid Build Coastguard Worker
47*523fa7a6SAndroid Build Coastguard Worker
48*523fa7a6SAndroid Build Coastguard Workerdef pytest_configure(config):
49*523fa7a6SAndroid Build Coastguard Worker    if config.option.arm_quantize_io:
50*523fa7a6SAndroid Build Coastguard Worker        load_libquantized_ops_aot_lib()
51*523fa7a6SAndroid Build Coastguard Worker        _test_options[arm_test_options.quantize_io] = True
52*523fa7a6SAndroid Build Coastguard Worker    if config.option.arm_run_corstone300:
53*523fa7a6SAndroid Build Coastguard Worker        corstone300_exists = shutil.which("FVP_Corstone_SSE-300_Ethos-U55")
54*523fa7a6SAndroid Build Coastguard Worker        if not corstone300_exists:
55*523fa7a6SAndroid Build Coastguard Worker            raise RuntimeError(
56*523fa7a6SAndroid Build Coastguard Worker                "Tests are run with --arm_run_corstone300 but corstone300 FVP is not installed."
57*523fa7a6SAndroid Build Coastguard Worker            )
58*523fa7a6SAndroid Build Coastguard Worker        _test_options[arm_test_options.corstone300] = True
59*523fa7a6SAndroid Build Coastguard Worker    if config.option.default_dump_path:
60*523fa7a6SAndroid Build Coastguard Worker        dump_path = Path(config.option.default_dump_path).expanduser()
61*523fa7a6SAndroid Build Coastguard Worker        if dump_path.exists() and os.path.isdir(dump_path):
62*523fa7a6SAndroid Build Coastguard Worker            _test_options[arm_test_options.dump_path] = dump_path
63*523fa7a6SAndroid Build Coastguard Worker        else:
64*523fa7a6SAndroid Build Coastguard Worker            raise RuntimeError(
65*523fa7a6SAndroid Build Coastguard Worker                f"Supplied argument 'default_dump_path={dump_path}' that does not exist or is not a directory."
66*523fa7a6SAndroid Build Coastguard Worker            )
67*523fa7a6SAndroid Build Coastguard Worker    _test_options[arm_test_options.date_format] = config.option.date_format
68*523fa7a6SAndroid Build Coastguard Worker    _test_options[arm_test_options.fast_fvp] = config.option.fast_fvp
69*523fa7a6SAndroid Build Coastguard Worker    logging.basicConfig(level=logging.INFO, stream=sys.stdout)
70*523fa7a6SAndroid Build Coastguard Worker
71*523fa7a6SAndroid Build Coastguard Worker
72*523fa7a6SAndroid Build Coastguard Workerdef pytest_collection_modifyitems(config, items):
73*523fa7a6SAndroid Build Coastguard Worker    if not config.option.arm_quantize_io:
74*523fa7a6SAndroid Build Coastguard Worker        skip_if_aot_lib_not_loaded = pytest.mark.skip(
75*523fa7a6SAndroid Build Coastguard Worker            "u55 tests can only run with quantize_io=True."
76*523fa7a6SAndroid Build Coastguard Worker        )
77*523fa7a6SAndroid Build Coastguard Worker
78*523fa7a6SAndroid Build Coastguard Worker        for item in items:
79*523fa7a6SAndroid Build Coastguard Worker            if "u55" in item.name:
80*523fa7a6SAndroid Build Coastguard Worker                item.add_marker(skip_if_aot_lib_not_loaded)
81*523fa7a6SAndroid Build Coastguard Worker
82*523fa7a6SAndroid Build Coastguard Worker
83*523fa7a6SAndroid Build Coastguard Workerdef pytest_sessionstart(session):
84*523fa7a6SAndroid Build Coastguard Worker    pass
85*523fa7a6SAndroid Build Coastguard Worker
86*523fa7a6SAndroid Build Coastguard Worker
87*523fa7a6SAndroid Build Coastguard Workerdef pytest_sessionfinish(session, exitstatus):
88*523fa7a6SAndroid Build Coastguard Worker    if get_option(arm_test_options.dump_path):
89*523fa7a6SAndroid Build Coastguard Worker        _clean_dir(
90*523fa7a6SAndroid Build Coastguard Worker            get_option(arm_test_options.dump_path),
91*523fa7a6SAndroid Build Coastguard Worker            f"ArmTester_{get_option(arm_test_options.date_format)}.log",
92*523fa7a6SAndroid Build Coastguard Worker        )
93*523fa7a6SAndroid Build Coastguard Worker
94*523fa7a6SAndroid Build Coastguard Worker
95*523fa7a6SAndroid Build Coastguard Worker# ==== End of Pytest hooks =====
96*523fa7a6SAndroid Build Coastguard Worker
97*523fa7a6SAndroid Build Coastguard Worker# ==== Custom Pytest decorators =====
98*523fa7a6SAndroid Build Coastguard Worker
99*523fa7a6SAndroid Build Coastguard Worker
100*523fa7a6SAndroid Build Coastguard Workerdef expectedFailureOnFVP(test_item):
101*523fa7a6SAndroid Build Coastguard Worker    if is_option_enabled("corstone300"):
102*523fa7a6SAndroid Build Coastguard Worker        test_item.__unittest_expecting_failure__ = True
103*523fa7a6SAndroid Build Coastguard Worker    return test_item
104*523fa7a6SAndroid Build Coastguard Worker
105*523fa7a6SAndroid Build Coastguard Worker
106*523fa7a6SAndroid Build Coastguard Worker# ==== End of Custom Pytest decorators =====
107*523fa7a6SAndroid Build Coastguard Worker
108*523fa7a6SAndroid Build Coastguard Worker
109*523fa7a6SAndroid Build Coastguard Workerdef load_libquantized_ops_aot_lib():
110*523fa7a6SAndroid Build Coastguard Worker    so_ext = {
111*523fa7a6SAndroid Build Coastguard Worker        "Darwin": "dylib",
112*523fa7a6SAndroid Build Coastguard Worker        "Linux": "so",
113*523fa7a6SAndroid Build Coastguard Worker        "Windows": "dll",
114*523fa7a6SAndroid Build Coastguard Worker    }.get(platform.system(), None)
115*523fa7a6SAndroid Build Coastguard Worker
116*523fa7a6SAndroid Build Coastguard Worker    find_lib_cmd = [
117*523fa7a6SAndroid Build Coastguard Worker        "find",
118*523fa7a6SAndroid Build Coastguard Worker        "cmake-out-aot-lib",
119*523fa7a6SAndroid Build Coastguard Worker        "-name",
120*523fa7a6SAndroid Build Coastguard Worker        f"libquantized_ops_aot_lib.{so_ext}",
121*523fa7a6SAndroid Build Coastguard Worker    ]
122*523fa7a6SAndroid Build Coastguard Worker    res = subprocess.run(find_lib_cmd, capture_output=True)
123*523fa7a6SAndroid Build Coastguard Worker    if res.returncode == 0:
124*523fa7a6SAndroid Build Coastguard Worker        library_path = res.stdout.decode().strip()
125*523fa7a6SAndroid Build Coastguard Worker        torch.ops.load_library(library_path)
126*523fa7a6SAndroid Build Coastguard Worker
127*523fa7a6SAndroid Build Coastguard Worker
128*523fa7a6SAndroid Build Coastguard Workerdef is_option_enabled(
129*523fa7a6SAndroid Build Coastguard Worker    option: str | arm_test_options, fail_if_not_enabled: bool = False
130*523fa7a6SAndroid Build Coastguard Worker) -> bool:
131*523fa7a6SAndroid Build Coastguard Worker    """
132*523fa7a6SAndroid Build Coastguard Worker    Returns whether an option is successfully enabled, i.e. if the flag was
133*523fa7a6SAndroid Build Coastguard Worker    given to pytest and the necessary requirements are available.
134*523fa7a6SAndroid Build Coastguard Worker    Implemented options are:
135*523fa7a6SAndroid Build Coastguard Worker        - corstone300.
136*523fa7a6SAndroid Build Coastguard Worker        - quantize_io.
137*523fa7a6SAndroid Build Coastguard Worker
138*523fa7a6SAndroid Build Coastguard Worker    The optional parameter 'fail_if_not_enabled' makes the function raise
139*523fa7a6SAndroid Build Coastguard Worker      a RuntimeError instead of returning False.
140*523fa7a6SAndroid Build Coastguard Worker    """
141*523fa7a6SAndroid Build Coastguard Worker    if isinstance(option, str):
142*523fa7a6SAndroid Build Coastguard Worker        option = arm_test_options[option.lower()]
143*523fa7a6SAndroid Build Coastguard Worker
144*523fa7a6SAndroid Build Coastguard Worker    if option in _test_options and _test_options[option]:
145*523fa7a6SAndroid Build Coastguard Worker        return True
146*523fa7a6SAndroid Build Coastguard Worker    else:
147*523fa7a6SAndroid Build Coastguard Worker        if fail_if_not_enabled:
148*523fa7a6SAndroid Build Coastguard Worker            raise RuntimeError(f"Required option '{option}' for test is not enabled")
149*523fa7a6SAndroid Build Coastguard Worker        else:
150*523fa7a6SAndroid Build Coastguard Worker            return False
151*523fa7a6SAndroid Build Coastguard Worker
152*523fa7a6SAndroid Build Coastguard Worker
153*523fa7a6SAndroid Build Coastguard Workerdef get_option(option: arm_test_options) -> Any | None:
154*523fa7a6SAndroid Build Coastguard Worker    if option in _test_options:
155*523fa7a6SAndroid Build Coastguard Worker        return _test_options[option]
156*523fa7a6SAndroid Build Coastguard Worker    return None
157*523fa7a6SAndroid Build Coastguard Worker
158*523fa7a6SAndroid Build Coastguard Worker
159*523fa7a6SAndroid Build Coastguard Workerdef maybe_get_tosa_collate_path() -> str | None:
160*523fa7a6SAndroid Build Coastguard Worker    """
161*523fa7a6SAndroid Build Coastguard Worker    Checks the environment variable TOSA_TESTCASES_BASE_PATH and returns the
162*523fa7a6SAndroid Build Coastguard Worker    path to the where to store the current tests if it is set.
163*523fa7a6SAndroid Build Coastguard Worker    """
164*523fa7a6SAndroid Build Coastguard Worker    tosa_test_base = os.environ.get("TOSA_TESTCASES_BASE_PATH")
165*523fa7a6SAndroid Build Coastguard Worker    if tosa_test_base:
166*523fa7a6SAndroid Build Coastguard Worker        current_test = os.environ.get("PYTEST_CURRENT_TEST")
167*523fa7a6SAndroid Build Coastguard Worker        #'backends/arm/test/ops/test_mean_dim.py::TestMeanDim::test_meandim_tosa_BI_0_zeros (call)'
168*523fa7a6SAndroid Build Coastguard Worker        test_class = current_test.split("::")[1]
169*523fa7a6SAndroid Build Coastguard Worker        test_name = current_test.split("::")[-1].split(" ")[0]
170*523fa7a6SAndroid Build Coastguard Worker        if "BI" in test_name:
171*523fa7a6SAndroid Build Coastguard Worker            tosa_test_base = os.path.join(tosa_test_base, "tosa-bi")
172*523fa7a6SAndroid Build Coastguard Worker        elif "MI" in test_name:
173*523fa7a6SAndroid Build Coastguard Worker            tosa_test_base = os.path.join(tosa_test_base, "tosa-mi")
174*523fa7a6SAndroid Build Coastguard Worker        else:
175*523fa7a6SAndroid Build Coastguard Worker            tosa_test_base = os.path.join(tosa_test_base, "other")
176*523fa7a6SAndroid Build Coastguard Worker
177*523fa7a6SAndroid Build Coastguard Worker        return os.path.join(tosa_test_base, test_class, test_name)
178*523fa7a6SAndroid Build Coastguard Worker
179*523fa7a6SAndroid Build Coastguard Worker    return None
180*523fa7a6SAndroid Build Coastguard Worker
181*523fa7a6SAndroid Build Coastguard Worker
182*523fa7a6SAndroid Build Coastguard Workerdef get_tosa_compile_spec(
183*523fa7a6SAndroid Build Coastguard Worker    tosa_version: str, permute_memory_to_nhwc=True, custom_path=None
184*523fa7a6SAndroid Build Coastguard Worker) -> list[CompileSpec]:
185*523fa7a6SAndroid Build Coastguard Worker    """
186*523fa7a6SAndroid Build Coastguard Worker    Default compile spec for TOSA tests.
187*523fa7a6SAndroid Build Coastguard Worker    """
188*523fa7a6SAndroid Build Coastguard Worker    return get_tosa_compile_spec_unbuilt(
189*523fa7a6SAndroid Build Coastguard Worker        tosa_version, permute_memory_to_nhwc, custom_path
190*523fa7a6SAndroid Build Coastguard Worker    ).build()
191*523fa7a6SAndroid Build Coastguard Worker
192*523fa7a6SAndroid Build Coastguard Worker
193*523fa7a6SAndroid Build Coastguard Workerdef get_tosa_compile_spec_unbuilt(
194*523fa7a6SAndroid Build Coastguard Worker    tosa_version: str, permute_memory_to_nhwc=False, custom_path=None
195*523fa7a6SAndroid Build Coastguard Worker) -> ArmCompileSpecBuilder:
196*523fa7a6SAndroid Build Coastguard Worker    """Get the ArmCompileSpecBuilder for the default TOSA tests, to modify
197*523fa7a6SAndroid Build Coastguard Worker    the compile spec before calling .build() to finalize it.
198*523fa7a6SAndroid Build Coastguard Worker    """
199*523fa7a6SAndroid Build Coastguard Worker    if not custom_path:
200*523fa7a6SAndroid Build Coastguard Worker        intermediate_path = maybe_get_tosa_collate_path() or tempfile.mkdtemp(
201*523fa7a6SAndroid Build Coastguard Worker            prefix="arm_tosa_"
202*523fa7a6SAndroid Build Coastguard Worker        )
203*523fa7a6SAndroid Build Coastguard Worker    else:
204*523fa7a6SAndroid Build Coastguard Worker        intermediate_path = custom_path
205*523fa7a6SAndroid Build Coastguard Worker
206*523fa7a6SAndroid Build Coastguard Worker    if not os.path.exists(intermediate_path):
207*523fa7a6SAndroid Build Coastguard Worker        os.makedirs(intermediate_path, exist_ok=True)
208*523fa7a6SAndroid Build Coastguard Worker    compile_spec_builder = (
209*523fa7a6SAndroid Build Coastguard Worker        ArmCompileSpecBuilder()
210*523fa7a6SAndroid Build Coastguard Worker        .tosa_compile_spec(tosa_version)
211*523fa7a6SAndroid Build Coastguard Worker        .set_permute_memory_format(permute_memory_to_nhwc)
212*523fa7a6SAndroid Build Coastguard Worker        .dump_intermediate_artifacts_to(intermediate_path)
213*523fa7a6SAndroid Build Coastguard Worker    )
214*523fa7a6SAndroid Build Coastguard Worker
215*523fa7a6SAndroid Build Coastguard Worker    return compile_spec_builder
216*523fa7a6SAndroid Build Coastguard Worker
217*523fa7a6SAndroid Build Coastguard Worker
218*523fa7a6SAndroid Build Coastguard Workerdef get_u55_compile_spec(
219*523fa7a6SAndroid Build Coastguard Worker    permute_memory_to_nhwc=True, quantize_io=False, custom_path=None
220*523fa7a6SAndroid Build Coastguard Worker) -> list[CompileSpec]:
221*523fa7a6SAndroid Build Coastguard Worker    """
222*523fa7a6SAndroid Build Coastguard Worker    Default compile spec for Ethos-U55 tests.
223*523fa7a6SAndroid Build Coastguard Worker    """
224*523fa7a6SAndroid Build Coastguard Worker    return get_u55_compile_spec_unbuilt(
225*523fa7a6SAndroid Build Coastguard Worker        permute_memory_to_nhwc, quantize_io=quantize_io, custom_path=custom_path
226*523fa7a6SAndroid Build Coastguard Worker    ).build()
227*523fa7a6SAndroid Build Coastguard Worker
228*523fa7a6SAndroid Build Coastguard Worker
229*523fa7a6SAndroid Build Coastguard Workerdef get_u85_compile_spec(
230*523fa7a6SAndroid Build Coastguard Worker    permute_memory_to_nhwc=True, quantize_io=False, custom_path=None
231*523fa7a6SAndroid Build Coastguard Worker) -> list[CompileSpec]:
232*523fa7a6SAndroid Build Coastguard Worker    """
233*523fa7a6SAndroid Build Coastguard Worker    Default compile spec for Ethos-U85 tests.
234*523fa7a6SAndroid Build Coastguard Worker    """
235*523fa7a6SAndroid Build Coastguard Worker    return get_u85_compile_spec_unbuilt(
236*523fa7a6SAndroid Build Coastguard Worker        permute_memory_to_nhwc, quantize_io=quantize_io, custom_path=custom_path
237*523fa7a6SAndroid Build Coastguard Worker    ).build()
238*523fa7a6SAndroid Build Coastguard Worker
239*523fa7a6SAndroid Build Coastguard Worker
240*523fa7a6SAndroid Build Coastguard Workerdef get_u55_compile_spec_unbuilt(
241*523fa7a6SAndroid Build Coastguard Worker    permute_memory_to_nhwc=True, quantize_io=False, custom_path=None
242*523fa7a6SAndroid Build Coastguard Worker) -> ArmCompileSpecBuilder:
243*523fa7a6SAndroid Build Coastguard Worker    """Get the ArmCompileSpecBuilder for the Ethos-U55 tests, to modify
244*523fa7a6SAndroid Build Coastguard Worker    the compile spec before calling .build() to finalize it.
245*523fa7a6SAndroid Build Coastguard Worker    """
246*523fa7a6SAndroid Build Coastguard Worker    artifact_path = custom_path or tempfile.mkdtemp(prefix="arm_u55_")
247*523fa7a6SAndroid Build Coastguard Worker    if not os.path.exists(artifact_path):
248*523fa7a6SAndroid Build Coastguard Worker        os.makedirs(artifact_path, exist_ok=True)
249*523fa7a6SAndroid Build Coastguard Worker    compile_spec = (
250*523fa7a6SAndroid Build Coastguard Worker        ArmCompileSpecBuilder()
251*523fa7a6SAndroid Build Coastguard Worker        .ethosu_compile_spec(
252*523fa7a6SAndroid Build Coastguard Worker            "ethos-u55-128",
253*523fa7a6SAndroid Build Coastguard Worker            system_config="Ethos_U55_High_End_Embedded",
254*523fa7a6SAndroid Build Coastguard Worker            memory_mode="Shared_Sram",
255*523fa7a6SAndroid Build Coastguard Worker            extra_flags="--debug-force-regor --output-format=raw",
256*523fa7a6SAndroid Build Coastguard Worker        )
257*523fa7a6SAndroid Build Coastguard Worker        .set_quantize_io(is_option_enabled("quantize_io") or quantize_io)
258*523fa7a6SAndroid Build Coastguard Worker        .set_permute_memory_format(permute_memory_to_nhwc)
259*523fa7a6SAndroid Build Coastguard Worker        .dump_intermediate_artifacts_to(artifact_path)
260*523fa7a6SAndroid Build Coastguard Worker    )
261*523fa7a6SAndroid Build Coastguard Worker    return compile_spec
262*523fa7a6SAndroid Build Coastguard Worker
263*523fa7a6SAndroid Build Coastguard Worker
264*523fa7a6SAndroid Build Coastguard Workerdef get_u85_compile_spec_unbuilt(
265*523fa7a6SAndroid Build Coastguard Worker    permute_memory_to_nhwc=True, quantize_io=False, custom_path=None
266*523fa7a6SAndroid Build Coastguard Worker) -> list[CompileSpec]:
267*523fa7a6SAndroid Build Coastguard Worker    """Get the ArmCompileSpecBuilder for the Ethos-U85 tests, to modify
268*523fa7a6SAndroid Build Coastguard Worker    the compile spec before calling .build() to finalize it.
269*523fa7a6SAndroid Build Coastguard Worker    """
270*523fa7a6SAndroid Build Coastguard Worker    artifact_path = custom_path or tempfile.mkdtemp(prefix="arm_u85_")
271*523fa7a6SAndroid Build Coastguard Worker    compile_spec = (
272*523fa7a6SAndroid Build Coastguard Worker        ArmCompileSpecBuilder()
273*523fa7a6SAndroid Build Coastguard Worker        .ethosu_compile_spec(
274*523fa7a6SAndroid Build Coastguard Worker            "ethos-u85-128",
275*523fa7a6SAndroid Build Coastguard Worker            system_config="Ethos_U85_SYS_DRAM_Mid",
276*523fa7a6SAndroid Build Coastguard Worker            memory_mode="Shared_Sram",
277*523fa7a6SAndroid Build Coastguard Worker            extra_flags="--output-format=raw",
278*523fa7a6SAndroid Build Coastguard Worker        )
279*523fa7a6SAndroid Build Coastguard Worker        .set_quantize_io(is_option_enabled("quantize_io") or quantize_io)
280*523fa7a6SAndroid Build Coastguard Worker        .set_permute_memory_format(permute_memory_to_nhwc)
281*523fa7a6SAndroid Build Coastguard Worker        .dump_intermediate_artifacts_to(artifact_path)
282*523fa7a6SAndroid Build Coastguard Worker    )
283*523fa7a6SAndroid Build Coastguard Worker    return compile_spec
284*523fa7a6SAndroid Build Coastguard Worker
285*523fa7a6SAndroid Build Coastguard Worker
286*523fa7a6SAndroid Build Coastguard Workerdef current_time_formated() -> str:
287*523fa7a6SAndroid Build Coastguard Worker    """Return current time as a formated string"""
288*523fa7a6SAndroid Build Coastguard Worker    return datetime.now().strftime(get_option(arm_test_options.date_format))
289*523fa7a6SAndroid Build Coastguard Worker
290*523fa7a6SAndroid Build Coastguard Worker
291*523fa7a6SAndroid Build Coastguard Workerdef _clean_dir(dir: Path, filter: str, num_save=10):
292*523fa7a6SAndroid Build Coastguard Worker    sorted_files: list[tuple[datetime, Path]] = []
293*523fa7a6SAndroid Build Coastguard Worker    for file in dir.iterdir():
294*523fa7a6SAndroid Build Coastguard Worker        try:
295*523fa7a6SAndroid Build Coastguard Worker            creation_time = datetime.strptime(file.name, filter)
296*523fa7a6SAndroid Build Coastguard Worker            insert_index = -1
297*523fa7a6SAndroid Build Coastguard Worker            for i, to_compare in enumerate(sorted_files):
298*523fa7a6SAndroid Build Coastguard Worker                compare_time = to_compare[0]
299*523fa7a6SAndroid Build Coastguard Worker                if creation_time < compare_time:
300*523fa7a6SAndroid Build Coastguard Worker                    insert_index = i
301*523fa7a6SAndroid Build Coastguard Worker                    break
302*523fa7a6SAndroid Build Coastguard Worker            if insert_index == -1 and len(sorted_files) < num_save:
303*523fa7a6SAndroid Build Coastguard Worker                sorted_files.append((creation_time, file))
304*523fa7a6SAndroid Build Coastguard Worker            else:
305*523fa7a6SAndroid Build Coastguard Worker                sorted_files.insert(insert_index, (creation_time, file))
306*523fa7a6SAndroid Build Coastguard Worker        except ValueError:
307*523fa7a6SAndroid Build Coastguard Worker            continue
308*523fa7a6SAndroid Build Coastguard Worker
309*523fa7a6SAndroid Build Coastguard Worker    if len(sorted_files) > num_save:
310*523fa7a6SAndroid Build Coastguard Worker        for remove in sorted_files[0 : len(sorted_files) - num_save]:
311*523fa7a6SAndroid Build Coastguard Worker            file = remove[1]
312*523fa7a6SAndroid Build Coastguard Worker            file.unlink()
313