Price the transport against the frame, and find dual address cannot fit

FINDINGS 59.7. tools/analysis/15_bus_occupancy.py has always answered "what does
each W cost" and never "what can the frame afford", and after 59.2 those are not
the same question. It now answers both, and takes an optional --kbps for the
auto-request rows -- the only rows whose cost depends on how long the record
takes to arrive.

On the gate container at 12 fps, decode term MEASURED: decode 68.5%, audio 1.25%,
HEADROOM 30.2% = 6.74 clocks per byte at a 37,403 B record. Against that, P4a
cut the transport from 391.7% of a frame to 40..95% -- four to ten times, the
largest movement in this project's cost model since the decoder was written --
and it still does not fit. A dual-address byte is a 4-clock read of the device
plus a 5-clock write to memory, so 9 clk/B is a FLOOR and the frame affords 6.74.
No GCR share goes under it and no delivery rate goes under it: a share decides
whether the channel sits at the floor or above it. At 460 KB/s max-rate totals
165.1% and LRAR at 50% totals 117.4%, and a 50% share tops out at 543 KB/s, above
which the channel is the bottleneck and the rate falls back to exactly that floor.

So 59.2's three bounds arrive in the budget as one sentence: the configurations
this machine can run are the ones the frame cannot afford, and the one it can
afford -- single address, 5 clk/B, 92.2% total, 7.8% spare -- needs the device to
ACK the DMAC, which needs a request line MAME does not connect and the slot
pinout does have at B36/B37.

ROADMAP re-ranks accordingly. B3 stops being a constant to look up and becomes
DOES THE CARD DRIVE #EXREQ, ahead of B1: B1 sets how much headroom the player
has, B3 decides whether there is any. New E7 carries the other branch -- if the
answer is no, the container must reach 27,995 B a frame, 328 KB/s of payload,
against 438 now. The dependency diagram is redrawn around that fork.

The scope is stated rather than buried: this is the GATE container, deliberately
the heaviest thing the encoder emits, and the lighter cpufit family was NOT
priced -- 15_bus_occupancy.py refuses it, correctly, because the C68K measurement
it cross-checks against belongs to the gate container. E7 therefore begins with a
harness re-run, and until then "34% too big" is a statement about the fixture and
not about the project.

check.sh ALL GREEN before and after.

Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
prosolis
2026-08-25 00:17:29 -07:00
parent 621a5bb457
commit 8800d8f8c0
5 changed files with 281 additions and 20 deletions
+72
View File
@@ -5731,3 +5731,75 @@ any of this work, so the red was unambiguously new, and the failure was in a
stage nobody would have re-run on suspicion. Both halves of "green before and
green after" earned their place; the map is now `$18500`, clear of everything
the streaming rig owns.
### 59.7 What it all costs: the frame affords 6.74 clocks a byte, and a dual-address byte is 9
The sweep in `15_bus_occupancy.py` has always answered *"what does each `W`
cost"*. It never answered *"what can the frame afford"*, and after 59.2 those
stopped being the same question. The tool now answers both; every figure below
is it, on the gate container at 12 fps, and the decode term is **measured**
(C68K) while the transport terms are datasheet arithmetic — except PIO, which
58.2 measured.
frame slot 833,333 clk
decoder, MEASURED 570,958 clk 68.5% (worst frame 110.8%)
audio DMA 10,417 clk 1.25%
------------------------------------------
HEADROOM 251,958 clk 30.2% = 6.74 clk/B at a 37,403 B record
| transport | clk/B | video | CPU+audio+video |
|---|---|---|---|
| PIO — **measured**, 58.2 | 87.28 | 391.7% | **461.5%** |
| dual address, arbitrated — the IPL ROM's own (52.5) | 16..19 | 71.8..85.3% | 141.6..155.0% |
| single address, arbitrated | 12 | 53.9% | 123.6% |
| **dual address, held — and the FLOOR of every dual-address configuration** | **9** | 40.4% | **110.2%** |
| single address, held | 5 | 22.4% | **92.2%** |
**WHAT P4a BOUGHT: the transport falls from 391.7% of a frame to 40..95%**, four
to ten times. That is the whole of the gain and it is the largest single
movement in the project's cost model since the decoder was written.
**WHAT IT DID NOT BUY IS A FIT, and the reason is one line of arithmetic.** A
dual-address byte is a 4-clock read of the device and a 5-clock write to memory
`buscost.DMA_DUAL_BYTE_CLK`, Fig 4-25 — so **9 clocks is a floor, and the
frame affords 6.74.** No GCR share goes under it and no delivery rate goes under
it: a share decides whether the channel sits *at* the floor or *above* it. So
**59.2's three bounds arrive in the budget as one sentence — the configurations
this machine can run are exactly the ones the frame cannot afford**, and the one
it can afford is single address, which needs the device to ACK, which needs the
request line ROADMAP B3 asks about.
**The rate sweep says the same thing from the other side.** At 460 KB/s
max-rate totals **165.1%** and LRAR at 50% totals **117.4%**; the smaller shares
total less but cannot carry the rate at all. A faster disc makes auto-request
cheaper — which no `W` does, and it is the first cost in this project that
improves when the medium does — but it cannot reach the floor: **a 50% share
tops out at 543 KB/s**, above which the channel is the bottleneck and the
delivered rate falls back to it, at which point the cost is exactly 9 clk/B
again.
**SO THE FIT NOW TURNS ON ONE OF TWO THINGS, AND ONE OF THEM IS OURS.**
1. **Does a real CZ-6BS1 drive `#EXREQ`/`#EXACK`?** It is the only route to
single address, 22.4%, 92.2% total, fitting with 7.8% to spare. MAME cannot
answer it — it does not connect the pin (59.2) — and the slot pinout has it
at B36/B37. **This is now the sharpest form ROADMAP B3 has ever had**, and it
is worth more than the throughput half of B1: B1 sets how much headroom the
player has, B3 decides whether there is any.
2. **Bytes.** At the 9 clk/B floor this container must come down to **27,995 B a
frame — 328 KB/s of payload**, against the 37,403 B and 438 KB/s it is now:
**34% too big.** That is an encoder target, it is entirely inside this
project, and **it is the pessimistic reading of the lever**, because a
lighter container also decodes cheaper and the decode term falls with the
byte term.
**WHAT THIS IS NOT.** It is the **gate container**, which is deliberately the
heaviest thing the encoder emits — the span-heavy scsi container encoded to the
488 recipe, chosen so that every block mode and the newest span path are
exercised (check.sh's own note). The lighter `cpufit` family exists and was NOT
measured here: `15_bus_occupancy.py` refuses it, correctly, because the C68K
measurement in `tmp/c68k_frames.csv` belongs to the gate container and the
cross-check at the top of the tool is what licenses every number under it.
**Re-deriving 59.7 against a lighter container needs that harness re-run first**,
and until it is, "34% too big" is a statement about the heaviest container and
not about the project.