diff --git a/.ci/docker/common/install_zephyr.sh b/.ci/docker/common/install_zephyr.sh index c24bb5aa8f1..7275c7b91f6 100644 --- a/.ci/docker/common/install_zephyr.sh +++ b/.ci/docker/common/install_zephyr.sh @@ -2,6 +2,7 @@ #!/bin/bash # Copyright (c) Meta Platforms, Inc. and affiliates. # All rights reserved. +# Copyright 2026 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. @@ -82,6 +83,13 @@ install_prerequiresites() { rm -f kitware-archive.sh pip_install --no-cache-dir west pip_install pyelftools + + # Zephyr SDK + wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/zephyr-sdk-0.17.4_linux-x86_64.tar.xz + tar -xf zephyr-sdk-0.17.4_linux-x86_64.tar.xz + rm -f zephyr-sdk-0.17.4_linux-x86_64.tar.xz* + # Save setup to later and this get symlinked in to another folder in the test in trunk.yml + #./zephyr-sdk-0.17.4/setup.sh -c -t arm-zephyr-eabi } install_prerequiresites diff --git a/.ci/scripts/setup-arm-baremetal-tools.sh b/.ci/scripts/setup-arm-baremetal-tools.sh index e27c52f5125..7f6b2d07b95 100755 --- a/.ci/scripts/setup-arm-baremetal-tools.sh +++ b/.ci/scripts/setup-arm-baremetal-tools.sh @@ -1,11 +1,16 @@ #!/bin/bash -# Copyright 2024 Arm Limited and/or its affiliates. +# Copyright 2024,2026 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. # NB: This function could be used to install Arm dependencies # Setup arm example environment (including TOSA tools) -git config --global user.email "github_executorch@arm.com" -git config --global user.name "Github Executorch" +# Configure git user only if not already set +if ! git config --get user.name >/dev/null 2>&1; then + git config --global user.name "Github Executorch" +fi +if ! git config --get user.email >/dev/null 2>&1; then + git config --global user.email "github_executorch@arm.com" +fi bash examples/arm/setup.sh --i-agree-to-the-contained-eula ${@:-} diff --git a/.ci/scripts/zephyr-utils.sh b/.ci/scripts/zephyr-utils.sh index c5ea4b3d328..8415a7c29cb 100644 --- a/.ci/scripts/zephyr-utils.sh +++ b/.ci/scripts/zephyr-utils.sh @@ -26,8 +26,8 @@ # # The blockheader is 'Install requirements' and the code block is 'pip install something ... \npip install something_else' # so if we run -# run_command_block_from_zephyr_readme 'Install requirements' '^(pip|pip3)[[:space:]]+install([[:space:]].*)?$' -# it will make sure each lite start with pip or pip3 and then run them one by one +# run_command_block_from_zephyr_readme 'Install requirements' +# it will run them one by one @@ -88,8 +88,7 @@ _zephyr_utils_extract_block () { _zephyr_utils_run_simple_commands () { local block="$1" - local allowedpattern="$2" - local description="$3" + local description="$2" temp_dir="$(mktemp -d)" if [[ ! -d "${temp_dir}" ]]; then echo "ERROR: Failed to create temporary directory for west init" >&2 @@ -103,16 +102,6 @@ _zephyr_utils_run_simple_commands () { cmd="${cmd%"${cmd##*[![:space:]]}"}" [[ -z "${cmd}" ]] && continue - if [[ ! "${cmd}" =~ ${allowedpattern} ]]; then - echo "ERROR: Unexpected command in '${description}' readme block: ${cmd} must match pattern: ${allowedpattern}" >&2 - return 1 - fi - - if [[ "${cmd}" == *";"* || "${cmd}" == *"&&"* || "${cmd}" == *"||"* || "${cmd}" == *"|"* ]]; then - echo "ERROR: Command chaining is not allowed in '${description}' readme block: ${cmd}" >&2 - return 1 - fi - echo "Running: ${cmd}" if ! eval "${cmd}"; then return 1 @@ -130,7 +119,6 @@ _zephyr_utils_run_simple_commands () { run_command_block_from_zephyr_readme () { local blockheader="$1" - local allowedpattern="$2" echo "Run block '${blockheader}' from zephyr/README.md" @@ -143,7 +131,7 @@ run_command_block_from_zephyr_readme () { echo "ERROR: Failed to locate ${blockheader} block in ${readme_path}" >&2 return 1 fi - _zephyr_utils_run_simple_commands "${block}" "${allowedpattern}" "${blockheader}" + _zephyr_utils_run_simple_commands "${block}" "${blockheader}" } # Check that zephyr/executorch.yaml match zephyr/README.md diff --git a/.github/workflows/trunk.yml b/.github/workflows/trunk.yml index 4ec1789846f..ff4ba94b8cc 100644 --- a/.github/workflows/trunk.yml +++ b/.github/workflows/trunk.yml @@ -59,6 +59,8 @@ jobs: name: test-arm-backend-zephyr uses: pytorch/test-infra/.github/workflows/linux_job.yml@main strategy: + matrix: + target: [ethos-u55, cortex-m55, ethos-u85] fail-fast: false with: runner: linux.2xlarge @@ -75,6 +77,13 @@ jobs: # Test zephyr backend set -e + # Support comma-separated TARGET_LIST or ${{ matrix.target }} list, e.g., TARGET_LIST="ethos-u55,cortex-m55,ethos-u85" + if [ -z "${TARGET_LIST:-}" ]; then + IFS=',' read -r -a TARGETS <<< "${{ matrix.target }}" + else + IFS=',' read -r -a TARGETS <<< "${TARGET_LIST}" + fi + export EXECUTORCH_PROJ_ROOT=$(realpath $(pwd)) # Source utility scripts @@ -86,32 +95,44 @@ jobs: # Based on instruction in zephyr/README.md - # Allowed only "pip install ..." commands - allowedpattern='^(pip|pip3)[[:space:]]+install([[:space:]].*)?$' - run_command_block_from_zephyr_readme 'Install requirements' "${allowedpattern}" + run_command_block_from_zephyr_readme "" + # Make sure to backup the zephyr_scratch folder if it exists to allow for local + # testing that does not lose code/data + if [ -d "zephyr_scratch" ]; then + mv "zephyr_scratch" "zephyr_scratch.backup.$(date +%Y%m%d%H%M%S)" + fi mkdir -p zephyr_scratch/ cd zephyr_scratch export ZEPHYR_PROJ_ROOT=$(realpath $(pwd)) - # TODO @Bujji: Should see if this can be moved into the docker image itself - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/zephyr-sdk-0.17.4_linux-x86_64.tar.xz - tar -xf zephyr-sdk-0.17.4_linux-x86_64.tar.xz - rm -f zephyr-sdk-0.17.4_linux-x86_64.tar.xz* + echo "---- Zephyr SDK ----" + # Use ZephyrSDK if on the disk (e.g. setup in the docker) + # Check for a zephyr-sdk-0.17.4 directory and make a symlink if found in parent directories + if sdk_dir=$(find ../../.. -maxdepth 4 -type d -name 'zephyr-sdk-0.17.4' -print -quit) && [ -n "${sdk_dir}" ]; then + echo "---- Found pre downloaded Zephyr SDK in ${sdk_dir} ----" + ln -s "${sdk_dir}" . + fi + + # Download and setup Zephyr SDK 0.17.4 if not already present + if [ ! -d "zephyr-sdk-0.17.4" ]; then + echo "---- Downloading Zephyr SDK ----" + wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/zephyr-sdk-0.17.4_linux-x86_64.tar.xz + tar -xf zephyr-sdk-0.17.4_linux-x86_64.tar.xz + rm -f zephyr-sdk-0.17.4_linux-x86_64.tar.xz* + fi ./zephyr-sdk-0.17.4/setup.sh -c -t arm-zephyr-eabi export ZEPHYR_SDK_INSTALL_DIR=$(realpath ./zephyr-sdk-0.17.4) cd ${ZEPHYR_PROJ_ROOT} - # Allowed only "west init ..." commands - run_command_block_from_zephyr_readme 'Setup zephyr repo' '^west[[:space:]]+init([[:space:]].*)?$' + run_command_block_from_zephyr_readme "" cp ${EXECUTORCH_PROJ_ROOT}/zephyr/executorch.yaml zephyr/submanifests/ - # Allowed only "west ..." commands - run_command_block_from_zephyr_readme 'Add ExecuTorch to Zephyr' '^west([[:space:]].*)?$' + run_command_block_from_zephyr_readme "" # Switch to executorch in this PR e.g. replace modules/lib/executorch with the root folder of this repo # instead of doing a re-checkout and figure out the correct commit hash etc @@ -119,55 +140,42 @@ jobs: ln -s ${EXECUTORCH_PROJ_ROOT} modules/lib/executorch # Setup git local user for Executorch git to allows modules/lib/executorch/examples/arm/setup.sh be run inside CI later - git config --global user.email "github_executorch@arm.com" - git config --global user.name "Github Executorch" - - # Allowed only "cd/git/install_executorch.sh" commands - run_command_block_from_zephyr_readme 'Setup ExecuTorch' '^(cd [^;&|]+|git submodule([[:space:]].*)?|\./install_executorch\.sh([[:space:]].*)?)$' - - # As "cd" was an allowed command in the last run_command_block_from_zephyr_readme - # lets ensure we are back to the expected folder - cd ${ZEPHYR_PROJ_ROOT} - - # Allowed only "examples/arm/setup.sh and source of the generated script" command - run_command_block_from_zephyr_readme 'Install TOSA, vela and FVPs' '^(modules/lib/executorch/examples/arm/setup\.sh([[:space:]].*)?|(source|\.) modules/lib/executorch/examples/arm/arm-scratch/setup_path\.sh)$' - - echo "===== Corstone300 FVP setup ====" - - # Allowed only "export" command - run_command_block_from_zephyr_readme 'Config Zephyr Corstone300 FVP' '^export([[:space:]].*)$' - - echo "---- Ethos-U55 ----" - rm -Rf build - - # Allowed only "aot_arm_compiler" command - run_command_block_from_zephyr_readme 'Prepare the Ethos-U55 PTE model' '^python -m modules.lib.executorch.examples.arm.aot_arm_compiler([[:space:]].*)?$' - - # Allowed only "west build" command - run_command_block_from_zephyr_readme 'Run the Ethos-U55 PTE model' '^west build([[:space:]].*)?$' + # Configure git user only if not already set + if ! git config --get user.name >/dev/null 2>&1; then + git config --global user.name "Github Executorch" + fi + if ! git config --get user.email >/dev/null 2>&1; then + git config --global user.email "github_executorch@arm.com" + fi - echo "---- Cortex-M55 ----" - rm -Rf build + run_command_block_from_zephyr_readme "" - # Allowed only "aot_arm_compiler" command - run_command_block_from_zephyr_readme 'Prepare the Cortex-M55 PTE model' '^python -m modules.lib.executorch.examples.arm.aot_arm_compiler([[:space:]].*)?$' + run_command_block_from_zephyr_readme "" - # Allowed only "west build" command - run_command_block_from_zephyr_readme 'Run the Cortex-M55 PTE model' '^west build([[:space:]].*)?$' + for TARGET in "${TARGETS[@]}"; do + TARGET="$(echo "$TARGET" | xargs)" # trim whitespace - echo "===== Corstone320 FVP setup ====" + echo "---- ${TARGET} ----" + rm -Rf build - # Allowed only "export" command - run_command_block_from_zephyr_readme 'Config Zephyr Corstone320 FVP' '^export([[:space:]].*)$' + if [[ ${TARGET} == "ethos-u55" || ${TARGET} == "cortex-m55" ]]; then + BOARD="corstone300" + elif [[ ${TARGET} == "ethos-u85" ]]; then + BOARD="corstone320" + else + echo "Fail unsupport target selection ${TARGET}" + exit 1 + fi - echo "---- Ethos-U85 ----" - rm -Rf build + echo "---- ${TARGET} Board ${BOARD} FVP setup ----" + run_command_block_from_zephyr_readme "" - # Allowed only "aot_arm_compiler" command - run_command_block_from_zephyr_readme 'Prepare the Ethos-U85 PTE model' '^python -m modules.lib.executorch.examples.arm.aot_arm_compiler([[:space:]].*)?$' + echo "---- ${TARGET} Create PTE ----" + run_command_block_from_zephyr_readme "" - # Allowed only "west build" command - run_command_block_from_zephyr_readme 'Run the Ethos-U85 PTE model' '^west build([[:space:]].*)?$' + echo "---- ${TARGET} Build and run ----" + run_command_block_from_zephyr_readme "" + done test-models-linux-aarch64: name: test-models-linux-aarch64 diff --git a/backends/arm/test/test_github_trunk_zephyr.sh b/backends/arm/test/test_github_trunk_zephyr.sh index d7b7351b16a..36d4e40411c 100755 --- a/backends/arm/test/test_github_trunk_zephyr.sh +++ b/backends/arm/test/test_github_trunk_zephyr.sh @@ -8,12 +8,68 @@ # instructions are correct.by running the tests content of test-arm-backend-zephyr in # github/workflows/trunk.yml as a bash script, (ignoring the conda commands) # This is mostly useful for testing this before upstreaming or for debugging CI issues. +# Or a way to setup zephyrOS so you can play with it. +# Parse optional argument to set TARGET_LIST environment variable -set -eu pipefail +# Target list (--target-list) adds a comma separated list of targets you want to test +# matching the zephyr/README.md tags: +# +# +# e.g. one or more of this: ethos-u55,cortex-m55,ethos-u85 + +set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" ROOT_DIR="$(cd "${SCRIPT_DIR}" && pwd)" +TARGET_LIST="${TARGET_LIST:-ethos-u55,cortex-m55,ethos-u85}" +usage() { + cat < ``` pip install west cmake==3.29 pyelftools ninja jsonschema ``` Setup zephyr repo + ``` west init --manifest-rev v4.3.0 ``` @@ -51,6 +53,7 @@ manifest: ## Run west config and update: Add ExecuTorch to Zephyr + ``` west config manifest.project-filter -- -.*,+zephyr,+executorch,+cmsis,+cmsis_6,+cmsis-nn,+hal_ethos_u west update @@ -59,6 +62,7 @@ west update ## Setup and install ExecuTorch Setup ExecuTorch + ``` cd modules/lib/executorch/ git submodule sync @@ -74,6 +78,7 @@ This is needed to convert python models to PTE files for Ethos™-Ux5 and al Make sure to read and agree to the Corstone™ eula Install TOSA, vela and FVPs + ``` modules/lib/executorch/examples/arm/setup.sh --i-agree-to-the-contained-eula . modules/lib/executorch/examples/arm/arm-scratch/setup_path.sh @@ -91,6 +96,7 @@ To run you need to point of the path to the installed Corstone™ FVP and yo Set up FVP paths and macs used, this will also set shutdown_on_eot so the FVP auto stops after it has run the example. Config Zephyr Corstone300 FVP + ``` export FVP_ROOT=$PWD/modules/lib/executorch/examples/arm/arm-scratch/FVP-corstone300 export ARMFVP_BIN_PATH=${FVP_ROOT}/models/Linux64_GCC-9.3 @@ -102,6 +108,7 @@ export ARMFVP_EXTRA_FLAGS="-C mps3_board.uart0.shutdown_on_eot=1 -C ethosu.num_m #### Prepare a PTE model file Prepare the Ethos-U55 PTE model + ``` python -m modules.lib.executorch.examples.arm.aot_arm_compiler --model_name=modules/lib/executorch/examples/arm/example_modules/add.py --quantize --delegate -t ethos-u55-128 --output=add_u55_128.pte ``` @@ -111,6 +118,7 @@ python -m modules.lib.executorch.examples.arm.aot_arm_compiler --model_name=modu #### Build and run Run the Ethos-U55 PTE model + ``` west build -b mps3/corstone300/fvp modules/lib/executorch/examples/arm/zephyr -t run -- -DET_PTE_FILE_PATH=add_u55_128.pte ``` @@ -120,6 +128,7 @@ west build -b mps3/corstone300/fvp modules/lib/executorch/examples/arm/zephyr -t #### Prepare a PTE model file Prepare the Cortex-M55 PTE model + ``` python -m modules.lib.executorch.examples.arm.aot_arm_compiler --model_name=modules/lib/executorch/examples/arm/example_modules/add.py --quantize --output=add_m55.pte ``` @@ -127,6 +136,7 @@ python -m modules.lib.executorch.examples.arm.aot_arm_compiler --model_name=modu #### Build and run Run the Cortex-M55 PTE model + ``` west build -b mps3/corstone300/fvp modules/lib/executorch/examples/arm/zephyr -t run -- -DET_PTE_FILE_PATH=add_m55.pte ``` @@ -138,10 +148,11 @@ west build -b mps3/corstone300/fvp modules/lib/executorch/examples/arm/zephyr -t Set up FVP paths, libs and macs used, this will also set shutdown_on_eot so the FVP auto stops after it has run the example. Config Zephyr Corstone320 FVP + ``` export FVP_ROOT=$PWD/modules/lib/executorch/examples/arm/arm-scratch/FVP-corstone320 -export LD_LIBRARY_PATH=${FVP_ROOT}/python/lib:${ARMFVP_BIN_PATH}:${LD_LIBRARY_PATH} export ARMFVP_BIN_PATH=${FVP_ROOT}/models/Linux64_GCC-9.3 +export LD_LIBRARY_PATH=${FVP_ROOT}/python/lib:${ARMFVP_BIN_PATH}:${LD_LIBRARY_PATH} export ARMFVP_EXTRA_FLAGS="-C mps4_board.uart0.shutdown_on_eot=1 -C mps4_board.subsystem.ethosu.num_macs=256" ``` @@ -150,6 +161,7 @@ export ARMFVP_EXTRA_FLAGS="-C mps4_board.uart0.shutdown_on_eot=1 -C mps4_board.s #### Prepare a PTE model file Prepare the Ethos-U85 PTE model + ``` python -m modules.lib.executorch.examples.arm.aot_arm_compiler --model_name=modules/lib/executorch/examples/arm/example_modules/add.py --quantize --delegate -t ethos-u85-256 --output=add_u85_256.pte ``` @@ -159,6 +171,7 @@ python -m modules.lib.executorch.examples.arm.aot_arm_compiler --model_name=modu #### Build and run Run the Ethos-U85 PTE model + ``` west build -b mps4/corstone320/fvp modules/lib/executorch/examples/arm/zephyr -t run -- -DET_PTE_FILE_PATH=add_u85_256.pte ```