Skip to content

processor: Kami words on stdlib bits; thin KamiWord bridge (stacked on #561) - #562

Open
JasonGross wants to merge 10 commits into
mit-plv:masterfrom
JasonGross:fable/kami-bits
Open

JasonGross wants to merge 10 commits into
mit-plv:masterfrom
JasonGross:fable/kami-bits

Conversation

@JasonGross

@JasonGross JasonGross commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #561: this branch contains #561's commits (the base branch lives on a fork, so GitHub cannot show the stacked diff alone). The Kami part is the last four commits, 728df75..efe4ea4; review those.

Pins deps/kami to mit-plv/kami#51, where Kami's word n is stdlib bits (Z.of_nat n) with the nat index kept, and simplifies the processor bridge accordingly: processor/src/processor/KamiWord.v shrinks from 598 to 332 lines because a Kami word 32 is now the same representation as coqutil's Naive.word 32, so the word.ok laws come from stdlib's Zmod lemmas instead of a hand-rolled bijection. The remaining edits are proof repairs in KamiRiscvStep.v (and KamiRiscv.v, End2EndPipeline.v) with unchanged statements; the last three commits follow Kami's Word.v cleanup (split1, wmsb, shifts and remainders as the stdlib operations, unused lemmas gone) and Kami's operations becoming the Zmod ones (the instance's fields are Zmod.add etc. and proofs name the stdlib lemmas; KamiRiscvStep.v keeps its simpl calls with file-local Arguments Z.pow/Z.of_nat : simpl never so the modulus stays folded) and Kami's Lt/Slt evaluating to Z.ltb (the instance's ltu/lts are Z.ltb on uwordToZ/wordToZ, and is_mmio_spec plus the eight branch cases decide that test from the riscv-side fact with one small tactic instead of change blocks); end2end/src/end2end/KamiRiscvWordProperties.v stays because it supplies word.riscv_ok for the Kami word (the division-by-zero and shift-masking conventions are unchanged). make all (compiler, processor, end2end, LiveVerif) passes; Print Assumptions end2end_lightbulb is unchanged. One caveat found on the way: with words as Zmod records, a bare lia whose Zify-translated context mentions many words can build a certificate deep enough to overflow the kernel stack at Qed (it did in End2EndPipeline.v); the offending step is now a small standalone lemma. Compile time of the processor + end2end cone is 10m09s versus 9m23s before the port (1.08x): the only real regression was a speculative eapply in prove_states_related that now failed slowly by unfolding through Zmod, fixed with simple eapply. After this port a failing eapply is much more expensive than a succeeding one, so simple eapply is the right tool wherever a hot tactic applies a lemma under try/repeat.

Depends on mit-plv/kami#51 and on #561; CI cannot fetch the pinned Kami commit until #51 merges, so this stays a draft until then.

Written by Claude Fable 5.1 and Claude Opus 5.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm

@JasonGross

JasonGross commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor Author

Stacked follow-up: #563 makes the Kami word instance be coqutil's Naive.word (all fields shown equal) and drops KamiRiscvWordProperties.v.


Written by Claude Fable 5.1 via Claude Code (session https://claude.ai/code/session_01YJbiRBkJtM7x6PvYV6hmEm).

@JasonGross
JasonGross force-pushed the fable/kami-bits branch 7 times, most recently from 3e65466 to 61831cc Compare September 14, 2026 21:31
@andres-erbsen
andres-erbsen marked this pull request as ready for review September 15, 2026 04:26
@JasonGross
JasonGross force-pushed the fable/kami-bits branch 4 times, most recently from e52c4ce to e32f886 Compare September 15, 2026 07:21
JasonGross and others added 10 commits September 15, 2026 07:38
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant