Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .ci/docker/common/install_zephyr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
11 changes: 8 additions & 3 deletions .ci/scripts/setup-arm-baremetal-tools.sh
Original file line number Diff line number Diff line change
@@ -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 "[email protected]"
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 "[email protected]"
fi
bash examples/arm/setup.sh --i-agree-to-the-contained-eula ${@:-}
20 changes: 4 additions & 16 deletions .ci/scripts/zephyr-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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



Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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"

Expand All @@ -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
Expand Down
112 changes: 60 additions & 52 deletions .github/workflows/trunk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -86,88 +95,87 @@ 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 "<!-- RUN install_reqs -->"

# 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 "<!-- RUN west_init -->"

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 "<!-- RUN west_config -->"

# 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
rm -Rf modules/lib/executorch
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 "[email protected]"
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 "[email protected]"
fi

echo "---- Cortex-M55 ----"
rm -Rf build
run_command_block_from_zephyr_readme "<!-- RUN install_executorch -->"

# 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 "<!-- RUN install_arm_tools -->"

# 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 "<!-- RUN setup_${BOARD}_fvp -->"

# 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 "<!-- RUN test_${TARGET}_generate_pte -->"

# 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 "<!-- RUN test_${TARGET}_build_and_run -->"
done

test-models-linux-aarch64:
name: test-models-linux-aarch64
Expand Down
58 changes: 57 additions & 1 deletion backends/arm/test/test_github_trunk_zephyr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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:
# <!-- RUN test_XX_generate_pte -->
# <!-- RUN test_XX_build_and_run -->
# 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 <<EOF
Usage: $(basename "$0") [OPTIONS]

Options:
-t, --target-list LIST Comma-separated targets (default: ${TARGET_LIST})
-h, --help Show this help and exit

You can also set TARGET_LIST environment variable.
Examples:
$(basename "$0")
$(basename "$0") -t ethos-u55,cortex-m55
$(basename "$0") --target-list=ethos-u85
EOF
}

# No-arg support: loop simply won't run and defaults are used
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
-t|--target-list)
if [[ -z "${2:-}" || "$2" == -* ]]; then
echo "Error: $1 requires a non-empty argument."
usage
exit 2
fi
TARGET_LIST="$2"
shift 2
;;
--target-list=*)
TARGET_LIST="${1#*=}"
shift
;;
*)
echo "Error: Unknown option: $1"
usage
exit 2
;;
esac
done
export TARGET_LIST

echo "Running .github/workflows/trunk.yml testing ${TARGET_LIST} from zephyr/README.md"

SCRIPT_CONTENT="$(python - <<'PY'
from ruamel.yaml import YAML
with open(".github/workflows/trunk.yml") as f:
Expand Down
Loading
Loading