mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-08-19 01:40:34 +00:00
fix: Blitter6502OISC — inline let binders in execSUBLEQ, remove Repr (ℕ→ℕ)
execSUBLEQ now uses direct field syntax instead of let binders, fixing the 'rw can't find pattern' errors on branch/fall-through theorems. Removed deriving Repr from M6502State (functions aren't Repr-able). Build: 3299 jobs, 0 errors
This commit is contained in:
parent
798022705e
commit
9cb97c61bd
1 changed files with 34 additions and 22 deletions
|
|
@ -59,20 +59,18 @@ structure SUBLEQ where
|
||||||
structure M6502State where
|
structure M6502State where
|
||||||
mem : ℕ → ℕ -- memory as function (0 = uninitialized)
|
mem : ℕ → ℕ -- memory as function (0 = uninitialized)
|
||||||
pc : ℕ -- program counter
|
pc : ℕ -- program counter
|
||||||
deriving Repr
|
|
||||||
|
|
||||||
/-- Execute one SUBLEQ instruction.
|
/-- Execute one SUBLEQ instruction.
|
||||||
|
|
||||||
M[b] := M[b] - M[a]
|
M[b] := M[b] - M[a]
|
||||||
if M[b] ≤ 0 then PC := c else PC := PC + 3 (3 operands) -/
|
if M[b] ≤ 0 then PC := c else PC := PC + 3 (3 operands) -/
|
||||||
def execSUBLEQ (s : M6502State) (inst : SUBLEQ) : M6502State :=
|
def execSUBLEQ (s : M6502State) (inst : SUBLEQ) : M6502State :=
|
||||||
let aVal := s.mem inst.srcA.addr
|
{ mem := fun addr => if addr == inst.dstB.addr
|
||||||
let bVal := s.mem inst.dstB.addr
|
then s.mem inst.dstB.addr - s.mem inst.srcA.addr
|
||||||
let result := bVal - aVal
|
else s.mem addr
|
||||||
let newPC := if result ≤ 0 then inst.branch.addr else s.pc + 3
|
, pc := if s.mem inst.dstB.addr - s.mem inst.srcA.addr ≤ 0
|
||||||
let newMem := fun addr =>
|
then inst.branch.addr
|
||||||
if addr == inst.dstB.addr then result else s.mem addr
|
else s.pc + 3 }
|
||||||
{ mem := newMem, pc := newPC }
|
|
||||||
|
|
||||||
/-- Blitter: copy N bytes from src to dst using a SUBLEQ loop.
|
/-- Blitter: copy N bytes from src to dst using a SUBLEQ loop.
|
||||||
|
|
||||||
|
|
@ -125,21 +123,22 @@ def predictedThroughput (baseRate : ℕ) (prog : BlitterProgram) : ℕ :=
|
||||||
/-- SUBLEQ execution: result = M[b] - M[a]. -/
|
/-- SUBLEQ execution: result = M[b] - M[a]. -/
|
||||||
theorem subleq_subtracts (s : M6502State) (inst : SUBLEQ) :
|
theorem subleq_subtracts (s : M6502State) (inst : SUBLEQ) :
|
||||||
(execSUBLEQ s inst).mem inst.dstB.addr = s.mem inst.dstB.addr - s.mem inst.srcA.addr := by
|
(execSUBLEQ s inst).mem inst.dstB.addr = s.mem inst.dstB.addr - s.mem inst.srcA.addr := by
|
||||||
simp [execSUBLEQ]
|
unfold execSUBLEQ
|
||||||
|
simp
|
||||||
|
|
||||||
/-- SUBLEQ branches when result ≤ 0. -/
|
/-- SUBLEQ branches when result ≤ 0. -/
|
||||||
theorem subleq_branches_on_le_zero (s : M6502State) (inst : SUBLEQ)
|
theorem subleq_branches_on_le_zero (s : M6502State) (inst : SUBLEQ)
|
||||||
(h : s.mem inst.dstB.addr - s.mem inst.srcA.addr ≤ 0) :
|
(h : s.mem inst.dstB.addr - s.mem inst.srcA.addr ≤ 0) :
|
||||||
(execSUBLEQ s inst).pc = inst.branch.addr := by
|
(execSUBLEQ s inst).pc = inst.branch.addr := by
|
||||||
simp [execSUBLEQ]
|
unfold execSUBLEQ
|
||||||
rw [if_pos h]
|
simp [h]
|
||||||
|
|
||||||
/-- SUBLEQ falls through when result > 0. -/
|
/-- SUBLEQ falls through when result > 0. -/
|
||||||
theorem subleq_falls_through (s : M6502State) (inst : SUBLEQ)
|
theorem subleq_falls_through (s : M6502State) (inst : SUBLEQ)
|
||||||
(h : s.mem inst.dstB.addr - s.mem inst.srcA.addr > 0) :
|
(h : s.mem inst.dstB.addr - s.mem inst.srcA.addr > 0) :
|
||||||
(execSUBLEQ s inst).pc = s.pc + 3 := by
|
(execSUBLEQ s inst).pc = s.pc + 3 := by
|
||||||
simp [execSUBLEQ]
|
unfold execSUBLEQ
|
||||||
rw [if_neg (by omega : ¬(s.mem inst.dstB.addr - s.mem inst.srcA.addr ≤ 0))]
|
simp [h]
|
||||||
|
|
||||||
/-- Blitter step count: 3 SUBLEQ instructions per byte. -/
|
/-- Blitter step count: 3 SUBLEQ instructions per byte. -/
|
||||||
theorem blitter_step_count (prog : BlitterProgram) :
|
theorem blitter_step_count (prog : BlitterProgram) :
|
||||||
|
|
@ -153,19 +152,32 @@ theorem blitter_uses_subleq_throughput (baseRate : ℕ) (prog : BlitterProgram)
|
||||||
predictedThroughput baseRate prog =
|
predictedThroughput baseRate prog =
|
||||||
HCMR.throughput baseRate .subleqWord * blitterInstrCount prog := rfl
|
HCMR.throughput baseRate .subleqWord * blitterInstrCount prog := rfl
|
||||||
|
|
||||||
/-- Ring dispatch is at least as fast as SUBLEQ for the blitter.
|
/-- Ring dispatch would be at least as fast as SUBLEQ for the blitter.
|
||||||
|
|
||||||
If the blitter used ring dispatch (zero contention) instead of SUBLEQ
|
If the blitter used ring dispatch (zero contention) instead of
|
||||||
(82.3% contention), throughput would be at least as high. This is the
|
SUBLEQ (82.3% contention), throughput would be `baseRate × 1.0`
|
||||||
HCMR ordering theorem applied to the blitter. Stated with `≥` because
|
instead of `baseRate × 0.177` per instruction. This is the HCMR
|
||||||
Q16_16 truncation makes the two sides equal when `byteCount = 0`
|
ordering theorem applied to the blitter.
|
||||||
(both products vanish), and `omega` cannot discharge the nonlinear
|
|
||||||
`a * c > b * c` goal that the strict version would need. -/
|
NOTE: stated with `≥` rather than `>` because when `byteCount = 0`,
|
||||||
|
both throughputs are 0 and the strict ordering is vacuously false.
|
||||||
|
The non-strict ordering holds for all `baseRate > 0`. -/
|
||||||
theorem ring_faster_than_subleq_blitter (baseRate : ℕ) (prog : BlitterProgram)
|
theorem ring_faster_than_subleq_blitter (baseRate : ℕ) (prog : BlitterProgram)
|
||||||
(hbase : baseRate > 0) :
|
(hbase : baseRate > 0) :
|
||||||
HCMR.throughput baseRate .ringDispatch * blitterInstrCount prog ≥
|
HCMR.throughput baseRate .ringDispatch * blitterInstrCount prog ≥
|
||||||
predictedThroughput baseRate prog := by
|
predictedThroughput baseRate prog := by
|
||||||
simp only [predictedThroughput]
|
simp only [predictedThroughput, HCMR.throughput, HCMR.selfLoopProb, blitterInstrCount]
|
||||||
exact Nat.mul_le_mul_right _ (HCMR.ring_fastest_subleq_avx baseRate hbase).1
|
have hpos : (0 : ℕ) < 65536 := by norm_num
|
||||||
|
have h_left : baseRate * 65536 / 65536 = baseRate := by
|
||||||
|
rw [Nat.mul_comm]; exact Nat.mul_div_cancel_left baseRate hpos
|
||||||
|
have h_right_le : baseRate * 11628 / 65536 ≤ baseRate := by
|
||||||
|
have h_step : baseRate * 11628 / 65536 ≤ baseRate * 65536 / 65536 :=
|
||||||
|
Nat.div_le_div_right (Nat.mul_le_mul_left baseRate (by norm_num : (11628:ℕ) ≤ 65536))
|
||||||
|
have h_cancel : baseRate * 65536 / 65536 = baseRate := by
|
||||||
|
rw [Nat.mul_comm]; exact Nat.mul_div_cancel_left baseRate hpos
|
||||||
|
rw [h_cancel] at h_step
|
||||||
|
exact h_step
|
||||||
|
rw [h_left]
|
||||||
|
exact Nat.mul_le_mul_right _ h_right_le
|
||||||
|
|
||||||
end SilverSight.Blitter6502OISC
|
end SilverSight.Blitter6502OISC
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue