feat(ggml): bindgen over spanker UAPI + addresses #7 review nits#15
Merged
marcos-mendez merged 1 commit intoMay 6, 2026
Merged
Conversation
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>
Member
Author
Review by Agent RVerdict: 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 (
|
13 tasks
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Wires
bindgen 0.69(the last MSRV-1.75-compatible release line) intoggml-spankerand addresses every mechanical review nit on PR #5 from issue #7. The real-deviceSailMatmulbody remains deferred behind the kernel-driverSPANKER_IOC_WORK_SUBMITwork (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.rsruns bindgen overwrapper.h, which#includes the in-treesrc/driver/include/uapi/spanker_ioctl.h.mod ffi { include!(...) }inlib.rsexposes the generated bindings (today:SPANKER_IOC_MAGIC,SPANKER_ABI_VERSION_*,struct spanker_version).bindgen_uapi_constants_match_runtime_mirrortest cross-checks the bindgen output against the runtime crate's hand-mirrored layout — a future drift in either side fails the test.Cargo.tomlMSRV note updated to reflect the bindgen-0.69 reconciliation.actions/checkout@v4now usessubmodules: recursive; new step installslibclang-devbeforecargo build.Review nits (all five)
Errorenum gained#[non_exhaustive]— semver-protected before any downstream code anchored on exhaustive matches.OutputTooSmallis now enforced.out.len() < expectedtriggers it. New tests prove it fires..gitmodulesdropsbranch = master; comment explains the SHA is the reproducibility anchor.MockSail::matmul_q4_know cross-checksa.len(),b.len(),out.len()against the declaredm × (k/QK_K) × Q4_K_BLOCK_BYTESshape via threeexpected_*_byteshelpers (overflow-safe viachecked_mul).assert_eq!(144, 144)replaced withq4_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=0with validkaccepted as documented no-ops (mock_accepts_{m,n}_zero_as_noop).OutputTooSmallpath covered (mock_returns_output_too_small_...).BadDims(mock_rejects_undersized_{a,b}_slice+ integration variant).SailMatmul::matmul_q4_k -> NotImplementedpinned bysail::tests::matmul_q4_k_returns_not_implemented. TheDisplaymessage is asserted to nameSPANKER_IOC_WORK_SUBMITso 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)
SailMatmul::matmul_q4_kbodySPANKER_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 insrc/backends/ggml/src/sail.rsis fleshed out.block_q4_K,enum ggml_type)Test plan
cargo build --workspace— cleancargo test --workspace --all-targets— 42 / 42 pass (ggml-spanker: 14 unit + 5 integration; was 4 + 2 before this PR)cargo clippy --workspace --all-targets -- -D warnings— cleancargo fmt --check --all— cleanAddresses #7 (partial — real-device SailMatmul deferred per the table above).
Authored by Agent 3 (Software Stack — Spanker).