Repository navigation
processor: the Kami word instance is coqutil's Naive.word (stacked on #562) - #563
Draft
JasonGross wants to merge 11 commits into
Draft
JasonGross wants to merge 11 commits into
JasonGross wants to merge 11 commits into
Conversation
This was referenced Sep 12, 2026
JasonGross
force-pushed
the
fable/kami-naive-unify
branch
9 times, most recently
from
September 14, 2026 21:31
14d189c to
207ec71
Compare
Contributor
|
Please include this same in the same multi-repo PR set as removing the Word interface in favor of direct use of stdlib |
Contributor
Author
|
Will do: the unification lands inside the word-removal set (the processor width is a concrete 32, so Kami's Written by Claude Fable 5.1 via Claude Code (session https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm). |
JasonGross
force-pushed
the
fable/kami-naive-unify
branch
3 times, most recently
from
September 15, 2026 06:42
04939e4 to
2d31122
Compare
JasonGross
force-pushed
the
fable/kami-naive-unify
branch
from
September 15, 2026 07:21
2d31122 to
2d65cab
Compare
deps/kami moves to the fable/word-on-bits branch (aff07cc), where Kami.Lib.Word.word n is the standard library's bits (Z.of_nat n) and every word operation is a simpl never wrapper specified through Zmod.unsigned. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
Kami's word is no longer inductive, so the bridge no longer needs its own induction and bit-blasting proofs: one lemma, Z.of_N (wordToN w) = Zmod.unsigned w, carries every Kami unsigned_* fact onto the goals the word.ok instance produces, and the file shrinks from 598 to 332 lines. The instance itself is unchanged: rep, unsigned, signed, of_Z and all the operations are the same Kami functions as before, so kunsigned, kofZ and kword keep their spellings for the rest of processor/ and end2end/. One thing to know when reading the ok proof: Zmod.unsigned's modulus is an implicit argument that mentions 2 ^ Z.of_nat (Z.to_nat width), so rewriting 2 ^ Z.of_nat sz into 2 ^ width would be ill-typed; the proof only ever rewrites the other way. Ten helper lemmas that nothing outside this file referenced were dropped rather than re-proved. No kept statement changed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
uwordToZ is Zmod.unsigned now rather than Z.of_N (wordToN _), so the six places that relied on it being kunsigned by conversion go through the new KamiWord.uwordToZ_kunsigned instead. word is not an inductive type, so injection on an equality of words takes the Zmod record apart; riscvMemInit's NoDup proof projects out of the option with f_equal instead. kami_evalSignExtendTrunc's zero-width case and the three shift lemmas are re-proved at the unsigned interface. End2EndPipeline.v needed two changes, both because reduction and lia now behave differently under the Zmod-based word. Its base case used a bare cbv, which reduces through Zmod.of_Z and duplicates subterms at every nesting level; it is now a restricted cbn. And one arithmetic goal deep inside the end2end proof took 140 s and built a certificate deep enough to overflow the kernel stack at Qed, because Kami's Word.v registers ZifyNat and ZifyN globally and lia then translates every nat and N hypothesis in a very large context; it is now discharged by imem_heap_stack_lengths, the same goal stated on its own, where lia takes two seconds. The file went from a stack overflow to 28 s. All theorem statements are unchanged; imem_heap_stack_lengths is new. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
… 34 s)
`prove_states_related`'s pc branch is
try (eapply pc_related_plus4; try eassumption; red; eauto; fail)
Over the 39 goals at one call site, the 37 eapply's that SUCCEED cost
0.000 s each; the 2 that fail cost 145.7 s and 13.0 s. Plain eapply
unifies the goal against `pc_related_and_valid (?kpc ^+ $4) (word.add
?rpc (word.of_Z 4))`, so on a goal without that shape it descends into
the Zmod-based word operations and their proof field before concluding
"no". `simple eapply` restricts unification, keeps the identical 37
success / 2 failure split, and fails instantly.
Measured on KamiRiscvStep.v with `rocq c -time`, cold:
baseline after port now
prove_states_related, all sites 8.4 s 1307 s 13 s
sum of all command times 455 s 1842 s 513 s
wall clock 8m18s 27m27s 8m34s
It is NOT the `cbv [RegsToT pRegsToT]; kregmap_red; exact eq_refl`
branch: that costs 6 s across all 39 goals. Kernel conversion over Zmod
records is cheap because it evaluates with sharing; the `of_Z`
duplication hazard only bites simpl/cbn/cbv, which rebuild terms.
KamiRiscvStep.v keeps its `From Stdlib Require Import Zmod.`: Kami.Lib.Word
does not re-export the Zmod prefix and this file uses
Zmod.unsigned/Zmod.signed in 9 places.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
Kami's Lt/Slt now evaluate to Z.ltb on uwordToZ/wordToZ, so the word instance's ltu/lts are spelled the same way, is_mmio_spec and the eight branch cases decide the test from the riscv-side comparison fact, and the deleted Kami lemma unsigned_inj is Zmod.unsigned_inj. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
The word instance's fields are Zmod.add, Zmod.sub, ... directly (Kami's names are notations for them now), kofZ and ksigned are eta-expanded since ZToWord sz z is a notation, and the Kami lemmas that were stdlib lemmas (wplus_comm, wplus_assoc, ZToWord_wordToZ, unsigned_ZToWord, unsigned_wplus, weqb_true_iff, ...) are named by their Zmod.* / bits.* names; KamiWord.v's own wnot_idempotent and ZToWord_zero were bits.not_not and Zmod.of_Z_0. KamiRiscvStep.v declares #[local] Arguments Z.pow / Z.of_nat : simpl never so that its simpl/cbn calls keep the modulus 2 ^ Z.of_nat sz that every Kami lemma is keyed on (they unfold the riscv and Kami evaluation functions, not these two constants); with that, one hypothesis that simpl used to close now survives and shifts the auto-generated names, so the ten AddrAligned sites rewrite by the shape of the remu equation instead of by name. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
wrshifta is Zmod.srs, so wrshifta_ZToWord goes through Z.shiftr_div_pow2 instead of reflexivity; wordToZ_inj is Zmod.signed_inj; the shifts are Zmod.slu/sru/srs at Z.of_nat n, one application deeper for f_equal in kami_word_riscv_ok. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
…are gone wordToZ, uwordToZ, weqb, wzero, wnot, ZToWord, wlshift, wrshift and wrshifta are Zmod.signed, Zmod.unsigned, Zmod.eqb, Zmod.zero, Zmod.not, bits.of_Z (Z.of_nat sz), Zmod.slu, Zmod.sru and Zmod.srs (the shifts at Z.of_nat n); End2EndPipeline.v imports Zmod for the name. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
KamiWord.word is now Naive.word with its rep spelled as Kami's nat-indexed word type, so that Kami's API still unifies against it; KamiWord.word 32 = Naive.word 32 holds by reflexivity. The hand-written instance, its word.ok proof and end2end/KamiRiscvWordProperties.v are gone; the lightbulb proof takes riscv_ok from the compiler's NaiveRiscvWordProperties. kunsigned is now Zmod.unsigned (word.unsigned by conversion). Consistency.v gains spelling lemmas (kunsigned_eq, kadd_eq, kofZ_eq, ...) and KamiWord.v gains kunsigned_wordToN, ltu_eq and lts_eq; the processor proofs rewrite with these where they used to cbv through the instance. Print Assumptions end2end_lightbulb is unchanged: the same 8 axioms and the same output. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm
JasonGross
force-pushed
the
fable/kami-naive-unify
branch
from
September 15, 2026 08:04
2d65cab to
9d947e4
Compare
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.
Stacked on #562 (which is stacked on #561); this branch contains their commits, and the new part is the last commit, d7805a7.
Follow-up to a review question on mit-plv/coqutil#186: with Kami's word now stdlib
bits, the Kami-sidewordinstance inprocessor/src/processor/KamiWord.vand coqutil'sNaive.wordagree on all 26 fields at widths 32 and 8 (division by zero, signed overflow, shift amounts at or above the width,sextend, themulh*family, comparisons), as lemmas. So the hand-written instance is replaced byNaive.wordfield for field (therepis still spelled as Kami's nat-indexed type, because a bare alias breaksWord.word ?szunification at every Kami use site),word 32 = Naive.word 32holds byreflexivity,word.okcomes fromNaive.ok, andend2end/src/end2end/KamiRiscvWordProperties.vis deleted:word.riscv_oknow comes from the compiler'sNaiveRiscvWordProperties.v.kunsignedisZmod.unsigned; proofs that used tocbvthrough the instance rewrite with a few spelling lemmas instead. No theorem statement changes;Print Assumptions end2end_lightbulbis byte-identical (the same 8 axioms).On the reviewer's question whether Naive's
adjust_too_big_shift_amountis still needed: it is, but not for the lightbulb proof specifically. An unadjustedNaive.wordviolatesriscv_ok'sslu_ignores_hibits(counterexample at y = 1, z = 32, proved in the analysis), so the adjustment is what makesNaive.wordsatisfy the RISC-V shift convention for the compiler theorem. Before this change the lightbulb proof used the Kami-side instance's ownmod widthmasking; after it, it relies on Naive's adjustment like every other Naive user.make allpasses in 9m21s (KamiRiscvStep.v7m52s, faster than before the Kami port). Depends on mit-plv/kami#51 and #562.Written by Claude Fable 5.1.
🤖 Generated with Claude Code
https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm