π§ v0.19.0 β the 0.18.5 lane-discipline misstep, fixed (plus fractional track margins, impedance neck-down & keep-out-aware planes) #476
drandyhaas
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Hey everyone! π
v0.19.0 is out β and it opens with an apology-shaped bugfix. 0.18.5 shipped a default we got wrong, and this release corrects it, then stacks a round of routing- and grading-quality improvements on top. Mea culpa first, then the new stuff.
π¦ How to get it: download KiCadRoutingTools-0.19.0.zip from the Releases page, then in KiCad open Plugin and Content Manager β Install from Fileβ¦ and pick that zip. Prebuilt router binaries for Linux/macOS/Windows are attached β
python build_router.pyfetches them automatically, no Rust toolchain needed.Remember 0.18.5's honesty section β "some boards now run ~1.5β3Γ longer" and "one net on one keyboard board still resists us"? Those weren't isolated quirks. They were the visible tip of a default we'd set far too aggressively.
0.18.5 bumped the direction-preference cost β the knob that nudges each layer toward horizontal-or-vertical "lanes," for that clean human-routed look β from 50 to 5000, a 100Γ jump. On open boards it produced gorgeous lanes. On dense boards it was a wall: a 5000Γ penalty on any off-axis move makes the short diagonal hops that diode/matrix nets need to weave between pads effectively unroutable, and the A* then burns its entire iteration budget failing them.
A full sets 6β11 A/B (real open-source boards) put numbers on it:
kbic65) collapsed from 98.9% β 15.1% routed.route.pyran ~2Γ slower β grinding the full 2 M-iteration budget on nets it could no longer route.0.19.0 dials the default back to 250 (~25% of a move) β enough to keep a real H/V lane nudge, without the cost-5000 wall. We confirmed it by isolating the single knob at fixed engine:
kbic65recovers 43/35 β 87/1 routed,bread_dcmotor23/11 β 36/0, and the ~2Γ slowdown vanishes. If you routed a dense board on 0.18.5 and saw nets fail that shouldn't have β that was this. Re-route on 0.19.0.β¨ Then, the new stuff
π― Fractional per-layer track margins (Rust 0.19.0, #156). The router's swept-capsule blocked-check now takes a fractional margin β grid cells as a float, per destination layer β instead of an integer Chebyshev margin, and Python computes it as the exact extra half-width over a single stamp-side source of truth, so obstacle stamps and the margins that check them can't drift apart. Power and impedance widths flow through one unified path, and the new "phase-exact" margin kills sub-cell grazes the old ceil-and-round missed (a 77 Β΅m graze on
berkeleyIn2 that needed margin 1.0 where the bare math gave 0.988).π Impedance neck-down (#465, env-gated, default on). An impedance-controlled net whose full-width route fails can now step down toward its nominal track width to complete β the same "connectivity over strict width" ladder power nets already use β necking near pads while keeping the wide impedance section wherever it fits.
berkeley_obsidianDDR3 at--impedance 40went from 70 clearance / 23 shorts β 8 / 0, all 44 nets connected. SetKICAD_IMPEDANCE_NECKDOWN=0to restore strict-impedance-or-fail.ποΈ Keep-out-aware plane fill (#477 + #478). KiCad's filler subtracts
(copperpour not_allowed)rule areas from zone fill, splitting a plane into real islands β and our fill model was blind to them. Onmokya, antenna/xtal keep-outs cut the In1 GND plane into pieces the model graded as one, and 3 of KiCad's 6 GND opens were invisible to our own connectivity checker. Now the fill model blocks copperpour-banned cells, so those splits surface as real islands the repair pass can join. #478 goes a level deeper: footprint-owned zones (KiCad 7+) were invisible to the text parser entirely β and 95 of 406 corpus boards carry them, almost always as copperpour keep-outs (includingcastor_pollux, the original #217 oracle problem board). Both fixes flow to the GUI for free β same shared extractor and fill model.Full commit-level detail in the v0.18.5β¦v0.19.0 compare and the Rust changelog in
rust_router/README.md.Bug reports and feedback hugely welcome β open an issue or reply here. Happy routing! π
π The original v0.18.5 announcement (kept for the record)
Hey everyone! π
New release β v0.18.5. If 0.18.3 was about making the DRC trustworthy, 0.18.5 is about making the connectivity trustworthy β and then using that truth to finish boards. The headline: our hardest benchmark board, a 4-layer BGA audio SoC design that has resisted every release since this project started, now routes to 100% connectivity with zero DRC violations β graded by KiCad itself, not by us β from a fully scripted 11-minute chain. This announcement is the story of how chasing that one board uncovered (and fixed) a stack of bugs that turned out to affect the whole corpus.
π¦ How to get it: download KiCadRoutingTools-0.18.5.zip from the Releases page, then in KiCad open Plugin and Content Manager β Install from Fileβ¦ and pick that zip. Prebuilt router binaries for Linux/macOS/Windows are attached β
python build_router.pyfetches them automatically, no Rust toolchain needed.π΅οΈ The plot: our grader said 1 unconnected. KiCad said 8.
Mid-push, with the benchmark board at what we believed was a record "1 unconnected net," KiCad's own DRC reported 8. The seven extras were all power-plane balls under the BGA whose fanout vias our checker credited as plane-connected β and KiCad didn't. Chasing that disagreement found three nested problems, each hiding the next:
2Γzone-clearance + min-fill-widthof gap to pass between obstacles. Our pours were being written with a fixed 0.2 mm clearance default while the whole board routed at 0.1 mm β so no gap anywhere in a 0.65 mm BGA via field was passable, and every interior plane via sat in a tiny fill island that KiCad prunes as isolated. Every chain, all along.β What 0.18.5 does about it: graders you can trust
--zone-clearancestill overrides), auto-stepping toward the fab floor when a dense BGA field it must serve can't be threaded β with a warning either way. On the benchmark this single change took the true unconnected count from 8 to 2.kicad_unconnected.pyoracle wrapskicad-cli pcb drc --refill-zonesso stress grading reports KiCad's authoritative count next to ours. On the corpus the two now agree.π Rescues that actually stick
The last-chance per-net rescue pass got three fixes, one of which is embarrassing in hindsight:
ποΈ Plane repair that sees islands
The plane-repair step's region joiner discovered regions with a coarse 0.5 mm flood fill β which pours straight through a sub-cell pinch, merging a stranded island into the main region so no join is ever attempted. The joiner now gates its floods with the fill model's components: islands appear as real regions and get routed connections (tracks/vias), not just tap attempts. On one FPGA corpus board this found and joined 56 genuinely pinched islands β with KiCad DRC still reporting a perfect 0 afterward.
βοΈ Seam dissolution: routes stopped shipping their scaffolding
A routed net is often a composition β a main edge routed early plus taps welded on later, or a diff pair assembled from escape legs and a coupled middle β and each piece was optimal against a board that no longer exists by the time the net completes. 0.18.5 re-asks the whole connection with one A* right when it completes, against the current board, and keeps the better answer (strictly-better, connectivity-verified, length-match groups exempt):
π Bus routing, rebuilt (Rust 0.18.4/0.18.5)
The bus machinery from 0.18.3 grew up: strict geometric bus detection (parallel cones, comparable lengths, no power nets β 31 sloppy groups became 6 real ones on the benchmark), laminar corridor planning (the corridor probe pays a steep via price, so the planned lane stays on one layer or the group is demoted to plain nets), corridor-span main-edge selection for multipoint members, and a direction-gated multiplicative attraction discount in the Rust router that can't zero out a step cost. Members hug their lane; defectors pay.
π Chains that stay consistent
<output>_planes.jsonsidecar declaring which nets they own; later route/fanout steps auto-exclude those nets from wildcard selection (naming one verbatim still includes it β that's the override). No more accidentally fanning out or signal-routing a net whose plane hasn't poured yet.KICAD_STOP_AFTER=bus,KICAD_STOP_CLEANUP=1) and a per-net story JSON (KICAD_NET_STORY=1: every rip, retry, blocker, and rescue per net) for debugging the journey, not just the destination.π The receipts
Corpus A/B against the 0.18.3-era baselines, zero DRC regressions anywhere, KiCad's own DRC agreeing:
Honesty section, as always: some boards now run ~1.5β3Γ longer β that's the router attempting work it used to silently skip (truthful gates, island joins, whole-net re-asks). A couple of experimental levers ship opt-in because they graded neutral-or-negative overall despite spectacular individual wins:
KICAD_FANOUT_DIRECT=1(skip fanout stubs for surface-reachable balls β it routed the benchmark's USB pair at 10.7 mm beating the 11.6 mm human reference, but reshuffled the rest of the board) andKICAD_FANOUT_TOWARD_TARGETS=1(aim escape stubs at their targets). And one net on one keyboard board still resists us. We know where it lives.Full commit-level detail in the compare view and the Rust changelog in
rust_router/README.md.Bug reports and feedback hugely welcome β open an issue or reply here. Happy routing! π
All reactions