75-1536-interposer
Valuation
Generous asset valuation: $40,000,000,000. The listed price is the platform maximum; acquisition at valuation is handled by direct enquiry.
BGA + IO Placement Standard
BGA + IO Placement Standard
This project now uses a reusable anchor standard for the primary BGA and
left-edge IN/OUT connectors.
Canonical Coordinates
- PCB edge left-bottom corner:
(61.100, 114.650)mm - BGA center (
U1):(141.500, 95.400)mm - BGA interchange window:
95.0 mm
Derived vector:
U1 - edge = (80.400, -19.250)mm
Connector Locking Rule
J2andJ3keep fixed deltas fromU1.- When
U1moves, both connectors move by the same translation vector. - This preserves IN/OUT spacing and makes the cluster reusable across boards.
Current offsets stored in placement.json:
J2 - U1 = (-75.817, -12.461)mmJ3 - U1 = (-75.817, 15.539)mm
Apply to Any Variant
Run from repository root:
python blueprints/apply_bga_io_standard.py ` --edge-x 61.1 --edge-y 114.65 ` --u1-x 141.5 --u1-y 95.4 ` --bga-travel-mm 95
This updates:
blueprints/placement.jsonpinned centers (U1,J2,J3)blueprints/placement.jsonmetadata (_placement_standard)
The auto-placer (blueprints/auto_place.py) will then use those pinned
coordinates for all board variants.
AutoPhi 34-Board Fork — Pipeline Handoff
AutoPhi 34-Board Fork — Pipeline Handoff
Rebuild-everything doc for the TIDA-00423 → 34 AutoPhi I/O variants pipeline.
Written after the session on 2026-04-08. Everything described here runs from
D:\special\35-autophi-quantum-pcie5\blueprints\.
Goal
Fork the Texas Instruments TIDA-00423 PCIe Gen3 reference PCB into **34
product variants**, one per I/O bracket connector type, to pair with the
AutoPhi V19 Pinnacle chip catalog (1,060 SKUs) on cri-one.com. Every variant
must:
1. Preserve the TI card outline verbatim (PCI-SIG compliance).
2. Carry all 46 RAG-canonical parts from autophi_engine/rag/components.py.
3. Pack at ≥ 2 mm (back) / 4 mm (front) edge-to-edge clearance with zero
courtyard collisions.
4. Have its .kicad_pcb, SVG preview, and Magento catalog row emitted by a
one-command pipeline.
One-shot build
cd D:/special/35-autophi-quantum-pcie5 python blueprints/build_all.py
That runs: fork → SVG render → collision check → Magento CSV → preview HTML.
Output summary ends with OK: 34 boards, 0 collisions.
Pipeline stages
Key architectural decisions
1. Outline: flatten the retention tab
flatten_top_edge() strips every Edge.Cut segment with both endpoints above
y = -51.44 (the TI retention tab) and the stair-step connectors that
straddle the body boundary, then adds three new segments:
- left vertical (
-14.92, -58.45) → (-14.92, -51.44) - horizontal top (
-14.92, -58.45) → (152.72, -58.45) - right vertical (
152.72, -58.45) → (152.72, -51.44)
Result: the top of every board is a clean horizontal line.
2. Main body bounding box
After flatten, usable main body is X ∈ [-14.92, 152.72], Y ∈ [-51.44, -3.4].
Anything outside is either the PCIe-finger cutout (bottom) or outside the
board entirely.
3. Fixed parts (pre-packer)
U1AutoPhi BGA-256 at(68.9, -29.5)20×20 mmU2-U5DS160PR810 retimers at(46.9/90.9, -36.5/-22.5)8×8 mm eachU6-U7LP3878 LDOs at(113.9, -39.5/-29.5)U20iCE40UP5K at(113.9, -16.5)(renamed from U10)J1PCIe x16 fingers at(72, 6.87)J2/J3I/O connectors at(-6.92, -42)and(-6.92, -14), rotated 90°,
flush with the left short edge (Edge.Cut at x = -14.92). Anchor x is
-14.92 + 8 mm (shield half-width) so pads hit the edge exactly.
MH1-MH4around U1 at(±15, ±15)offsetMH5at(5, -48),MH6at(148, -48)- 128 decoupling caps in rings around U2-U5 (32 each), 20 around U1
- 8 bulk caps around U6/U7
4. RT / TP / D placements (post-fix)
RT1-RT8NTC thermistors at inter-chip gaps:
(55/83/103, -33), (55/83/103, -26), (36, -33), (36, -26)
TP1-TP6at(5,10,15,20,25,30; -28)in the left corridor between J2/J3D1-D4power LEDs at(143, -40/-35/-30/-25)
5. Option-A packer (37 extra RAG canonical parts)
Zone-packer in fork_ti_board.py:build_components:
CLEARANCE_F = 4.0 # front side (F.Cu) CLEARANCE_B = 2.0 # back side (B.Cu)
Packer computes real pad bboxes — declared w/h in the part table is
advisory. _real_pad_bbox(pads) measures actual pad extents so _soic_pads
and _qfn_pads don't overflow zones.
Front mid row @ y=-11, ranges [(4,41), (52,85), (96,109), (120,138)]:
- Big parts: U8, U40, U41, U43, U44, J4, TEC1, TEC2, LED1
Back top row @ y=-47, ranges [(4,41), (52,85), (96,109), (120,146)]:
- Power/telemetry: U12-U14, U21-U24, U25-U30, U42, U29, U30, J10, J11
Back mid row @ y=-6, ranges [(4,148)]:
- SW1-SW8 + U45-U52 ESD arrays
Back terminator rows @ y=-30 and y=-28.5, ranges [(4,148)], clearance 1.5:
- RT9-RT34 (26× 49.9Ω 0402 under U1 BGA — back is empty there)
Zone left edges start at x=4 (not x=2) so the packer never touches J3's
shield pad at x=1.08.
6. Side-split rule
Front side gets big / visible / connector-bearing parts. Back side gets
small SMD / config / terminator parts. This lets the front keep 4 mm
clearance (the physical density limit of the HHHL main body).
7. Renderer colors
render_board_svg.py parses the footprint's (layer "...") and draws:
- Front parts: gold pads (
#e7b74d) + white courtyard outlines - Back parts: cyan pads (
#5dc1d9) + muted cyan outlines - Every SMD gets a bbox outline so collisions are visible at a glance.
8. Collision detector
Inline in build_all.py. Uses parse_footprints() + rotated pad bboxes,
ignores C* refs (cap rings are dense by design), and only flags same-side
overlaps. Output: 0 collisions on all 34 boards.
Known gotchas (bugs we hit and fixed, don't repeat)
Open TODOs
1. Real footprints from Ultra Librarian. Most Option-A parts use
placeholder tiny_pads() bodies. Swap for real ones from
<https://www.ultralibrarian.com/cad-vendors/kicad/>.
2. kicad-cli compatibility. Fix the fork's sexpr so native KiCad 10 can
open the .kicad_pcb files (needed for gerber export).
3. Route traces. build_nets() defines 232 nets but no traces are
actually routed. Add autophi_engine/layout/router.py-style routing.
4. Narrow related_skus per tier. Currently every board lists all 1060
chip SKUs. Should probably be per-tier (SEE→all Seed chips, etc.).
5. Variant Y-coordinate for goal image match. The SMD-15-2026 product
image has a specific aesthetic the user wants matched — still waiting on
a screenshot to diff against.
6. Prices calibration. Current $15k-50k tiers were derived from
io_configs.py anchors + category floors. User may want to override.
Autorouter (auto_route.py)
Grid A* routing writes the .kicad_pcb in place. After each successful write,
the script runs kicad-cli pcb drc when the CLI is on PATH or under
typical Windows KiCad install paths (override with env KICAD_CLI). Use
--no-drc to skip (e.g. CI without KiCad). The second-pass retry of failed
nets follows R.A_STAR["backoff_if_fail"] in autophi_engine/rag/routing.py.
CI: GitHub Actions .github/workflows/ci.yml runs pytest tests/ on
push/PR (fast unit tests; integration is skipped by default). Weekly /
manual integration.yml sets AUTOPHI_INTEGRATION=1 for the optional
route_board smoke test.
Pad order: Target-first chaining (route connector/retimer before BGA) uses
R.NET_PAD_ORDER["target_first_refs"] (default U1). Override with
--target-first-refs REFS or disable with --no-target-first.
Global + detailed: R.GLOBAL_ROUTE runs a coarse tile BFS on the
start layer, builds an inflated fine-cell corridor, then runs detailed A\*
inside it; if that fails, it falls back to full-grid A\*. Disable with
--no-global-route.
Easy button (Windows): from repo root, run easy.cmd (double-click or in a terminal)
for a small menu (tests / integration / route a board). Same as .\scripts\easy.ps1
with arguments test, integration, or route. The first test run installs pytest
via pip if needed (requirements-dev.txt); or run easy.cmd deps first.
File map
blueprints/
├── fork_ti_board.py # main forker (flatten + place + write)
├── generate_pcb.py # 34 IO_CONNECTOR_DEFS + IO_BOARD_NAMES
├── render_board_svg.py # custom Python SVG renderer (bypasses kicad-cli)
├── placement.json # fixed-part coordinates (U1, J1, J2, J3, etc.)
├── build_magento_34_boards.py # RAG-grounded Magento CSV builder
├── build_all.py # one-shot pipeline runner (fork→svg→check→csv)
├── HANDOFF.md # this file
└── boards/
├── preview-34.html # grid viewer of all 34 SVGs
├── manifest_34.csv # board-level SKU+name+path table
├── magento_import_34.csv # full Magento product rows
└── NN-<key>/
├── autophi-pcie5-<key>.kicad_pcb
└── preview.svg
Memory
The user's durable-memory note at
C:\Users\Administrator\.claude\projects\D--special-35-autophi-quantum-pcie5\memory\feedback_consult_rag_each_step.md
says: review the RAG at every step, not just generation. Before making
changes to any of the stages above, read the relevant
autophi_engine/rag/*.py file first.
Integration parts — “today” PCs vs “tomorrow” servers
Integration parts — “today” PCs vs “tomorrow” servers
Canonical narrative: D:\special\18-autophi-future · Engineering + RAG: D:\special\35-autophi-quantum-pcie5 · This tree: D:\special\39-autophi-pcie5.
This document names what must exist on the card and what the host must provide so the accelerator integrates into real machines—not only a schematic fantasy.
Sourcing policy: AutoPhi Quantum (U1) is the only custom / non–catalog silicon you own; every other line item is chosen from commercial vendors (TI where the reference design calls for it—e.g. DS80PCI810—plus DRAM, connectors, passives, PMICs, etc. from their normal supply chains and MPNs).
A. On-card silicon & companions (from 35 / ARCHITECTURE.md)
Machine-readable rows: integration_parts_today_tomorrow.json (same folder).
B. “Today” — typical workstation / white-box PC
Host must have
- [ ] Open PCIe ×16 slot (electrical + mechanical: full-height vs low-profile matches bracket).
- [ ] Enough continuous +12 V / +3.3 V / +3.3 V AUX headroom for your power map (see board power nets in schematic).
- [ ] Air path: case fans or GPU-style shroud if TDP is not trivial.
- [ ] OS + driver path: if you expose standard PCIe class devices, plan signed driver or inbox class; if custom, plan attestation story.
You ship / certify
- [ ] One bracket + faceplate variant that matches retail PCs.
- [ ] Thermal interface spec (max °C at case inlet, throttle policy if any).
- [ ] Labeling + regulatory bucket (FCC/CE as applicable).
C. “Tomorrow” — rack servers / data-center hosts
Host must have
- [ ] Same electrical lane budget (or deliberate bifurcation / retimer path if you split the link).
- [ ] Cooling: front-to-rear airflow, inlet temperature class, N+1 fan policy if required.
- [ ] BMC / inventory: FRU EEPROM or SMBus plan if operators must discover the card without opening the chassis.
- [ ] Security: firmware update channel, secure boot interaction if you have option ROM or management endpoint.
You ship / certify
- [ ] Server-grade bracket / EMI finger stock if the variant needs it.
- [ ] Vibration and shock notes for heavy heatsinks or optical modules.
- [ ] Multi-tenant story: noisy neighbour on the same PCIe root complex (QoS, SR-IOV only if you actually implement it).
D. Next concrete engineering steps (repo)
1. Bind U1 to a real part number or FPGA + carrier plan—until then, “integration” stops at retimer+DDR+edge.
2. Pull MPNs for passives / PMICs from board_inventory.json into the JSON (or a generated BOM CSV from KiCad).
3. Re-run Update PCB from Schematic after any GND / MH fixes so host-side DRC matches reality.
4. Align stackup in KiCad with ARCHITECTURE.md (10-layer vs 18-layer: pick one truth per product generation).
This file is meant to evolve. When U1 is frozen, add a row in the JSON with mpn, manufacturer, and lifecycle.
KiCad Plugin -- AutoPhi Router
KiCad Plugin -- AutoPhi Router
7 action plugins for KiCad 10.0 that bring AutoPhi routing tools into the editor.
Source (repo): blueprints/kicad_plugin/autophi_router/__init__.py
Install: copy that autophi_router folder to
Documents/KiCad/10.0/scripting/plugins/autophi_router/
Plugin Actions
1. AutoPhi: Route Board
Opens a dialog with routing settings:
Currently delegates to external python blueprints/auto_route.py for the full
routing run. The dialog logs settings and provides a launch point.
If Route Board “does nothing” or never finishes: KiCad’s sys.executable is
often kicad.exe, not Python. The plugin now starts python from your PATH
(Windows: also tries the py -3 launcher) so auto_route.py actually runs.
To force an interpreter, set the environment variable AUTOPHI_PYTHON to
the full path of python.exe (e.g. a venv: D:\…\project\.venv\Scripts\python.exe).
You must be able to run python blueprints\auto_route.py from a terminal in
the repository root with that same Python (imports autophi_engine).
A separate console may open on Windows so you can see router output; when it
exits, reload the .kicad_pcb in Pcbnew (file was overwritten on disk).
2. AutoPhi: Via Cascade
Implemented in the plugin (not stub): for each via, measures distance
from the via position to the nearest anchor footprint in this set:
U1, U2–U5, U8, U63–U66, J1. Then sets the via layer pair (F.Cu to inner,
or F.Cu to B.Cu) as follows.
If you pre-select vias, only the selection is updated; otherwise every via
on the board is updated. Microvias are skipped. The CLI router still
applies its own row-to-layer policy during auto_route.py; this action is
for interactive post-adjustment in Pcbnew. Ensure blind/buried vias are
allowed in Board Setup for inner layer spans, or the engine may not apply
all pairs; failed counts are shown in the dialog.
3. AutoPhi: DRC Check
Basic post-route clearance verification:
- Via-to-via center distance check
- Min clearance: 0.09 mm (JLCPCB 6L)
- Caps at 1,000 violations for performance
- Reports total violation count
4. AutoPhi: Smart Place
Moves small bypass caps near their connected IC power pins:
- Targets: C_0201, C_0402, C_0805, R_0402, R_0805
- Finds the IC pad connected to each passive via shared net
- Places passive 2.0mm from the IC pad
- All placed components stay within the board boundary
5. AutoPhi: Unroute All
Strips all tracks and vias from the board. Reports counts removed.
Use before a full re-route.
6. AutoPhi: Party Grid Place
Fast placement helper after a messy netlist / import (many footprints stacked at
the board origin, hard to see, “no airwires” confusion):
Sorts by reference (C2 before C10). Does not add footprints missing from the PCB;
fix the schematic / Update PCB from schematic first, then use this to unstack what
landed on the board.
7. AutoPhi: Fancy Silk Outline
Adds a halo (duplicate PCB_TEXT strokes) around board-level silk text on
F.SilkS / B.SilkS, rotated with the original lettering so the outline tracks
rotated labels. Optional: turn on KiCad silk knockout for footprint
Reference/Value when those fields sit on silk (improves contrast on soldermask).
Dialog controls: outline offset (mm), 8- or 16-way ring, extra halo stroke width,
and the knockout checkbox. Uses pcbnew.COMMIT when available so a single Undo
reverts the halo pass.
Installation
1. Copy the folder blueprints/kicad_plugin/autophi_router/ into the KiCad
scripting plugins directory (so __init__.py ends up at):
C:\Users\<user>\Documents\KiCad\10.0\scripting\plugins\autophi_router\__init__.py
2. Restart KiCad
3. Plugins appear under Tools > External Plugins > AutoPhi Router
4. Or use the toolbar buttons (if show_toolbar_button = True)
KiCad 10 API Notes
- Via type constant changed: code uses try/except for
VIATYPE_THROUGH->VIA_THROUGHfallback pcbnew.FromMM()/pcbnew.ToMM()for coordinate conversionpcbnew.VECTOR2I()for position settingpcbnew.Refresh()after board modifications
Relationship to CLI Scripts
The plugin provides quick access to individual tools. For production routing
of all 34 board variants, use the CLI pipeline:
python blueprints/auto_route.py "board.kicad_pcb" --grid 0.12 --timeout 15
Manufacturing Specification
Manufacturing Specification
> Target fab: JLCPCB | 10-layer | 1.6mm | ENIG finish
Target Fab Houses
10-Layer Stackup
Material: Megtron 6 (Dk=3.15, Df=0.002) with HVLP2 copper foil.
Total thickness: 1.6 mm (standard JLCPCB).
Design Rules
Impedance Targets
JLCPCB controlled impedance is free on multilayer boards (tick-box enable).
Via Policy
Layer-specific vias: Standard through-drill at JLCPCB, but KiCad's (layers "X" "Y")
directive means the via only connects the specified layers. No HDI process needed.
Surface Finish
ENIG (Electroless Nickel Immersion Gold) -- required for BGA pads at 1.0mm pitch.
Board Boundary
All traces, vias, and components must stay within the Edge.Cuts board outline.
The router rasterizes the outline and marks all cells outside as OUTSIDE (blocked).
Mounting holes (MH1-MH6) have 3mm keepout zones on all layers.
Assembly Notes
Known Constraints
- No blind/buried vias (JLCPCB standard process) -- use layer-specific through-vias instead
- Max hole aspect ratio 10:1 (1.6mm board -> 0.16mm min drill, we use 0.20mm)
- BGA requires ENIG finish (HASL/OSP not flat enough for 1.0mm pitch)
- All components and traces must remain within board outline boundaries
- No traces under mounting holes (3mm keepout radius on all layers)
Blueprints -- Pipeline Scripts
Blueprints -- Pipeline Scripts
33 Python scripts (~14,000 lines) that transform the TI TIDA-00423 reference design
into 34 routed AutoPhi PCIe 5.0 product variants.
One-Command Build
python blueprints/build_all.py
This runs all 5 stages: fork -> place -> route -> DRC -> export.
Pipeline Stages
Stage 0: Schematic Stage 1: Fork Stage 2: Place
generate_schematic.py fork_ti_board.py place_passives_clustered.py
skidl_autophi_v3.py ti_net_mapping.py resolve_collisions.py
generate_pcb.py snap_passives.py
| | |
v v v
.kicad_sch 34x .kicad_pcb Caps wrapped around ICs
+ netlist (one per variant) Collisions resolved
|
v
Stage 3: Route Stage 4: Verify
auto_route.py drc_check.py
propagate_routes.py
| |
v v
Routed .kicad_pcb Violation report
+ route cache
|
v
Stage 5: Export
render_board_svg.py -> SVG previews
build_magento_34_boards.py -> Magento CSV
domino_pipeline.py -> Product packaging
Command Cheatsheet
# Route a board (preserves existing wires) python blueprints/auto_route.py "boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb" \ --exclude-refs J2,J3,J4 --grid 0.12 --timeout 15 # Unwire and reroute from scratch python blueprints/auto_route.py "boards/01-.../....kicad_pcb" --unwire # DRC check python blueprints/drc_check.py "boards/01-.../....kicad_pcb" # Render SVG preview python blueprints/render_board_svg.py "boards/01-.../....kicad_pcb" # Place passives around ICs python blueprints/place_passives_clustered.py "boards/01-.../....kicad_pcb" # Resolve component collisions python blueprints/resolve_collisions.py "boards/01-.../....kicad_pcb" # Export to Specctra DSN (for Freerouting interop) python blueprints/kicad_to_dsn.py "boards/01-.../....kicad_pcb" --exclude-refs J2,J3,J4 # Build all 34 variants python blueprints/build_all.py # Regenerate schematic set with large-BGA override (U16 -> BGA1536) python blueprints/extract_board_netlist.py python blueprints/generate_schematic.py \ --bga-pinmap "d:\special\40-autophi-bga\pinmaps\AUTOPHI_BGA1536_pinmap_working.csv" \ --bga-ref "U16" \ --bga-value "AUTOPHI_BGA1536" \ --bga-footprint "AutoPhi:BGA-1536_95x90mm_P2.0mm" # Propagate core routes to all variants python blueprints/propagate_routes.py # Generate Magento import CSV python blueprints/build_magento_34_boards.py
Script Reference
Core Pipeline
Placement
Routing Support
Netlist and Schematic
Output and Export
Utilities
Board Variant Directory
See VARIANTS.md for the full 34-board catalog.
blueprints/boards/ 01-qsfp28-optical/ -- Primary development board 02-sfp-optical/ ... 34-audio-trs/ magento_import_34.csv -- Magento product import manifest_34.csv -- Variant manifest preview-34.html -- 34-board grid viewer interactive_editor.html -- Web-based layout editor
Routing Technique Documentation
- ROUTING_PROCESS.md -- Pipeline overview
- ROUTING_RECURRING_PROCESS.md -- Repeatable mission loop and runbook
- ROUTING_DRC_MECHANISM.md -- DRC-safe mechanism (8 failure iterations)
- ROUTING_TECHNIQUE_DIFF_PAIR.md -- P+N differential pair routing
- ROUTING_TECHNIQUE_ROW_LAYER_FANOUT.md -- BGA row-to-layer
- ROUTING_TECHNIQUE_CACHED_INCREMENTAL.md -- Cache + incremental
- ROUTING_TECHNIQUE_TARGET_FIRST.md -- Target-first routing
- ROUTING_TECHNIQUE_CONGESTION_HEATMAP.md -- Congestion analysis
Other Documentation
- MANUFACTURING.md -- JLCPCB fab specifications
- KICAD_PLUGIN.md -- KiCad action plugin guide
- SCHEMATIC_PROCESS.md -- Schematic generation pipeline
- rag-pcb-knowledge-base.md -- Full RAG citation index
- HANDOFF.md -- Pipeline handoff guide
AutoPhi Routing Checkpoint — v7 (Dual-Stripline 6L)
AutoPhi Routing Checkpoint — v7 (Dual-Stripline 6L)
Date: 2026-04-09
Branch state: working tree, not committed yet
Current focus: custom RAG-grounded A* router for the 34-board TIDA-00423 fork
TL;DR
We built our own PCB autorouter from scratch this session. Lives at:
blueprints/auto_route.py— the router (A* grid maze, ~460 lines)autophi_engine/rag/routing.py— the routing RAG / knowledge base (~660 lines,
22 citations, 19 net classes, JLCPCB-grounded)
blueprints/kicad_to_dsn.py— Specctra.dsnexporter (kept for future
Freerouting / TopoR / Allegro interop)
blueprints/ses_to_kicad.py— Specctra.ses→.kicad_pcbmerger (same)blueprints/render_board_svg.py— SVG renderer updated to draw segments + vias
on 4 signal layers, color-coded per layer
Why custom: Freerouting choked on our board's density even after multiple
retries, DeepPCB.ai stalled at validation, TopoR Lite is effectively unobtainable
in 2026. Writing our own maze router gave us deterministic control over every
trade-off we hit.
Router evolution (this session)
Architecture decisions
1. RAG-grounded, citation-heavy
Every routing parameter is read from autophi_engine/rag/routing.py which
cites its sources inline. The router echoes the citations it relies on at
startup (see main() banner in auto_route.py). Current citations include:
- [1]–[14] — general high-speed PCB routing guides (Sierra, Altium,
Eremex, Wikipedia, Quilter.ai, NXP, Toradex)
- [15]–[18] — Advanced PCB routing/trace-width/schematic guidance
- [19] — Howard Johnson, "High-Speed Digital Design: Black Magic"
- [20] — Zhang/Krooswyk/Ou, "High-Speed Digital Design"
- [21] — JLCPCB published capabilities
- [22] — Schemalyzer third-party JLCPCB design rules summary
The CITATIONS dict in routing.py maps short tags → quoted rules so the
router can log "I consulted X because Y" without hardcoding the guidance.
2. Net classes + priority order
19 net classes, each with its own track width / clearance / diff gap / skew
budgets / via-count limits / A* cost weights. Examples:
pcie_diff: 127 um trace, 127 um clearance, 5 mil skew, max 4 TX / 2 RX viasddr_strobe: 152 um trace, 90 um clearance, 5 mil intra-pair skewddr_data: 152 um trace, 90 um clearance, 20 mil byte-lane skewio_ingress: 152 um trace, 90 um clearance, 100 mil loose skewjtag/spi/i2c/uart: 200 um trace, 90 um clearance, loosethermal_hv: 500 um trace (TEC current), 300 um clearance
Nets are routed in priority order (PCIe diff first, DDR next, control last).
3. A* grid router
- Sparse dict-based grid:
{(cx, cy, layer): reason_string} - State key:
(cell_x, cell_y, layer)— no direction (see v3 fix) - 8-connected: 0°/45°/90° moves (per
R.ANY_ANGLE["allow_45"]) - Cost model per class:
straight: 1turn: 2–3 (cheap)via: 4–20 (depends on class)- Layer transitions: via = jump to any other signal layer at the same XY,
pay via cost. Current stackup: 4 routable signal layers.
- Per-net timeout: 5s
- Net chaining: pad0 → nearest already-routed point → next pad (greedy
chaining, not full MST)
4. JLCPCB fab-grounded constraints
Everything is sized to JLCPCB 6-layer standard (no upcharge):
(Agent is fetching the rest in the background.)
5. Dual-stripline 6-layer stackup (v7)
L1 F.Cu signal (microstrip, ref'd to L2 GND) <- routable L2 In1.Cu GND (continuous reference plane) <- not routable L3 In2.Cu signal (stripline, ref'd to L2 GND above) <- routable L4 In3.Cu signal (stripline, ref'd to L5 GND below) <- routable L5 In4.Cu GND (continuous reference plane) <- not routable L6 B.Cu signal (microstrip, ref'd to L5 GND) <- routable
4 routable signal layers, 2 dedicated GND reference planes, 0 dedicated power
planes (power comes off F/B pours with stitched short inner islands).
6. Real Edge.Cuts boundary rasterization
The router scanline-rasterizes the real TI card outline polygon into the grid
and marks every cell OUTSIDE the polygon as blocked. Routes stay inside the
actual board shape instead of leaking into a padded bounding rectangle.
Fixed one upstream bug along the way: fork_ti_board.py's flatten_top_edge
was stripping body-wall segments that straddled body_top_y=-51.44 instead
of truncating them at that y, leaving the body with no left/right walls.
Now splits at the boundary cleanly.
7. DRC clearance
- Pad halo:
clearance_mm=0.09(JLCPCB min spacing) — every non-own-net
pad is inflated by 0.09 mm in all directions before marking cells blocked.
Own-net pads are relaxed via is_blocked() reason-string parsing so the
router can start / end inside its own pads.
- Trace-to-trace: currently only the path cells themselves are marked,
so different-net traces may sit in adjacent grid cells. This is a known
DRC gap — fixing it requires either a finer grid with neighbour marking
or a 2-cell halo, both of which were tried earlier and hurt capacity too
much. Deferred; to be post-processed with a cleanup pass in KiCad.
Current working state (as of v7 launch)
- Router is running on board 01 (
01-qsfp28-optical) in the background - Research agent is running to pull exhaustive JLCPCB capabilities into
the RAG
- Last successfully-written
.kicad_pcbon disk = v4 state
(213/291 routed, 6,520 segs, 4,879 vias, pad halo clean, H/V only, 2 layers)
- SVG renderer updated to draw F.Cu / In2.Cu / In3.Cu / B.Cu in distinct colors
render_board_svg.pynow parses(segment ...)and(via ...)sexprs and
draws them as solid traces; ratsnest is suppressed for routed nets
Open issues
1. Trace-to-trace DRC gap — deferred, see §7
2. BGA fanout — no dedicated BGA breakout pattern; A* just routes from
ball center. The RAG has a BGA_FANOUT dict (dogbone, via-in-pad rules)
but the router doesn't consume it yet
3. Length matching — per-class skew budgets are in the RAG but the
router doesn't enforce them (treats nets independently)
4. Differential pair coupling — pairs are routed as two independent nets
5. Via stitching — no ground-stitching vias along high-speed traces yet
6. Power pour regeneration — the original build_zones_ti pours assumed
L3/L4 were power planes; with the new dual-stripline stackup those layers
are signal. Pours need to be regenerated accordingly before fab
Scripts / file map (this checkpoint)
blueprints/ ├── auto_route.py # v7 A* grid maze router ├── kicad_to_dsn.py # Specctra .dsn exporter (working) ├── ses_to_kicad.py # Specctra .ses → .kicad_pcb merger (working) ├── render_board_svg.py # SVG renderer (updated for 4 signal layers) ├── fork_ti_board.py # forker (flatten_top_edge bug fixed) ├── build_all.py # pipeline runner ├── HANDOFF.md # original layout decisions ├── SCHEMATIC_PROCESS.md # schematic pipeline docs ├── ROUTING_PROCESS.md # r10 (MST) routing docs -- stale ├── MANUFACTURING.md # Advanced Circuits spec └── ROUTING_CHECKPOINT_v7.md # you are here autophi_engine/rag/ └── routing.py # routing RAG, 22 citations, JLCPCB-grounded
How to resume
cd D:/special/35-autophi-quantum-pcie5
# 1. Run the v7 router on any board
python -u blueprints/auto_route.py \
blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb \
--exclude-refs J2,J3,J4 --grid 0.1 --timeout 5
# 2. Regenerate the SVG after routing
python -c "
import sys; sys.path.insert(0, 'blueprints')
from render_board_svg import render
render('blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb',
'blueprints/boards/01-qsfp28-optical/preview.svg')
"
# 3. Open the routed board in KiCad 10
"C:/Program Files/KiCad/10.0/bin/pcbnew.exe" \
blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb
# 4. Export Specctra DSN from KiCad for Freerouting / TopoR / Allegro
# (manual step: File -> Export -> Specctra DSN)
Next steps (in order)
1. Finish v7 run, regenerate SVG, visual review
2. Integrate JLCPCB agent's exhaustive spec sheet into routing.py
3. Propagate board 01's routed core to all 34 variants (placement is
identical across variants, only J2/J3/J4 differ, so the routed segments
are directly copy-pastable)
4. Per-variant J2/J3/J4 stub routing pass (short hops from core to
bracket connectors)
5. Regenerate zone pours to match the dual-stripline stackup
6. Open every board in KiCad, run Tools → Cleanup Tracks & Vias, export
Specctra SES for a Freerouting re-pass if desired
7. Build manifest / Magento CSV / preview HTML via build_all.py rerouting
around the routed boards (skip stage_fork which would overwrite)
AutoPhi DRC-Safe Routing Mechanism
AutoPhi DRC-Safe Routing Mechanism
> Last verified: 2026-04-12 | Current violations: ~348 | See ../STATUS.md
Problem Statement
PCB traces must not short-circuit. This means:
1. No two traces from different nets on the same layer may touch
2. Minimum edge-to-edge clearance between traces (JLCPCB 6L: 0.09mm)
3. Minimum via-to-via clearance (JLCPCB 4L+: 0.127mm pad-to-pad)
4. Minimum via-to-trace clearance
What Failed (and why)
Attempt 1: Grid-only A* (no halo)
- A* marks exact cells along routed path as occupied
- Next net checks if cell is blocked before entering
- Problem: Adjacent cells are only 1 grid step apart (0.15mm). Two traces
on adjacent cells have edge-to-edge clearance of only 0.15 - 0.127 = 0.023mm,
far below the 0.09mm JLCPCB minimum.
- Result: 76,643 DRC violations
Attempt 2: Grid A* with clearance halo (stale cache)
- Added trace halo: after routing each net, block cells within radius
ceil((trace_width/2 + min_clearance) / grid_mm) around every path cell
- Problem: Route cache (
shared_core.json) held paths from pre-halo runs.
Cache replays bypassed halo marking entirely.
- Result: 57,659 violations (cache replays = no halos)
Attempt 3: Fixed cache replay halo
- Updated
_mark_cached_path()to apply same halo as fresh routes - Problem: Still using stale cache FILE from wrong directory
(blueprints/boards/.../shared_core.json vs blueprints/route_cache/shared_core.json)
- Result: 35,940 violations (partial cache contamination)
Attempt 4: Correct cache deletion + halo
- Deleted the REAL cache at
blueprints/route_cache/shared_core.json - All routes freshly computed with halos
- Problem: theta* post-processing and TI-style chamfering moved traces
OFF the grid after A* found them. Off-grid positions violated clearance.
- Result: 16,672 violations
Attempt 5: Disabled post-processing, fresh routes
- Disabled
theta_star_smooth()andti_style_postprocess() - Traces stay exactly on grid points
- Problem: Diagonal moves (45-degree) create line segments that pass
between grid cells. Two diagonal segments on adjacent cells can cross
in the inter-cell space even though their grid cells are separated.
- Result: 10,333 violations
Attempt 6: Orthogonal-only routing (CURRENT)
- Disabled diagonal moves (
allow_diag = False) - All traces are horizontal or vertical only
- With orthogonal routing, grid distance == geometric distance
- Halo of N cells guarantees N * grid_mm clearance (no diagonal shortcuts)
- Expected result: 0 trace-to-trace violations
The Working Mechanism
Grid Construction
1. Quantize board area to cells of size grid_mm (default 0.15mm)
2. Rasterize board outline (Edge.Cuts polygon) -- cells outside = blocked
3. Block all pad locations with clearance halos
Clearance Halo Formula
trace_halo_cells = max(1, ceil((trace_width/2 + min_clearance) / grid_mm)) via_halo_cells = ceil((via_pad/2 + via_clearance) / grid_mm)
For PCIe 0.127mm traces on 0.15mm grid: halo = 2 cells
Minimum center-to-center distance: (2+1+2) * 0.15 = 0.75mm >> 0.217mm required
A* Pathfinding
- 4-connected (orthogonal only) -- no diagonal moves
- Checks
is_blocked(cx, cy, layer)before entering any cell - Own-net cells are traversable (for multi-pad daisy chain)
- Via cost penalty discourages unnecessary layer changes
Post-Route Marking (critical for DRC)
After each net is routed:
1. For every cell along the path, block a disc of radius trace_halo_cells
on that layer, tagged with NET:<netname>
2. At each via (layer change), block a disc of radius via_halo_cells
on ALL signal layers
3. Save path to cache WITH the halo radius metadata
Cache Replay
Cached paths are validated before replay:
1. Check every cell along the cached path is still reachable
2. Apply the SAME halo marking as fresh routes
3. Cache invalidated if grid size or layer stackup changed
Verification
Post-route DRC sweep (drc_check.py):
1. Trace-to-trace: geometric segment distance vs (w1+w2)/2 + clearance
2. Via-to-via: center distance vs (size1+size2)/2 + clearance
3. Via-to-trace: point-to-segment distance vs via_r + trace_w/2 + clearance
Key Lessons
1. Grid halos only guarantee clearance for orthogonal traces
2. Post-processing must not move traces off-grid (or must re-verify DRC)
3. Cache must be invalidated when halo logic changes
4. DRC check must run after EVERY routing change -- the router can't self-certify
5. Document each failed approach -- it prevents revisiting dead ends
AutoPhi PCB Routing Pipeline
AutoPhi PCB Routing Pipeline
How the router gets from bare pad positions to 3,400+ trace segments across
5 signal layers. Read this when returning to the project after a break.
> Current status: 347/417 nets (83.2%). See ../STATUS.md.
TL;DR Command Cheatsheet
cd D:\special\35-autophi-quantum-pcie5 # Route board 01 (preserves existing wires) python blueprints/auto_route.py "blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb" \ --exclude-refs J2,J3,J4 --grid 0.12 --timeout 15 # Unwire and reroute from scratch python blueprints/auto_route.py "blueprints/boards/01-.../....kicad_pcb" --unwire # DRC check after routing python blueprints/drc_check.py "blueprints/boards/01-.../....kicad_pcb" # Render SVG preview python blueprints/render_board_svg.py "blueprints/boards/01-.../....kicad_pcb"
Router Algorithm: A* Grid Maze
The core router (auto_route.py, 1,749 lines) uses A* pathfinding on a rasterized
grid. Every decision is grounded in the RAG knowledge base (autophi_engine/rag/routing.py).
Pipeline Flow
.kicad_pcb
|
v
1. Parse footprints, pads, existing nets
|
v
2. Build obstacle grid (0.12mm cells, 1642x602)
- Mark every non-target pad as blocked
- Mark mounting hole keepouts (3mm radius, all layers)
- Rasterize board outline (Edge.Cuts) -> mark OUTSIDE cells
|
v
3. Load route cache (shared_core.json)
- Cache hit: replay path, mark halos, skip A*
- Cache miss: fall through to A*
|
v
4. Per-net A* routing (sorted by RAG priority)
For each net (PCIe diff first, power last):
a. Chain pads via A* (pad0 -> pad1 -> pad2 -> ...)
b. compress_path() -> segments + vias
c. Mark trace halos on grid (DRC-safe clearance)
d. If diff-pair: route N partner immediately after P
e. Save to cache
|
v
5. Retry pass (failed nets, randomized pad order)
- 4 random orderings x 5 layers = up to 20 attempts per net
- Layer-series fallback: try assigned layer, then cycle all 5
|
v
6. Congestion analysis: top-10 hotspot cells with blocker IDs
|
v
7. GND via stitching (5.0mm grid across board)
|
v
8. Write .kicad_pcb (strip old traces, insert new segments + vias)
Cost Model
Via span scaling: Short-hop vias (e.g., F.Cu <-> In2.Cu, span=2) cost 60% of
full-span vias (F.Cu <-> B.Cu, span=9). This encourages the router to use nearby
layers rather than punching through the entire stackup. Citation: [50]
Grid Configuration
Routing Techniques
Each technique is documented separately:
Net Priority Order
The RAG defines 18 net classes routed in this order (lowest priority number first):
0: pcie_diff -- PCIe Gen5 differential pairs (32 GT/s, 85 ohm) 1: refclk -- PCIe reference clock 2: ddr_strobe -- DDR DQS strobes 3: ddr_clock -- DDR CK reference 4: ddr_data -- DDR DQ byte lanes 5: ddr_addr -- DDR address/command 6: ddr_ctrl -- DDR control (CAS/RAS/WE) 7: io_ingress -- SmartNIC offload bus 8: pcie_sb -- PCIe sideband + straps 9: strap -- DS80PCI810 config straps 10: jtag -- JTAG debug 11: spi -- SPI flash + config 12: i2c -- I2C sideband 13: uart -- UART console 14: sdio -- SD card bus 15: thermal_hv -- TEC + LED high-current 16: analog -- Current sense + thermistors 17: usb_pd -- USB-PD CC lines 100: default -- Everything else
Output Files
Related Documents
- ../STATUS.md -- Current routing metrics
- ../ARCHITECTURE.md -- System architecture
- README.md -- Script reference and command guide
QSFP28 Recurring Routing Process
QSFP28 Recurring Routing Process
This is the repeatable mission loop for 01-qsfp28-optical.
Use this runbook every session so routing, cleanup, and DRC converge instead of drifting.
Scope
- Canonical board:
blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb - Canonical project:
blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pro - Acceptance gate: KiCad 10 DRC JSON + in-editor DRC, not
drc_check.pyalone
Session Rules
- Never route from stale copies; always use the canonical board path.
- Keep non-core artifacts in
blueprints/boards/01-qsfp28-optical/_trash_unincluded/. - Run routing with
--no-drc, then run KiCad DRC as a separate deterministic step. - If retry hangs on one net, kill it and continue with per-net retries (hard timeout).
Standard Loop
0) Preflight
Set-Location "D:\special\39-autophi-quantum-pcie5-standard"
Confirm KiCad CLI is available:
& "C:\Program Files\KiCad\10.0\bin\kicad-cli.exe" --version
1) Main Route Pass
python -u blueprints/auto_route.py ` "blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb" ` --grid 0.12 --timeout 20 --checkpoint-before-retry --verbose-retry --no-drc
Expected artifacts:
blueprints/boards/01-qsfp28-optical/route_failures_main_pass.txt- updated
.kicad_pcbwith checkpointed copper
2) Retry Pass (Batch)
python -u blueprints/auto_route.py ` "blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb" ` --retry-only ` --failures-file "blueprints/boards/01-qsfp28-optical/route_failures_main_pass.txt" ` --grid 0.12 --timeout 12 --verbose-retry --no-drc
If batch retry stalls on one net, switch to per-net retries.
3) Retry Pass (Per-Net Hard Timeout)
Use one-net subprocess retries with a hard kill timeout (120s per net) and keep advancing.
Output files to keep:
retry_one_by_one.logretry_one_by_one_recovered.txtretry_one_by_one_stuck.txt
Then build a reduced failures list from stuck nets and continue next session.
4) Geometry Cleanup Pass
Remove obvious synthetic debris before DRC:
- duplicate vias
- zero-length segments
- duplicate segments
Then sanity-parse:
python -c "import sexpdata; p='blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb'; sexpdata.loads(open(p,encoding='utf-8').read()); print('OK')"
5) KiCad DRC Baseline
& "C:\Program Files\KiCad\10.0\bin\kicad-cli.exe" pcb drc ` --format json ` --output "blueprints/boards/01-qsfp28-optical/kicad_drc_qsfp28.json" ` "blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb"
Summarize:
python -u blueprints/autophi_drc_report.py ` "blueprints/boards/01-qsfp28-optical/kicad_drc_qsfp28.json" ` -o "blueprints/boards/01-qsfp28-optical"
6) Targeted Fix Buckets
Fix in this order:
1. shorting_items (must be zero)
2. unconnected_items (must trend down every run)
3. clearance
4. geometry/rule noise (track_width, via_diameter, drill)
5. cosmetic warnings (silk_edge_clearance, text_height)
6b) Electrical-Only Three-Stage Loop (Copy/Paste Template)
Use this when you want deterministic "true electrical error" work and no
scope drift.
Stage 1: Hole-clearance (simple gate pass)
- Keep geometry intact, remove hole-clearance from error gating for this loop:
- In
.kicad_proset"hole_clearance": "ignore" - Run error-only DRC snapshot:
& "C:\Program Files\KiCad\10.0\bin\kicad-cli.exe" pcb drc ` --severity-error ` --format json ` --output "blueprints/boards/01-qsfp28-optical/kicad_drc_qsfp28_errors_stage1_hole.json" ` "blueprints/boards/01-qsfp28-optical/autophi-pcie5-qsfp28-optical.kicad_pcb"
Stage 2: Shorting-focused retries
1) Build a net list from shorting_items top offenders.
2) Retry one net at a time with hard timeout.
3) Repair router writeback syntax before DRC:
- keep only one root
(embedded_fonts no) - convert routing
(net N "NAME")to(net N)onsegment/via/arc/zone
4) Re-run error-only DRC snapshot.
Stage 3: Clearance-focused retries
1) Build a net list from clearance top offenders.
2) Retry one net at a time with hard timeout.
3) Run geometry artifact cleanup:
- duplicate vias
- duplicate segments
- zero-length segments
4) Re-run error-only DRC snapshot.
Rules for this 3-stage loop
- Never skip the syntax repair after retry-only writes.
- Keep immutable snapshots per stage:
...errors_stage1_hole.json...errors_stage2_shorting.json...errors_stage3_clearance.json- If a stage regresses totals, keep the best snapshot and continue from that file.
7) Power Rail Verification
Every loop, verify rails are still active and not regressed:
+12V,12V,+3V3,3_3V- check token presence in
.kicad_pcb - check DRC entries for opens/shorts on those rails
Definition of Done (per milestone)
- Board opens in KiCad 10 without parse errors.
- DRC report exists and is timestamped for the run.
shorting_items= 0.unconnected_itemsreduced vs previous checkpoint.STATUS.mdupdated with:- routed/failed counts
- DRC totals by major type
- known stuck nets list
Naming Convention for Run Artifacts
Use immutable snapshots per run:
kicad_drc_qsfp28_<run-id>.jsonkicad_drc_qsfp28_<run-id>_autophi_drc.summary.jsonkicad_drc_qsfp28_<run-id>_autophi_drc.report.txt
<run-id> example: 2026-04-21-pass2
Operator Notes
- Multiple GND layers are valid and not a parser failure cause.
- KiCad parser errors near a
(zone ... (net ...))line are often syntax-shape issues, not that net itself. - Keep this process strict and mechanical; avoid ad-hoc edits outside the loop.
This archive contains 23 documents; 13 more beyond this preview. The complete folder ships as the product.