Repository navigation
test(runtime): Zig-native C-ABI tests for lower.zig (issue #14) - #28
Merged
Merged
Conversation
….zig Address issue #14: shinro_step's path previously had only the Python ctypes oracle. Add a Zig-native test that compiles the comptime VM against a small committed fixture graph and drives it in-process — no .so, no ctypes, no Python — so a VM regression fails in the plain `zig build test` step. To let the VM take any graph, separate the deployment binding from the VM: - lower.zig is now graph-agnostic: `pub fn Vm(Ctx)` wraps the VM, with `step` marked `inline` so entry.zig's exported wrapper compiles to exactly the pre-split body (the shipped ReleaseFast .so is byte-identical). - entry.zig (new): the only file that imports graph_data (plus solver_meta/qp for QP graphs), assembles Ctx, and exports shinro_step. - build.zig roots the shared library at entry.zig; the VM test binds its own fixture graph instead of relying on a module-level graph_data import. - README.md / docs/codegen.md updated for entry.zig and the generic VM. Verified: `zig build test` 51/51; `make test-zig` 91 passed, 2 skipped (ctypes oracle matches interpret() for KF+LQR, MPC/.solve_qp, ONNX, recurrent). The pre-refactor ReleaseFast .so is byte-identical (sha256 7d42e97b...).
…Go2, GRU) Extend the Zig-native VM tests (issue #14) to a menu of real graph types, frozen once and committed so the oracle never churns. scripts/gen_lower_fixtures.py lowers each composed graph, compacts its f32 weight blob into a raw little-endian .bin re-exposed via @embedfile + bytesAsSlice (an align(@Alignof(f32)) copy keeps it safe for the kernel's vector weight loads), and emits interpret() vectors on 8 seeded samples. Fixtures under runtime/tests/graphs/: KF+LQR (classical), toy_lstm (fused LSTM), the real Unitree Go2 MLP, and the real eco-drone GRU. tests/lower_graph.zig is a single shared driver compiled once per fixture; build.zig gains a graph_fixtures table, so adding a graph type is one row + one generator entry. Payload ~1.2 MB vs ~6 MB as hex-literal Zig. Generated deliberately — not wired into make zig-gen or CI. Test-only: the library wiring (entry.zig / lower.zig / -Dgraph) is untouched and the shipped ReleaseFast .so stays byte-identical. Verified: zig build test 55/55; make test-zig 91 passed, 2 skipped.
…ymbol TestFrozenFixturesCAbi builds a .so per committed fixture and calls the exported shinro_step via ctypes, checked against the same committed vectors. This covers the export / port-packing surface the in-process Vm(Ctx).step oracle bypasses, plus the compiled path for the compact @embedfile graph format. Self-contained: reads only the committed fixtures (no shinro-bench, no ONNX). Verified: make test-zig 95 passed, 2 skipped (was 91).
…he C-ABI Close the last VM op without Zig-native coverage: add an `mpc` frozen fixture (KF + MPC_LTI, has_solve_qp=true, tol 1e-3) and route the frozen-fixture driver through the exported `shinro_step` instead of `Vm(Ctx).step`. Each fixture gets its own `entry` module (rooted at entry.zig) so `graph_data` resolves to that fixture; the QP one also compiles the baked OSQP solver. entry.zig's shinro_step becomes `pub export` (symbol name unchanged). The generator gains a per-fixture tolerance and runs `zig fmt` on its output so regeneration is a no-op; TestFrozenFixturesCAbi gains `mpc`. Verified: zig build test 56/56; make test-zig 96 passed, 2 skipped.
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.
Closes #14.
What
Zig-native C-ABI tests for the comptime graph VM (
lower.zig), reducing reliance on the Python ctypes oracle. The issue's blocker (lower.zigimporting the generatedgraph_data.zigdirectly) is resolved two ways:lower.zigis now graph-agnostic (pub fn Vm(Ctx)); the deployed graph binding and theshinro_stepexport moved into a thinentry.zig.tests/lower_fixture_graph.zig(hand-authored) andtests/graphs/(5 generated, frozen fixtures).Commits
6528fd7— Zig-native VM tests; split the C-ABI export intoentry.zig.e08d9f2— frozen multi-graph fixtures: KF+LQR, toy LSTM, the real Unitree Go2 MLP, and the real eco-drone GRU. Weights are a raw little-endian f32.binembedded with@embedFile(~5x smaller than hex literals).278c7c8— drive the frozen fixtures through the exportedshinro_step(ctypes).4967159— nativempc(.solve_qp) fixture; route the Zig-native tests through the exported C-ABI.Coverage
zig build test: 56/56 — linalg kernels (48), hand-fixture VM ABI (2), 5 frozen fixtures (KF+LQR, toy LSTM, Go2 MLP, eco-GRU, KF+MPC.solve_qp), emosqp solver (1). All through the exportedshinro_stepexcept the hand fixture (VM directly).make test-zig: 96 passed, 2 skipped — the 5 fixtures are also validated through a built.so.solve_qpwas the last).Production unchanged
The shipped ReleaseFast
.sostays byte-identical (7d42e97b...). Theentry.zigsplit relocates the graph binding + export; it does not change the compiled kernel. Fixtures are test-only and never enter the binary.Notes
scripts/gen_lower_fixtures.py(needs the siblingshinro-benchcheckout for the real policies) and committed; deliberately not wired intomake zig-gen/CI so they never churn.runtime/tests/; that can be excluded separately if desired.