Skip to content

Commit d978236

Browse files
ExecuTorch on Ethos-U85 via the PyTorch::ExecuTorch source pack
Docker-free alternative to main: the model is exported in a plain venv and the NPU/Vela configuration is driven by the csolution's mlops: node. The ExecuTorch runtime comes from a source CMSIS pack, so only the operators the model uses are linked. Targets Corstone-320 / Ethos-U85; Load/Run/Debug are wired to the FVP through fvp-gdb, with a Codespaces devcontainer. The model export runs on Linux, macOS and Windows. All the setup logic lives in setup_venv.py, with thin .sh/.bat wrappers, and the convert-model build step dispatches through CMake (executes: has no host-OS conditional, and bash is not available on Windows by default). Python pins follow ExecuTorch release/1.4: torch 2.13.0 from PyPI, executorch and torchao from the PyTorch nightly index, and the TOSA serializer installed with --no-deps so tosa-tools cannot upgrade flatbuffers past 24.3.25.
0 parents  commit d978236

981 files changed

Lines changed: 190434 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/devcontainer.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "cmsis-executorch-simple",
3+
"image": "mcr.microsoft.com/devcontainers/base:ubuntu-22.04",
4+
"features": {
5+
"ghcr.io/devcontainers/features/sshd:1": {}
6+
},
7+
"hostRequirements": {
8+
"cpus": 4,
9+
"memory": "8gb",
10+
"storage": "32gb"
11+
},
12+
"customizations": {
13+
"vscode": {
14+
"extensions": [
15+
"Arm.keil-studio-pack",
16+
"llvm-vs-code-extensions.vscode-clangd"
17+
]
18+
}
19+
},
20+
"postCreateCommand": "bash .devcontainer/post-create.sh"
21+
}

.devcontainer/post-create.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env bash
2+
# Copyright 2026 Arm Limited and/or its affiliates.
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Devcontainer/Codespaces bootstrap. Deliberately minimal: the Arm Environment
6+
# Manager (part of the Keil Studio extension pack) reads
7+
# vcpkg-configuration.json itself and installs/activates CMSIS-Toolbox,
8+
# arm-none-eabi-gcc, cmake, ninja and the AVH FVPs (incl.
9+
# FVP_Corstone_SSE-320), and it bundles armlm for the license activation.
10+
# This script only covers what the extension does not:
11+
set -euo pipefail
12+
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
13+
cd "${HERE}"
14+
15+
# FVP runtime dependencies (libpython3.9 via deadsnakes on Ubuntu 22.04) and
16+
# lsof for .vscode/start-fvp-gdb.sh. software-properties-common first: the
17+
# devcontainer base image does not ship add-apt-repository.
18+
sudo apt-get update
19+
sudo apt-get install -y --no-install-recommends software-properties-common
20+
sudo add-apt-repository -y ppa:deadsnakes/ppa
21+
sudo apt-get install -y --no-install-recommends \
22+
libatomic1 libpython3.9 libstdc++6 lsof python3-venv python3-pip
23+
sudo rm -rf /var/lib/apt/lists/*
24+
25+
# fvp-gdb: GDB-RSP front-end for the FVP's Iris interface; drives the CMSIS
26+
# Solution panel's Load/Run/Debug buttons (see .vscode/start-fvp-gdb.sh).
27+
python3 -m pip install --user --index-url https://test.pypi.org/simple/ \
28+
--extra-index-url https://pypi.org/simple fvp-gdb
29+
sudo ln -sf "${HOME}/.local/bin/fvp-gdb" /usr/local/bin/fvp-gdb
30+
31+
# Model-export venv (executorch + ethos-u-vela). setup_venv.py is idempotent
32+
# and rebuilds the venv by itself if its interpreter no longer runs -- the case
33+
# after a container rebuild, since /workspaces persists but the image's Python
34+
# does not.
35+
./setup_venv.sh
36+
37+
echo
38+
echo "Devcontainer ready. The Arm Environment Manager installs the vcpkg"
39+
echo "artifacts (toolbox, gcc, FVPs) on first activation and prompts for the"
40+
echo "license. Then: ./build.sh, and use the CMSIS Solution panel's buttons."
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# Copyright 2026 Arm Limited and/or its affiliates.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# CI for the pack-based-mlops branch.
5+
#
6+
# Unlike main's build_ai_layer.yml, this workflow commits nothing back: the AI
7+
# layer is regenerated from the .pte on every developer build, so there is no
8+
# artifact to sync into the repository.
9+
name: Build and Run (pack-based MLOps)
10+
11+
on:
12+
workflow_dispatch:
13+
push:
14+
branches: [pack-based-mlops]
15+
pull_request:
16+
branches: [pack-based-mlops]
17+
18+
jobs:
19+
# Full build plus an FVP run. Linux only: the FVP needs an Arm user-based
20+
# license, so matrixing this across hosts is not cheap.
21+
build-and-run:
22+
name: Build and run on Corstone-320
23+
runs-on: ubuntu-latest
24+
25+
steps:
26+
- name: Checkout repo
27+
uses: actions/checkout@v7
28+
29+
- name: Install tools
30+
uses: ARM-software/cmsis-actions/vcpkg@v1
31+
32+
- name: Activate Arm tool license
33+
uses: ARM-software/cmsis-actions/armlm@v1
34+
35+
- name: Cache packs
36+
uses: actions/cache@v6
37+
with:
38+
key: cmsis-packs
39+
path: /home/runner/.cache/arm/packs
40+
41+
# torch + executorch is a multi-gigabyte install and otherwise dominates
42+
# the job. Keyed on the requirements files so a pin change rebuilds it.
43+
- name: Cache model-export venv
44+
uses: actions/cache@v6
45+
with:
46+
key: venv-${{ runner.os }}-${{ hashFiles('requirements*.txt', 'setup_venv.py') }}
47+
path: .venv
48+
49+
- name: Create model-export venv
50+
run: ./setup_venv.sh
51+
52+
- name: Build
53+
run: |
54+
# The convert-model step aborts the first build if the model's
55+
# operator set no longer matches the committed ai_layer.clayer.yml,
56+
# having just regenerated it. Steady state is a single clean pass;
57+
# the retry keeps the job self-healing rather than red.
58+
./build.sh || {
59+
echo "::notice::First build regenerated the component list; re-running."
60+
./build.sh
61+
}
62+
63+
- name: Run on the FVP
64+
run: |
65+
ELF=$(find out -name '*.elf' | head -1)
66+
echo "Running ${ELF}"
67+
# Note: stdio is retargeted to semihosting (not a UART model), so the
68+
# output arrives on the FVP's own stdout -- there is no
69+
# -C mps3_board.uart0.out_file as in main's workflow.
70+
FVP_Corstone_SSE-320 \
71+
-f board/Corstone-320/fvp_config.txt \
72+
-a "${ELF}" \
73+
--simlimit 60 --stat \
74+
| tee fvp_stdout.log
75+
76+
echo "Checking simulation output"
77+
grep -q "Test_result: PASS" fvp_stdout.log
78+
79+
- name: Upload artifacts
80+
if: always()
81+
uses: actions/upload-artifact@v4
82+
with:
83+
name: corstone-320-build
84+
path: |
85+
fvp_stdout.log
86+
out/**/*.elf
87+
model/model.pte
88+
89+
# The export flow must work on all three host OSes -- that is the point of a
90+
# venv-based (rather than Docker-based) model build. No FVP and no Arm
91+
# license needed, so this is cheap to matrix. Without this job, Windows
92+
# support regresses on the first refactor and nobody notices.
93+
venv-cross-platform:
94+
name: Model export venv (${{ matrix.os }})
95+
runs-on: ${{ matrix.os }}
96+
97+
strategy:
98+
fail-fast: false
99+
matrix:
100+
os: [ubuntu-latest, macos-latest, windows-latest]
101+
102+
steps:
103+
- name: Checkout repo
104+
uses: actions/checkout@v7
105+
106+
- name: Set up Python
107+
uses: actions/setup-python@v5
108+
with:
109+
python-version: '3.12'
110+
111+
- name: Create model-export venv (POSIX)
112+
if: runner.os != 'Windows'
113+
run: ./setup_venv.sh
114+
115+
- name: Create model-export venv (Windows)
116+
if: runner.os == 'Windows'
117+
run: .\setup_venv.bat
118+
119+
# Exercises run_export.py directly, without cbuild: the cbuild-mlops.yml
120+
# it consumes is generated by csolution, so commit a check that the
121+
# exporter and the component generator both import and run.
122+
- name: Check the export entry points
123+
shell: bash
124+
run: |
125+
if [ "$RUNNER_OS" = "Windows" ]; then
126+
PY=.venv/Scripts/python.exe
127+
else
128+
PY=.venv/bin/python
129+
fi
130+
"${PY}" -c "import executorch.backends.arm.quantizer.quantization_annotator; print('arm quantizer OK')"
131+
"${PY}" model/export_model.py --help > /dev/null
132+
"${PY}" scripts/gen_components.py --help > /dev/null
133+
echo "export entry points OK"
134+
135+
- name: Report resolved versions
136+
shell: bash
137+
run: |
138+
if [ "$RUNNER_OS" = "Windows" ]; then
139+
PY=.venv/Scripts/python.exe
140+
else
141+
PY=.venv/bin/python
142+
fi
143+
"${PY}" -m pip list | grep -iE "torch|executorch|vela|tosa|flatbuffers"
144+
# flatbuffers must stay at 24.3.25: tosa-tools wants 25.2.10 and is
145+
# installed --no-deps precisely to stop that. See
146+
# requirements-arm-tosa.txt.
147+
"${PY}" -m pip show flatbuffers | grep -q "Version: 24.3.25" \
148+
|| { echo "::error::flatbuffers pin regressed"; exit 1; }

.gitignore

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Python
2+
.venv/
3+
__pycache__/
4+
*.pyc
5+
6+
# Model conversion outputs (regenerated by the convert-model build step on
7+
# every build; committing them only causes pull conflicts).
8+
model/model.pte
9+
ai_layer/model/model_pte.h
10+
11+
# CMSIS-Toolbox build outputs
12+
out/
13+
tmp/
14+
RTE/
15+
.cmsis/
16+
*.cbuild-idx.yml
17+
*.cbuild-pack.yml
18+
*.cbuild-set.yml
19+
*.cbuild.yml
20+
*.cbuild-run.yml
21+
*.cbuild-mlops.yml
22+
23+
# Toolchain / editor
24+
*.elf
25+
*.map
26+
27+
# Regenerated by the CMSIS Solution / clangd extensions on every build, with
28+
# absolute paths for the machine that built it -- so it cannot be committed in
29+
# a portable form. Not committing it loses nothing: it is generated for you.
30+
.clangd
31+
32+
# Local support-ticket material (logs, screenshots); never part of the example.
33+
support-cases/
34+
35+
# .vscode/ and .vscode.d/ are committed on this branch (they carry the FVP
36+
# run/debug wiring); the negation overrides machine-global excludes rules.
37+
!.vscode/
38+
!.vscode/**

.vscode.d/tasks.json

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"label": "CMSIS Load",
6+
"type": "shell",
7+
"command": "${workspaceFolder}/.vscode/start-fvp-gdb.sh",
8+
"args": ["--reload", "${command:cmsis-csolution.getBinaryFile}"],
9+
"dependsOn": ["FVP Output (fvp-gdb)"],
10+
"options": { "cwd": "${workspaceFolder}/" },
11+
"isBackground": true,
12+
"presentation": { "panel": "dedicated", "reveal": "always", "showReuseMessage": false },
13+
"problemMatcher": {
14+
"pattern": [{ "regexp": ".", "file": 1, "location": 2, "message": 3 }],
15+
"background": {
16+
"activeOnStart": true,
17+
"beginsPattern": "Starting fvp-gdb|Reload requested",
18+
"endsPattern": "ready on :|already listening on :|not found|did not come up|exited before|Docker is not running"
19+
}
20+
}
21+
},
22+
{
23+
"label": "CMSIS Run",
24+
"type": "shell",
25+
"command": "arm-none-eabi-gdb",
26+
"args": ["-batch", "-ex", "target remote localhost:3333", "-ex", "detach"],
27+
"options": { "cwd": "${workspaceFolder}/" },
28+
"problemMatcher": []
29+
},
30+
{
31+
"label": "CMSIS Erase",
32+
"type": "shell",
33+
"command": "echo",
34+
"args": ["FVP target: nothing to erase"],
35+
"problemMatcher": []
36+
},
37+
{
38+
"label": "Start FVP (fvp-gdb)",
39+
"type": "shell",
40+
"command": "${workspaceFolder}/.vscode/start-fvp-gdb.sh",
41+
"args": ["${command:cmsis-csolution.getBinaryFile}"],
42+
"dependsOn": ["FVP Output (fvp-gdb)"],
43+
"options": { "cwd": "${workspaceFolder}/" },
44+
"isBackground": true,
45+
"presentation": { "panel": "dedicated", "reveal": "always", "showReuseMessage": false },
46+
"problemMatcher": {
47+
"pattern": [{ "regexp": ".", "file": 1, "location": 2, "message": 3 }],
48+
"background": {
49+
"activeOnStart": true,
50+
"beginsPattern": "Starting fvp-gdb|Reload requested",
51+
"endsPattern": "ready on :|already listening on :|not found|did not come up|exited before|Docker is not running"
52+
}
53+
}
54+
},
55+
{
56+
"label": "Stop FVP (fvp-gdb)",
57+
"type": "shell",
58+
"command": "${workspaceFolder}/.vscode/stop-fvp-gdb.sh",
59+
"problemMatcher": []
60+
},
61+
{
62+
"label": "FVP Output (fvp-gdb)",
63+
"type": "shell",
64+
"command": "${workspaceFolder}/.vscode/tail-fvp-log.sh",
65+
"options": { "cwd": "${workspaceFolder}/" },
66+
"isBackground": true,
67+
"presentation": { "panel": "dedicated", "reveal": "always", "showReuseMessage": false },
68+
"problemMatcher": {
69+
"pattern": [{ "regexp": ".", "file": 1, "location": 2, "message": 3 }],
70+
"background": {
71+
"activeOnStart": true,
72+
"beginsPattern": "FVP output terminal ready",
73+
"endsPattern": "FVP output terminal ready"
74+
}
75+
}
76+
}
77+
]
78+
}

0 commit comments

Comments
 (0)