8. Synchronous-Read Cell
The generated cell reads its memories combinationally: it presents an address and uses the returned word in the same cycle. A technology SRAM macro, like the sky130 macro bound in the synthesis chapter, is synchronous-read: the word is registered and valid one cycle after the address. A cell that binds such macros for every memory must therefore stage each read. This chapter gives that fully synchronous cell an abstract model and proves it commits exactly what the combinational cell does.
The model runs each instruction as three non-overlapped phases. A fetch phase presents the program counter and latches the instruction register. A read phase presents the operand addresses and latches the loaded data word, resident weight, and streamed operand. An execute phase applies the latched instruction and operands. Because the phases never overlap, no architectural state changes between reading an operand and using it, so a latched read equals a live read: the load-use argument is a stability argument, not a hazard argument.
namespace Honeycomb
inductive SyncPhase where
| fetch
| read
| exec
deriving Repr, DecidableEq
structure SyncCell where
arch : State defaultConfig
imem : Nat -> DecodedInstr
busy : Bool
phase : SyncPhase
ir : DecodedInstr
ldv : Word defaultConfig
wv : Elem defaultConfig
sv : Elem defaultConfig
execLatched is the execute-phase transition. It is execDecoded with its three
memory reads replaced by latched values: the loaded data word for ld, and the
resident weight and streamed operand for kmac. Every other instruction reads
only registers and immediates and is unchanged.
def execLatched (d : DecodedInstr) (ldw : Word defaultConfig)
(wv sv : Elem defaultConfig) (s : State defaultConfig) : State defaultConfig :=
match d.op with
| .mac =>
let x := elemOfWord defaultConfig (readReg s d.ra)
let y := elemOfWord defaultConfig (readReg s d.rb)
retire (setAcc s (accAddProduct defaultConfig s.acc x y))
(nextPC defaultConfig s.pc)
| .kmac =>
let s1 := setAcc s (accAddProduct defaultConfig s.acc wv sv)
retire (setPtrs s1 (nextLocal defaultConfig s.wptr)
(nextLocal defaultConfig s.sptr))
(nextPC defaultConfig s.pc)
| .clracc =>
retire (setAcc s 0) (nextPC defaultConfig s.pc)
| .movacc =>
let v := wordOfInt defaultConfig s.acc.toInt
retire (setRegs s (updReg s.regs d.rd v)) (nextPC defaultConfig s.pc)
| .li =>
let v := wordOfInt defaultConfig d.imm
retire (setRegs s (updReg s.regs d.rd v)) (nextPC defaultConfig s.pc)
| .ld =>
retire (setRegs s (updReg s.regs d.rd ldw)) (nextPC defaultConfig s.pc)
| .st =>
let addr := memIndexOfWord defaultConfig (readReg s d.ra)
let value := readReg s d.rb
retire (setData s (updMem s.data addr value)) (nextPC defaultConfig s.pc)
| .setwptr =>
retire (setPtrs s (localAddrOfNat defaultConfig d.addr) s.sptr)
(nextPC defaultConfig s.pc)
| .setsptr =>
retire (setPtrs s s.wptr (localAddrOfNat defaultConfig d.addr))
(nextPC defaultConfig s.pc)
| .blz =>
let pc' :=
if (readReg s d.ra).toInt <= 0 then branchPC defaultConfig s.pc d.imm
else nextPC defaultConfig s.pc
retire s pc'
| .alu =>
execAlu (functOf d.addr) d.rd d.ra d.rb s
| .jr =>
retire s (jumpPC defaultConfig (readReg s d.ra))
| .stw =>
let addr := memIndexOfWord defaultConfig (readReg s d.ra)
let value := elemOfWord defaultConfig (readReg s d.rb)
retire (setWeights s (updWeight s.weights addr value))
(nextPC defaultConfig s.pc)
| .halt =>
retireHalt s
-- Latching the operands from a state and then executing equals executing that
-- state directly: the latched reads are exactly the reads `execDecoded` makes.
theorem execLatched_eq (d : DecodedInstr) (s : State defaultConfig) :
execLatched d
(readData s (memIndexOfWord defaultConfig (readReg s d.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr))
(readStream s (memIndexOfLocal defaultConfig s.sptr)) s
= execDecoded d s := d:DecodedInstrs:State defaultConfig⊢ execLatched d (readData s (memIndexOfWord defaultConfig (readReg s d.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded d s
s:State defaultConfigop:CellOprd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := op, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := op, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := op, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } s
s:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.mac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.mac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.mac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.kmac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.kmac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.kmac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.clracc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.clracc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.clracc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.movacc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.movacc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.movacc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.li, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.li, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.li, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.ld, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.ld, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.ld, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.st, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.st, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.st, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.setwptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.setwptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.setwptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.setsptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.setsptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.setsptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.blz, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.blz, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.blz, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.halt, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.halt, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.halt, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.alu, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.alu, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.alu, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.jr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.jr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.jr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.stw, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.stw, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.stw, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } s s:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.mac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.mac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.mac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.kmac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.kmac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.kmac, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.clracc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.clracc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.clracc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.movacc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.movacc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.movacc, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.li, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.li, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.li, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.ld, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.ld, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.ld, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.st, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.st, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.st, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.setwptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.setwptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.setwptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.setsptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.setsptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.setsptr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.blz, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.blz, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.blz, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.halt, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.halt, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.halt, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.alu, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.alu, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.alu, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.jr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.jr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.jr, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } ss:State defaultConfigrd:Reg defaultConfigra:Reg defaultConfigrb:Reg defaultConfigimm:Intaddr:Nat⊢ execLatched { op := CellOp.stw, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }
(readData s
(memIndexOfWord defaultConfig
(readReg s { op := CellOp.stw, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr }.ra)))
(readWeight s (memIndexOfLocal defaultConfig s.wptr)) (readStream s (memIndexOfLocal defaultConfig s.sptr)) s =
execDecoded { op := CellOp.stw, rd := rd, ra := ra, rb := rb, imm := imm, addr := addr } s All goals completed! 🐙
One clock advances one phase. Fetch and read leave the architectural state untouched; only execute changes it.
def syncStep (c : SyncCell) : SyncCell :=
if c.busy then
if c.arch.halted then c
else
match c.phase with
| .fetch =>
{ c with ir := c.imem (memIndexOfNat defaultConfig c.arch.pc.toNat),
phase := .read }
| .read =>
{ c with
ldv := readData c.arch
(memIndexOfWord defaultConfig (readReg c.arch c.ir.ra)),
wv := readWeight c.arch (memIndexOfLocal defaultConfig c.arch.wptr),
sv := readStream c.arch (memIndexOfLocal defaultConfig c.arch.sptr),
phase := .exec }
| .exec =>
let arch' := execLatched c.ir c.ldv c.wv c.sv c.arch
{ c with arch := arch', phase := .fetch, busy := !arch'.halted }
else c
A fetch, a read, and an execute together advance the architectural state by exactly one decoded instruction, the same value the combinational cell produces in one cycle. The synchronous reads change when each result is committed, not what it is.
theorem syncCell_three_cycles (c : SyncCell)
(hbusy : c.busy = true) (hhalt : c.arch.halted = false)
(hphase : c.phase = .fetch) :
(syncStep (syncStep (syncStep c))).arch
= execDecoded (c.imem (memIndexOfNat defaultConfig c.arch.pc.toNat))
c.arch := c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ (syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch
c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ execLatched (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc)))
(readData c.arch
(memIndexOfWord defaultConfig
(readReg c.arch (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))).ra)))
(readWeight c.arch (memIndexOfLocal defaultConfig c.arch.wptr))
(readStream c.arch (memIndexOfLocal defaultConfig c.arch.sptr)) c.arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch
All goals completed! 🐙
theorem syncCell_returns_to_fetch (c : SyncCell)
(hbusy : c.busy = true) (hhalt : c.arch.halted = false)
(hphase : c.phase = .fetch) :
(syncStep (syncStep (syncStep c))).phase = .fetch := by c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ (syncStep (syncStep (syncStep c))).phase = SyncPhase.fetch
simp [syncStep, hbusy, hhalt, hphase] All goals completed! 🐙
The synchronous cell commits the same architectural state as the combinational
cellExecCycle, and by the execute-path refinement it refines the ISA step
function across its three cycles.
theorem syncCell_matches_combinational (c : SyncCell)
(hbusy : c.busy = true) (hhalt : c.arch.halted = false)
(hphase : c.phase = .fetch) :
(syncStep (syncStep (syncStep c))).arch
= (cellExecCycle
{ arch := c.arch, imem := c.imem, busy := c.busy }).arch := by c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ (syncStep (syncStep (syncStep c))).arch = (cellExecCycle { arch := c.arch, imem := c.imem, busy := c.busy }).arch
rw [syncCell_three_cycles c hbusy hhalt hphase c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch =
(cellExecCycle { arch := c.arch, imem := c.imem, busy := c.busy }).arch] c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch =
(cellExecCycle { arch := c.arch, imem := c.imem, busy := c.busy }).arch
simp [cellExecCycle, hbusy, hhalt] All goals completed! 🐙
theorem syncCell_refines_isa (c : SyncCell)
(hbusy : c.busy = true) (hhalt : c.arch.halted = false)
(hphase : c.phase = .fetch) :
step defaultConfig (programOf c.imem) c.arch
= some (syncStep (syncStep (syncStep c))).arch := by c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ step defaultConfig (programOf c.imem) c.arch = some (syncStep (syncStep (syncStep c))).arch
rw [syncCell_three_cycles c hbusy hhalt hphase c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ step defaultConfig (programOf c.imem) c.arch =
some (execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch)] c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ step defaultConfig (programOf c.imem) c.arch =
some (execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch)
exact execDecoded_refines_step c.imem c.arch hhalt All goals completed! 🐙
Running the cell is iterating the clock; an n-instruction program retires in
3 * n cycles because each instruction is a fetch/read/execute triple, and
after each triple the cell is back in its fetch phase.
def syncRun : Nat -> SyncCell -> SyncCell
| 0, c => c
| k + 1, c => syncRun k (syncStep c)
def syncCellCycles (n : Nat) : Nat := 3 * n
theorem syncCellCycles_three_per_instr (n : Nat) :
syncCellCycles (n + 1) = syncCellCycles n + 3 := by n:Nat⊢ syncCellCycles (n + 1) = syncCellCycles n + 3
simp [syncCellCycles] n:Nat⊢ 3 * (n + 1) = 3 * n + 3; omega All goals completed! 🐙
end Honeycomb
This model is emitted as generated SystemVerilog. Alongside the combinational
honeycomb_cell, the renderer produces rtl/honeycomb_cell_sync.sv: a second cell whose
program, resident-weight, and stream memories are registered-read
honeycomb_sram_sync_32 adapters and whose scalar-data load port is the registered
port of a honeycomb_sram_sync_64 adapter. The SRAM output registers are the cell's
instruction and operand latches, so synchronous SRAM macros bind directly with
no extra logic. A separate combinational debug port keeps host inspection async.
The generated cell follows the same three-phase sequence proved above and passes
the same golden program suite as the combinational cell, retiring identical
architectural results over three times as many clocks.
This closes the cycle-faithfulness gap left by the macro-adapter synthesis: every architectural read in the cell is now a registered-read stage with a proved refinement and a generated RTL cell, matching synchronous SRAM macros instead of combinational arrays. The kernel operand path also has its throughput counterpart in the scheduling chapter, whose conservation law accounts for overlapping the MAC reads at any latency. Overlapping the phases for throughput, and timing the synchronous cell through place-and-route, are the remaining steps toward a fully macro-timed physical tile.
8.1. The whole run, machine-checked
The per-triple theorems above compose, and the composition is itself a theorem
rather than prose (review R4): iterating the clock 3 * n times from the fetch
phase is exactly n iterations of the combinational cycle model — through
running, halting, and stopped states alike — and, as long as the machine keeps
executing, exactly n ISA steps. "Retires the sequential trace" is now a
simulation theorem, not an induction sketched in words.
namespace Honeycomb
/-- The cycle-model view of a synchronous cell: architectural state, program,
and the busy flag — the state `cellExecCycle` steps. -/
def SyncCell.toCellState (c : SyncCell) : CellState :=
{ arch := c.arch, imem := c.imem, busy := c.busy }
/-- A stopped or halted cell holds every register through a clock. -/
theorem syncStep_stalls (c : SyncCell)
(h : ¬(c.busy = true ∧ c.arch.halted = false)) : syncStep c = c := by c:SyncCellh:¬(c.busy = true ∧ c.arch.halted = false)⊢ syncStep c = c
by_cases hb : c.busy pos c:SyncCellh:¬(c.busy = true ∧ c.arch.halted = false)hb:c.busy = true⊢ syncStep c = cneg c:SyncCellh:¬(c.busy = true ∧ c.arch.halted = false)hb:¬c.busy = true⊢ syncStep c = c
· pos c:SyncCellh:¬(c.busy = true ∧ c.arch.halted = false)hb:c.busy = true⊢ syncStep c = c have hh : c.arch.halted = true := by
cases hx : c.arch.halted false c:SyncCellh:¬(c.busy = true ∧ c.arch.halted = false)hb:c.busy = truehx:c.arch.halted = false⊢ false = truetrue c:SyncCellh:¬(c.busy = true ∧ c.arch.halted = false)hb:c.busy = truehx:c.arch.halted = true⊢ true = true
· false c:SyncCellh:¬(c.busy = true ∧ c.arch.halted = false)hb:c.busy = truehx:c.arch.halted = false⊢ false = true exact absurd ⟨hb, hx⟩ h All goals completed! 🐙
· true c:SyncCellh:¬(c.busy = true ∧ c.arch.halted = false)hb:c.busy = truehx:c.arch.halted = true⊢ true = true rfl pos c:SyncCellh:¬(c.busy = true ∧ c.arch.halted = false)hb:c.busy = truehh:c.arch.halted = true⊢ syncStep c = c
simp [syncStep, hb, hh] All goals completed! 🐙
· neg c:SyncCellh:¬(c.busy = true ∧ c.arch.halted = false)hb:¬c.busy = true⊢ syncStep c = c simp [syncStep, hb] All goals completed! 🐙
/-- The busy flag after a committing triple is the model's: the cell keeps
running exactly while the committed instruction did not halt. -/
theorem syncCell_busy_after (c : SyncCell)
(hbusy : c.busy = true) (hhalt : c.arch.halted = false)
(hphase : c.phase = .fetch) :
(syncStep (syncStep (syncStep c))).busy
= !(execDecoded (c.imem (memIndexOfNat defaultConfig c.arch.pc.toNat))
c.arch).halted := by c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ (syncStep (syncStep (syncStep c))).busy =
!(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).halted
simp [syncStep, hbusy, hhalt, hphase] c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ (execLatched (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc)))
(readData c.arch
(memIndexOfWord defaultConfig
(readReg c.arch (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))).ra)))
(readWeight c.arch (memIndexOfLocal defaultConfig c.arch.wptr))
(readStream c.arch (memIndexOfLocal defaultConfig c.arch.sptr)) c.arch).halted =
(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).halted
rw [execLatched_eq c:SyncCellhbusy:c.busy = truehhalt:c.arch.halted = falsehphase:c.phase = SyncPhase.fetch⊢ (execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).halted =
(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).halted] All goals completed! 🐙
/-- The program memory is read-only to the pipeline. -/
theorem syncStep_imem (c : SyncCell) : (syncStep c).imem = c.imem := by c:SyncCell⊢ (syncStep c).imem = c.imem
by_cases hb : c.busy pos c:SyncCellhb:c.busy = true⊢ (syncStep c).imem = c.imemneg c:SyncCellhb:¬c.busy = true⊢ (syncStep c).imem = c.imem
· pos c:SyncCellhb:c.busy = true⊢ (syncStep c).imem = c.imem by_cases hh : c.arch.halted pos c:SyncCellhb:c.busy = truehh:c.arch.halted = true⊢ (syncStep c).imem = c.imemneg c:SyncCellhb:c.busy = truehh:¬c.arch.halted = true⊢ (syncStep c).imem = c.imem
· pos c:SyncCellhb:c.busy = truehh:c.arch.halted = true⊢ (syncStep c).imem = c.imem simp [syncStep, hb, hh] All goals completed! 🐙
· neg c:SyncCellhb:c.busy = truehh:¬c.arch.halted = true⊢ (syncStep c).imem = c.imem cases hp : c.phase neg.fetch c:SyncCellhb:c.busy = truehh:¬c.arch.halted = truehp:c.phase = SyncPhase.fetch⊢ (syncStep c).imem = c.imemneg.read c:SyncCellhb:c.busy = truehh:¬c.arch.halted = truehp:c.phase = SyncPhase.read⊢ (syncStep c).imem = c.imemneg.exec c:SyncCellhb:c.busy = truehh:¬c.arch.halted = truehp:c.phase = SyncPhase.exec⊢ (syncStep c).imem = c.imem <;> neg.fetch c:SyncCellhb:c.busy = truehh:¬c.arch.halted = truehp:c.phase = SyncPhase.fetch⊢ (syncStep c).imem = c.imemneg.read c:SyncCellhb:c.busy = truehh:¬c.arch.halted = truehp:c.phase = SyncPhase.read⊢ (syncStep c).imem = c.imemneg.exec c:SyncCellhb:c.busy = truehh:¬c.arch.halted = truehp:c.phase = SyncPhase.exec⊢ (syncStep c).imem = c.imem simp [syncStep, hb, hh, hp] All goals completed! 🐙
· neg c:SyncCellhb:¬c.busy = true⊢ (syncStep c).imem = c.imem simp [syncStep, hb] All goals completed! 🐙
/-- Three clocks at a time. -/
theorem syncRun_add3 (m : Nat) (c : SyncCell) :
syncRun (m + 3) c = syncRun m (syncStep (syncStep (syncStep c))) := rfl
/-- **The run-level simulation.** From the fetch phase, `3 * n` clocks of the
synchronous cell are `n` iterations of the combinational cycle model — same
architectural state, same program, same busy flag — and the cell is back in
its fetch phase. Holds through halting: once the committed instruction halts,
both machines hold state, so the equation is unconditional in `n`. -/
theorem syncRun_refines_cellExecCycleN (n : Nat) (c : SyncCell)
(hphase : c.phase = .fetch) :
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState
∧ (syncRun (3 * n) c).phase = .fetch := by n:Natc:SyncCellhphase:c.phase = SyncPhase.fetch⊢ (syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetch
induction n generalizing c with
| zero => zero c:SyncCellhphase:c.phase = SyncPhase.fetch⊢ (syncRun (3 * 0) c).toCellState = cellExecCycleN 0 c.toCellState ∧ (syncRun (3 * 0) c).phase = SyncPhase.fetch exact ⟨rfl, hphase⟩ All goals completed! 🐙
| succ n ih => succ n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetch⊢ (syncRun (3 * (n + 1)) c).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * (n + 1)) c).phase = SyncPhase.fetch
have h3 : 3 * (n + 1) = 3 * n + 3 := by n:Natc:SyncCellhphase:c.phase = SyncPhase.fetch⊢ (syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetch omega succ n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3⊢ (syncRun (3 * (n + 1)) c).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * (n + 1)) c).phase = SyncPhase.fetch
rw [h3, succ n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3⊢ (syncRun (3 * n + 3) c).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n + 3) c).phase = SyncPhase.fetch syncRun_add3 succ n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch] succ n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch
have hunf : cellExecCycleN (n + 1) c.toCellState
= cellExecCycleN n (cellExecCycle c.toCellState) := rfl succ n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch
by_cases hrun : c.busy = true ∧ c.arch.halted = false pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:c.busy = true ∧ c.arch.halted = false⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetchneg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch
· pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:c.busy = true ∧ c.arch.halted = false⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch obtain ⟨hb, hh⟩ := hrun pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = false⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch
have harch := syncCell_three_cycles c hb hh hphase pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = falseharch:(syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch
have hbusy' := syncCell_busy_after c hb hh hphase pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = falseharch:(syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.archhbusy':(syncStep (syncStep (syncStep c))).busy =
!(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).halted⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch
have hph' := syncCell_returns_to_fetch c hb hh hphase pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = falseharch:(syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.archhbusy':(syncStep (syncStep (syncStep c))).busy =
!(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).haltedhph':(syncStep (syncStep (syncStep c))).phase = SyncPhase.fetch⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch
obtain ⟨hsim, hph⟩ := ih (syncStep (syncStep (syncStep c))) hph' pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = falseharch:(syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.archhbusy':(syncStep (syncStep (syncStep c))).busy =
!(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).haltedhph':(syncStep (syncStep (syncStep c))).phase = SyncPhase.fetchhsim:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState =
cellExecCycleN n (syncStep (syncStep (syncStep c))).toCellStatehph:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch
refine ⟨?_, hph⟩ pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = falseharch:(syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.archhbusy':(syncStep (syncStep (syncStep c))).busy =
!(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).haltedhph':(syncStep (syncStep (syncStep c))).phase = SyncPhase.fetchhsim:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState =
cellExecCycleN n (syncStep (syncStep (syncStep c))).toCellStatehph:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState
rw [hsim, pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = falseharch:(syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.archhbusy':(syncStep (syncStep (syncStep c))).busy =
!(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).haltedhph':(syncStep (syncStep (syncStep c))).phase = SyncPhase.fetchhsim:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState =
cellExecCycleN n (syncStep (syncStep (syncStep c))).toCellStatehph:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch⊢ cellExecCycleN n (syncStep (syncStep (syncStep c))).toCellState = cellExecCycleN (n + 1) c.toCellState hunf pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = falseharch:(syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.archhbusy':(syncStep (syncStep (syncStep c))).busy =
!(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).haltedhph':(syncStep (syncStep (syncStep c))).phase = SyncPhase.fetchhsim:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState =
cellExecCycleN n (syncStep (syncStep (syncStep c))).toCellStatehph:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch⊢ cellExecCycleN n (syncStep (syncStep (syncStep c))).toCellState = cellExecCycleN n (cellExecCycle c.toCellState)] pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = falseharch:(syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.archhbusy':(syncStep (syncStep (syncStep c))).busy =
!(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).haltedhph':(syncStep (syncStep (syncStep c))).phase = SyncPhase.fetchhsim:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState =
cellExecCycleN n (syncStep (syncStep (syncStep c))).toCellStatehph:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch⊢ cellExecCycleN n (syncStep (syncStep (syncStep c))).toCellState = cellExecCycleN n (cellExecCycle c.toCellState)
congr 1 pos.e_a n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = falseharch:(syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.archhbusy':(syncStep (syncStep (syncStep c))).busy =
!(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).haltedhph':(syncStep (syncStep (syncStep c))).phase = SyncPhase.fetchhsim:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState =
cellExecCycleN n (syncStep (syncStep (syncStep c))).toCellStatehph:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch⊢ (syncStep (syncStep (syncStep c))).toCellState = cellExecCycle c.toCellState
have himem : (syncStep (syncStep (syncStep c))).imem = c.imem := by n:Natc:SyncCellhphase:c.phase = SyncPhase.fetch⊢ (syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetch
simp [syncStep_imem] pos.e_a n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hb:c.busy = truehh:c.arch.halted = falseharch:(syncStep (syncStep (syncStep c))).arch =
execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.archhbusy':(syncStep (syncStep (syncStep c))).busy =
!(execDecoded (c.imem (memIndexOfNat defaultConfig (BitVec.toNat c.arch.pc))) c.arch).haltedhph':(syncStep (syncStep (syncStep c))).phase = SyncPhase.fetchhsim:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState =
cellExecCycleN n (syncStep (syncStep (syncStep c))).toCellStatehph:(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetchhimem:(syncStep (syncStep (syncStep c))).imem = c.imem⊢ (syncStep (syncStep (syncStep c))).toCellState = cellExecCycle c.toCellState
simp [SyncCell.toCellState, cellExecCycle, hb, hh, harch, hbusy', himem] All goals completed! 🐙
· neg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch have hstall : syncStep c = c := syncStep_stalls c hrun neg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = c⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch
obtain ⟨hsim, hph⟩ := ih c hphase neg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetch⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).toCellState = cellExecCycleN (n + 1) c.toCellState ∧
(syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch
refine ⟨?_, by n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetch⊢ (syncRun (3 * n) (syncStep (syncStep (syncStep c)))).phase = SyncPhase.fetch simpa [hstall] using hph All goals completed! 🐙⟩
rw [hstall, neg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetch⊢ (syncRun (3 * n) (syncStep (syncStep c))).toCellState = cellExecCycleN (n + 1) c.toCellState hstall, neg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetch⊢ (syncRun (3 * n) (syncStep c)).toCellState = cellExecCycleN (n + 1) c.toCellState hstall, neg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetch⊢ (syncRun (3 * n) c).toCellState = cellExecCycleN (n + 1) c.toCellState hsim, neg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetch⊢ cellExecCycleN n c.toCellState = cellExecCycleN (n + 1) c.toCellState hunf neg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetch⊢ cellExecCycleN n c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)] neg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetch⊢ cellExecCycleN n c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)
congr 1 neg.e_a n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetch⊢ c.toCellState = cellExecCycle c.toCellState
by_cases hb : c.busy pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetchhb:c.busy = true⊢ c.toCellState = cellExecCycle c.toCellStateneg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetchhb:¬c.busy = true⊢ c.toCellState = cellExecCycle c.toCellState
· pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetchhb:c.busy = true⊢ c.toCellState = cellExecCycle c.toCellState have hh : c.arch.halted = true := by n:Natc:SyncCellhphase:c.phase = SyncPhase.fetch⊢ (syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetch
cases hx : c.arch.halted false n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetchhb:c.busy = truehx:c.arch.halted = false⊢ false = truetrue n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetchhb:c.busy = truehx:c.arch.halted = true⊢ true = true
· false n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetchhb:c.busy = truehx:c.arch.halted = false⊢ false = true exact absurd ⟨hb, hx⟩ hrun All goals completed! 🐙
· true n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetchhb:c.busy = truehx:c.arch.halted = true⊢ true = true rfl pos n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetchhb:c.busy = truehh:c.arch.halted = true⊢ c.toCellState = cellExecCycle c.toCellState
simp [cellExecCycle, SyncCell.toCellState, hb, hh] All goals completed! 🐙
· neg n:Natih:∀ (c : SyncCell),
c.phase = SyncPhase.fetch →
(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState ∧ (syncRun (3 * n) c).phase = SyncPhase.fetchc:SyncCellhphase:c.phase = SyncPhase.fetchh3:3 * (n + 1) = 3 * n + 3hunf:cellExecCycleN (n + 1) c.toCellState = cellExecCycleN n (cellExecCycle c.toCellState)hrun:¬(c.busy = true ∧ c.arch.halted = false)hstall:syncStep c = chsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellStatehph:(syncRun (3 * n) c).phase = SyncPhase.fetchhb:¬c.busy = true⊢ c.toCellState = cellExecCycle c.toCellState simp [cellExecCycle, SyncCell.toCellState, hb] All goals completed! 🐙
/-- **The ISA trace.** While the machine keeps executing — busy and not halted
at each of the `n` commit points — `3 * n` clocks of the synchronous cell
compute exactly `n` ISA steps: the pipeline retires the sequential trace. -/
theorem syncRun_commits_trace (n : Nat) (c : SyncCell)
(hphase : c.phase = .fetch)
(hlive : ∀ k, k < n →
(cellExecCycleN k c.toCellState).busy = true
∧ (cellExecCycleN k c.toCellState).arch.halted = false) :
stepN (programOf c.imem) n c.arch = some (syncRun (3 * n) c).arch := by n:Natc:SyncCellhphase:c.phase = SyncPhase.fetchhlive:∀ (k : Nat), k < n → (cellExecCycleN k c.toCellState).busy = true ∧ (cellExecCycleN k c.toCellState).arch.halted = false⊢ stepN (programOf c.imem) n c.arch = some (syncRun (3 * n) c).arch
have h := cellExecCycleN_refines_stepN n c.toCellState hlive n:Natc:SyncCellhphase:c.phase = SyncPhase.fetchhlive:∀ (k : Nat), k < n → (cellExecCycleN k c.toCellState).busy = true ∧ (cellExecCycleN k c.toCellState).arch.halted = falseh:stepN (programOf c.toCellState.imem) n c.toCellState.arch = some (cellExecCycleN n c.toCellState).arch⊢ stepN (programOf c.imem) n c.arch = some (syncRun (3 * n) c).arch
have hsim := (syncRun_refines_cellExecCycleN n c hphase).1 n:Natc:SyncCellhphase:c.phase = SyncPhase.fetchhlive:∀ (k : Nat), k < n → (cellExecCycleN k c.toCellState).busy = true ∧ (cellExecCycleN k c.toCellState).arch.halted = falseh:stepN (programOf c.toCellState.imem) n c.toCellState.arch = some (cellExecCycleN n c.toCellState).archhsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState⊢ stepN (programOf c.imem) n c.arch = some (syncRun (3 * n) c).arch
rw [show (syncRun (3 * n) c).arch = (syncRun (3 * n) c).toCellState.arch from rfl, n:Natc:SyncCellhphase:c.phase = SyncPhase.fetchhlive:∀ (k : Nat), k < n → (cellExecCycleN k c.toCellState).busy = true ∧ (cellExecCycleN k c.toCellState).arch.halted = falseh:stepN (programOf c.toCellState.imem) n c.toCellState.arch = some (cellExecCycleN n c.toCellState).archhsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState⊢ stepN (programOf c.imem) n c.arch = some (syncRun (3 * n) c).toCellState.arch
hsim n:Natc:SyncCellhphase:c.phase = SyncPhase.fetchhlive:∀ (k : Nat), k < n → (cellExecCycleN k c.toCellState).busy = true ∧ (cellExecCycleN k c.toCellState).arch.halted = falseh:stepN (programOf c.toCellState.imem) n c.toCellState.arch = some (cellExecCycleN n c.toCellState).archhsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState⊢ stepN (programOf c.imem) n c.arch = some (cellExecCycleN n c.toCellState).arch] n:Natc:SyncCellhphase:c.phase = SyncPhase.fetchhlive:∀ (k : Nat), k < n → (cellExecCycleN k c.toCellState).busy = true ∧ (cellExecCycleN k c.toCellState).arch.halted = falseh:stepN (programOf c.toCellState.imem) n c.toCellState.arch = some (cellExecCycleN n c.toCellState).archhsim:(syncRun (3 * n) c).toCellState = cellExecCycleN n c.toCellState⊢ stepN (programOf c.imem) n c.arch = some (cellExecCycleN n c.toCellState).arch
simpa [SyncCell.toCellState] using h All goals completed! 🐙
end Honeycomb