From 3ae7a78bc924223821113eab144b6a87f67cb139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5ns=20Nilsson?= Date: Mon, 18 Aug 2025 18:52:56 +0200 Subject: [PATCH] Arm backend: Add NGP unit test scripts Change-Id: I9a57e61364d110419af89a5e5a34cba0eb8f17da --- backends/arm/CMakeLists.txt | 5 +- backends/arm/README.md | 16 ++- .../arm/scripts/build_executor_runner_vkml.sh | 87 ++++++++++++++ backends/arm/scripts/run_vkml.sh | 4 +- backends/arm/test/ops/test_add.py | 16 +-- backends/arm/test/runner_utils.py | 21 +++- backends/arm/test/setup_testing.sh | 3 +- backends/arm/test/setup_testing_vkml.sh | 14 +++ backends/arm/test/test_arm_baremetal.sh | 81 ++++++++++++- backends/arm/test/test_model.py | 110 +++++++++++++++--- backends/arm/test/tester/test_pipeline.py | 4 +- examples/arm/aot_arm_compiler.py | 5 +- examples/arm/run.sh | 13 ++- examples/arm/setup.sh | 69 ++++++++++- 14 files changed, 393 insertions(+), 55 deletions(-) create mode 100755 backends/arm/scripts/build_executor_runner_vkml.sh create mode 100755 backends/arm/test/setup_testing_vkml.sh diff --git a/backends/arm/CMakeLists.txt b/backends/arm/CMakeLists.txt index cdde13a85a4..ede7a96a389 100644 --- a/backends/arm/CMakeLists.txt +++ b/backends/arm/CMakeLists.txt @@ -73,9 +73,10 @@ if(EXECUTORCH_BUILD_VGF) # vgf backend list(TRANSFORM _vgf_backend_sources PREPEND "${EXECUTORCH_ROOT}/") add_library(vgf_backend ${_vgf_backend_sources}) + install(TARGETS vgf_backend EXPORT ExecuTorchTargets) target_include_directories( - vgf_backend PUBLIC ${_common_include_directories} ${VULKAN_HEADERS_PATH} - ${VOLK_HEADERS_PATH} + vgf_backend PRIVATE ${_common_include_directories} ${VULKAN_HEADERS_PATH} + ${VOLK_HEADERS_PATH} ) target_compile_options( vgf_backend PRIVATE -DUSE_VULKAN_WRAPPER -DUSE_VULKAN_VOLK diff --git a/backends/arm/README.md b/backends/arm/README.md index e2e49c0c10f..e1df44bdb13 100644 --- a/backends/arm/README.md +++ b/backends/arm/README.md @@ -88,6 +88,19 @@ You can test to run some models with the full fvp test flow backends/arm/test/test_arm_baremetal.sh test_full_ethosu_fvp ``` +To run the unit test suite with VKML use the following. Note Vulkan SDK need to be installed. +Have a look at install_vulkan_sdk() in .ci/scripts/setup-vulkan-linux-deps.sh on how to install Vulkan SDK. + +``` +backends/arm/test/test_arm_baremetal.sh test_pytest_vkml +``` + +You can test to run some models with the full VKML flow + +``` +backends/arm/test/test_arm_baremetal.sh test_full_vkml +``` + ## Unit tests This is the structure of the test directory @@ -102,6 +115,7 @@ test # Root test folder ├── tosautil # Utility functions for TOSA artifacts ├ common.py # Common functions and definitions used by many tests ├ setup_testing.sh # Script to prepare testing for using the Corstone 3x0 FVP +├ setup_testing_vkml.sh # Script to prepare testing for using the VKML ├ test_arm_baremetal.sh # Help script to trigger testing ``` @@ -123,7 +137,7 @@ first you need to build and prepare some used target libs ``` examples/arm/run.sh --model_name=add --build_only -backends/arm/test/setup_testing.sh +backends/arm/test/setup_testing.sh and/or backends/arm/test/setup_testing_vkml.sh ``` The you can run the tests with diff --git a/backends/arm/scripts/build_executor_runner_vkml.sh b/backends/arm/scripts/build_executor_runner_vkml.sh new file mode 100755 index 00000000000..ecd33768577 --- /dev/null +++ b/backends/arm/scripts/build_executor_runner_vkml.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# Copyright 2025 Arm Limited and/or its affiliates. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +set -eu + +script_dir=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) +et_root_dir=$(cd ${script_dir}/../../.. && pwd) +et_root_dir=$(realpath ${et_root_dir}) +setup_path_script=${et_root_dir}/examples/arm/ethos-u-scratch/setup_path.sh +_setup_msg="please refer to ${et_root_dir}/examples/arm/setup.sh to properly install necessary tools." + +build_type="Release" +build_with_etdump=false +extra_build_flags="" +output_folder="cmake-out-vkml" + +build_with_etdump_flags=" -DEXECUTORCH_ENABLE_EVENT_TRACER=OFF " + +help() { + echo "Usage: $(basename $0) [options]" + echo "Options:" + echo " --build_type= Build with Release, Debug or RelWithDebInfo, default is ${build_type}" + echo " --etdump Adds Devtools etdump support to track timing, etdump area will be base64 encoded in the log" + echo " --extra_build_flags= Extra flags to pass to cmake. Default: none " + echo " --output= Output folder Default: $(output_folder)" + exit 0 +} + +for arg in "$@"; do + case $arg in + -h|--help) help ;; + --build_type=*) build_type="${arg#*=}";; + --etdump) build_with_etdump=true ;; + --extra_build_flags=*) extra_build_flags="${arg#*=}";; + --output=*) output_folder="${arg#*=}";; + --select_ops_list=*) select_ops_list="${arg#*=}";; + *) + ;; + esac +done + +# Source the tools +# This should be prepared by the setup.sh +[[ -f ${setup_path_script} ]] \ + || { echo "Missing ${setup_path_script}. ${_setup_msg}"; exit 1; } + +source ${setup_path_script} + +mkdir -p "${output_folder}" +output_folder=$(realpath ${output_folder}) + +echo "--------------------------------------------------------------------------------" +echo "Build Arm VKML executor runner: '${output_folder}' with extra build flags: ${extra_build_flags}" +echo "--------------------------------------------------------------------------------" + +cd ${et_root_dir}/examples/arm/executor_runner + +if [ "$build_with_etdump" = true ] ; then + build_with_etdump_flags=" -DEXECUTORCH_ENABLE_EVENT_TRACER=ON " +fi + +echo "Building with extra flags: ${build_with_etdump_flags} ${extra_build_flags}" +cmake \ + -DCMAKE_BUILD_TYPE=${build_type} \ + -DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \ + -DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \ + -DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \ + -DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \ + -DEXECUTORCH_BUILD_XNNPACK=OFF \ + -DEXECUTORCH_BUILD_VULKAN=ON \ + -DEXECUTORCH_BUILD_VGF=ON \ + -DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \ + -DEXECUTORCH_BUILD_KERNELS_QUANTIZED_AOT=ON \ + -DEXECUTORCH_ENABLE_LOGGING=ON \ + -DPYTHON_EXECUTABLE=$(which python3) \ + ${extra_build_flags} \ + -B ${output_folder} ${et_root_dir} + +echo "[${BASH_SOURCE[0]}] Configured CMAKE" + +cmake --build ${output_folder} -j$(nproc) + +echo "[${BASH_SOURCE[0]}] Built VKML runner: " +find ${output_folder} -name "executor_runner" diff --git a/backends/arm/scripts/run_vkml.sh b/backends/arm/scripts/run_vkml.sh index ebbdb7e415f..8a64a937638 100755 --- a/backends/arm/scripts/run_vkml.sh +++ b/backends/arm/scripts/run_vkml.sh @@ -19,14 +19,14 @@ _setup_msg="please refer to ${et_root_dir}/examples/arm/setup.sh to properly ins model="" -build_path="cmake-out" +build_path="cmake-out-vkml" converter="model-converter" help() { echo "Usage: $(basename $0) [options]" echo "Options:" echo " --model= .pte model file to run" - echo " --build= Target to build and run for Default: ${build_path}" + echo " --build_path= Path to executor_runner build. for Default: ${build_path}" exit 0 } diff --git a/backends/arm/test/ops/test_add.py b/backends/arm/test/ops/test_add.py index 6bf3830d038..0e825d57894 100644 --- a/backends/arm/test/ops/test_add.py +++ b/backends/arm/test/ops/test_add.py @@ -7,7 +7,6 @@ from typing import Tuple -import pytest import torch from executorch.backends.arm.quantizer import arm_quantizer from executorch.backends.arm.test import common, conftest @@ -186,13 +185,13 @@ def test_add_tensor_u85_INT_2(test_data: input_t2): pipeline.run() -@common.parametrize("test_data", Add.test_data) +# TODO/MLETORCH-1282: remove once inputs are not hard coded to ones +skip_keys = {"5d_float", "1d_ones", "1d_randn"} +filtered_test_data = {k: v for k, v in Add.test_data.items() if k not in skip_keys} + + +@common.parametrize("test_data", filtered_test_data) @common.SkipIfNoModelConverter -@common.XfailfNoVKMLEmulationLayer -@pytest.mark.xfail( - reason="VGF runtime is not yet fully supported for FP pipeline (MLETORCH-1234)", - strict=True, -) def test_add_tensor_vgf_FP(test_data: input_t1): pipeline = VgfPipeline[input_t1]( Add(), @@ -205,7 +204,7 @@ def test_add_tensor_vgf_FP(test_data: input_t1): pipeline.run() -@common.parametrize("test_data", Add.test_data) +@common.parametrize("test_data", filtered_test_data) @common.SkipIfNoModelConverter def test_add_tensor_vgf_INT(test_data: input_t1): pipeline = VgfPipeline[input_t1]( @@ -214,5 +213,6 @@ def test_add_tensor_vgf_INT(test_data: input_t1): aten_op, exir_op, tosa_version="TOSA-1.0+INT", + run_on_vulkan_runtime=True, ) pipeline.run() diff --git a/backends/arm/test/runner_utils.py b/backends/arm/test/runner_utils.py index 523a3f30a54..9234f4dd7e5 100644 --- a/backends/arm/test/runner_utils.py +++ b/backends/arm/test/runner_utils.py @@ -257,11 +257,21 @@ def run_vkml_emulation_layer( result_stdout = result.stdout.decode() # noqa: F841 # TODO: MLETORCH-1234: Support VGF e2e tests in VgfPipeline # TODO: Add regex to check for error or fault messages in stdout from Emulation Layer - # TODO: Retrieve and return the output tensors once VGF runtime is able to dump them. - raise NotImplementedError( - "Output parsing from VKML Emulation Layer is not yet implemented. " + # Regex to extract tensor values from stdout + output_np = [] + matches = re.findall( + r"Output\s+\d+:\s+tensor\(sizes=\[(.*?)\],\s+\[(.*?)\]\)", + result_stdout, + re.DOTALL, ) + for shape_str, values_str in matches: + shape = list(map(int, shape_str.split(","))) + values = list(map(float, re.findall(r"[-+]?\d*\.\d+|\d+", values_str))) + output_np.append(torch.tensor(values).reshape(shape)) + + return tuple(output_np) + def run_corstone( executorch_program_manager: ExecutorchProgramManager, @@ -626,7 +636,8 @@ def vkml_emulation_layer_installed() -> bool: def assert_elf_path_exists(elf_path): if not os.path.exists(elf_path): raise FileNotFoundError( - f"Did not find build arm_executor_runner or executor_runner in path {elf_path}, run setup_testing.sh?" + f"Did not find build arm_executor_runner or executor_runner in path {elf_path}, \ + run setup_testing.sh or setup_testing_vkml.sh?" ) @@ -643,7 +654,7 @@ def get_elf_path(target_board): assert_elf_path_exists(elf_path) elif target_board == "vkml_emulation_layer": elf_path = os.path.join( - "cmake-out", + "arm_test/arm_executor_runner_vkml", "executor_runner", ) assert_elf_path_exists(elf_path) diff --git a/backends/arm/test/setup_testing.sh b/backends/arm/test/setup_testing.sh index 449075f9611..d1e4725d93b 100755 --- a/backends/arm/test/setup_testing.sh +++ b/backends/arm/test/setup_testing.sh @@ -1,6 +1,5 @@ #!/usr/bin/env bash # Copyright 2024-2025 Arm Limited and/or its 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. @@ -13,4 +12,4 @@ build_executor_runner=${et_root_dir}/backends/arm/scripts/build_executor_runner. build_root_test_dir=${et_root_dir}/arm_test/arm_semihosting_executor_runner ${build_executor_runner} --pte=semihosting --target=ethos-u55-128 --output="${build_root_test_dir}_corstone-300" -${build_executor_runner} --pte=semihosting --target=ethos-u85-128 --output="${build_root_test_dir}_corstone-320" \ No newline at end of file +${build_executor_runner} --pte=semihosting --target=ethos-u85-128 --output="${build_root_test_dir}_corstone-320" diff --git a/backends/arm/test/setup_testing_vkml.sh b/backends/arm/test/setup_testing_vkml.sh new file mode 100755 index 00000000000..6edb2dca361 --- /dev/null +++ b/backends/arm/test/setup_testing_vkml.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# Copyright 2024-2025 Arm Limited and/or its affiliates. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +set -eu + +script_dir=$(realpath "$(dirname "${BASH_SOURCE[0]}")") +et_root_dir=$(realpath "${script_dir}/../../..") +build_executor_runner=${et_root_dir}/backends/arm/scripts/build_executor_runner_vkml.sh +build_root_test_dir=${et_root_dir}/arm_test/arm_executor_runner_vkml + +${build_executor_runner} --output="${build_root_test_dir}" diff --git a/backends/arm/test/test_arm_baremetal.sh b/backends/arm/test/test_arm_baremetal.sh index 80621528efb..53c707cad28 100755 --- a/backends/arm/test/test_arm_baremetal.sh +++ b/backends/arm/test/test_arm_baremetal.sh @@ -4,6 +4,8 @@ # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. +# TODO: Rename this script + set -e script_dir=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) @@ -151,6 +153,51 @@ test_pytest_ethosu_fvp() { # Same as test_pytest but also sometime verify using echo "${TEST_SUITE_NAME}: PASS" } + +test_pytest_ops_vkml() { # Same as test_pytest but also sometime verify using VKML runtime + echo "${TEST_SUITE_NAME}: Run pytest with VKML" + + backends/arm/scripts/build_executorch.sh + backends/arm/test/setup_testing_vkml.sh + + pytest --verbose --color=yes --numprocesses=auto --durations=10 backends/arm/test/ --ignore=backends/arm/test/models + echo "${TEST_SUITE_NAME}: PASS" +} + +test_pytest_models_vkml() { # Same as test_pytest but also sometime verify VKML runtime + echo "${TEST_SUITE_NAME}: Run pytest with VKML" + + backends/arm/scripts/build_executorch.sh + backends/arm/test/setup_testing_vkml.sh + + # Install model dependencies for pytest + source backends/arm/scripts/install_models_for_test.sh + + pytest --verbose --color=yes --numprocesses=auto --durations=0 backends/arm/test/models + echo "${TEST_SUITE_NAME}: PASS" +} + +test_pytest_vkml() { # Same as test_pytest but also sometime verify VKML runtime + echo "${TEST_SUITE_NAME}: Run pytest with VKML" + test_pytest_ops_vkml + test_pytest_models_vkml + echo "${TEST_SUITE_NAME}: PASS" +} + +test_run_vkml() { # End to End model tests using run.sh + echo "${TEST_SUITE_NAME}: Test VKML delegate examples with run.sh" + + echo "${TEST_SUITE_NAME}: Test VKML" + out_folder="arm_test/test_run" + examples/arm/run.sh --et_build_root=${out_folder} --target=vgf --model_name=add --output=${out_folder}/runner + examples/arm/run.sh --et_build_root=${out_folder} --target=vgf --model_name=mul --output=${out_folder}/runner + + examples/arm/run.sh --et_build_root=${out_folder} --target=vgf --model_name=qadd --output=${out_folder}/runner + examples/arm/run.sh --et_build_root=${out_folder} --target=vgf --model_name=qops --output=${out_folder}/runner + + echo "${TEST_SUITE_NAME}: PASS" +} + test_run_ethosu_fvp() { # End to End model tests using run.sh echo "${TEST_SUITE_NAME}: Test ethos-u delegate examples with run.sh" @@ -196,7 +243,21 @@ test_run_ethosu_fvp() { # End to End model tests using run.sh examples/arm/run.sh --et_build_root=arm_test/test_run --target=ethos-u85-128 --model_name=qops --bundleio echo "${TEST_SUITE_NAME}: PASS" - } +} + +test_models_vkml() { # End to End model tests using model_test.py + echo "${TEST_SUITE_NAME}: Test VKML delegated models with test_model.py" + + # Build common libs once + python3 backends/arm/test/test_model.py --test_output=arm_test/test_model --build_libs + + # VKML + echo "${TEST_SUITE_NAME}: Test target VKML" + python3 backends/arm/test/test_model.py --test_output=arm_test/test_model --target=vgf --model=mv2 + python3 backends/arm/test/test_model.py --test_output=arm_test/test_model --target=vgf --no_quantize --model=mv2 + + echo "${TEST_SUITE_NAME}: PASS" +} test_models_tosa() { # End to End model tests using model_test.py echo "${TEST_SUITE_NAME}: Test TOSA delegated models with test_model.py" @@ -219,7 +280,7 @@ test_models_tosa() { # End to End model tests using model_test.py python3 backends/arm/test/test_model.py --test_output=arm_test/test_model --target=TOSA-1.0+INT --model=resnet50 echo "${TEST_SUITE_NAME}: PASS" - } +} test_models_ethos-u55() { # End to End model tests using model_test.py echo "${TEST_SUITE_NAME}: Test Ethos-U55 delegated models with test_model.py" @@ -238,7 +299,7 @@ test_models_ethos-u55() { # End to End model tests using model_test.py #python3 backends/arm/test/test_model.py --test_output=arm_test/test_model --target=ethos-u55-128 --model=resnet50 --extra_flags="-DET_ATOL=6.2 -DET_RTOL=6.2" echo "${TEST_SUITE_NAME}: PASS" - } +} test_models_ethos-u85() { # End to End model tests using model_test.py echo "${TEST_SUITE_NAME}: Test Ethos-U85 delegated models with test_model.py" @@ -257,7 +318,7 @@ test_models_ethos-u85() { # End to End model tests using model_test.py python3 backends/arm/test/test_model.py --test_output=arm_test/test_model --target=ethos-u85-128 --model=resnet50 --extra_flags="-DET_ATOL=0.2 -DET_RTOL=0.2" echo "${TEST_SUITE_NAME}: PASS" - } +} test_full_ethosu_fvp() { # All End to End model tests @@ -268,7 +329,15 @@ test_full_ethosu_fvp() { # All End to End model tests test_models_ethos-u55 test_models_ethos-u85 echo "${TEST_SUITE_NAME}: PASS" - } +} + +test_full_vkml() { # All End to End model tests + echo "${TEST_SUITE_NAME}: Test VGF delegate models and examples with VKML" + + test_run_vkml + test_models_vkml + echo "${TEST_SUITE_NAME}: PASS" +} test_smaller_stories_llama() { echo "${TEST_SUITE_NAME}: Test smaller_stories_llama" @@ -294,7 +363,7 @@ test_smaller_stories_llama() { --llama_inputs stories110M/stories110M.pt stories110M/params.json stories110m echo "${TEST_SUITE_NAME}: PASS" - } +} ${TEST_SUITE} diff --git a/backends/arm/test/test_model.py b/backends/arm/test/test_model.py index f0dd9f3ff9c..8833b7050e7 100755 --- a/backends/arm/test/test_model.py +++ b/backends/arm/test/test_model.py @@ -56,6 +56,13 @@ def get_args(): default=False, help="Don't save temporary files during compilation", ) + parser.add_argument( + "--no_quantize", + action="store_true", + required=False, + default=False, + help="Don't quantize model", + ) parser.add_argument( "--extra_flags", required=False, @@ -120,30 +127,37 @@ def build_pte( memory_mode: str, build_output: str, no_intermediate: bool, + no_quantize: bool, ): + pte_file_ending = "pte" + command_list = [ + "python3", + "-m", + "examples.arm.aot_arm_compiler", + "--delegate", + f"--model_name={model_name}", + f"--target={target}", + f"--output={build_output}", + ] + + if "vgf" != target: + pte_file_ending = "bpte" + command_list.append("--bundleio") + command_list.append(f"--system_config={system_config}") + command_list.append(f"--memory_mode={memory_mode}") + + if not no_quantize: + command_list.append("--quantize") - intermediate = "" if not no_intermediate: - intermediate = f"--intermediate={output}" + command_list.append(f"--intermediate={output}") - run_external_cmd( - [ - "python3", - "-m", - "examples.arm.aot_arm_compiler", - "--delegate", - "--quantize", - "--bundleio", - intermediate, - f"--model_name={model_name}", - f"--target={target}", - f"--output={build_output}", - f"--system_config={system_config}", - f"--memory_mode={memory_mode}", - ] + run_external_cmd(command_list) + + pte_file = os.path.join( + output, f"{model_name}_arm_delegate_{args.target}.{pte_file_ending}" ) - pte_file = os.path.join(output, f"{model_name}_arm_delegate_{args.target}.bpte") return pte_file @@ -191,6 +205,39 @@ def run_elf_with_fvp(script_path: str, elf_file: str, target: str, timeout: int) ) +def build_vkml_runtime( + et_build_root: str, + script_path: str, + extra_flags: str, + build_path: str, +): + run_external_cmd( + [ + "bash", + os.path.join(script_path, "build_executor_runner_vkml.sh"), + f"--et_build_root={et_build_root}", + "--etdump", + "--build_type=Release", + f"--extra_build_flags=-DET_DUMP_OUTPUT=OFF {extra_flags}", + f"--output={build_path}", + ] + ) + + runner = os.path.join(build_path, "executor_runner") + return runner + + +def run_vkml(script_path: str, pte_file: str, runner_build_path: str): + run_external_cmd( + [ + "bash", + os.path.join(script_path, "run_vkml.sh"), + f"--model={pte_file}", + f"--build_path={runner_build_path}", + ] + ) + + if __name__ == "__main__": total_start_time = time.perf_counter() args = get_args() @@ -224,13 +271,38 @@ def run_elf_with_fvp(script_path: str, elf_file: str, target: str, timeout: int) args.memory_mode, output, args.no_intermediate, + args.no_quantize, ) end_time = time.perf_counter() print( f"[Test model: {end_time - start_time:.2f} s] PTE file created: {pte_file}" ) - if "ethos-u" in args.target: + if "vgf" == args.target: + build_path = os.path.join( + output, f"{model_name}_arm_delegate_{args.target}" + ) + + start_time = time.perf_counter() + vkml_runner = build_vkml_runtime( + args.test_output, + script_path, + args.extra_flags, + build_path, + ) + end_time = time.perf_counter() + print( + f"[Test model: {end_time - start_time:.2f} s] ELF file created: {vkml_runner}" + ) + + start_time = time.perf_counter() + run_vkml(script_path, pte_file, build_path) + end_time = time.perf_counter() + print( + f"[Test model: {end_time - start_time:.2f} s] Tested VKML runner: {vkml_runner}" + ) + + elif "ethos-u" in args.target: elf_build_path = os.path.join( output, f"{model_name}_arm_delegate_{args.target}" ) diff --git a/backends/arm/test/tester/test_pipeline.py b/backends/arm/test/tester/test_pipeline.py index 5c648d5ff2c..b9c01e195b2 100644 --- a/backends/arm/test/tester/test_pipeline.py +++ b/backends/arm/test/tester/test_pipeline.py @@ -892,9 +892,7 @@ class VgfPipeline(BasePipelineMaker, Generic[T]): exir_ops: Exir dialect ops expected to be found in the graph after to_edge. if not using use_edge_to_transform_and_lower. - run_on_vulkan_runtime: Partially supported. However, comparison between reference and model - outputs is expected to fail, as the VGF runtime doesn't dump the output tensors in a usable - format at the moment. + run_on_vulkan_runtime: Set to true to test VGF output on VKML runtime. vgf_compiler_flags: Optional compiler flags. diff --git a/examples/arm/aot_arm_compiler.py b/examples/arm/aot_arm_compiler.py index 72e91fc640d..c1e98816b95 100644 --- a/examples/arm/aot_arm_compiler.py +++ b/examples/arm/aot_arm_compiler.py @@ -834,8 +834,9 @@ def transform_for_cortex_m_backend(edge): exported_program, args, model, example_inputs ) - # Transform so we can use ops from the Cortex M backend - edge = transform_for_cortex_m_backend(edge) + if args.target != "vgf": + # Transform so we can use ops from the Cortex M backend + edge = transform_for_cortex_m_backend(edge) dump_delegation_info(edge, args.intermediates) diff --git a/examples/arm/run.sh b/examples/arm/run.sh index 172635a7744..397dd35ea36 100755 --- a/examples/arm/run.sh +++ b/examples/arm/run.sh @@ -60,7 +60,7 @@ function help() { echo " --etdump Adds Devtools etdump support to track timing, etdump area will be base64 encoded in the log" echo " --build_type= Build with Release, Debug or RelWithDebInfo, default is ${build_type}" echo " --extra_build_flags= Extra flags to pass to cmake like -DET_ARM_BAREMETAL_METHOD_ALLOCATOR_POOL_SIZE=60000 Default: none " - echo " --build_only Only build, don't run FVP" + echo " --build_only Only build, don't run" echo " --toolchain= Ethos-U: Toolchain can be specified (e.g. bare metal as arm-none-eabi-gcc or zephyr as arm-zephyr-eabi-gcc Default: ${toolchain}" echo " --system_config= Ethos-U: System configuration to select from the Vela configuration file (see vela.ini). Default: Ethos_U55_High_End_Embedded for EthosU55 targets, Ethos_U85_SYS_DRAM_Mid for EthosU85 targets." echo " NOTE: If given, this option must match the given target. This option also sets timing adapter values customized for specific hardware, see ./executor_runner/CMakeLists.txt." @@ -287,6 +287,17 @@ for i in "${!test_model[@]}"; do if [[ ${target} == *"TOSA"* ]]; then echo "Build for ${target} skip generating a .elf and running it" + elif [[ ${target} == *"vgf"* ]]; then + echo "Build and run for VKML, (target: ${target})" + set -x + backends/arm/scripts/build_executor_runner_vkml.sh --build_type=${build_type} \ + --extra_build_flags="${extra_build_flags}" \ + --output="${output_folder}" + if [ "$build_only" = false ] ; then + backends/arm/scripts/run_vkml.sh --model=${pte_file} --build_path=${output_folder} + fi + set +x + else # Build the application, the pte is imported as a header/c array or the address specified by --pte_placement model_data="" diff --git a/examples/arm/setup.sh b/examples/arm/setup.sh index 050b0f93c46..48a681bc8f8 100755 --- a/examples/arm/setup.sh +++ b/examples/arm/setup.sh @@ -9,9 +9,9 @@ set -u -######## +######################## ### Hardcoded constants -######## +######################## script_dir=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) et_dir=$(realpath $script_dir/../..) ARCH="$(uname -m)" @@ -25,8 +25,10 @@ enable_vela=1 enable_model_converter=0 # model-converter tool for VGF output enable_vgf_lib=0 # vgf reader - runtime backend dependency enable_emulation_layer=0 # Vulkan layer driver - emulates Vulkan ML extensions +enable_vulkan_sdk=0 # Download and export Vulkan SDK required by emulation layer mlsdk_manifest_url="https://github.com/arm/ai-ml-sdk-manifest.git" - +vulkan_sdk_version="1.4.321.1" +vulkan_sdk_base_dir="vulkan_sdk" # Figure out if setup.sh was called or sourced and save it into "is_script_sourced" (return 0 2>/dev/null) && is_script_sourced=1 || is_script_sourced=0 @@ -45,6 +47,11 @@ if [[ "${ARCH}" == "x86_64" ]]; then corstone320_url="https://developer.arm.com/-/media/Arm%20Developer%20Community/Downloads/OSS/FVP/Corstone-320/FVP_Corstone_SSE-320_11.27_25_Linux64.tgz?rev=a507bffc219a4d5792f1192ab7002d89&hash=D9A824AA8227D2E679C9B9787FF4E8B6FBE3D7C6" corstone320_model_dir="Linux64_GCC-9.3" corstone320_md5_checksum="3deb3c68f9b2d145833f15374203514d" + + # Vulkan SDK + vulkan_sdk_url="https://sdk.lunarg.com/sdk/download/${vulkan_sdk_version}/linux/vulkansdk-linux-x86_64-${vulkan_sdk_version}.tar.xz" + vulkan_sdk_sha256="f22a3625bd4d7a32e7a0d926ace16d5278c149e938dac63cecc00537626cbf73" + elif [[ "${ARCH}" == "aarch64" ]] || [[ "${ARCH}" == "arm64" ]]; then # FVPs corstone300_url="https://developer.arm.com/-/media/Arm%20Developer%20Community/Downloads/OSS/FVP/Corstone-300/FVP_Corstone_SSE-300_11.22_20_Linux64_armv8l.tgz?rev=9cc6e9a32bb947ca9b21fa162144cb01&hash=7657A4CF27D42E892E3F08D452AAB073" @@ -54,6 +61,11 @@ elif [[ "${ARCH}" == "aarch64" ]] || [[ "${ARCH}" == "arm64" ]]; then corstone320_url="https://developer.arm.com/-/media/Arm%20Developer%20Community/Downloads/OSS/FVP/Corstone-320/FVP_Corstone_SSE-320_11.27_25_Linux64_armv8l.tgz?rev=b6ebe0923cb84f739e017385fd3c333c&hash=8965C4B98E2FF7F792A099B08831FE3CB6120493" corstone320_model_dir="Linux64_armv8l_GCC-9.3" corstone320_md5_checksum="3889f1d80a6d9861ea4aa6f1c88dd0ae" + + # Vulkan SDK + vulkan_sdk_url="https://github.com/jakoch/vulkan-sdk-arm/releases/download/1.4.321.1/vulkansdk-ubuntu-22.04-arm-1.4.321.1.tar.xz" + vulkan_sdk_sha256="c57e318d0940394d3a304034bb7ddabda788b5b0b54638e80e90f7264efe9f84" + else echo "[main] Error: only x86-64 & aarch64/arm64 architecture is supported for now!"; exit 1; fi @@ -64,6 +76,7 @@ vela_rev="d37febc1715edf0d236c2ff555739a8a9aadcf9a" # MLSDK dependencies mlsdk_manifest_dir="ml-sdk-for-vulkan-manifest" +vulkan_sdk_bin_dir="${vulkan_sdk_base_dir}/${vulkan_sdk_version}/${ARCH}/bin" # List of supported options and their descriptions OPTION_LIST=( @@ -156,6 +169,10 @@ function check_options() { enable_emulation_layer=1 shift ;; + --enable-vulkan-sdk) + enable_vulkan_sdk=1 + shift + ;; --disable-ethos-u-deps) enable_baremetal_toolchain=0 enable_fvps=0 @@ -166,6 +183,7 @@ function check_options() { enable_model_converter=1 enable_vgf_lib=1 enable_emulation_layer=1 + enable_vulkan_sdk=1 shift ;; --mlsdk-manifest-url) @@ -272,6 +290,36 @@ function setup_fvp() { done } +function setup_vulkan_sdk() { + + if command -v vulkaninfo > /dev/null 2>&1; then + echo "[${FUNCNAME[0]}] Vulkan SDK already installed..." + enable_vulkan_sdk=0 + return + fi + + cd "${root_dir}" + + vulkan_sdk_tar_file="${vulkan_sdk_url##*/}" + if [[ ! -e "${vulkan_sdk_tar_file}" ]]; then + echo "[${FUNCNAME[0]}] Downloading Vulkan SDK - ${vulkan_sdk_url}.." + curl -L --output "${vulkan_sdk_tar_file}" "${vulkan_sdk_url}" + echo "${vulkan_sdk_sha256} ${vulkan_sdk_tar_file}" | sha256sum -c - + rm -fr ${vulkan_sdk_base_dir} + fi + + mkdir -p ${vulkan_sdk_base_dir} + tar -C ${vulkan_sdk_base_dir} -xJf "${vulkan_sdk_tar_file}" + + vulkan_sdk_bin_path="$(cd ${vulkan_sdk_bin_dir} && pwd)" + if ${vulkan_sdk_bin_path}/vulkaninfo > /dev/null 2>&1; then + echo "[${FUNCNAME[0]}] Vulkan SDK OK" + else + echo "[${FUNCNAME[0]}] Vulkan SDK NOK - perhaps need manual install of swifthshader or mesa-vulkan driver?" + exit 1 + fi +} + function select_toolchain() { if [[ "${ARCH}" == "x86_64" ]]; then if [[ "${OS}" == "Linux" ]]; then @@ -372,6 +420,12 @@ function create_setup_path(){ append_env_in_setup_path PATH ${toolchain_bin_path} fi + if [[ "${enable_vulkan_sdk}" -eq 1 ]]; then + cd "${root_dir}" + vulkan_sdk_bin_path="$(cd ${vulkan_sdk_bin_dir} && pwd)" + append_env_in_setup_path PATH ${vulkan_sdk_bin_path} + fi + if [[ "${enable_model_converter}" -eq 1 ]]; then cd "${root_dir}" model_converter_bin_path="$(cd ${mlsdk_manifest_dir}/sw/model-converter/build && pwd)" @@ -432,6 +486,7 @@ if [[ $is_script_sourced -eq 0 ]]; then echo "enable-model-converter=${enable_model_converter}" echo "enable-vgf-lib=${enable_vgf_lib}" echo "enable-emulation-layer=${enable_emulation_layer}" + echo "enable-vulkan-sdk=${enable_vulkan_sdk}" echo "enable-vela=${enable_vela}" echo "mlsdk-manifest-url=${mlsdk_manifest_url}" @@ -451,6 +506,11 @@ if [[ $is_script_sourced -eq 0 ]]; then setup_fvp fi + # Setup Vulkan SDK + if [[ "${enable_vulkan_sdk}" -eq 1 ]]; then + setup_vulkan_sdk + fi + if [[ "${enable_model_converter}" -eq 1 || \ "${enable_vgf_lib}" -eq 1 || \ "${enable_emulation_layer}" -eq 1 ]]; then @@ -460,7 +520,8 @@ if [[ $is_script_sourced -eq 0 ]]; then # Create new setup_path script if [[ "${enable_baremetal_toolchain}" -eq 1 || \ - "${enable_fvps}" -eq 1 || \ + "${enable_fvps}" -eq 1 || \ + "${enable_vulkan_sdk}" -eq 1 || \ "${enable_model_converter}" -eq 1 ]]; then create_setup_path fi