Sync from GitHub at 25c8330: hardware-in-the-loop rig, SAM D21 board, guard elimination on RV32/Cortex-M3
0e9783b verified Download backend/cortexm0/CM0/Correct.lean from Snapkitty/ai-free: direct link, hf CLI and curl.
- Browser
- Download file 10.3 kB
-
https://huggingface.co/Snapkitty/ai-free/resolve/main/backend/cortexm0/CM0/Correct.lean
- Command line
-
hf download hf://Snapkitty/ai-free/backend/cortexm0/CM0/Correct.lean
-
curl -L -o Correct.lean https://huggingface.co/Snapkitty/ai-free/resolve/main/backend/cortexm0/CM0/Correct.lean
10.3 kB
| import CM0.SimStep | |
| /-! | |
| # CM0.Correct | |
| Whole-program preservation: running the lowered ARMv6-M code from a state related to the IR state | |
| `s` reaches the same final outcome the IR semantics reaches from `s`. | |
| * IR `halted s'` ⇒ the ARMv6-M code halts in a state `x'` with `Rel0 c p s' x'` (so the data | |
| stack, virtual registers, IR memory and return stack agree with `s'`); | |
| * IR `trapped t` ⇒ the ARMv6-M code exits with the same trap `t`. | |
| Every instruction that grows the data stack or the auxiliary stack, and every `call`, checks for | |
| room first and exits with `overflow` (exit code 6) when the stack is full, so there are two forms: | |
| * `lowerProg_correct_or_overflow` has no capacity hypothesis: the ARMv6-M code reaches the IR outcome | |
| as above, or exits with `overflow` (the run needed more stack than the target provides); | |
| * `lowerProg_correct` additionally assumes the IR run stays within the capacities (`Fits` at every | |
| reachable state); then no guard fires and the outcome is exactly the IR's. | |
| Hypotheses of both (all explicit): | |
| * `Geom c` the memory regions (data stack, register file, IR memory, return stack, | |
| auxiliary stack) are disjoint and within the 32-bit address space, the | |
| data and auxiliary stacks hold at least one word each and the return stack | |
| at least two; | |
| * `L` matches `c` data-stack end and limit, return-stack gap, auxiliary-stack end and limit, | |
| and IR memory size; | |
| * `hLf`, `hok`, `I` the code was lowered with the configuration's facts: its lower-bound | |
| certificate passes `certOk`, and its upper bound `c.ub` is implied by an | |
| invariant `I` kept by every step within the data stack's capacity (`hIs`, | |
| `hIb`; `WordDialect.UbSound`); the runs carry `DepthInv` and `I`, so every | |
| underflow or overflow guard the lowering left out would have passed; | |
| * `hsz` code indices fit in 32 bits; | |
| * `RegsOk` every `push r`/`pop r` names a register inside the register file. | |
| -/ | |
| namespace WordDialect | |
| namespace CM0 | |
| open Reg | |
| /-- Every register index used by the program lies in the virtual register file. -/ | |
| def RegsOk (c : Cfg) (p : Prog 32) : Prop := | |
| ∀ (k : Nat) (i : WordDialect.Instr 32), p[k]? = some i → ∀ r : Nat, (i = WordDialect.Instr.push r ∨ i = WordDialect.Instr.pop r) → r < c.nregs | |
| /-- The final-outcome form of `Sim`. -/ | |
| def Final (c : Cfg) (p : Prog 32) (code : List (Instr Nat)) (x : M) : Outcome 32 → Prop | |
| | .next _ => False | |
| | .halted s' => ∃ x', RExec code x (.halted x') ∧ Rel0 c p s' x' | |
| | .trapped t => RExec code x (.trapped t) | |
| theorem offs_ge (cf : Nat → Facts) {p : Prog 32} {k : Nat} (h : p.length ≤ k) : | |
| offs cf p k = offs cf p p.length := by | |
| induction p generalizing cf k with | |
| | nil => cases k <;> simp [offs] | |
| | cons i is ih => | |
| cases k with | |
| | zero => simp at h | |
| | succ k => simp only [List.length_cons, offs]; rw [ih _ (by simp at h; omega)] | |
| /-- A related state is within the data stack's capacity. -/ | |
| theorem cap_of_rel {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (hs : Rel c p s x) : | |
| s.dstack.length ≤ c.dCap := by | |
| have := hs.1.capD | |
| unfold Cfg.dCap | |
| omega | |
| /-- One IR step from a related state: the bad-pc stub, or the dispatched instruction. -/ | |
| theorem step_sim {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c) | |
| (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4)) | |
| (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd) | |
| (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true) | |
| (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p) | |
| {s : State 32} {x : M} (hs : Rel c p s x) (hdi : DepthInv c.cert s) | |
| (hub : s.dstack.length ≤ c.ub s.pc) : | |
| Sim c p (lowerProg L p) x (WordDialect.step p s) ∨ | |
| (¬ Fits c s ∧ RExec (lowerProg L p) x .overflow) := by | |
| cases hi : p[s.pc]? with | |
| | none => | |
| left | |
| have hst : WordDialect.step p s = .trapped .badPc := by simp [WordDialect.step, hi] | |
| rw [hst] | |
| have hge : p.length ≤ s.pc := by | |
| by_cases hh : s.pc < p.length | |
| · rw [List.getElem?_eq_getElem hh] at hi; simp at hi | |
| · omega | |
| obtain ⟨f0, _⟩ := lowerProg_stub L p | |
| rw [hLf] at f0 | |
| have hpc : x.pc = offs c.facts p p.length := by rw [hs.2, offs_ge _ hge] | |
| exact RExec.trap (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl) | |
| | some i => | |
| have hst : WordDialect.step p s = WordDialect.exec i s := by simp [WordDialect.step, hi] | |
| rw [hst] | |
| exact sim_exec hg hL hMs hLd hLr hLa hLal hLf hsz hs hdi.depth hub hi (fun r hr => hreg s.pc i hi r hr) | |
| /-- Whole-program preservation, with no capacity hypothesis: the ARMv6-M code reaches the IR | |
| outcome, or exits with `overflow` because a stack was full. -/ | |
| theorem lowerProg_correct_or_overflow {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c) | |
| (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4)) | |
| (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd) | |
| (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true) | |
| {I : State 32 → Prop} | |
| (hIs : ∀ s s', I s → s.dstack.length ≤ c.dCap → WordDialect.step p s = .next s' → I s') | |
| (hIb : ∀ s, I s → s.dstack.length ≤ c.ub s.pc) | |
| (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p) | |
| {s : State 32} {o : Outcome 32} (h : Exec p s o) : | |
| ∀ {x : M}, Rel c p s x → DepthInv c.cert s → I s → | |
| Final c p (lowerProg L p) x o ∨ RExec (lowerProg L p) x .overflow := by | |
| induction h with | |
| | @halt s s' hst => | |
| intro x hs hdi hbi | |
| have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi) | |
| rw [hst] at this | |
| rcases this with this | ⟨_, h6⟩ | |
| · exact .inl this | |
| · exact .inr h6 | |
| | @trap s t hst => | |
| intro x hs hdi hbi | |
| have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi) | |
| rw [hst] at this | |
| rcases this with this | ⟨_, h6⟩ | |
| · exact .inl this | |
| · exact .inr h6 | |
| | @next s s' o hst _ ih => | |
| intro x hs hdi hbi | |
| have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi) | |
| rw [hst] at this | |
| rcases this with ⟨x1, hsteps, hrel⟩ | ⟨_, h6⟩ | |
| · rcases ih hrel (DepthInv.step hok hdi hst) (hIs s _ hbi (cap_of_rel hs) hst) with hih | h6 | |
| · left | |
| cases o with | |
| | next _ => exact hih.elim | |
| | halted r5 => | |
| obtain ⟨x', hx, hr⟩ := hih | |
| exact ⟨x', RExec.of_steps hsteps hx, hr⟩ | |
| | trapped t => exact RExec.of_steps hsteps hih | |
| · exact .inr (RExec.of_steps hsteps h6) | |
| · exact .inr h6 | |
| /-- Whole-program preservation. When the IR run stays within the stack capacities (`Fits` at | |
| every reachable state), no overflow guard fires and the outcome is exactly the IR's. -/ | |
| theorem lowerProg_correct {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c) | |
| (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4)) | |
| (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd) | |
| (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true) | |
| {I : State 32 → Prop} | |
| (hIs : ∀ s s', I s → s.dstack.length ≤ c.dCap → WordDialect.step p s = .next s' → I s') | |
| (hIb : ∀ s, I s → s.dstack.length ≤ c.ub s.pc) | |
| (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p) | |
| {s : State 32} {o : Outcome 32} (h : Exec p s o) : | |
| ∀ {x : M}, Rel c p s x → DepthInv c.cert s → I s → (∀ s', Steps p s s' → Fits c s') → | |
| Final c p (lowerProg L p) x o := by | |
| induction h with | |
| | @halt s s' hst => | |
| intro x hs hdi hbi hb | |
| have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi) | |
| rw [hst] at this | |
| rcases this with this | ⟨hnf, _⟩ | |
| · exact this | |
| · exact absurd (hb s .refl) hnf | |
| | @trap s t hst => | |
| intro x hs hdi hbi hb | |
| have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi) | |
| rw [hst] at this | |
| rcases this with this | ⟨hnf, _⟩ | |
| · exact this | |
| · exact absurd (hb s .refl) hnf | |
| | @next s s' o hst _ ih => | |
| intro x hs hdi hbi hb | |
| have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi) | |
| rw [hst] at this | |
| rcases this with ⟨x1, hsteps, hrel⟩ | ⟨hnf, _⟩ | |
| · have hih := ih hrel (DepthInv.step hok hdi hst) (hIs s _ hbi (cap_of_rel hs) hst) (fun s'' hss => hb s'' (Steps.cons hst hss)) | |
| cases o with | |
| | next _ => exact hih.elim | |
| | halted r5 => | |
| obtain ⟨x', hx, hr⟩ := hih | |
| exact ⟨x', RExec.of_steps hsteps hx, hr⟩ | |
| | trapped t => exact RExec.of_steps hsteps hih | |
| · exact absurd (hb s .refl) hnf | |
| /-- The state the runtime prologue establishes (`CM0.Emit`): empty stacks, `r9 = sp = sp0`, | |
| `r8 r5 r4 r6` at the conventions, and the register file and IR memory regions holding the IR | |
| state's initial contents. `Rel` then holds at the entry point, so `lowerProg_correct` applies. -/ | |
| theorem init_rel {c : Cfg} {p : Prog 32} {s0 : State 32} {x0 : M} (hg : Geom c) | |
| (hd : s0.dstack = []) (hr : s0.rstack = []) (ha : s0.astack = []) (hrc : 1 ≤ c.rcap) | |
| (h15 : x0.regs Reg.r4 = ofN c.dEnd) (h14 : x0.regs Reg.r5 = ofN c.rf) | |
| (h13 : x0.regs Reg.r8 = ofN c.mb) (h12 : x0.regs Reg.r9 = ofN c.sp0) | |
| (hsp : x0.regs Reg.sp = ofN c.sp0) (hbp : x0.regs Reg.r6 = ofN c.aEnd) (hregs : RegRel c x0.mem s0.regs) | |
| (hmem : MemRel c x0.mem s0.mem) (hiv : ∀ a : Word 32, s0.mem.valid a = decide (a.toNat < c.M)) | |
| (hxv : RegionsValid c x0.mem.valid) (hpc : x0.pc = offs c.facts p s0.pc) : Rel c p s0 x0 := | |
| ⟨{ r4 := by simpa [hd] using h15 | |
| r5 := h14 | |
| r8 := h13 | |
| r9 := h12 | |
| sp := by simpa [hr] using hsp | |
| r6 := by simpa [ha] using hbp | |
| aux := by intro i v h; simp [ha] at h | |
| stack := by intro i v h; simp [hd] at h | |
| regs := hregs | |
| mem := hmem | |
| rs := by intro i a h; simp [hr] at h | |
| irvalid := hiv | |
| xvalid := hxv | |
| capD := by simp [hd]; exact hg.dBase_le | |
| capR := by simp [hr]; exact hrc | |
| capA := by have := hg.aBase_8; simp [ha]; omega }, hpc⟩ | |
| end CM0 | |
| end WordDialect | |