The project's README from github.com/parisxmas/fastroute. As one markdown file: README.md.
PCB autorouter for KiCad and Specctra DSN — a Rust port of the Freerouting PCB autorouter. (Not related to the FastRoute global router for IC design used in OpenROAD.)
Same algorithms, same input/output (Specctra .dsn → .ses), same
command line — without Java, several times faster and with a fraction of the memory.
--parity) produces SES output byte-identical to Freerouting's
deterministic mode (source commit aa909a3, single-threaded optimizer, count-based
time limits) on all 20 benchmark boards.--live): watch the board being routed in your browser.integrations/kicad.The bug fixes and routing improvements are on by default; --no-enhancements switches them
off (the DSN parser fixes stay), --parity gives byte-identical Freerouting results. The new
features are used when asked for (an option, or a rule in the KiCad board). Details,
measurements and the reasoning for each change: docs/IMPROVEMENTS.md.
| Freerouting behaviour | fastroute |
|---|---|
| The optimizer never runs after the autorouter stopped itself: the stop request stays set, so every optimizer candidate fails to route | The router's own stop is withdrawn before the optimizer |
| When the stagnation rule stops the autorouter, the final tail removal is skipped and unused fanout escapes (via + stub) stay on the board | Tails are removed in every case |
| The optimizer's score is clamped at 0; on boards whose score is below 0 (e.g. DAC2020_bm01) no candidate can ever be accepted | Unclamped scores are compared (bm01: −182 → 107) |
| A connection that ends in a via into its net's plane layer is rejected ("layers disabled"), so plane nets only reach the plane through fanout | Such connections are accepted |
ignore_net_classes is honoured by the autorouter but not by the fanout, which still adds stubs to the ignored nets |
No fanout on ignored classes |
| A failing connection rips its whole net on every failure from the second on; unroutable connections make large nets (GND, 3V3) oscillate | Only once per net |
| Class-pair clearances from the DSN only reach the clearance classes named after the net classes, not the pin/SMD classes of the same nets | Applied to all item classes of both net classes |
| Nets with a pad on or outside the board edge (edge connectors, castellated pads, headers across Edge.Cuts) ignore the outline completely, so their traces can run outside the board anywhere | The area outside the outline is a keepout except right around those pads |
| DSN lexer: non-ASCII letters dropped from names, desynchronisation on some quoted strings, a pin token swallowing a character of the next pin | Parsed correctly |
router.autorouter.max_threads) and a parallel
optimizer, deterministic for a given thread count.--multi-start): if connections stay unrouted, the autorouter is
rerun with shuffled orders in parallel and the best result is kept.router.min_trace_width_um).--max-time, Ctrl+C / SIGTERM stop the run and keep the result.Live routing view (--live[=PORT], a checkbox in the KiCad plugin): a local page at
http://127.0.0.1:7878 shows the board as it is routed — traces appearing and being ripped
up, the remaining airlines, progress of each pass, unrouted connections per pass, clearance
violations, score and the log — with zoom, layer toggles, net highlighting and a Stop
button that keeps the best result. Served by fastroute itself (no internet needed);
results are the same with or without it.

Length matching (--tune): groups of nets (buses, pair skew) are matched with
meanders after routing; every meander is clearance-checked, via heights count as in KiCad.
Controlled impedance: trace widths per layer from the board stackup (microstrip,
stripline, differential), no neck-down for those classes (--no-neckdown-classes).
Differential pairs (--pairs): pairs are routed first with the second net following
the first at the pair gap, held while the rest of the board is routed; afterwards the
shorter net gets meanders until the two lengths match (--pair-skew, default 0.1 mm).
The plugin (integrations/kicad) exports the board, fills
the gaps of KiCad's Specctra export and imports the result:
.kicad_dru rules are carried over: class clearances, per-layer track widths, length and
skew rules, differential pair gaps; minimum track width and copper-to-edge clearance too.impedance_cli.py computes controlled-impedance widths and writes the DRC rules.cargo build --release -p fastroute # or scripts/build-pgo.sh (~15 % faster)
target/release/fastroute -de board.dsn -do board.ses
The session file (-do) is rewritten with the best board so far whenever routing or
optimizing improves, so a run that is stopped or killed still leaves its best result.
Ctrl+C, SIGTERM and Ctrl+Break stop the run and write the best result (a second signal exits
at once). fastroute --help lists the options and the common --router.* settings.
Windows x64 build (cross-compiled with MinGW-w64): scripts/build-windows.sh →
dist/windows/fastroute.exe. Linux x64 and arm64 builds (cargo-zigbuild, glibc 2.17):
scripts/build-linux.sh → dist/linux-*/fastroute. The KiCad package can bundle several
platforms: integrations/kicad/package.sh --bin <macos binary> macos-arm64 --bin dist/windows/fastroute.exe windows-x64 --bin dist/linux-x64/fastroute linux-x64 ....
Freerouting's options are accepted: -mp <passes>, --router.<path>=<value> (e.g.
--router.optimizer.enabled=false, --router.scoring.via_costs=80); GUI/API options such
as --gui.enabled are ignored. fastroute adds:
| Option | Meaning |
|---|---|
--parity |
Exact Freerouting results: java-compatible optimizer, count-based time limits |
--optimizer-mode=java-compat|parallel |
Optimizer strategy (default: parallel if more than one thread) |
--time-limit-mode=wall|count|disabled, --time-limit-factor=N |
How Freerouting's internal time limits are evaluated |
--router.min_trace_width_um=<w> |
Never neck traces down below this width |
--multi-start=N |
Rerun the autorouter with N−1 shuffled orders in parallel if connections remain unrouted (default 4) |
--no-enhancements |
Freerouting's behaviour without fastroute's routing/optimizer improvements (see docs/IMPROVEMENTS.md) |
--router.autorouter.max_threads=N |
Threads of the parallel autorouting pass (default: all cores; 1 = sequential pass) |
--tune=FILE |
Length matching after routing: groups of nets matched with meanders (see fastroute --help) |
--layer-heights=MM,.. |
Height of each copper layer (stackup), so that vias count in length matching |
--pairs=FILE |
Differential pairs: routed first, the second net following the first at the pair gap |
--no-neckdown-classes=A,B |
Keep the full trace width of these classes at pins (controlled impedance) |
--max-time=SECONDS |
Stop after this time and write the best result so far |
--router.autorouter.min_passes=N |
The stagnation rules do not stop the autorouter before N passes (for long runs bounded by --max-time) |
--initial-session=FILE |
Start from the wiring of a session file (e.g. a checkpoint of an earlier run) and continue routing and optimizing it |
--live[=PORT] |
Watch the routing live in the web browser (http://127.0.0.1:7878 by default, opened automatically): traces and airlines as they change, pass progress, unrouted connections per pass, log, and a Stop button. Results are unaffected |
--report=FILE |
Write a JSON summary: statistics, timings, every unrouted connection and clearance violation |
--diagnose |
With --report: route each unrouted connection alone on the loaded board, classifying it as congestion (other traces in the way) or blocked (geometry or rules) |
-V, --version |
Print the version |
-v |
Verbose progress |
Full pipeline (autorouter + optimizer), exact mode, 20 benchmark boards (docs/PERFORMANCE.md):
| Freerouting (Java) | fastroute | fastroute + PGO | |
|---|---|---|---|
| Sum of 20 boards | 2102 s | 510 s | 420 s |
| DAC2020_bm01 | 960 s | 380 s | 310 s |
| CM5_MINIMA_3 | 410 s | 23 s | 20 s |
| Peak memory (typical) | 1–2 GB | 20–300 MB |
The parallel optimizer mode is another 1.5–3× faster on most boards.
| Crate | Contents |
|---|---|
fr-dsn |
Specctra S-expression reader and typed DSN model |
fr-geom |
Planar geometry (port of geometry.planar) |
fr-jcompat |
Bit-exact emulation of the Java library behaviour the router depends on |
fr-settings |
Router settings, defaults, CLI/DSN settings sources |
fr-engine |
Board model, search trees, autorouter, pull-tight/shove/optimizer, DRC, scoring, pipeline |
fr-io |
DSN → board loader, post-load processing, SES writer/reader |
fastroute |
Command-line tool |
How the port was done and how parity is tested: docs/PORTING.md.
The Java reference build and scripts: scripts/java-parity.sh, scripts/parity-route.sh.
fastroute is developed in spare time. If it saves you routing hours or a Java setup, you can
support its development through GitHub Sponsors or
Open Collective. Bug reports with a board that shows
the problem (a .dsn file is enough) are just as welcome.
GPL-3.0-or-later (LICENSE). fastroute is a derivative work of Freerouting (GPL-3.0); all credit for the routing algorithms goes to the Freerouting authors. See NOTICE for the attribution, the Freerouting version it is based on, and the third-party crates.