Skip to content
107 changes: 106 additions & 1 deletion docs/gpu-router-m6-results.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# GPU Router M6 — first end-to-end results

> **Correction (2026-07-25).** Every DRC figure in this document was computed
> against a baseline a geometry bug had inflated, and the SI comparison table
> understated our own delta as a result. See
> [the correction section](#correction-2026-07-25--the-drc-baseline-was-inflated)
> at the end. Claims move only with runs; a correction is a run.

Companion to [gpu-router-m0.md](gpu-router-m0.md) (the charter). This is the
first measured run of the complete chain on the CM5 benchmark
(schlae/cm5-reveng: 10 copper layers, 436 nets, 3,037 pads, human-routed
Expand Down Expand Up @@ -99,9 +105,108 @@ toward 30 min (~40–60 min of wall-clock) and possibly a quality gain.
(Competitor rows are qualitative — none publish CM5-class results; that is
the point of the row.)

## Correction (2026-07-25) — the DRC baseline was inflated

Every DRC number published above and in
[gpu-router-m7-pair-si.md](gpu-router-m7-pair-si.md) was measured against a
stripped-fixture baseline that one of our own bugs had inflated.

**The bug.** KiCad stores a pad's angle as an **absolute** value — it already
includes the footprint's orientation. vcad's importer stored that raw value
while eleven consumers compose `fp.rotation + pad.rotation`, double-counting the
footprint rotation on every rotated part. On fine-pitch rotated packages the
neighbouring pads **overlapped**, manufacturing phantom shorts and clearance
violations out of thin air. Fixed in PR #684.

**Why it mattered more than a normal measurement error.** The phantom violations
landed in the *baseline*, and the baseline is the denominator of every
route-attributable claim. A bigger floor makes our delta look smaller, so the
error flattered us in every published comparison — the direction that most needs
correcting.

Re-measured from scratch on merged main with #684 in. DRC and SI are
deterministic given a fixed board file, and every figure below was run twice
with **identical** results; the route stage is the only stochastic step and is
reported with its spread.

### The baseline itself

| stripped fixture, all copper removed | before | after |
|---|---|---|
| short/clearance | 980 | **311** |
| `Clearance` | 74 | **23** |
| `Short` | ~906 | **258** |

**648 violations this project attributed to the reverse-engineered source were
ours.**

### The human production board

| | before | after |
|---|---|---|
| total violations | 16,485 | **14,104** |
| short/clearance | — | **6,994** |

The repeated "the production board scores 16,485 violations under these rules"
line was itself inflated by 2,381. The board is still far outside our rule set —
that part of the argument stands — but the number was wrong.

### Our board, re-routed clean

Full-board route on the corrected importer, **two runs**: **routability 0.994**
both times, producing a byte-identical board (3,791 segments / 895 vias,
5,301 mm copper, 380 routed / 28 unrouted), 0.31× human via count. The route is
deterministic given the tree; only wall-clock varies (958.9 s and 895.5 s).

| | published | corrected |
|---|---|---|
| `Clearance` | 74 (claimed = the floor) | **173** |
| floor | 74 | **23** |
| **route-attributable `Clearance`** | **0** | **150** |

**"Route-attributable violations: ZERO" was false.** It read `74 − 74 = 0`
because the inflated floor happened to equal what our board scored. The honest
figure is 150 against a floor of 23.

### What did *not* move

The receipt bounds are untouched, and they remain a valid envelope: the human
board's anchor re-measures **bit-identical** after the fix —
`worst_group_skew 9.756`, `worst_intra_pair_skew 1.074`,
`min_pair_coupled_fraction 0.857`, `vias_per_si_net 2.265`, **ALL HOLD**. Pad
angles feed pad geometry, not trace lengths, so the calibration anchor and the
argument it supports survive this correction intact.

### The <30 min chain target is met

| stage | before | now |
|---|---|---|
| route | 113 min (pre-GPU-fix) | **895.5 / 958.9 s ≈ 14.9–16.0 min** (2 runs) |
| full chain (route + si_finish) | 2 h 51 m → 67 min | **1,634 s ≈ 27.2 min** (1 run) |

The M6 scoreboard row `< 30 min chain | 2 h 51 m` is **closed**.

Two honesty notes on these timings, since a prior version of this document
published a single lucky run as typical:

- Both runs shared the machine with another session's full-board route (load
average 23.4). Contention only inflates wall-clock, so the `<30 min`
conclusion holds a fortiori — but neither number is a clean solo measurement.
- The chain figure rests on **one** complete run, not two. The second attempt's
route stage finished normally (895.5 s, identical board) but its `si_finish`
stage was truncated when the machine's disk filled, so its 1,288 s is not a
valid chain sample and is not averaged in. The route-stage spread above is
from two complete runs; the chain number needs a second clean run to earn the
same standing.

The pad fix also helped routing directly: pair-first now lands **47** pairs
coupled in round 0, up from the published 43. Overlapping pads had been sealing
the BGA fields that pairs escape through.

## Next

1. Wire M4 negotiation into the route/ratchet stages (the <30 min path).
1. ~~Wire M4 negotiation into the route/ratchet stages (the <30 min path).~~ —
done; the chain is 27.2 min, see the correction section above.
2. ~~Reroute-then-descend for extreme-skew pairs; descent for the rest.~~ —
done, see [gpu-router-m7-pair-si.md](gpu-router-m7-pair-si.md). Coupled
construction went 17 → 39 of 49 pairs (the phantom centerline had been
Expand Down
123 changes: 123 additions & 0 deletions docs/gpu-router-m7-pair-si.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# M7 — universal pair coupling and the SI receipt

> **Correction (2026-07-25).** The results below were measured against a DRC
> baseline our own pad-rotation bug had inflated (PR #684), and the "40-net
> subset — receipt Pass" headline does not reproduce. Corrected figures are in
> [the correction section](#correction-2026-07-25--re-measured-after-the-pad-rotation-fix)
> at the end; the numbers in the body are left as originally published so the
> record shows what moved. Claims move only with runs; a correction is a run.

Follow-on to [gpu-router-m6-results.md](gpu-router-m6-results.md), whose
scoreboard closed with `receipt Pass | 1/4 HOLDS` and named the levers:
coupled routing during construction, and reroute-then-descend for the
Expand Down Expand Up @@ -210,8 +217,124 @@ fixture. The import carries ~906 pad-level shorts, and every routed trace
merges copper clusters, multiplying reported net-pair shorts — routing only 40
nets adds ~409. Use the `Clearance` rule for attribution.

## Correction (2026-07-25) — re-measured after the pad-rotation fix

vcad's KiCad importer stored pad angles as read, but KiCad's pad angle is
absolute (it includes the footprint's orientation) while eleven consumers
compose `fp.rotation + pad.rotation`. Rotated fine-pitch packages therefore had
**overlapping pads**, inflating the DRC baseline every attribution claim in this
document is measured against. Fixed in PR #684; see
[gpu-router-m6-results.md](gpu-router-m6-results.md#correction-2026-07-25--the-drc-baseline-was-inflated)
for the full baseline correction.

Everything below is re-measured on merged main with #684 in. DRC and SI are
deterministic on a fixed board; every figure was run twice with identical
results.

### The 40-net subset was not a Pass

The headline "40-net subset — receipt Pass (ALL HOLD)" is **withdrawn**. It also
failed to reproduce on merged main *before* this fix (measured 2026-07-25:
`worst_intra_pair_skew` 1.347mm against the 1.1mm bound, i.e. 3/4), so the
original Pass was a property of that one branch state, not a reproducible
result.

| 40-net subset | published | corrected (2 runs, identical) |
|---|---|---|
| worst_group_skew | 0.000 HOLDS | 0.000 HOLDS |
| **worst_intra_pair_skew** | **0.983 HOLDS** | **1.353 BROKEN** (bound 1.100) |
| min_pair_coupled_fraction | 0.777 HOLDS | 0.582 HOLDS |
| vias_per_si_net | 2.727 HOLDS | 2.474 HOLDS |
| pair_impedance_correct_fraction | — | 0.000 HOLDS *(vacuous, see below)* |
| **verdict** | **ALL HOLD** | **3 of 4** (4 of 5 counting the vacuous claim) |

Routability is unchanged at 1.000 (4.7–5.1 s over two runs).

**The claim that survives**: the finishing pass still introduces no clearance
violations. Published as "the board's total `Clearance` count is identical with
the finishing pass on and off (74)". The 74 was the inflated floor; corrected,
the 40-net board scores `Clearance` **23** — *exactly* the stripped-fixture
floor. Same finding, honest number.

### The full board is 1 of 4, not 2 of 4

Full-board route on the corrected importer, two runs: routability **0.994**
both times, byte-identical board (3,791 segments / 895 vias) — the route is
deterministic given the tree. Wall-clock 895.5 / 958.9 s.

| full board | published (routed + si_finish) | corrected |
|---|---|---|
| worst_group_skew | 9.297 HOLDS | **8.397** HOLDS |
| worst_intra_pair_skew | 37.853 BROKEN | **38.521** BROKEN |
| min_pair_coupled_fraction | 0.000 BROKEN | **0.101** BROKEN |
| **vias_per_si_net** | **2.766 HOLDS** | **3.128 BROKEN** (bound 3.000) |
| pair_impedance_correct_fraction | — | 0.000 HOLDS *(vacuous, see below)* |
| **verdict** | **2 of 4** | **1 of 4** (2 of 5 counting the vacuous claim) |

`vias_per_si_net` crossed the bound: 294 vias over 94 routed SI nets. The board
now routes more connections (0.994 vs 0.983) and pays for them in vias, so this
claim broke as coverage improved — worth stating plainly rather than reporting
only the routability gain.

`min_pair_coupled_fraction` moved off exactly zero (0.101) because pair-first
now couples **47** pairs in round 0, up from 43 — overlapping pads had been
sealing the BGA fields pairs escape through. Still far under the 0.5 bound, and
the short `/HS.*` pairs diagnosed above remain the pin.

### DRC attribution, corrected

| | published | corrected |
|---|---|---|
| stripped-fixture floor, `Clearance` | 74 | **23** |
| our full board, `Clearance` | — | **173** |
| **route-attributable `Clearance`** | claimed **0** | **150** |

The note "the import carries ~906 pad-level shorts, and routing only 40 nets
adds ~409" is corrected: the import carries **258** pad-level shorts, and the
40-net route adds **27** (285 total). The *conclusion* is unchanged and still
correct — `Short` counts are not route-attributable on this fixture, because
every routed trace transitively merges same-net copper clusters. Use `Clearance`
for attribution.

### Re-verified against current main (#685, #687, #691)

Main moved while this correction was being measured: #685 (Eagle `.brd` pad
rotation), #687 (Gerber apertures turn with the pad), and #691 (per-layer
controlled-impedance geometry). #691 rewrites `router/pair.rs` and adds a fifth
SI claim, so the corrected figures were re-run against it rather than assumed
still valid.

**Nothing moved.** The stripped floor (311 / 23), our board's DRC (`Clearance`
173), and the 40-net route (byte-identical board — 762 segments, 92 vias,
receipt 1.353 / 0.582 / 2.474) all reproduce exactly. #691's per-layer widths
are opt-in on `target_impedance`, which the CM5 fixture's classes do not
declare, so the router's behaviour on this board is unchanged.

The new `pair_impedance_correct_fraction` claim is therefore **vacuous here** —
it reports `0.000` against a bound of `0.000` with the reason "no differential
net class declares a target impedance — nothing to verify", and HOLDS trivially.
The receipt is now 5 claims wide, so the raw fraction reads 2 of 5 on the full
board and 4 of 5 on the subset. **Those are not improvements.** The honest
counts against claims that actually verify something are unchanged: **1 of 4**
and **3 of 4**.

### The bounds are untouched, and still valid

The human board's anchor re-measures **bit-identical** after the fix —
9.756 / 1.074 / 0.857 / 2.265, ALL HOLD. Pad angles feed pad geometry, not
trace lengths, so the calibration anchor is unaffected and the envelope
argument stands. No bound was adjusted.

### The open A/B is now closed on the honest baseline

The "no new route-attributable DRC — router: **not A/B'd**" gap above is
answered: against the corrected floor of 23, the router's own delta is
**+150 `Clearance`**. That is the missing evidence, and it is not zero.

## Next

0. Reduce the 150 route-attributable clearance violations — now measurable
against an honest floor, and the router's real debt.
1. A short-pair path that keeps both legs on one layer without the lead inset
— this alone unpins `min_pair_coupled_fraction` from zero.
2. Higher-effort polish for the detour pairs, or catching them during
Expand Down