From 895479880e2b1d3a521600f6e435cb9e0376f42e Mon Sep 17 00:00:00 2001 From: bong-water-water-bong Date: Wed, 23 Sep 2026 13:33:37 -0300 Subject: [PATCH] XDNA: pin upstream amd/xdna-driver (and its XRT), build it privately, keep it current third_party/xdna-driver pins upstream amd/xdna-driver 5d302c9, whose xrt submodule pins XRT d8ececf: the userspace the NPU lane runs on (XRT and the XDNA shim plugin libxrt_driver_xdna). The kernel driver ships in the kernel (drivers/accel/amdxdna) and is not built from the pin. - scripts/build-xdna.sh : builds XRT (NPU package, without its OpenCL layer: it does not compile against newer distro ocl_icd.h headers and the NPU does not use it) and the shim, staged with DESTDIR under /root (XRT hard-codes /etc/OpenCL/vendors), and puts the shim next to XRT, where XRT loads plugins from. Nothing is installed system-wide. - .github/workflows/bump-xdna.yml: daily, opens a PR when upstream main moves. - docs/npu.md, "The XDNA stack". Strix Halo: the engine built with -DONEBIT_XRT_ROOT=/root/opt/xilinx/xrt loads libxrt_core and libxrt_driver_xdna from the pinned prefix (strace); tests/npu_lane_e2e.sh gives logits bit-identical to the reference lane, 24/24 steps, 10.8 ms/token, 327 ms warm load. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/bump-xdna.yml | 100 ++++++++++++++++++++++++++++++++ .gitmodules | 4 ++ docs/npu.md | 28 +++++++++ scripts/build-xdna.sh | 56 ++++++++++++++++++ third_party/xdna-driver | 1 + 5 files changed, 189 insertions(+) create mode 100644 .github/workflows/bump-xdna.yml create mode 100755 scripts/build-xdna.sh create mode 160000 third_party/xdna-driver diff --git a/.github/workflows/bump-xdna.yml b/.github/workflows/bump-xdna.yml new file mode 100644 index 00000000..4fa131b6 --- /dev/null +++ b/.github/workflows/bump-xdna.yml @@ -0,0 +1,100 @@ +# Copyright 2026 bong-water-water-bong +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Keep third_party/xdna-driver on upstream amd/xdna-driver main (docs/npu.md, +# "The XDNA stack"): when upstream moves, open a PR here moving the submodule. +# It pins XRT too (xdna-driver's own xrt submodule). GitHub-hosted CI has no +# NPU; build with scripts/build-xdna.sh and run tests/npu_lane_e2e.sh on Strix +# Halo before merging. +# +# Uses the secret HRX_BUMP_TOKEN (Contents and Pull requests read/write on +# 1bit-MONSTER/engine): a PR opened with the default GITHUB_TOKEN would not +# start CI. +name: bump-xdna + +on: + schedule: + - cron: "41 6 * * *" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: bump-xdna + cancel-in-progress: false + +jobs: + bump: + runs-on: ubuntu-latest + steps: + - name: Require the token + env: + HRX_BUMP_TOKEN: ${{ secrets.HRX_BUMP_TOKEN }} + run: | + if [ -z "$HRX_BUMP_TOKEN" ]; then + echo "::error::secret HRX_BUMP_TOKEN is not set (see the header of this workflow)" + exit 1 + fi + + - uses: actions/checkout@v4 + with: + token: ${{ secrets.HRX_BUMP_TOKEN }} + + - name: Compare with upstream + id: pins + env: + GH_TOKEN: ${{ secrets.HRX_BUMP_TOKEN }} + run: | + set -euo pipefail + upstream=$(gh api repos/amd/xdna-driver/commits/main --jq .sha) + upstream_xrt=$(gh api "repos/amd/xdna-driver/contents/xrt?ref=$upstream" --jq .sha) + ours=$(git ls-tree HEAD third_party/xdna-driver | awk '{print $3}') + echo "upstream $upstream (xrt $upstream_xrt), ours $ours" + { + echo "upstream=$upstream"; echo "upstream_xrt=$upstream_xrt"; echo "ours=$ours" + if [ "$upstream" = "$ours" ]; then echo "changed=false"; else echo "changed=true"; fi + } >> "$GITHUB_OUTPUT" + + - name: Open the bump PR + if: steps.pins.outputs.changed == 'true' + env: + GH_TOKEN: ${{ secrets.HRX_BUMP_TOKEN }} + UPSTREAM: ${{ steps.pins.outputs.upstream }} + UPSTREAM_XRT: ${{ steps.pins.outputs.upstream_xrt }} + OURS: ${{ steps.pins.outputs.ours }} + run: | + set -euo pipefail + branch="bump-xdna/${UPSTREAM:0:12}" + if git ls-remote --exit-code origin "refs/heads/$branch" > /dev/null; then + echo "$branch already exists"; exit 0 + fi + log=$(gh api "repos/amd/xdna-driver/compare/${OURS}...${UPSTREAM}" \ + --jq '.commits[-30:][] | "- \(.sha[0:9]) \(.commit.message | split("\n")[0])"' || true) + git config user.name "xdna-bump" + git config user.email "xdna-bump@users.noreply.github.com" + git switch -c "$branch" + git update-index --cacheinfo "160000,$UPSTREAM,third_party/xdna-driver" + git commit -q -m "Bump XDNA: amd/xdna-driver ${UPSTREAM:0:12} (XRT ${UPSTREAM_XRT:0:12})" + git push -q origin "$branch" + gh pr create --base main --head "$branch" \ + --title "Bump XDNA: amd/xdna-driver ${UPSTREAM:0:12}" \ + --body "Moves third_party/xdna-driver from \`${OURS:0:12}\` to upstream main \`${UPSTREAM:0:12}\` (its XRT submodule: \`${UPSTREAM_XRT:0:12}\`). + + Upstream commits (last 30): + ${log} + + CI here has no NPU. Before merging, on Strix Halo: + \`scripts/build-xdna.sh ~/.cache/xdna-pin/prefix && cmake -B build -G Ninja -DONEBIT_NPU=ON -DONEBIT_XRT_ROOT=\$HOME/.cache/xdna-pin/prefix && cmake --build build --target onebit && tests/npu_lane_e2e.sh ...\`" diff --git a/.gitmodules b/.gitmodules index 7486a640..f5c980d9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -27,3 +27,7 @@ url = https://github.com/bong-water-water-bong/llama.cpp.git branch = 1bit-engine/hrx-vulkan shallow = true +[submodule "third_party/xdna-driver"] + path = third_party/xdna-driver + url = https://github.com/amd/xdna-driver.git + branch = main diff --git a/docs/npu.md b/docs/npu.md index f3cc22b4..1bc35190 100644 --- a/docs/npu.md +++ b/docs/npu.md @@ -180,6 +180,34 @@ The `1bit` binary links only `libxrt_coreutil`: no xclbin, no FastFlowLM library greedy. - Requests are served one at a time: the lane has one KV cache. +## The XDNA stack + +The lane runs on XRT and the XDNA shim plugin (`libxrt_driver_xdna`), which XRT loads at run +time. Both are pinned: `third_party/xdna-driver` is upstream +[amd/xdna-driver](https://github.com/amd/xdna-driver), and its own `xrt` submodule pins XRT. + +- **The kernel driver is not built from this pin.** `amdxdna` ships in the kernel + (`drivers/accel/amdxdna`), and Strix Halo runs the kernel's copy. +- **Building the pinned stack:** `scripts/build-xdna.sh ` builds XRT (the NPU package) + and then the shim, staged under `/root`. Nothing is installed system-wide: XRT hard-codes + `/etc/OpenCL/vendors`, so both installs use `DESTDIR`. The engine then builds against it: + + ``` + scripts/build-xdna.sh ~/.cache/xdna-pin/prefix + cmake -B build -G Ninja -DONEBIT_NPU=ON -DONEBIT_XRT_ROOT=$HOME/.cache/xdna-pin/prefix/root/opt/xilinx/xrt + ``` +- **XRT's OpenCL layer (`xocl`) is excluded** (`XRT_EXCLUDE_SUB_DIRECTORY`). The NPU does not use + it, and it fails to compile where the distro's `ocl_icd.h` is newer than XRT's bundled OpenCL + 1.2 headers. +- **Keeping current:** `.github/workflows/bump-xdna.yml` runs daily and opens a PR whenever + upstream `main` moves (secret `HRX_BUMP_TOKEN`). CI has no NPU, so run the check below on + Strix Halo before merging. + +Verified on 2026-09-23 with xdna-driver `5d302c9` and XRT `d8ececf`, in place of the system's +XRT 2.21.75. Both `libxrt_core` and `libxrt_driver_xdna` were loaded from the pinned prefix +(strace). `tests/npu_lane_e2e.sh` gave logits bit-identical to the reference lane on 24/24 steps, +at 10.8 ms/token (92.6 tok/s), with a 327 ms warm load. + ## Open: where the kernel artifacts come from CONTRIBUTING rule 4 requires NPU kernels to be built from source. The layer kernel and diff --git a/scripts/build-xdna.sh b/scripts/build-xdna.sh new file mode 100755 index 00000000..1a8aa918 --- /dev/null +++ b/scripts/build-xdna.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +# Copyright 2026 bong-water-water-bong +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# build-xdna.sh [jobs] +# +# Builds the XDNA userspace stack pinned in third_party/xdna-driver (upstream +# amd/xdna-driver and its xrt submodule) into : XRT, then the XDNA shim +# plugin (libxrt_driver_xdna). It installs nothing system-wide: both are staged +# with DESTDIR=/root (XRT hard-codes /etc/OpenCL/vendors), so the XRT +# root is /root/opt/xilinx/xrt. Point the engine at it with +# -DONEBIT_XRT_ROOT=/root/opt/xilinx/xrt (docs/npu.md, "The XDNA stack"). +# +# The kernel driver is not built: amdxdna ships in the kernel (drivers/accel). +# Build dependencies come from upstream's third_party/xdna-driver/tools/amdxdna_deps.sh. +set -euo pipefail +prefix=${1:?usage: build-xdna.sh [jobs]} +jobs=${2:-$(nproc)} +root=$(cd "$(dirname "$0")/.." && pwd) +src=$root/third_party/xdna-driver +mkdir -p "$prefix" +prefix=$(cd "$prefix" && pwd) + +[ -f "$src/build/build.sh" ] || { echo "third_party/xdna-driver is empty: git submodule update --init third_party/xdna-driver"; exit 1; } +git -C "$src" submodule update --init --recursive --depth 1 + +# XRT, NPU package. Its OpenCL layer (xocl) is left out: the NPU does not use +# it, and it fails to compile where the distro's ocl_icd.h is newer than XRT's +# bundled OpenCL 1.2 headers. +(cd "$src/xrt/build" && ./build.sh -npu -opt -noctest -j "$jobs" \ + -cmake-flags "-DXRT_EXCLUDE_SUB_DIRECTORY=src/runtime_src/xocl") +stage=$prefix/root +xrt=$stage/opt/xilinx/xrt +DESTDIR=$stage cmake --install "$src/xrt/build/Release" + +# The XDNA shim plugin, against that XRT; no kernel module. +(cd "$src/build" && XILINX_XRT="$xrt" ./build.sh -release -nokmod -j "$jobs") +DESTDIR=$stage cmake --install "$src/build/Release" +# XRT loads device plugins from its own lib directory; the shim installs under +# its build's prefix, so put it next to XRT. +find "$stage" -name 'libxrt_driver_xdna.so*' -not -path "$xrt/*" -exec cp -a {} "$xrt/lib/" \; + +echo "XDNA stack (XRT root): $xrt" +ls "$xrt"/lib*/libxrt_coreutil.so* "$xrt"/lib*/libxrt_driver_xdna.so* 2>/dev/null diff --git a/third_party/xdna-driver b/third_party/xdna-driver new file mode 160000 index 00000000..5d302c99 --- /dev/null +++ b/third_party/xdna-driver @@ -0,0 +1 @@ +Subproject commit 5d302c9986a58dce6f5c488369543bd7e0484414