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
99 changes: 32 additions & 67 deletions .github/workflows/zx_fvp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,26 +129,18 @@ jobs:
# Matches gcc_check.yml so the two share one toolchain cache entry.
GCC_VERSION: 14.3.rel1

# Where the Armv8-R AEM FVP comes from.
# The Armv8-R AEM FVP, from Arm's unauthenticated download permalink.
# Only the _Linux_x86.tar.gz name resolves; the _Linux64.tgz name of
# older releases returns 404. The archive holds Arm's installer, which
# refuses to run until its EULA is accepted, so the install step accepts
# it. The model is fetched from Arm on every cache miss and never
# re-hosted.
#
# Arm distributes it free of charge but behind a click-through licence,
# with no stable unauthenticated download URL that can be hard-coded --
# the permalink forms under developer.arm.com/-/cdn-downloads all 404 for
# this model. So the location is a repository variable rather than a
# literal, and a maintainer sets it once to somewhere the runner can
# reach: an Eclipse-hosted mirror, a release asset, or Arm's own URL if a
# durable one ever appears.
#
# Set FVP_AEMV8R_URL to a .tgz/.tar.gz of the model, and optionally
# FVP_AEMV8R_SHA256 to its checksum. With the checksum set the download
# is verified; without it the run says so rather than pretending.
#
# When the variable is unset the build lanes still run and still gate the
# pull request -- only execution is skipped, loudly, in the log and in the
# job summary. A silent green here would recreate the exact hole this
# workflow exists to close.
FVP_URL: ${{ vars.FVP_AEMV8R_URL }}
FVP_SHA256: ${{ vars.FVP_AEMV8R_SHA256 }}
# Pinned with its checksum so that a change of model is a reviewed diff.
# Keep the version in step with the find_program hint in
# examples/fvp_baser_aemv8r/CMakeLists.txt.
FVP_URL: https://developer.arm.com/-/cdn-downloads/permalink/FVPs-Architecture/FM-11.32/FVP_Base_AEMv8R_11.32_19_Linux_x86.tar.gz
FVP_SHA256: e6d046946529db86129ee6d8e7a2d5c3667d6c4c98365ad815586db8bca06613

steps:
- name: Check out the repository
Expand Down Expand Up @@ -205,36 +197,32 @@ jobs:
sudo apt-get install -y --no-install-recommends ninja-build
fi

# Keyed on the URL's own hash rather than a version string, so pointing the
# variable at a different model fetches it instead of serving the old one
# from cache. A raw URL may contain characters a cache key cannot.
# Keyed on the archive's checksum, which changes exactly when the model
# does.
- name: Cache the Armv8-R AEM FVP
id: cache-fvp
if: env.FVP_URL != ''
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: fvp
key: fvp-aemv8r-${{ hashFiles('.github/workflows/zx_fvp.yml') }}-${{ env.FVP_SHA256 || 'nosum' }}
key: fvp-aemv8r-${{ env.FVP_SHA256 }}

- name: Install the Armv8-R AEM FVP
if: env.FVP_URL != '' && steps.cache-fvp.outputs.cache-hit != 'true'
if: steps.cache-fvp.outputs.cache-hit != 'true'
run: |
set -eu
mkdir -p fvp && cd fvp
curl -fsSL -o fvp.tgz "$FVP_URL"
if [ -n "${FVP_SHA256:-}" ]; then
echo "$FVP_SHA256 fvp.tgz" | sha256sum -c -
else
echo "::warning::FVP_AEMV8R_SHA256 is not set; the download was not verified."
fi
tar xf fvp.tgz
rm -f fvp.tgz
mkdir -p fvp-download
curl -fsSL --retry 3 -o fvp-download/fvp.tar.gz "$FVP_URL"
echo "$FVP_SHA256 fvp-download/fvp.tar.gz" | sha256sum -c -
tar xzf fvp-download/fvp.tar.gz -C fvp-download
sh fvp-download/FVP_Base_AEMv8R_*_Linux_x86.sh \
--i-agree-to-the-contained-eula --no-interactive \
-d "$GITHUB_WORKSPACE/fvp"
rm -rf fvp-download

# The model links against libatomic. Everything else it needs is already
# on the runner image, and its own libscxframework/libsystemc ship inside
# the tarball. Guarded for the same reason the ninja step is.
# on the runner image, and its own libscxframework/libsystemc ship with
# the model. Guarded for the same reason the ninja step is.
- name: Ensure the FVP's runtime dependencies are present
if: env.FVP_URL != ''
run: |
set -eu
if ldconfig -p | grep -q 'libatomic\.so\.1'; then
Expand All @@ -252,33 +240,19 @@ jobs:
# ZX_FVP_BASER_AEMV8R, which means -DZX_FVP_BASER_AEMV8R=<path> overrides
# it with no change to the CMake files.
#
# "present", not a bare "did the variable exist", so that a URL which
# downloads something that is not the model fails here rather than silently
# skipping every test later.
# A missing binary fails here, rather than leaving CMake without a model
# and CTest with no tests to run.
- name: Locate the FVP
id: fvp
run: |
set -eu
if [ -z "${FVP_URL:-}" ]; then
echo "present=false" >>"$GITHUB_OUTPUT"
echo "::warning::FVP_AEMV8R_URL is not set for this repository, so the ZoneX images were built but NOT executed. Set the repository variable to enable the execution lanes."
{
echo "### ZoneX FVP execution: SKIPPED"
echo ""
echo "\`FVP_AEMV8R_URL\` is not set, so this run built the images but executed none of them."
echo "Set the repository variable (Settings -> Secrets and variables -> Actions -> Variables)"
echo "to a download URL for the Armv8-R AEM FVP to turn the execution lanes on."
} >>"$GITHUB_STEP_SUMMARY"
exit 0
fi
binary="$(find fvp -type f -name FVP_BaseR_AEMv8R -perm -u+x | head -1)"
if [ -z "$binary" ]; then
echo "FVP_AEMV8R_URL was set, but no FVP_BaseR_AEMv8R binary was found in the archive." >&2
echo "::error::The FVP install produced no FVP_BaseR_AEMv8R binary."
find fvp -maxdepth 3 -type d | sed 's/^/ /' >&2
exit 1
fi
binary="$(cd "$(dirname "$binary")" && pwd)/$(basename "$binary")"
echo "present=true" >>"$GITHUB_OUTPUT"
echo "binary=$binary" >>"$GITHUB_OUTPUT"
"$binary" --version

Expand All @@ -288,21 +262,15 @@ jobs:
export PATH="$GITHUB_WORKSPACE/toolchain/arm-gnu-toolchain-${GCC_VERSION}-x86_64-arm-none-eabi/bin:$PATH"
arm-none-eabi-gcc --version | head -1

fvp_present='${{ steps.fvp.outputs.present }}'
fvp_binary='${{ steps.fvp.outputs.binary }}'

fvp_arg=""
if [ "$fvp_present" = "true" ]; then
fvp_arg="-DZX_FVP_BASER_AEMV8R=$fvp_binary"
fi

cmake -S . -B build/fvp -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/cortex_r52.cmake \
-DCMAKE_COMPILE_WARNING_AS_ERROR=ON \
-DZX_BUILD_FVP_EXAMPLE=ON \
-DZX_BUILD_S32Z280_EXAMPLE=OFF \
-DZX_THREADX_SOURCE_DIR="$GITHUB_WORKSPACE/threadx" \
$fvp_arg
-DZX_FVP_BASER_AEMV8R="$fvp_binary"

cmake --build build/fvp

Expand Down Expand Up @@ -380,9 +348,6 @@ jobs:
# shellcheck disable=SC2086
cmake --build build/fvp --target $images

if [ "$fvp_present" != "true" ]; then
echo "Built, not executed (no FVP configured)."
exit 0
fi

ctest --test-dir build/fvp --output-on-failure
# --no-tests=error, because ctest reports success when it finds
# nothing to run.
ctest --test-dir build/fvp --output-on-failure --no-tests=error
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ Five GitHub Actions workflows. **Every one triggers on `pull_request` against `d
| `clang_check.yml` | The same sources with Arm Toolchain for Embedded. GNU `as` accepts non-canonical assembly forms that LLVM's assembler rejects, and ZoneX is going to be substantially assembly. |
| `zx_fvp.yml` | Builds the Cortex-R52 images and **executes** them on the Armv8-R AEM FVP, judging each by its self-reported result. There is no static check for "the partition still runs". |

Arm distributes the Armv8-R AEM FVP free of charge but behind a click-through licence with no stable unauthenticated URL, so `zx_fvp.yml` takes the download location from the `FVP_AEMV8R_URL` repository variable (with an optional `FVP_AEMV8R_SHA256`). When it is unset the build lanes still run and still gate the pull request; only execution is skipped, and it says so in the log and in the job summary rather than passing quietly.
`zx_fvp.yml` downloads the Armv8-R AEM FVP from Arm's public permalink, verifies it against a SHA-256 pinned in the workflow, and installs it with Arm's installer, so every run executes the images. A missing model fails the job.

Toolchain versions are pinned explicitly, so a bump is a reviewable commit. Third-party actions are pinned to a commit SHA rather than a tag, and `.github/dependabot.yml` keeps those pins moving — a SHA pin without Dependabot freezes CI on whatever was current the day it was written.

Expand Down