Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 90 additions & 24 deletions CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -866,29 +866,83 @@ C64U, fits T(f)=D+C/f, residuals <=4.1%):
whose device has to be inferred from a heading is not interpretable.
64 MHz exists only on the C64U (the U64E's CPU Speed enum stops at 48):

device profile 1 MHz 8 MHz 48 MHz 64 MHz
C64U v0.3.0 REU -- -- 73.0 s 64.7-65.9 s
C64U v0.5.0 onchip -- -- 59.9 s 47.5 s (n=3)
C64U v0.6.0 onchip -- -- 51.0 s 39.7 s
C64U v0.6.0 onchip+comb -- -- 38.4 s **31.0 s**
U64E REU @ 2ceb5b1 1157.7 s 196.5 s 80.8 s n/a (no enum)

The U64E row is a 2026-08-13 clock sweep at master 2ceb5b1, one clean
`BACKEND=uci` build reused across all three runs so clock is the only
variable, all three PASS with server-side evidence (the listener
decrypted the full GET; no TLS error). Times are handshake + GET
measured C64-side from `run_prg`, not whole-script wall-clock.

Fitting T(f) = D + C/f to that row gives **D = 58.5 s, C = 1099 MHz*s**,
residuals <= 0.69% across a 48x clock range. Two things follow. The
floor is ~58 s, and the documented REU-profile *verify* floor is
48.2 s, so roughly **10 s of the e2e is clock-invariant non-verify
cost** — UCI firmware round-trips and network latency, which no amount
of turbo touches. And the returns are visibly diminishing: 1->8 MHz
(8x clock) bought 5.9x, while 8->48 MHz (6x clock) bought only 2.4x.
Extrapolating the fit to 64 MHz predicts 75.6 s, which is why the
REU profile is the wrong choice above ~7 MHz — compare the C64U comb
rows above.
device profile 1 MHz 8 MHz 16 MHz 20 MHz 48 MHz 64 MHz
C64U v0.3.0 REU -- -- -- -- 73.0 s 64.7-65.9 s
C64U v0.5.0 onchip -- -- -- -- 59.9 s 47.5 s (n=3)
C64U v0.6.0 onchip -- -- -- -- 51.0 s 39.7 s
C64U v0.6.0 onchip+comb -- -- -- -- 38.4 s **31.0 s**
U64E REU @ 2ceb5b1 1157.7 s 196.5 s 124.0 s 108.9 s 80.8 s n/a (no enum)
U64E onchip @ 2ceb5b1 2120.7 s 264.5 s 131.8 s 103.9 s 45.5 s n/a (no enum)

The U64E rows are a 2026-08-13 sweep at master 2ceb5b1. One clean
build per profile, reused across that profile's clocks, so clock is
the only variable within a row. Every run PASSes with server-side
evidence (the listener decrypted the full GET; no TLS error). Times
are handshake + GET measured C64-side from `run_prg`, not
whole-script wall-clock (which runs ~35-55% higher: boot, table init
and turbo setup).

The onchip 16 MHz entry is the median of two retries (132.4 / 131.2).
Its first attempt died on `net_last_error = $88 UCI_ERR_NO_SOCKET` —
the TCP_CONNECT bridge glitch, not a result. Note that failure
occurred with the REU *enabled*, which is evidence against the
REU-quiet-boot explanation for this device and in favour of the
turbo-switch settle race.

**Footnote — an inactive REU costs nothing.** The onchip rows above
ran with the device's REU enabled but unused. Re-running that
byte-identical PRG with `RAM Expansion Unit = Disabled`: 48 MHz
44.9 s (-1.32%), 8 MHz 262.0 s (-0.95%), 1 MHz 2130.9 s (+0.48%).
Sub-1.5% and not consistently signed, i.e. noise, not an effect.
All three PASS with zero `NO_SOCKET` hits, so a REU-quiet boot did
**not** drop the first TCP_CONNECT on the U64E — behaviour the C64U
notes record as general. This is also the first confirmation of the
shipped "no REU required" onchip claim on UCI hardware rather than
in VICE.

Fitting T(f) = D + C/f across all five clocks:

U64E REU D = 56.4 s C = 1101 MHz*s max|resid| 2.35%
U64E onchip D = -0.6 s C = 2121 MHz*s max|resid| 4.09%

**The two profiles differ in floor, not just slope**, and that is the
whole story of the crossover. REU carries a ~56 s floor that no clock
touches, because `fp_mul`'s row fetches are anchored to the ~1 MHz
bus; onchip has none, paying instead ~1.9x the clock-scaling work.
The fits cross at **17.9 MHz** (17.6 from the three-point version),
against the independently-derived verify-only figure of ~18 MHz.

That crossover is **measured, not just fitted**: REU wins at 16 MHz
by 5.9% and onchip wins at 20 MHz by 4.6%, so the sign flips inside
[16, 20]. There is no 18 in the CPU Speed enum, so that interval is
the finest bracket this hardware can produce.

Read the onchip D as *indistinguishable from zero*, never as a
quantity: the five-point fit returns -0.6 s, a physically impossible
floor. At 48 MHz the C/f term is ~99% of the total, so D is fitted
from rounding. This is the same ill-conditioning the turbo campaign
hit with 2-point fits.

Two cautions on reading these fits. The onchip D is **poorly
conditioned** — at 48 MHz the C/f term is ~99% of the total, so D is
fitted from what little is left; treat it as "under ~2 s", not as
0.5 s. And an earlier revision of this section claimed the REU floor
minus the 48.2 s verify floor localised "~10 s of clock-invariant
non-verify cost". **That was wrong**: a genuinely clock-invariant
cost would appear in the onchip floor too, and it does not (forcing
D=10 on the onchip points throws the 8 MHz prediction off by 16%).
The fixed network cost is instead ~0.6 s — 16 drain polls at ~40 ms,
matching the onchip floor — and the REU floor is almost entirely DMA.

Returns diminish steeply on the REU profile: 1->8 MHz (8x clock)
bought 5.9x, 8->48 MHz (6x clock) bought only 2.4x. Extrapolating it
to 64 MHz predicts 75.6 s, which is the quantitative case for the REU
profile being wrong above the crossover — compare the C64U comb rows.

A cross-validation worth keeping: the onchip fit built from only the
8 and 48 MHz points predicted 1 MHz at 2104 s before that run
happened; the measurement came in at 2120.7 s, +0.8% over a 48x
extrapolation.

Those rows are the 2026-07-20 campaign state. **Current HEAD is
faster** — see "Post-#74 e2e numbers" below; the onchip rows in
Expand DownExpand Up@@ -952,6 +1006,7 @@ feth/pcap rig (see "VICE ip65 rig" under Smoke tests). These are the
ip65 + onchip, no REU honest 1 MHz **2,159.7 s (36.0 min)**
ip65 + onchip, no REU ~1.2x accelerated 1,813.9 s
ip65 + REU profile ~1.2x accelerated 988.9 s
ip65 + onchip @ 2ceb5b1 ~1.2x accelerated 1,876.0 s (2026-08-13)

Honest-1 MHz phase breakdown (seconds after 'G'):
TCP CONNECTED 3.0 | CH 329.2 | SH 700.7 | PROC 718.9 |
Expand All@@ -962,7 +1017,18 @@ feth/pcap rig (see "VICE ip65 rig" under Smoke tests). These are the
holds at 1 MHz, three orders of magnitude from where it was fit.
- X25519 scalarmults measured 326 s / ~356 s vs ~324 s analytical.
- ip65's drain budget is **unchanged by #74** (the ip65 PRG is
byte-identical across it), so these numbers stand at HEAD.
byte-identical across it), so those numbers stand at HEAD.
- **Re-validated at master 2ceb5b1 on 2026-08-13**: PASS,
`http_status=200`, `resp_len=22`, body match, 1,876.0 s
accelerated (+3.4% vs the 1,813.9 s reference). Phase shape
unchanged: TCP 3.0 | CH 276.0 | SH 585.4 | PROC 600.6 |
FIN 1,823.0 | REQUEST SENT 1,838.2 | CLOSED 1,841.2. This matters
beyond the number — the ip65 PRG is **no longer** byte-identical
to the #71-era build (`417c708594...` vs `db31111031e2...`)
because #75's span-input parser is real code, and until this run
that change had only ever been exercised on the UCI backend. It
was also ip65's first end-to-end run since July, so it is the
first to cover #74, #75 and the ten audit PRs.
- VICE 3.10 SDL2 has no usable runtime warp: its `Speed` resource
caps at ~1.2x and `WarpMode` is gone, so "accelerated" runs are
only ~1.2x. Divide accelerated figures by ~1.2 for honest 1 MHz.
Expand Down