From bc10c9c63d7af28f326baa8b62864762d967e0be Mon Sep 17 00:00:00 2001 From: Chima Emmanuel <178203816+Dox45@users.noreply.github.com> Date: Fri, 23 Oct 2026 14:08:34 +0000 Subject: [PATCH] Arm backend: Run a minimal Cortex-M image on FVP in size test job The Cortex-M size test job only builds size_test and checks its size, so a build that links but does not run would still pass. Let run_fvp.sh run a cortex-m ELF directly when no --bundle is given, and add test_minimal_classic_ml_cortex_m55, which embeds a small add model in the minimal_classic_ml runner and runs it on Corstone-300. The bare_metal leg of the size test job now runs it after the size check. Fixes #12812 --- .github/workflows/pull.yml | 5 +++++ backends/arm/scripts/run_fvp.sh | 11 +++++---- backends/arm/test/test_arm_backend.sh | 32 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index dca55ee5d24..a8825733c36 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -796,6 +796,11 @@ jobs: exit 1 fi + # Run a minimal image on the FVP to check the build actually executes + if [[ ${{ matrix.os }} == "bare_metal" ]]; then + backends/arm/test/test_arm_backend.sh test_minimal_classic_ml_cortex_m55 + fi + test-mcu-cortex-m-backend: needs: docker-image name: test-mcu-cortex-m-backend diff --git a/backends/arm/scripts/run_fvp.sh b/backends/arm/scripts/run_fvp.sh index 7fe87676883..57f1c7eab4c 100755 --- a/backends/arm/scripts/run_fvp.sh +++ b/backends/arm/scripts/run_fvp.sh @@ -33,7 +33,7 @@ help() { echo "Options:" echo " --elf= elf file to run" echo " --data=@
Place a file in memory at this address, useful to emulate a PTE flashed into memory instead as part of the code." - echo " --bundle= Bundled program (.bpte) to load via semihosting. Required for cortex-m targets; the FVP launches a semihosting executor_runner that reads the bundle from the host filesystem and checks the embedded reference outputs." + echo " --bundle= Bundled program (.bpte) to load via semihosting for cortex-m targets; the FVP launches a semihosting executor_runner that reads the bundle from the host filesystem and checks the embedded reference outputs. Optional; without it the ELF is run directly." echo " --target= Target to build and run for Default: ${target}" echo " --timeout= Maximum target runtime, used to detect hanging, might need to be higer on large models Default: ${timeout}" echo " --etrecord= If ETDump is used you can supply a ETRecord file matching the PTE" @@ -185,9 +185,7 @@ if [[ -n "${semihosting_cmd_line}" ]]; then ) fi -if [[ ${target} == cortex-m* ]]; then - [[ -z "${bundle_file}" ]] \ - && { echo "[${BASH_SOURCE[0]}] --bundle= is required for cortex-m targets"; exit 1; } +if [[ ${target} == cortex-m* && -n "${bundle_file}" ]]; then bundle_file=$(realpath "${bundle_file}") bundle_dir=$(dirname "${bundle_file}") bundle_name=$(basename "${bundle_file}") @@ -221,7 +219,8 @@ if [[ ${target} == cortex-m* ]]; then rm "${log_file}" exit 1 fi -elif [[ ${target} == *"ethos-u55"* || ${target} == *"ethos-u65"* ]]; then +elif [[ ${target} == *"ethos-u55"* || ${target} == *"ethos-u65"* \ + || ( ${target} == cortex-m* && ${target} != cortex-m85* ) ]]; then run_simulation ${nobuf} ${fvp_model} \ -C ethosu.num_macs=${num_macs} \ -C mps3_board.visualisation.disable-visualisation=1 \ @@ -233,7 +232,7 @@ elif [[ ${target} == *"ethos-u55"* || ${target} == *"ethos-u65"* ]]; then -a "${elf_file}" \ ${data_file} \ --timelimit ${timeout} # seconds -elif [[ ${target} == *"ethos-u85"* ]]; then +elif [[ ${target} == *"ethos-u85"* || ${target} == cortex-m85* ]]; then run_simulation ${nobuf} ${fvp_model} \ -C mps4_board.subsystem.ethosu.num_macs=${num_macs} \ -C mps4_board.visualisation.disable-visualisation=1 \ diff --git a/backends/arm/test/test_arm_backend.sh b/backends/arm/test/test_arm_backend.sh index 02e7aca1882..7c713b5e558 100755 --- a/backends/arm/test/test_arm_backend.sh +++ b/backends/arm/test/test_arm_backend.sh @@ -340,6 +340,38 @@ test_minimal_classic_ml_ethos_u55() { echo "${TEST_SUITE_NAME}: PASS" } +test_minimal_classic_ml_cortex_m55() { + echo "${TEST_SUITE_NAME}: Test minimal classic ML runner on Cortex-M55" + + local build_dir="${et_root_dir}/arm_test/minimal_classic_ml_cortex_m55" + local pte_path="${build_dir}/add.pte" + local fvp_log="${build_dir}/run_fvp.log" + mkdir -p "${build_dir}" + + python3 -m backends.arm.scripts.aot_arm_compiler \ + --model_name=add \ + --target=cortex-m55 \ + --intermediates="${build_dir}" \ + --output="${pte_path}" + + cmake \ + -S examples/arm/minimal_classic_ml \ + -B "${build_dir}" \ + -DCMAKE_TOOLCHAIN_FILE="${et_root_dir}/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake" \ + -DCMAKE_BUILD_TYPE=Release \ + -DET_PTE_FILE_PATH="${pte_path}" + cmake --build "${build_dir}" --target arm_classic_ml_runner -j"$(nproc)" + + backends/arm/scripts/run_fvp.sh \ + --elf="${build_dir}/arm_classic_ml_runner" \ + --target=cortex-m55 | tee "${fvp_log}" + local fvp_status="${PIPESTATUS[0]}" + [[ "${fvp_status}" -eq 0 ]] + grep -Fq "Inference complete: 1 output(s)" "${fvp_log}" + + echo "${TEST_SUITE_NAME}: PASS" +} + # ---------------------------------------------- # -------- Arm Ethos-U85 specific tests -------- # ----------------------------------------------