From 8087ec89e5f4d7202276aef1af9611f7acddb6bd Mon Sep 17 00:00:00 2001 From: Scott Date: Mon, 6 Jul 2026 13:41:26 -0500 Subject: [PATCH 1/2] Fix hardcoded /home/scott path in test_blur.py test_blur.py wrote its before/after PNGs to a hardcoded /home/scott/npu-linux-kit/camera/... path, which only worked on the original author's machine. Write next to the script instead, using the same os.path.dirname(__file__) pattern the file already uses for sys.path. Still needs the real NPU + IRON toolchain to actually run (import aie.iron), so I can't execute this end to end here, but the path fix itself is a one-line, low-risk portability correction. Signed-off-by: Scott --- camera/test_blur.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/camera/test_blur.py b/camera/test_blur.py index 18915ea..eb6cff3 100644 --- a/camera/test_blur.py +++ b/camera/test_blur.py @@ -1,6 +1,7 @@ import sys, time, os import numpy as np, cv2 -sys.path.insert(0, os.path.dirname(__file__) or ".") +HERE = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, HERE) import aie.iron as iron from blur_pipeline import blur @@ -24,8 +25,8 @@ sharp_var = float(img[H // 2, :, 0].astype(np.float32).var()) blur_var = float(o[H // 2, :, 0].astype(np.float32).var()) -cv2.imwrite("/home/scott/npu-linux-kit/camera/blur_before.png", cv2.cvtColor(img, cv2.COLOR_RGBA2BGR)) -cv2.imwrite("/home/scott/npu-linux-kit/camera/blur_after.png", cv2.cvtColor(o, cv2.COLOR_RGBA2BGR)) +cv2.imwrite(os.path.join(HERE, "blur_before.png"), cv2.cvtColor(img, cv2.COLOR_RGBA2BGR)) +cv2.imwrite(os.path.join(HERE, "blur_after.png"), cv2.cvtColor(o, cv2.COLOR_RGBA2BGR)) smoothed = "SMOOTHED ok" if blur_var < sharp_var * 0.8 else "NOT smoothed?" print(f"blur @720p: {dt*1e3:.2f} ms/frame -> {1/dt:.0f} FPS") print(f"row variance sharp={sharp_var:.0f} -> blurred={blur_var:.0f} ({smoothed})") From e4c29bc5a85f7f0dd42bd2bfcbf9f43e4f98898a Mon Sep 17 00:00:00 2001 From: Scott Date: Mon, 6 Jul 2026 13:43:14 -0500 Subject: [PATCH 2/2] Add CI for the hardware-independent surface Every module here is an application on top of the open-xdna NPU stack (IRON/mlir-aie + Peano + a real XDNA1 NPU), none of which exists on a GitHub-hosted runner. This CI covers what's left: - byte-compiles all of camera/*.py (syntax only) - installs requirements.txt (opencv-python-headless, onnxruntime, numpy, ml_dtypes, pyvirtualcam) in a clean venv, confirming the host-side deps resolve on Linux/x86_64 - runs each camera/*.py module and asserts it gets through all of its own host-side imports and fails only at "import aie.iron" (the NPU toolchain boundary) - any other failure is a real bug and fails CI I ran this exact sequence locally first: requirements.txt installs clean, and all six camera/*.py files (including test_blur.py after the path fix) fail only at the aie import, nothing earlier. This does not and cannot verify any effect actually running on the NPU, camera/kernels/blur3x3.cc compiling (needs the Peano AIE2 cross-compiler), or the measured FPS numbers in camera/README.md. Signed-off-by: Scott --- .github/workflows/ci.yml | 58 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f2c69a5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,58 @@ +name: CI (software-only) + +# Every module in this kit is an application layer on top of the open-xdna +# NPU stack (IRON/mlir-aie + Peano + a real XDNA1 NPU + amdxdna driver). +# None of that toolchain or hardware exists on a normal GitHub-hosted +# runner, so this workflow does NOT and CANNOT verify: +# - any camera/*.py effect actually running on the NPU +# - camera/kernels/blur3x3.cc compiling (needs the Peano AIE2 +# cross-compiler and aie_api headers) +# - any of the measured FPS/latency numbers in camera/README.md +# +# What IS hardware-independent and checked here: +# - every Python file parses (byte-compiles) cleanly +# - the host-side pip requirements (opencv, onnxruntime, numpy, +# ml_dtypes, pyvirtualcam) install cleanly on Linux/x86_64 +# - each camera/*.py module imports up through all of ITS OWN +# host-side deps and fails only at `import aie.iron` (i.e. the NPU +# toolchain boundary), never earlier on a host-side bug. If a +# module fails on anything other than a missing `aie` module, that +# is a real bug this CI will catch. + +on: + push: + branches: [main] + pull_request: + +jobs: + syntax-and-host-deps: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Byte-compile all Python sources (syntax only, no NPU/aie needed) + run: python -m compileall -q camera + + - name: Install host-side requirements (no NPU stack involved) + run: pip install -r requirements.txt + + - name: Import each camera module up to the NPU-toolchain boundary + run: | + set -e + fail=0 + for f in camera/*.py; do + echo "--- $f ---" + out=$(python3 "$f" 2>&1) && { echo "ran to completion (unexpected without hardware, but not a failure)"; continue; } + if echo "$out" | grep -q "ModuleNotFoundError: No module named 'aie'"; then + echo "OK: fails only at the expected NPU-toolchain (aie) boundary" + else + echo "$out" + echo "FAIL: $f errored before reaching the aie import boundary" + fail=1 + fi + done + exit $fail