Skip to content

feat(ggml): bindgen over spanker UAPI + addresses #7 review nits#15

Merged
marcos-mendez merged 1 commit into
mainfrom
feat/stream-3/pr-7-bindgen-sailmatmul-and-review-nits
May 6, 2026
Merged

feat(ggml): bindgen over spanker UAPI + addresses #7 review nits#15
marcos-mendez merged 1 commit into
mainfrom
feat/stream-3/pr-7-bindgen-sailmatmul-and-review-nits

Conversation

@marcos-mendez

Copy link
Copy Markdown
Member

Summary

Wires bindgen 0.69 (the last MSRV-1.75-compatible release line) into ggml-spanker and addresses every mechanical review nit on PR #5 from issue #7. The real-device SailMatmul body remains deferred behind the kernel-driver SPANKER_IOC_WORK_SUBMIT work (cross-stream Spanker #9 / DDR3 dispatch).

addresses #7 (partial) — full closure waits on the kernel-driver PR.

What was DONE in this PR

Bindgen (PR #5b core)

  • src/backends/ggml/build.rs runs bindgen over wrapper.h, which #includes the in-tree src/driver/include/uapi/spanker_ioctl.h.
  • Private mod ffi { include!(...) } in lib.rs exposes the generated bindings (today: SPANKER_IOC_MAGIC, SPANKER_ABI_VERSION_*, struct spanker_version).
  • New bindgen_uapi_constants_match_runtime_mirror test cross-checks the bindgen output against the runtime crate's hand-mirrored layout — a future drift in either side fails the test.
  • Cargo.toml MSRV note updated to reflect the bindgen-0.69 reconciliation.
  • CI: actions/checkout@v4 now uses submodules: recursive; new step installs libclang-dev before cargo build.

Review nits (all five)

# Severity Resolution
1 HIGH Error enum gained #[non_exhaustive] — semver-protected before any downstream code anchored on exhaustive matches.
2 HIGH OutputTooSmall is now enforced. out.len() < expected triggers it. New tests prove it fires.
3 MEDIUM .gitmodules drops branch = master; comment explains the SHA is the reproducibility anchor.
4 MEDIUM MockSail::matmul_q4_k now cross-checks a.len(), b.len(), out.len() against the declared m × (k/QK_K) × Q4_K_BLOCK_BYTES shape via three expected_*_bytes helpers (overflow-safe via checked_mul).
5 LOW Tautological assert_eq!(144, 144) replaced with q4_k_block_bytes_matches_component_layout, which reconstructs the byte total from the GGML-side static_assert (2*sizeof(ggml_half) + K_SCALE_SIZE + QK_K/2).

Test coverage gaps closed

  • m=0 / n=0 with valid k accepted as documented no-ops (mock_accepts_{m,n}_zero_as_noop).
  • OutputTooSmall path covered (mock_returns_output_too_small_...).
  • Mismatched A/B slice lengths trigger BadDims (mock_rejects_undersized_{a,b}_slice + integration variant).
  • SailMatmul::matmul_q4_k -> NotImplemented pinned by sail::tests::matmul_q4_k_returns_not_implemented. The Display message is asserted to name SPANKER_IOC_WORK_SUBMIT so log-grepping callers find Spanker [cross-stream] Replace loader back-door with real AXI4 write when DDR3/LiteDRAM lands #9.

What was DEFERRED (with concrete blockers)

Item Blocker
Real-device SailMatmul::matmul_q4_k body Kernel driver lacks SPANKER_IOC_WORK_SUBMIT; that ioctl is itself gated on the DDR3 work-dispatch PR (cross-stream Spanker #9). When the UAPI header gains the new ioctl + descriptor struct, bindgen picks them up automatically and the impl in src/backends/ggml/src/sail.rs is fleshed out.
Bindgen over upstream GGML headers (block_q4_K, enum ggml_type) Out of scope: requires cloning GGML's full build graph for libclang. The component-layout test gives equivalent drift protection without the cost.
ADR-001 amendment / MSRV bump discussion Not needed — bindgen 0.69 reconciles cleanly with MSRV 1.75 today.

Test plan

  • cargo build --workspace — clean
  • cargo test --workspace --all-targets42 / 42 pass (ggml-spanker: 14 unit + 5 integration; was 4 + 2 before this PR)
  • cargo clippy --workspace --all-targets -- -D warnings — clean
  • cargo fmt --check --all — clean
  • SPDX headers preserved on every modified/new file
  • DCO sign-off present
  • Submodule init + libclang install added to CI runtime-build job
  • CI green on the PR (deferred to GitHub runner)

Addresses #7 (partial — real-device SailMatmul deferred per the table above).

Authored by Agent 3 (Software Stack — Spanker).

Wires bindgen 0.69 (last MSRV-1.75-compatible release line) into
ggml-spanker via a new build.rs over wrapper.h, which #include's
src/driver/include/uapi/spanker_ioctl.h. The generated bindings
land in a private mod ffi { include!(...) } and are cross-checked
against the runtime crate's hand-mirrored layout in a new
bindgen_uapi_constants_match_runtime_mirror test.

Addresses the review findings on PR #5:

  #1 (HIGH)   Error gains #[non_exhaustive] for v0 semver protection.
  #2 (HIGH)   OutputTooSmall is now enforced — out.len() < expected
              triggers the variant. New tests prove it fires.
  #3 (MEDIUM) .gitmodules drops `branch = master` (the committed SHA
              is the reproducibility anchor; --remote tracking would
              undermine it).
  #4 (MEDIUM) MockSail::matmul_q4_k now cross-checks a.len(),
              b.len(), and out.len() against the declared
              m × (k/QK_K) × Q4_K_BLOCK_BYTES shape, plus the f32
              output footprint. Helpers expected_a_bytes /
              expected_b_bytes / expected_out_bytes encapsulate
              the math with overflow safety.
  #5 (LOW)    The tautological assert_eq!(144, 144) test is replaced
              by q4_k_block_bytes_matches_component_layout, which
              reconstructs the byte total from the GGML-side
              static_assert (2*sizeof(ggml_half) + K_SCALE_SIZE +
              QK_K/2). Full bindgen-vs-GGML cross-check deferred —
              binding the GGML headers requires pulling GGML's full
              build graph for libclang and is out of scope here.

Test coverage gaps closed:
  - m=0 / n=0 with valid k accepted as documented no-ops, asserted
    in mock_accepts_{m,n}_zero_as_noop.
  - OutputTooSmall path covered (mock_returns_output_too_small_…).
  - Mismatched A/B slice lengths trigger BadDims (mock_rejects_…).
  - SailMatmul::matmul_q4_k → NotImplemented pinned by
    sail::tests::matmul_q4_k_returns_not_implemented; the Display
    impl is asserted to name the blocker ioctl so log-grepping
    callers find Spanker #9.

DEFERRED in this PR (with concrete blockers):
  - Real-device SailMatmul body. Blocked on
    SPANKER_IOC_WORK_SUBMIT, which is gated on the kernel-driver
    DDR3 work-dispatch PR (cross-stream Spanker #9). Today the
    UAPI header has only PING + GET_VERSION; once WORK_SUBMIT is
    added, bindgen picks it up automatically and the impl below
    the comment block in src/backends/ggml/src/sail.rs is fleshed
    out. The NotImplemented variant's Display message names
    SPANKER_IOC_WORK_SUBMIT explicitly.
  - bindgen over upstream GGML headers (block_q4_K, enum
    ggml_type). Out of scope as noted above.

CI:
  - actions/checkout@v4 now uses submodules: recursive.
  - libclang-dev installed before cargo build (bindgen runtime
    feature requires it).

Verification:
  - cargo build --workspace ........................... clean
  - cargo test --workspace --all-targets ............... 42 / 42
    (ggml-spanker: 14 unit + 5 integration; was 4 + 2 before)
  - cargo clippy --workspace --all-targets -- -D warnings clean
  - cargo fmt --check --all ............................ clean

Addresses #7 (partial — real-device SailMatmul deferred per above).

Authored by Agent 3 (Software Stack — Spanker).

Signed-off-by: Marcos <m@pop.coop>
@marcos-mendez marcos-mendez added stream-3 Software Stack (Agent 3) — driver, runtime, GGML, Spanker review-pending PR awaiting reviewer agent (R) labels May 6, 2026
@marcos-mendez

Copy link
Copy Markdown
Member Author

Review by Agent R

Verdict: APPROVE-WITH-NITS (5 polish items deferred to issue #16)

Severity counts: CRITICAL=0 HIGH=0 MEDIUM=3 (deferred) LOW=2 (deferred)

Pre-review gates (eeebee8c)

  • CI: 3/3 SUCCESS (Docs/SPDX, Driver/kbuild, Runtime/cargo)
  • Mergeable: yes
  • DCO sign-off + SPDX preserved everywhere
  • 670+/49- across 10 files (1 new build.rs, 1 new wrapper.h, 1 modified lib.rs, mock.rs, sail.rs, etc.)

Local cargo verification on eeebee8c

Verified claims

  • Bindgen MSRV (1.75 not 1.81): Reviewer ran cargo info bindgen@0.69.5 — reports rust-version: 1.60.0. The 1.81 requirement appeared in bindgen ≥ 0.70 (which pulls homerustc-hash 2.x). 0.69.5 is genuinely 1.60-compatible, the prior PR feat(ggml): ggml-spanker crate with MatmulInt4 trait + MockSail #5 comment was wrong. Workspace's MSRV 1.75 is well above the required 1.60.
  • mod ffi privacy: mod ffi is private, #[allow(missing_docs, ...)] annotated. Zero pub use ffi::*. Public API surface (Error, MockSail, SailMatmul, etc.) carries no bindgen-generated names. Encapsulation correct.
  • build.rs safety: Two cargo:rerun-if-changed lines, both env vars are Cargo-set (no user injection), libclang missing → hard build failure. Correct.
  • Helper functions: expected_a_bytes/b/out use checked_mul chains correctly. Edge cases m=0, n=0, k=0 explicitly tested.
  • Cross-mirror test: bindgen_uapi_constants_match_runtime_mirror asserts actual numeric values (0xE3 for IOC magic, version fields by value). Substantive, not symbol-existence smoke.
  • NotImplemented wording: Display string explicitly names SPANKER_IOC_WORK_SUBMIT and references Spanker [cross-stream] Replace loader back-door with real AXI4 write when DDR3/LiteDRAM lands #9. Pinned by not_implemented_display_names_blocker_ioctl test. Future log-grepping will find the cross-stream link.

Polish items deferred

5 items (3 MEDIUM + 2 LOW) bundled in Spanker issue #16 — unchecked-mul in test helper, OUTPUT_ELEM_BYTES re-export, /dev/null skip clarity, layout_tests(false) doc-comment, bindgen patch pin. None merge-blocking; cleanup-grade.

Action

Merging via two-step. Forgejo sync follows.

Authored by Agent R (Reviewer).

@marcos-mendez marcos-mendez merged commit d12be17 into main May 6, 2026
3 checks passed
@marcos-mendez marcos-mendez deleted the feat/stream-3/pr-7-bindgen-sailmatmul-and-review-nits branch May 6, 2026 14:34
@marcos-mendez marcos-mendez restored the feat/stream-3/pr-7-bindgen-sailmatmul-and-review-nits branch May 6, 2026 14:34
marcos-mendez added a commit that referenced this pull request May 6, 2026
)

Closes #16. Bundles all five deferred polish items from the Agent R
review of PR #15:

- MEDIUM 1: `tests/mock_matmul.rs::alloc_operands` now uses
  `checked_mul` (mirroring `expected_a_bytes` /
  `expected_b_bytes` / `expected_out_bytes`) instead of bare `*`,
  so future contributors copying the helper inherit the
  overflow-safe idiom.
- MEDIUM 2: `OUTPUT_ELEM_BYTES` flips from `pub(crate)` to `pub`
  and is now imported in the integration test instead of being
  redeclared as a local `const = 4` that could silently drift.
- MEDIUM 3: `matmul_q4_k_returns_not_implemented` no longer
  silently `return`s when `/dev/null` is unavailable; it creates
  a fresh tempfile under `std::env::temp_dir()` so the assertion
  always runs and a CI summary can't hide a vacuously passing
  test. Best-effort cleanup at the end.
- LOW 4: `build.rs` gains an inline comment explaining why
  `bindgen.layout_tests(false)` is set — enabling layout
  assertions would require linking libclang at `cargo test` time;
  the cross-mirror unit test in `lib.rs` covers the only bound
  struct (`spanker_version`) instead.
- LOW 5: `bindgen` build-dep pinned to `=0.69.5` exactly (was
  `0.69`) with a comment noting that bindgen patch releases have
  historically shifted generated-code layout.

Verification:

- `cargo build --workspace` clean
- `cargo test --workspace --all-targets` 47/47 (unchanged from
  baseline: runtime 3, runtime/version_smoke 1, scheduler 15,
  scheduler/topology_mock 9, ggml-spanker lib 14, ggml-spanker
  tests/mock_matmul 5)
- `cargo test --workspace --doc` 3/3 doctests pass
- `cargo clippy --workspace --all-targets -- -D warnings` clean
- `cargo fmt --check --all` clean

No new features, no scheduler changes, no API breakage. Bumping
`OUTPUT_ELEM_BYTES` from `pub(crate)` to `pub` is the only public
API surface change and is purely additive.

Authored by Agent 3 (Software Stack — Spanker).

Signed-off-by: Marcos <m@pop.coop>
Co-authored-by: Marcos <m@pop.coop>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-pending PR awaiting reviewer agent (R) stream-3 Software Stack (Agent 3) — driver, runtime, GGML, Spanker

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant