open-standards/.github/workflows/wai-quantum-dsp.yml
Transaction Science 9c3c42ee28
Some checks failed
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
wai-quantum dataflow member / does this change touch it (pull_request) Successful in 5s
standards workspaces build + test / macOS energy backends (pull_request) Has been skipped
wai-quantum signal processor / does this change touch it (pull_request) Successful in 5s
wai-quantum matrix-extension member / does this change touch it (pull_request) Successful in 8s
wai-quantum tensor-engine member / does this change touch it (pull_request) Successful in 7s
wai-quantum portable tensor program / does this change touch it (pull_request) Successful in 6s
wai-quantum CPU vector units / does this change touch it (pull_request) Successful in 7s
wai-quantum on every processor / emulated · riscv64gc-unknown-linux-gnu (pull_request) Successful in 3m16s
wai-quantum on every processor / emulated · loongarch64-unknown-linux-gnu (pull_request) Successful in 4m25s
wai-quantum on every processor / emulated · powerpc64le-unknown-linux-gnu (pull_request) Successful in 5m28s
wai-quantum on every processor / emulated · powerpc64-unknown-linux-gnu (pull_request) Successful in 6m8s
wai-quantum on every processor / emulated · aarch64-unknown-linux-gnu (pull_request) Successful in 10m30s
wai-quantum on every processor / emulated · sparc64-unknown-linux-gnu (pull_request) Successful in 15m45s
wai-quantum on every processor / emulated · armv7-unknown-linux-gnueabihf (pull_request) Successful in 23m51s
wai-quantum on every processor / emulated · s390x-unknown-linux-gnu (pull_request) Successful in 32m33s
wai-quantum on every processor / emulated · i686-unknown-linux-gnu (pull_request) Successful in 38m4s
wai-quantum portable tensor program / tensor program · integrated GPU (framework-128gb) (pull_request) Failing after 0s
wai-quantum CPU vector units / member · vector units, avx2 and avx512 (framework-128gb silicon) (pull_request) Failing after 0s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 3m31s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:401e) (pull_request) Successful in 2m45s
wai-quantum CPU vector units / member · vector unit, rvv 1024-bit (riscv64, emulated) (pull_request) Successful in 21s
wai-quantum matrix-extension member / member · matrix extension, emulated (aarch64 Linux) (pull_request) Successful in 1m5s
wai-quantum CPU vector units / member · vector unit, sve 128-bit (aarch64, emulated) (pull_request) Successful in 29s
wai-quantum portable tensor program / tensor program · CPU, mutants, GPU builds (pull_request) Successful in 57s
wai-quantum CPU vector units / member · vector unit, sve 2048-bit (aarch64, emulated) (pull_request) Successful in 24s
wai-quantum CPU vector units / member · vector unit, avx2 (x86_64 silicon) (pull_request) Successful in 29s
wai-quantum CPU vector units / member · vector unit, sve 512-bit (aarch64, emulated) (pull_request) Successful in 26s
wai-quantum CPU vector units / member · vector unit, rvv 128-bit (riscv64, emulated) (pull_request) Successful in 1m11s
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Successful in 5m25s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:b140) (pull_request) Successful in 12m50s
wai-quantum dataflow member / member · dataflow device absent (macos) (pull_request) Successful in 17s
wai-quantum matrix-extension member / member · matrix extension absent (macos) (pull_request) Successful in 12s
wai-quantum portable tensor program / tensor program · Metal and the arm64 CPU (macos) (pull_request) Successful in 18s
wai-quantum CPU vector units / member · vector unit absent (macos) (pull_request) Successful in 16s
wai-quantum signal processor / processor and member · signal processor, emulated (pull_request) Successful in 21m58s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Has been cancelled
wai-quantum portable tensor program / tensor program · GPUs (jetson-hub) (pull_request) Has been cancelled
ci: the wai-quantum legs build the commit they test, and fail when they did not
Seven wai-quantum workflows (processors, dsp, dataflow, sme, tensor-engine,
tensor-program, vector) take the forge's archive of the commit, extract it to
the same path on every run, and build into a target directory kept in the
runner's cache. tar gave every file its commit's time, and cargo takes a crate
as built when no source file is newer than its last build. So a commit older
than the cache's last build ran the binary another commit had built there, and
its tests said nothing about its own code. On 5 Nov, 16 emulated legs went
green on another commit's binary, and #662's three reds were its legs running
#660's two frame_reference tests against #662's check for three.

- Fetch the source extracts with tar -m: every file gets the time it was
  extracted.
- That alone does not close it. Each build waits on the host-wide lock after
  its extraction, and another run can build in the cache meanwhile, after
  which this one's files are again the older. So every step that builds
  touches the extracted tree once it holds the lock.
- The first build in each such step must print "Compiling wai-quantum v...";
  one that compiled nothing fails the leg, saying its tests would run a binary
  already in the cache.

The host-runner legs (macOS, linux-hw, linux-amd, linux-arm64) check out with
git into a fresh tree, and are not changed here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 03:09:57 -05:00

255 lines
16 KiB
YAML

name: wai-quantum signal processor
# The signal processor (DSP) as a processor and as a fabric member, under its
# user-mode emulator:
#
# - the processor: the byte-pinned bit-identity digests, the frame fixtures and
# the byte-pinning library tests, built for the processor's Linux target (a
# tier-3 target: the standard library is built from source);
# - the member: the vector unit (128-byte vectors) runs the gate's
# arithmetic, and its device tests must find it, agree with the CPU, reproduce
# all four pinned certificates (each naming the emulator) and catch three
# kernel mutants;
# - the same build on x86_64, where the member is absent and says so.
#
# The emulator is QEMU 11.1.1, built here from its release tarball (SHA-256
# pinned; its signature was checked against the release key when it was pinned).
# Releases before 11.0 test a whole predicate register, not its low bit, when a
# branch reads a predicate written in the same packet, and the processor
# branches on the low bit. Compiled code relies on that (a predicate built from
# a general register's 1 and xored with a comparison's 0xff, so 0xfe means
# "equal"), and a library test fails under such an emulator though the code is
# right. A probe shows which emulator does what before any suite runs on it.
#
# The cross toolchain (clang, lld and the musl sysroot for the target) is the
# open-source release for this processor, SHA-256 pinned.
#
# RUSTC_BOOTSTRAP: building the standard library for a tier-3 target, and the
# vector unit's intrinsics, are unstable; this workflow's builds for this
# processor are the only ones that use it.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
pull_request:
paths:
- 'wai/wai-quantum/**'
- 'rust-toolchain.toml'
- '.github/workflows/wai-quantum-dsp.yml'
schedule:
- cron: '17 4 * * *'
jobs:
# Does this pull request's own diff touch the paths below? This forge matches a
# workflow's `paths:` against the push, so a merge of main into a branch fires the
# workflow whatever the pull request changes; every job here waits on this answer.
# A push to main, a schedule, or anything the script cannot determine answers
# `true` (scripts/pr-touches-paths.py).
relevant:
name: does this change touch it
runs-on: linux
outputs:
run: ${{ steps.gate.outputs.run }}
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- id: gate
run: |
set -euo pipefail
r=$(python3 scripts/pr-touches-paths.py .github/workflows/wai-quantum-dsp.yml \
"${{ github.event.pull_request.base.sha }}" \
"${{ github.event.pull_request.head.sha }}")
echo "this change touches wai-quantum-dsp: $r"
echo "run=$r" >> "$GITHUB_OUTPUT"
dsp-emulated:
name: processor and member · signal processor, emulated
needs: relevant
if: needs.relevant.outputs.run == 'true'
runs-on: linux
timeout-minutes: 180
container:
image: debian@sha256:913f6706df59a68922d1dd08f78c2476560a8d367897200a6005b00e5f67c2d5
options: --memory=6g --memory-swap=6g
env:
TOOLCHAIN_VERSION: 22.1.8
TOOLCHAIN_SHA256: bc122fe6473ead9693613a6ab3a177c5583653ff76b937e7578cf7de0273315b
# Not QEMU_*: qemu-user reads every QEMU_<option> variable as that
# option, and QEMU_VERSION is -version (print it and exit).
HEXAGON_EMULATOR_VERSION: 11.1.1
HEXAGON_EMULATOR_SHA256: 079ffbff8a7111bbc89022107cbabf3bbfd614d5fc9d7cc675991196aca12482
WAI_QUANTUM_DSP_EXPECT: dsp-vector
WAI_QUANTUM_DSP_EMULATOR: qemu-user 11.1.1 (built from the signed release)
steps:
- name: Tools
shell: bash
run: |
set -euo pipefail
apt-get update -qq
apt-get install -y -qq --no-install-recommends ca-certificates curl git xz-utils zstd build-essential \
ninja-build meson python3 python3-venv pkg-config libglib2.0-dev flex bison >/dev/null
# No Node for a checkout action: the forge's archive of the exact commit,
# its embedded commit id checked.
- name: Fetch the source
shell: bash
run: |
set -euo pipefail
want="${{ github.event.pull_request.head.sha || github.sha }}"
rm -rf src src.tar.gz src.tar && mkdir src
curl -sSf -o src.tar.gz "http://100.64.224.0:3400/Transaction-Science/open-standards/archive/$want.tar.gz"
gzip -dc src.tar.gz > src.tar
got="$(git get-tar-commit-id < src.tar)"
[ "$got" = "$want" ] || { echo "::error::the archive is of $got, not $want"; exit 1; }
# -m: every file gets the time it was extracted, not its commit's. The builds
# reuse target directories kept between runs, and cargo takes a crate as
# built when no source file is newer than its last build: with the commit's
# times, an older commit ran the binary another commit had built there.
tar -xmf src.tar -C src --strip-components=1
rm src.tar.gz src.tar
- name: The cross toolchain, the emulator and Rust (cached, pinned)
shell: bash
working-directory: src/wai/wai-quantum
run: |
set -euo pipefail
cache=/ci-cache/wai-quantum-hexagon
mkdir -p "$cache"
exec 9>"$cache/.lock"
flock 9
tc="$cache/toolchain-$TOOLCHAIN_VERSION"
if [ ! -x "$tc/clang+llvm-$TOOLCHAIN_VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/bin/hexagon-linux-musl-clang" ]; then
f="clang+llvm-$TOOLCHAIN_VERSION-cross-hexagon-unknown-linux-musl_x86_64-linux-gnu.tar.zst"
# The release directory's name carries trailing underscores.
curl -sSfL -o "$cache/$f" "https://artifacts.codelinaro.org/artifactory/codelinaro-toolchain-for-hexagon/${TOOLCHAIN_VERSION}________/$f"
echo "$TOOLCHAIN_SHA256 $cache/$f" | sha256sum -c -
rm -rf "$tc.tmp" && mkdir "$tc.tmp"
tar --zstd -xf "$cache/$f" -C "$tc.tmp"
rm -rf "$tc" && mv "$tc.tmp" "$tc" && rm "$cache/$f"
fi
q="$cache/qemu-hexagon-$HEXAGON_EMULATOR_VERSION"
if [ ! -x "$q" ]; then
curl -sSfL -o "$cache/qemu.tar.xz" "https://download.qemu.org/qemu-$HEXAGON_EMULATOR_VERSION.tar.xz"
echo "$HEXAGON_EMULATOR_SHA256 $cache/qemu.tar.xz" | sha256sum -c -
b="$cache/qemu-build"
rm -rf "$b" && mkdir "$b" && tar -xJf "$cache/qemu.tar.xz" -C "$b" --strip-components=1
(cd "$b" && ./configure --target-list=hexagon-linux-user --static --disable-docs --disable-tools --disable-werror > configure.log 2>&1 && ninja -C build -j 4 qemu-hexagon > ninja.log 2>&1) || { tail -30 "$b/configure.log" "$b"/ninja.log 2>/dev/null; exit 1; }
cp "$b/build/qemu-hexagon" "$q.tmp" && mv "$q.tmp" "$q"
rm -rf "$b" "$cache/qemu.tar.xz"
fi
"$q" --version | head -1
export RUSTUP_HOME="$cache/rustup" CARGO_HOME="$cache/cargo"
export PATH="$CARGO_HOME/bin:$PATH"
if ! command -v rustup >/dev/null; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path --profile minimal --default-toolchain none
fi
rustup toolchain install
rustup component add rust-src
- name: Which emulator branches on a predicate's low bit
shell: bash
working-directory: src/wai/wai-quantum
run: |
set -euo pipefail
cache=/ci-cache/wai-quantum-hexagon
bin="$cache/toolchain-$TOOLCHAIN_VERSION/clang+llvm-$TOOLCHAIN_VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/bin"
"$bin/hexagon-linux-musl-clang" -O1 -mv68 -static -o "$RUNNER_TEMP/predicate_branch" ci/dsp/predicate_branch.c
echo "== the pinned emulator"
# The probe must say what it found: an emulator that exits without
# running the program (as qemu-user does for an environment variable
# it reads as -version) would otherwise pass this check.
"$cache/qemu-hexagon-$HEXAGON_EMULATOR_VERSION" "$RUNNER_TEMP/predicate_branch" > "$RUNNER_TEMP/predicate.log" 2>&1 || true
cat "$RUNNER_TEMP/predicate.log"
grep -qx "this emulator branches on the low bit" "$RUNNER_TEMP/predicate.log" || { echo "::error::the pinned emulator does not branch on the low bit, or did not run the probe"; exit 1; }
# The host's own emulator, where it has one registered: shown, not required.
if [ -e /proc/sys/fs/binfmt_misc/qemu-hexagon ]; then
echo "== the host's emulator"
"$RUNNER_TEMP/predicate_branch" || echo "(the host's emulator differs; the suites below run on the pinned one)"
fi
- name: The processor's suites
shell: bash
working-directory: src/wai/wai-quantum
run: |
set -euo pipefail
cache=/ci-cache/wai-quantum-hexagon
exec 9>"$cache/.lock"
flock 9
# Every source file newer than every build in the cache, now that the lock is
# held: another run may have built here while this one waited for it, after
# this one's extraction. (../.. is the extracted tree.) Each step below that
# builds takes the lock afresh, and refreshes again.
find ../.. -type f -exec touch {} +
tc="$cache/toolchain-$TOOLCHAIN_VERSION/clang+llvm-$TOOLCHAIN_VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu"
export RUSTUP_HOME="$cache/rustup" CARGO_HOME="$cache/cargo" CARGO_TARGET_DIR="$cache/target"
export PATH="$CARGO_HOME/bin:$tc/bin:$PATH" RUSTC_BOOTSTRAP=1
export CARGO_TARGET_HEXAGON_UNKNOWN_LINUX_MUSL_LINKER=hexagon-linux-musl-clang
export CARGO_TARGET_HEXAGON_UNKNOWN_LINUX_MUSL_RUNNER="$cache/qemu-hexagon-$HEXAGON_EMULATOR_VERSION -L $tc/target/hexagon-unknown-linux-musl"
export CC_hexagon_unknown_linux_musl=hexagon-linux-musl-clang AR_hexagon_unknown_linux_musl=hexagon-linux-musl-ar
logs="$cache/logs"; mkdir -p "$logs"
# FEATURES names the build (full, unless a step says otherwise).
t() {
name="$1"; shift
timeout 2700 cargo test --locked --release -j 6 -Zbuild-std -Zbuild-std-features=system-llvm-libunwind \
--target hexagon-unknown-linux-musl --features "${FEATURES:-full}" "$@" 2>&1 | tee "$logs/$name.log"
}
t bit_identity --test bit_identity -- --test-threads=1
# The first build after the refresh compiles wai-quantum; one that compiled
# none ran a binary another commit left in the cache.
grep -qE '^ *Compiling wai-quantum v[0-9]' "$logs/bit_identity.log" || { echo "::error::the build compiled no wai-quantum: its tests ran a binary already in the cache"; exit 1; }
grep -qE '^test result: ok\. 23 passed; 0 failed' "$logs/bit_identity.log" || { echo "::error::the 23 bit-identity digests did not all pass"; exit 1; }
t frame --test frame_reference -- --test-threads=1
grep -qE '^test result: ok\. 2 passed; 0 failed' "$logs/frame.log" || { echo "::error::the fixtures did not pass"; exit 1; }
# The library's tests with the features their modules need, not full: the
# whole engine's test binary is past the processor's direct-call reach
# (R_HEX_B22_PCREL, ±8 MiB), and these modules need none of the rest.
FEATURES="quantum_fabric quantum_receipt quantum_qbom" t lib --lib -- quantum:: quantum_fabric:: ijson:: quantum_receipt quantum_energy quantum_qbom merkle
grep -qE '^test result: ok\. [1-9][0-9]+ passed; 0 failed' "$logs/lib.log" || { echo "::error::the byte-pinning library tests did not pass"; exit 1; }
- name: The vector-unit member's tests
shell: bash
working-directory: src/wai/wai-quantum
run: |
set -euo pipefail
cache=/ci-cache/wai-quantum-hexagon
exec 9>"$cache/.lock"
flock 9
find ../.. -type f -exec touch {} +
tc="$cache/toolchain-$TOOLCHAIN_VERSION/clang+llvm-$TOOLCHAIN_VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu"
# The vector unit in 128-byte mode, for the whole build (the standard
# library included): a separate target directory.
export RUSTUP_HOME="$cache/rustup" CARGO_HOME="$cache/cargo" CARGO_TARGET_DIR="$cache/target-vector"
export PATH="$CARGO_HOME/bin:$tc/bin:$PATH" RUSTC_BOOTSTRAP=1 RUSTFLAGS="-C target-feature=+hvxv68,+hvx-length128b"
export CARGO_TARGET_HEXAGON_UNKNOWN_LINUX_MUSL_LINKER=hexagon-linux-musl-clang
export CARGO_TARGET_HEXAGON_UNKNOWN_LINUX_MUSL_RUNNER="$cache/qemu-hexagon-$HEXAGON_EMULATOR_VERSION -L $tc/target/hexagon-unknown-linux-musl"
export CC_hexagon_unknown_linux_musl=hexagon-linux-musl-clang AR_hexagon_unknown_linux_musl=hexagon-linux-musl-ar
b="-Zbuild-std -Zbuild-std-features=system-llvm-libunwind --target hexagon-unknown-linux-musl --features quantum_fabric_dsp"
timeout 1800 cargo test --locked --release -j 6 $b --lib -- quantum_fabric_dsp:: 2>&1 | tee "$RUNNER_TEMP/unit.log"
grep -qE '^ *Compiling wai-quantum v[0-9]' "$RUNNER_TEMP/unit.log" || { echo "::error::the build compiled no wai-quantum: its tests ran a binary already in the cache"; exit 1; }
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/unit.log" || { echo "::error::no unit test ran"; exit 1; }
report="$RUNNER_TEMP/dsp-report.txt"; : > "$report"
WAI_QUANTUM_DSP_REPORT="$report" timeout 5400 cargo test --locked --release -j 6 $b --test dsp_member -- --test-threads=1 2>&1 | tee "$RUNNER_TEMP/device.log"
grep -qE '^test result: ok\. 9 passed; 0 failed' "$RUNNER_TEMP/device.log" || { echo "::error::not every device test ran and passed"; exit 1; }
cat "$report"
key="$WAI_QUANTUM_DSP_EXPECT"
grep -qx "dsp devices: as declared ($key)" "$report" || { echo "::error::the member found is not the declared one"; exit 1; }
grep -q "^dsp member: key=$key .*emulator:qemu-user 11.1.1" "$report" || { echo "::error::the member does not say it ran under the pinned emulator"; exit 1; }
n="$(grep -c "^dsp certified: key=$key .* parity=bit-exact " "$report")"
[ "$n" = 4 ] || { echo "::error::$n of 4 certificates were earned"; exit 1; }
grep -qx "dsp mutants: key=$key killed 3 of 3" "$report" || { echo "::error::a kernel mutant survived"; exit 1; }
- name: Elsewhere the member is absent and says so (x86_64)
shell: bash
working-directory: src/wai/wai-quantum
run: |
set -euo pipefail
cache=/ci-cache/wai-quantum-hexagon
exec 9>"$cache/.lock"
flock 9
find ../.. -type f -exec touch {} +
export RUSTUP_HOME="$cache/rustup" CARGO_HOME="$cache/cargo" CARGO_TARGET_DIR="$cache/target-host"
export PATH="$CARGO_HOME/bin:$PATH"
cargo test --locked -j 6 --features quantum_fabric_dsp --lib -- quantum_fabric_dsp:: 2>&1 | tee "$RUNNER_TEMP/host-unit.log"
grep -qE '^ *Compiling wai-quantum v[0-9]' "$RUNNER_TEMP/host-unit.log" || { echo "::error::the build compiled no wai-quantum: its tests ran a binary already in the cache"; exit 1; }
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/host-unit.log" || { echo "::error::no unit test ran"; exit 1; }
report="$RUNNER_TEMP/dsp-absent.txt"; : > "$report"
WAI_QUANTUM_DSP_EXPECT=none WAI_QUANTUM_DSP_REPORT="$report" cargo test --locked -j 6 --features quantum_fabric_dsp --test dsp_member -- --test-threads=1 2>&1 | tee "$RUNNER_TEMP/host-device.log"
grep -qE '^test result: ok\. 9 passed; 0 failed' "$RUNNER_TEMP/host-device.log" || { echo "::error::not every device test ran and passed"; exit 1; }
grep -qx 'dsp devices: as declared (none)' "$report" || { echo "::error::the absent case was not established"; exit 1; }