ai-free / backend /rv32 /RV32 /SimMemOps.lean
SNAPKITTYWEST's picture
Sync from GitHub at 25c8330: hardware-in-the-loop rig, SAM D21 board, guard elimination on RV32/Cortex-M3
0e9783b verified
Raw History Blame Contribute Delete
15.9 kB
import RV32.SimMem
/-!
# RV32.SimMemOps
The address bounds guard `movImm rt, memSize; bltu t0, rt, ok; exitTrap badAddress`, and the
simulation theorems for `push`, `pop`, `load`, `store`. RV32 has no indexed addressing, so `load`
and `store` compute the cell's address with `slli t0, t0, 2; add t0, s3` (`idx_steps`).
-/
namespace WordDialect
namespace RV32
open Reg
section Ops
variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
{L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
theorem ult_memSize {a : W} {n : Nat} (hn : n < 2 ^ 32) :
a.ult (BitVec.ofNat 32 n) = decide (a.toNat < n) := by
simp [BitVec.ult_eq_decide, BitVec.toNat_ofNat, Nat.mod_eq_of_lt hn]
/-- The bounds guard, passing case. -/
theorem addr_pass (hs : Rel0 c p s x) {rt : Reg} (hrt : rt = t1 ∨ rt = t2) {n : Nat}
(hn : n < 2 ^ 32) {t : Nat} (ht : t = x.pc + 3) {a : W} (hrax : x.regs t0 = a) (ha : a.toNat < n)
(hat : RAt code x.pc [.movImm rt (BitVec.ofNat 32 n), .bcc .ult t0 rt t,
.exitTrap .badAddress]) :
∃ x', RSteps code x x' ∧ Rel0 c p s x' ∧ x'.pc = x.pc + 3 ∧ x'.regs t0 = a ∧
(∀ r, r ≠ rt → x'.regs r = x.regs r) ∧ x'.mem = x.mem := by
subst ht
obtain ⟨f0, f1, f2, _⟩ := hat
have hrt' : rt = t0 ∨ rt = t1 ∨ rt = t2 ∨ rt = t3 := by rcases hrt with h | h <;> simp [h]
have hne : t0 ≠ rt := by rcases hrt with h | h <;> simp [h]
obtain ⟨x1, hs1, hr1, hpc1, hv1, ho1, hm1⟩ := movimm_step (code := code) hs (rd := rt) hrt'
(v := BitVec.ofNat 32 n) f0
have hax1 : x1.regs t0 = a := by rw [ho1 t0 hne, hrax]
have hhold : Cond.eval .ult (x1.regs t0) (x1.regs rt) = true := by
simp only [Cond.eval, hax1, hv1]; rw [ult_memSize hn]; simpa using ha
have hg := guard_pass (code := code) (pc := x.pc + 1) (m := x1) (t := .badAddress)
⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩ hpc1 hhold
refine ⟨{ x1 with pc := x.pc + 1 + 2 }, hs1.trans hg, hr1.congr rfl rfl rfl rfl rfl rfl rfl,
by simp, by simp [hax1], ?_, by simp [hm1]⟩
intro r hr; simp [ho1 r hr]
/-- The bounds guard, failing case. -/
theorem addr_trap (hs : Rel0 c p s x) {rt : Reg} (hrt : rt = t1 ∨ rt = t2) {n : Nat}
(hn : n < 2 ^ 32) {t : Nat} (ht : t = x.pc + 3) {a : W} (hrax : x.regs t0 = a) (ha : ¬ a.toNat < n)
(hat : RAt code x.pc [.movImm rt (BitVec.ofNat 32 n), .bcc .ult t0 rt t,
.exitTrap .badAddress]) :
RExec code x (.trapped .badAddress) := by
subst ht
obtain ⟨f0, f1, f2, _⟩ := hat
have hrt' : rt = t0 ∨ rt = t1 ∨ rt = t2 ∨ rt = t3 := by rcases hrt with h | h <;> simp [h]
have hne : t0 ≠ rt := by rcases hrt with h | h <;> simp [h]
obtain ⟨x1, hs1, hr1, hpc1, hv1, ho1, hm1⟩ := movimm_step (code := code) hs (rd := rt) hrt'
(v := BitVec.ofNat 32 n) f0
have hax1 : x1.regs t0 = a := by rw [ho1 t0 hne, hrax]
have hhold : Cond.eval .ult (x1.regs t0) (x1.regs rt) = false := by
simp only [Cond.eval, hax1, hv1]; rw [ult_memSize hn]; simpa using ha
exact RExec.of_steps hs1
(guard_trap (code := code) (pc := x.pc + 1) (m := x1) (t := .badAddress)
⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩ hpc1 hhold)
theorem sim_push_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {r : Nat}
(hr : r < c.nregs) (hLd : L.dLim = ofN (c.dBase + 4))
(hat : RAt code base (lowerInstr L base off g (.push r)))
(hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := s.regs r :: s.dstack } x' ∧
x'.pc = base + isize g (.push r : WordDialect.Instr 32) := by
obtain ⟨hato, f0, f1, f2⟩ := xat_ovf3 (L := L) (by exact hat)
obtain ⟨x0, hs0, hr0, hpc0, _, _⟩ := ovfG_pass hg hs hLd hfit hpc hato
have hst : step code x0 = .next (x0.mov t0 (s.regs r)) := by
rw [rstep_of_fetch (by rw [hpc0]; exact f0), ld_reg hr0 hr t0 rfl]
have hr1 : Rel0 c p s (x0.mov t0 (s.regs r)) := mov_rel0 hr0 t0 (scratch_ne t0 (by simp)) _
have hpc1 : (x0.mov t0 (s.regs r)).pc = base + ovfSize g + 1 := by simp [M.mov, M.setReg, M.adv, hpc0]
obtain ⟨x2, hs2, hr2, hpc2, _⟩ := push_pair hg hr1 t0 (by decide) hfit
⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
have hv : (x0.mov t0 (s.regs r)).regs t0 = s.regs r := by simp [M.mov, M.setReg, M.adv]
rw [hv] at hr2
exact ⟨x2, (hs0.trans (RSteps.single hst)).trans hs2, hr2, by simp [isize]; omega⟩
theorem sim_push_ovf (hn : g.noOvf = false) (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {r : Nat}
(hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.push r)))
(h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow := by
obtain ⟨hato, _⟩ := xat_ovf3 (L := L) (by exact hat)
exact ovfG_trap hn hg hs hLd h hpc hato
theorem sim_pop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
{r : Nat} (hr : r < c.nregs) (hat : RAt code base (lowerInstr L base off g (.pop r)))
{a : W} {d : List W} (hd : s.dstack = a :: d) :
∃ x', RSteps code x x' ∧
Rel0 c p { s with dstack := d, regs := State.setReg s.regs r a } x' ∧
x'.pc = base + isize g (.pop r : WordDialect.Instr 32) := by
have hat' : RAt code base (uf L (need g 1) base ++ [.load t0 Reg.s1 0, .addImm Reg.s1 4,
.store Reg.s2 (4 * (r : Int)) t0]) := hat
obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
have hufl := uf_length L (need g 1) base
rw [hufl] at hatr
obtain ⟨f0, f1, f2, _⟩ := hatr
have hk : 1 ≤ s.dstack.length := by simp [hd]
obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
(by simp [hd]) (rd := t0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := adj_step (code := code) hg hr2 (n := 1) (by simp [hd])
(δ := 4) (by simp) (fetch_cast f1 (by omega))
have hax3 : x3.regs t0 = a := by rw [ho3 t0 (by decide), hv2]
obtain ⟨mem', e4, hr4⟩ := st_reg hg hr3 hr t0 (disp := 4 * (r : Int)) rfl
have hst4 : step code x3 = .next { x3.adv with mem := mem' } := by
rw [rstep_of_fetch (fetch_cast f2 (by omega)), e4]
have hr4' : Rel0 c p { s with dstack := s.dstack.drop 1, regs := State.setReg s.regs r (x3.regs t0) }
{ x3.adv with mem := mem' } := hr4
have e : s.dstack.drop 1 = d := by simp [hd]
rw [e, hax3] at hr4'
exact ⟨_, ((hs1.trans hs2).trans hs3).trans (RSteps.single hst4), hr4',
by simp [M.adv, isize]; omega⟩
theorem sim_load_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
(hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .load))
{a v : W} {d : List W} (hd : s.dstack = a :: d) (hv : s.mem.read? a = some v) :
∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := v :: d } x' ∧
x'.pc = base + isize g (.load : WordDialect.Instr 32) := by
have hat' : RAt code base (uf L (need g 1) base ++ [.load t0 Reg.s1 0, .movImm t1 (BitVec.ofNat 32 L.memSize),
.bcc .ult t0 t1 (base + ufSize (need g 1) + 4), .exitTrap .badAddress, .shlImm t0 2, .add t0 Reg.s3,
.load t0 t0 0, .store Reg.s1 0 t0]) := hat
obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
have hufl := uf_length L (need g 1) base
rw [hufl] at hatr
obtain ⟨f0, f1, f2, f3, f4, f5, f6, f7, _⟩ := hatr
have hk : 1 ≤ s.dstack.length := by simp [hd]
have hMlt : c.M < 2 ^ 32 := by have := hg.mb_lt; omega
have hlt : a.toNat < c.M := by
obtain ⟨hvv, _⟩ := Memory.read?_some hv
have := hs.irvalid a
rw [hvv] at this
simpa using this.symm
obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
(by simp [hd]) (rd := t0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
obtain ⟨x3, hs3, hr3, hpc3, hax3, ho3, hm3⟩ := addr_pass (code := code) hr2 (rt := t1) (by simp)
(n := c.M) hMlt (t := base + ufSize (need g 1) + 4) (by omega) hv2 hlt (by
rw [← hMs]
refine ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩)
obtain ⟨x4, hs4, hr4, hpc4, hax4, _, _⟩ := idx_steps hr3 hax3
⟨fetch_cast f4 (by omega), fetch_cast f5 (by omega), trivial⟩
have hst5 : step code x4 = .next (x4.mov t0 v) := by
rw [rstep_of_fetch (fetch_cast f6 (by omega)), ld_mem hr4 hv hax4]
have hr5 : Rel0 c p s (x4.mov t0 v) := mov_rel0 hr4 t0 (scratch_ne t0 (by simp)) v
obtain ⟨x6, hs6, hr6, hpc6, _⟩ := st_step (code := code) hg hr5 (j := 0) (by simp [hd])
(rs := t0) (disp := 0) (by simp) (fetch_cast f7 (by simp [M.mov, M.setReg, M.adv]; omega))
have e : s.dstack.set 0 ((x4.mov t0 v).regs t0) = v :: d := by
simp [hd, M.mov, M.setReg, M.adv]
rw [e] at hr6
exact ⟨x6, ((((hs1.trans hs2).trans hs3).trans hs4).trans (RSteps.single hst5)).trans hs6, hr6,
by simp [M.mov, M.setReg, M.adv, isize] at *; omega⟩
theorem sim_load_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
(hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .load))
{a : W} {d : List W} (hd : s.dstack = a :: d) (hv : s.mem.read? a = none) :
RExec code x (.trapped .badAddress) := by
have hat' : RAt code base (uf L (need g 1) base ++ [.load t0 Reg.s1 0, .movImm t1 (BitVec.ofNat 32 L.memSize),
.bcc .ult t0 t1 (base + ufSize (need g 1) + 4), .exitTrap .badAddress, .shlImm t0 2, .add t0 Reg.s3,
.load t0 t0 0, .store Reg.s1 0 t0]) := hat
obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
have hufl := uf_length L (need g 1) base
rw [hufl] at hatr
obtain ⟨f0, f1, f2, f3, _⟩ := hatr
have hk : 1 ≤ s.dstack.length := by simp [hd]
have hMlt : c.M < 2 ^ 32 := by have := hg.mb_lt; omega
have hge : ¬ a.toNat < c.M := by
have hvv := (Memory.read?_none_iff s.mem a).mp hv
have := hs.irvalid a
rw [hvv] at this
simpa using this
obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
(by simp [hd]) (rd := t0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
exact RExec.of_steps (hs1.trans hs2) (addr_trap (code := code) hr2 (rt := t1) (by simp)
(n := c.M) hMlt (t := base + ufSize (need g 1) + 4) (by omega) hv2 hge (by
rw [← hMs]
refine ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩))
theorem sim_store_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
(hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .store))
{a v : W} {d : List W} (hd : s.dstack = a :: v :: d) {m : Memory 32}
(hw : s.mem.write? a v = some m) :
∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, mem := m } x' ∧
x'.pc = base + isize g (.store : WordDialect.Instr 32) := by
have hat' : RAt code base (uf L (need g 2) base ++ [.load t0 Reg.s1 0, .load t1 Reg.s1 4,
.movImm t2 (BitVec.ofNat 32 L.memSize), .bcc .ult t0 t2 (base + ufSize (need g 2) + 5),
.exitTrap .badAddress, .shlImm t0 2, .add t0 Reg.s3, .store t0 0 t1, .addImm Reg.s1 8]) := hat
obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
have hufl := uf_length L (need g 2) base
rw [hufl] at hatr
obtain ⟨f0, f1, f2, f3, f4, f5, f6, f7, f8, _⟩ := hatr
have hk : 2 ≤ s.dstack.length := by simp [hd]
have hMlt : c.M < 2 ^ 32 := by have := hg.mb_lt; omega
have hv : s.mem.valid a = true := by
by_cases hh : s.mem.valid a = true
· exact hh
· have := (Memory.write?_none_iff s.mem a v).mpr (by simpa using hh); rw [hw] at this; simp at this
have hlt : a.toNat < c.M := by
have := hs.irvalid a
rw [hv] at this
simpa using this.symm
obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
(by simp [hd]) (rd := t0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, hm3⟩ := ld_step (code := code) hr2 (j := 1) (v := v)
(by simp [hd]) (rd := t1) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
have hax3 : x3.regs t0 = a := by rw [ho3 t0 (by decide), hv2]
obtain ⟨x4, hs4, hr4, hpc4, hax4, ho4, hm4⟩ := addr_pass (code := code) hr3 (rt := t2) (by simp)
(n := c.M) hMlt (t := base + ufSize (need g 2) + 5) (by omega) hax3 hlt (by
rw [← hMs]
refine ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), fetch_cast f4 (by omega), trivial⟩)
have hcx4 : x4.regs t1 = v := by rw [ho4 t1 (by decide), hv3]
obtain ⟨x5, hs5, hr5, hpc5, hax5, ho5, _⟩ := idx_steps hr4 hax4
⟨fetch_cast f5 (by omega), fetch_cast f6 (by omega), trivial⟩
have hcx5 : x5.regs t1 = v := by rw [ho5 t1 (by decide), hcx4]
obtain ⟨mem', e6, hr6⟩ := st_mem hg hr5 hw hax5 hcx5
have hst6 : step code x5 = .next { x5.adv with mem := mem' } := by
rw [rstep_of_fetch (fetch_cast f7 (by omega)), e6]
have hlen : 2 ≤ ({ s with mem := m } : State 32).dstack.length := by simp [hd]
obtain ⟨x7, hs7, hr7, hpc7, _⟩ := adj_step (code := code) hg hr6 (n := 2) hlen (δ := 8) (by simp)
(fetch_cast f8 (by simp [M.adv]; omega))
have hr7' : Rel0 c p { s with dstack := d, mem := m } x7 := by
have : ({ { s with mem := m } with dstack := ({ s with mem := m } : State 32).dstack.drop 2 } : State 32)
= { s with dstack := d, mem := m } := by simp [hd]
rw [← this]; exact hr7
exact ⟨x7, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs5).trans (RSteps.single hst6)).trans hs7,
hr7', by simp [M.adv, isize] at *; omega⟩
theorem sim_store_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
(hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .store))
{a v : W} {d : List W} (hd : s.dstack = a :: v :: d) (hw : s.mem.write? a v = none) :
RExec code x (.trapped .badAddress) := by
have hat' : RAt code base (uf L (need g 2) base ++ [.load t0 Reg.s1 0, .load t1 Reg.s1 4,
.movImm t2 (BitVec.ofNat 32 L.memSize), .bcc .ult t0 t2 (base + ufSize (need g 2) + 5),
.exitTrap .badAddress, .shlImm t0 2, .add t0 Reg.s3, .store t0 0 t1, .addImm Reg.s1 8]) := hat
obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
have hufl := uf_length L (need g 2) base
rw [hufl] at hatr
obtain ⟨f0, f1, f2, f3, f4, _⟩ := hatr
have hk : 2 ≤ s.dstack.length := by simp [hd]
have hMlt : c.M < 2 ^ 32 := by have := hg.mb_lt; omega
have hge : ¬ a.toNat < c.M := by
have hvv := (Memory.write?_none_iff s.mem a v).mp hw
have := hs.irvalid a
rw [hvv] at this
simpa using this
obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
(by simp [hd]) (rd := t0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, hm3⟩ := ld_step (code := code) hr2 (j := 1) (v := v)
(by simp [hd]) (rd := t1) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
have hax3 : x3.regs t0 = a := by rw [ho3 t0 (by decide), hv2]
exact RExec.of_steps ((hs1.trans hs2).trans hs3) (addr_trap (code := code) hr3 (rt := t2)
(by simp) (n := c.M) hMlt (t := base + ufSize (need g 2) + 5) (by omega) hax3 hge (by
rw [← hMs]
refine ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), fetch_cast f4 (by omega), trivial⟩))
end Ops
end RV32
end WordDialect