Measure the finer chain tail: 84/120 becomes 18/120, and the derivation was right by cancellation
blit.s gains v7 -- v6's 24-pixel movem chain plus a second chain whose unit is
one `move.l (a0)+,(a2)+`. Measured over 13 span lengths by span.sh, every config
pixel-exact:
cycles = 66.0 per span + 9.143 per COARSE pixel + 9.978 per FINE pixel
fitting all 13 to within 0.2%. v5 and v6 re-measure to FINDINGS 30 exactly, so
the harness has not drifted underneath the new variant.
Rescored against the same scsi window and the same additive model, v7 takes
84/120 frames over budget to 18/120 -- exactly what FINDINGS 39.4 derived, and
that agreement is two cancelling errors: the derivation's 2-register movem tail
is 29% too dear per pixel, and its "nothing per span" for the second chain entry
is 22.3 clocks too cheap. The plain post-incrementing move.l is the right tail
instruction, and it makes the padding quantum 2 pixels, which a run of 4x4
blocks pads to exactly zero.
The DMAC stays dropped on a measurement now rather than an argument: v7 takes
back 37 of the 43 frames the array chain would, with no reserved channel and no
timing neither emulator here can verify. Break-even against all-V1 moves from
L=4 blocks to L=2.
The fine displacement is carried mid-stream rather than in the span record, so
the decoder holds nothing across the copy and keeps all 12 payload registers --
which is the whole reason the coarse unit is 24 pixels.
span.sh is now -seconds_to_run 200 (30 s wall, 36 configs) and takes its
expected snapshot count from the generated metadata instead of a literal 23.
Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -41,8 +41,11 @@ CPU + DMA, additive. Session 10's first pass used max(CPU, bus) and got 53/120
|
||||
where the additive model gives 84/120; FINDINGS 35's flat debit was right.
|
||||
|
||||
So the only material difference left is v6's 24-pixel padding quantum -- and
|
||||
that is a property of v6's unrolled chain, not of the CPU. The `v6 fine tail`
|
||||
column prices fixing it in software instead.
|
||||
that is a property of v6's unrolled chain, not of the CPU. The `v7 fine tail`
|
||||
column prices fixing it in software instead, and as of session 11 that column
|
||||
is MEASURED on the 68000 (blit.s v7, tools/bench/span.sh, FINDINGS 40) rather
|
||||
than derived: 66.0 clocks per span + 9.143 per coarse pixel + 9.978 per fine
|
||||
pixel, with a 2-pixel quantum that a run of 4x4 blocks pads to exactly.
|
||||
"""
|
||||
import sys, os, argparse
|
||||
sys.path.insert(0, "tools/encoder")
|
||||
@@ -100,8 +103,8 @@ def span_cost(design, L):
|
||||
if design == "v6":
|
||||
px = B.pad24(4 * L)
|
||||
return 4 * px, 4 * (B.V6_SPAN_CYC + px * B.V6_PX_CYC)
|
||||
if design == "v6fine":
|
||||
px, c = B.v6_fine(4 * L)
|
||||
if design == "v7":
|
||||
px, c = B.v7_span(4 * L)
|
||||
return 4 * px, 4 * c
|
||||
px = 4 * L
|
||||
return 4 * px, 4 * (B.DMA_CHAIN_CLK + px * a.dma_px_clk)
|
||||
@@ -127,7 +130,9 @@ def score(design):
|
||||
cur_b = sum(BLK_B[int(b)] for b in m[by][i:j])
|
||||
px, sc = span_cost(design, L)
|
||||
sc += L * C_SKIP_MIXED # the dispatch still happens
|
||||
span_b = 4 * SPAN_HDR + px * SPAN_BYTES_PX
|
||||
# v7 carries a second u16 (the fine displacement) per span.
|
||||
hdr = B.V7_SPAN_HDR if design == "v7" else SPAN_HDR
|
||||
span_b = 4 * hdr + px * SPAN_BYTES_PX
|
||||
if sc < cur_c:
|
||||
cand.append((cur_c - sc, span_b - cur_b, by, i, j, sc, L))
|
||||
cand.sort(key=lambda s: -(s[0] / max(s[1], 1)))
|
||||
@@ -154,7 +159,7 @@ def score(design):
|
||||
|
||||
|
||||
DESIGNS = [("today", "none"), ("v6 span", "v6"),
|
||||
("v6 fine tail", "v6fine"), ("DMAC chain", "dmac")]
|
||||
("v7 fine tail", "v7"), ("DMAC chain", "dmac")]
|
||||
res = {n: score(k) for n, k in DESIGNS}
|
||||
|
||||
print(f"{a.container}: {d.nframes} frames, {d.nb} blocks, {a.fps:g} fps")
|
||||
@@ -188,11 +193,11 @@ print(f"\n ADDITIVE: frame = CPU + span painting + disk DMA. The 68000 has no"
|
||||
|
||||
# What is left of the case, isolated.
|
||||
v6m = int((res["v6 span"][0] > FRAME_CYC).sum())
|
||||
finem = int((res["v6 fine tail"][0] > FRAME_CYC).sum())
|
||||
finem = int((res["v7 fine tail"][0] > FRAME_CYC).sum())
|
||||
dmam = int((res["DMAC chain"][0] > FRAME_CYC).sum())
|
||||
print(f"\nWHAT THE DMAC ACTUALLY BUYS, decomposed")
|
||||
print(f" v6 as built {v6m}/{d.nframes} frames over")
|
||||
print(f" v6 with a finer chain tail (software) {finem}/{d.nframes}")
|
||||
print(f" v7, a finer chain tail (MEASURED) {finem}/{d.nframes}")
|
||||
print(f" DMAC chain {dmam}/{d.nframes}")
|
||||
print(f" -> of the gap between v6 and the DMAC, "
|
||||
f"{100*(v6m-finem)/max(v6m-dmam,1):.0f}% is the 24-pixel padding")
|
||||
@@ -206,9 +211,9 @@ print(f" in software. The rest is 1.7% a pixel and 7.7 clocks a span.")
|
||||
|
||||
print(f"\nbreak-even against all-V1 ({C_V1:.1f} cycles/block), clocks per block")
|
||||
print(f" {'L':<16}" + "".join(f"{L:>8}" for L in (1, 2, 3, 4, 8, 16, 64)))
|
||||
for nm, dz in (("v6 as built", "v6"), ("v6 fine tail", "v6fine"), ("DMAC chain", "dmac")):
|
||||
for nm, dz in (("v6 as built", "v6"), ("v7 fine tail", "v7"), ("DMAC chain", "dmac")):
|
||||
print(f" {nm:<16}" + "".join(f"{span_cost(dz, L)[1]/L:>8.0f}"
|
||||
for L in (1, 2, 3, 4, 8, 16, 64)))
|
||||
for nm, dz in (("v6 as built", "v6"), ("v6 fine tail", "v6fine"), ("DMAC chain", "dmac")):
|
||||
for nm, dz in (("v6 as built", "v6"), ("v7 fine tail", "v7"), ("DMAC chain", "dmac")):
|
||||
brk = next((L for L in range(1, 65) if span_cost(dz, L)[1] < L * C_V1), None)
|
||||
print(f" {nm:<16} beats all-V1 from L={brk} blocks up")
|
||||
|
||||
Reference in New Issue
Block a user