Skip to content

drandyhaas/KiCadRoutingTools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,113 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

KiCadRoutingTools

KiCad Routing Tools

A fast Rust-accelerated A* autorouter for KiCad PCB files. Compatible with KiCad 9 and KiCad 10. Available as both a KiCad Plugin with full GUI and a Command-Line Interface for scripting and automation.

Routed PCB example Routed PCB example 2

Features

  • Grid-based A* pathfinding with Rust acceleration (~10x faster than Python)
  • Octilinear routing - Horizontal, vertical, and 45-degree diagonal moves
  • Multi-layer routing with automatic via insertion
  • Differential pair routing with pose-based A* and Dubins path heuristic for orientation-aware centerline routing
  • Rip-up and reroute - When routing fails, automatically rips up blocking routes and retries with progressive N+1 strategy (tries 1 blocker, then 2, up to configurable max). Re-analyzes blocking tracks after each failure for better recovery. Also triggers rip-up when quick probes detect blocking early, before attempting full routes. See Rip-Up and Reroute for details
  • Ripped route corridor avoidance - When a net is ripped up, soft penalties are applied to its former corridor. This encourages the current route to avoid that area, increasing the chance the ripped net can be successfully re-routed later.
  • Blocking analysis - Shows which previously-routed nets are blocking when routes fail
  • Stub layer switching - Optimization that moves stubs to different layers to avoid vias when source/target are on different layers. Works for both differential pairs and single-ended nets. Finds compatible swap pairs (two nets that can exchange layers to help each other) or moves stubs solo when safe. Tries multiple swap options (source/source, target/target, source/target, target/source) to find valid combinations. Validates that stub endpoints won't be too close to other stubs on the destination layer.
  • Batch routing with incremental obstacle caching (~7x speedup)
  • Net ordering strategies - MPS (crossing conflicts with diff pairs treated as units, shorter routes first using BGA-aware distance; uses segment intersection with MST for non-BGA boards), inside-out (BGA), or original order
  • MPS layer swap - When MPS detects crossing conflicts (nets in Round 2+), attempts layer swaps to eliminate same-layer crossings. Tries swapping both the conflicting Round 2 unit and Round 1 unit. Re-runs MPS after swaps to verify conflict resolution
  • Board edge clearance - Tracks and vias respect Edge.Cuts boundaries including curved edges (gr_arc), non-rectangular outlines, and interior cutouts. Arcs are automatically linearized into polylines for accurate clearance checking
  • Keep-out rule areas - Tracks and/or vias respect KiCad keep-out zones (rule areas with (keepout (tracks not_allowed) (vias not_allowed) ...)), blocking only the disallowed item on the keepout's listed layers (or all routing layers if none are listed). Track/via copper is kept clear of the boundary by the configured clearance, e.g. an antenna-flange RF exclusion
  • BGA exclusion zones - Auto-detected from footprints, prevents vias under BGAs
  • Stub proximity avoidance - Penalizes routes near unrouted stubs, with direction-aware costs (moving away from stubs costs less)
  • BGA proximity avoidance - Penalizes routes near BGA edges, with direction-aware costs (moving away from BGA zones costs less)
  • Track proximity avoidance - Penalizes routes near previously routed tracks on the same layer, encouraging spread-out routing
  • Vertical track alignment - Attracts tracks on different layers to stack vertically (on top of each other), consolidating routing corridors and leaving more room for through-hole vias
  • Adaptive setback angles - Evaluates 9 setback angles (0°, ±max/4, ±max/2, ±3max/4, ±max) and selects the one that maximizes separation from neighboring stub endpoints, improving routing success when stubs are tightly spaced. Uses 0° when clearance to the nearest stub is sufficient (≥2× spacing), only angling away when stubs are too close
  • U-turn prevention - Prevents differential pair routes from making U-turns (>180° cumulative turn)
  • GND via placement - Automatically places GND vias adjacent to differential pair signal vias for return current paths. The Rust router checks clearance and determines optimal placement (ahead or behind signal vias)
  • Automatic polarity resolution - Detects when differential pair P/N polarity differs between source and target pads and resolves it by swapping target pad net assignments and/or routing the connectors out the opposite side at one end (bare-pad endpoints only); when both mechanisms can route, the shorter result wins. Swaps are applied consistently in the output file (CLI), the live board (plugin), and in-memory state. Use --no-fix-polarity to forbid pad swaps (default in the plugin GUI) - the pair is then skipped with a warning if no opposite-side route exists; crossing tracks are never written
  • Bare-pad differential pairs - Routes diff pairs directly between SMD pads with no fanout stubs (e.g., SOIC pins, termination resistors). The escape direction is derived from the pad geometry (perpendicular to the pad axis, away from the component body), and the pair's own pads are treated as obstacles outside the pad-entry corridors so the P/N tracks cannot cross the partner polarity's pad
  • Multi-point differential pairs - Pairs with 3+ pad-pair terminals (e.g., connector → termination → IC) are routed as a chain of legs passing "through" each terminal: a continuation leg leaves on the opposite side from the leg that arrived, since a pair cannot tap mid-track without P/N crossing. Alternative chain orderings are tried automatically if one fails
  • Electrically-short legs route single-ended - A coupled diff pair only earns its keep over an electrically long run. A leg shorter than ~5× the connector setback (measured by the shorter of its P/N runs) has no real coupled section — only fan-in/out — and forcing a coupled pair through clustered connector pads just tangles and shorts it. Such legs are deferred to single-ended: a 2-terminal pair is left whole for the single-ended pass, while a multi-point pair couples its long legs and defers only its short ones. The deferred nets are reported in the JSON summary (single_ended_diff_pairs, single_ended_followup_nets); the plan-pcb-routing workflow finishes them with a single-ended pass. That follow-up must use the same track width / via size as the coupled pass — mismatched widths between coupled and single-ended copper would themselves cause clearance errors (physics rule of thumb: even a 10 GHz / 10 Gb/s edge is electrically short over only ~1–3 mm, so a few-mm connector fan-in never needs coupling)
  • Target swap optimization - For swappable nets (e.g., memory lanes), uses Hungarian algorithm to find optimal source-to-target assignments that minimize crossings. Works for both differential pairs and single-ended nets
  • Schematic synchronization - When --schematic-dir is specified, updates KiCad schematic files with any pad swaps (target swaps or polarity swaps) to keep schematics in sync with PCB. Handles multi-unit symbols correctly by updating all schematic files containing the lib_symbol. Disabled by default
  • Chip boundary crossing detection - Uses chip boundary "unrolling" to accurately detect route crossings for MPS ordering and target swap optimization
  • Turn cost penalty - Penalizes direction changes during routing to encourage straighter paths with fewer wiggles
  • Bus routing - Automatically detects groups of nets with clustered endpoints (buses) and routes them together. Uses direction-based attraction so each net follows its neighbor's path in parallel, creating clean parallel traces. Routes from the middle of the bus outward, alternating sides. Enable with --bus flag. Configurable detection radius, attraction radius, and attraction bonus. See Bus Routing for details
  • Guide corridor (preferred route) - Draw a polyline on a User layer (e.g. User.1) in KiCad and the selected nets are routed to follow it as waypoints — source → along your drawn path → target — getting as close to the line as obstacles allow. For multi-point nets each waypoint steers the nearest segment of the net's existing MST, so endpoints/topology are untouched. It's strictly best-effort: a waypoint it can't follow on the current layer is skipped (so a guide never makes a route fail or adds vias the direct route wouldn't need), and multiple nets following the same corridor pack alongside without overlapping. Enable with --guide-corridor (CLI) or the "Follow User-layer guide path" checkbox (plugin); configurable layer and waypoint spacing. See Guide Corridor Options for details
  • Keepout zones - Draw one or more closed polygons on a User layer (e.g. User.2) in KiCad and routed tracks (and vias) are kept out of those areas on every copper layer. It's a hard keepout that applies across single-ended, multipoint, and differential-pair routing, plus plane via-stitching and plane repair — useful for reserving analog regions, antenna clearances, or mechanical exclusions. Enable with --keepout (route.py / route_diff.py) or the "Keep out of User-layer polygon(s)" checkbox (plugin); configurable layer. (Don't draw a zone over a pad you need to route.)
  • Length matching - Adds trombone-style meanders to match route lengths within groups (e.g., DDR4 byte lanes). Auto-groups DQ/DQS nets by byte lane. Per-bump clearance checking with automatic amplitude reduction to avoid conflicts with other traces. Supports multi-layer routes with vias. Calculates via barrel length from board stackup for accurate length matching that matches KiCad's measurements. Includes stub via barrel lengths (BGA pad vias) using actual stub-layer-to-pad-layer distance. See Length Matching for details
  • Time matching - Alternative to length matching that matches propagation delay instead of physical length. Accounts for different signal speeds on outer layers (microstrip, faster) vs inner layers (stripline, slower) using effective dielectric constants from the board stackup. Use --time-matching to enable. Tolerance specified in picoseconds. See Length Matching for details
  • Multi-point routing - Routes nets with 3+ pads using an MST-based 3-phase approach: (1) compute MST between all pads and route the longest edge, (2) apply length matching, (3) route remaining MST edges in length order (longest first). This ensures length-matched routes are clean 2-point paths while connecting all pads optimally
  • Impedance-controlled routing - Specify target impedance (e.g., 50Ω single-ended, 100Ω differential) and track widths are automatically calculated per layer from the board stackup. Uses IPC-2141 formulas for microstrip (outer layers) and stripline (inner layers). Widths adjust automatically when switching layers via vias to maintain target impedance
  • Power net routing - Route power nets (GND, VCC, etc.) with wider tracks than signal nets. Specify patterns and corresponding widths (e.g., --power-nets "*GND*" "*VCC*" --power-nets-widths 0.4 0.5). First matching pattern determines width for each net. Obstacle clearances automatically adjust for wider power traces. Power net widths are never smaller than the base track width
  • Power route neck-down - When a wide power route cannot fit (e.g. escaping a fine-pitch pad), it is automatically retried at the layer's default track width: narrow within --neckdown-length (default 2.5mm) of the pads, returning to the power width beyond that wherever clearance allows, with a stepped width taper at each transition (--neckdown-taper-length, default 0.5mm). Disable with --no-power-tap-neckdown
  • Net class support - The KiCad plugin reads net class parameters (track width, via size, clearance) from the board and uses them automatically. Nets can be organized by net class in separate tabs for easier selection. When routing nets from different classes, obstacle clearances properly account for the larger clearance requirements (e.g., routing "Wide" class nets with 0.4mm clearance near "Default" class pads)
  • AI-powered power net analysis - Use the /analyze-power-nets skill to identify power nets and recommend track widths. The skill uses WebSearch to look up component datasheets, classifies components by their role (power source, current sink, pass-through, shunt), traces current paths, and generates ready-to-use --power-nets configurations. See Power Net Analysis for details
  • Power/ground plane via connections - Automatically places vias to connect SMD pads to inner-layer copper planes. Supports multiple nets in one run (e.g., GND and VCC planes). Smart via placement tries pad center first (or, with --same-net-pad-clearance >= 0, forces vias outside same-net pads with the given edge-to-edge clearance), then spirals outward with A* routing to pads. Optional blocker rip-up removes interfering nets to maximize via placement, with automatic re-routing of ripped nets
  • Multi-net plane layers - Multiple power nets can share a single copper layer using Voronoi partitioning. Each net's vias get their own non-overlapping zone polygon. MST-based routing connects all vias of each net, with routes sampled as additional Voronoi seeds to ensure connected zones. Retries with net reordering when edges fail to route. Displays plane resistance and max current capacity (IPC-2152) for each polygon
  • Disconnected plane region repair - After power planes are created, regions may be effectively split due to vias and traces from other nets cutting through the plane. The route_disconnected_planes.py script detects disconnected regions and routes wide, short tracks between them to ensure electrical continuity. It also runs a pad-level repair: a plane-net pad with no connection to its plane gets a via dropped (or a trace to a nearby same-net via). A pad too small to drop a via in (e.g. a tiny USB-connector GND pin on the outer layer) is connected by a trace to an adjacent same-net pad — the human's connector-pin-to-shield strategy. With --rip-blocker-nets (--max-rip-nets), a signal net blocking that trace is ripped, the pad connected, and the ripped net re-routed (--reroute-ripped-nets) with the original signal parameters (--power-nets/--power-nets-widths/--no-bga-zone), restoring any net that can't re-route rather than leaving it disconnected. Exposed in the plugin's Planes "repair" tab ("Rip up blocking nets" / "Auto-reroute ripped nets")
  • GND return via placement - Automatically places GND vias near signal vias for return current paths. Searches from minimum viable distance outward (24 angles, fine step), placing GND vias as close as possible while respecting track clearances. Through-hole GND pads count as existing return paths. Use --add-gnd-vias with route_planes.py
  • Post-route copper cleanup - After routing settles, the output is reconciled to the actual board so it can never contain copper that was ripped off and not restored - including a different-net via that another net legitimately took while this net was ripped (an un-manufacturable drill-on-drill short). A whole-net dead-end sweep then trims dangling stubs left by rip-and-reroute and unused fanout/escape tails (tap tails, superseded spurs), and a per-commit prune keeps a route's own dead copper from blocking later routes. Every removal is gated against the connectivity model, so it never trims copper that carries a pad (plane landings, sole paths, T-junction taps are kept). Conversely, where a route stopped a fraction of a track width short of its same-net pad/via/trace, a short connector is added to physically close the gap (when it clears other nets, including not entering another net's copper pour), so the copper actually touches instead of relying on a connectivity tolerance to bridge it. The same sweep + gap-snap also runs on the plane tools' output (route_planes.py, route_disconnected_planes.py), so plane copper gets cleaned too. check_orphan_stubs.py reports what genuinely remains
  • Real-time visualization - Watch the A* search explore the grid live with the optional PyGame visualizer (route.py --visualize), with pause/step, zoom/pan, per-layer filtering, and speed control
  • AI-assisted routing from the plugin (Claude tab) - The plugin GUI drives Claude Code headless: a Claude tab generates a full routing plan (/plan-pcb-routing) that fills the dialog's parameters and executes as a checkable step list in-process on the live board, plus one-click reviews and per-field "Ask Claude" buttons on the Basic/Differential/Planes tabs (power nets, diff pairs, plane mappings, GND via distance, stackup). See Claude Skills - Plugin GUI Integration
  • AI-powered high-speed net analysis - Use the /find-high-speed-nets skill to identify which nets carry high-speed signals. Looks up component datasheets via WebSearch to find max interface frequencies and rise times, traces signals through series passives, and recommends --gnd-via-distance values based on the fastest signals on the board. See Claude Skills and the GND return via distance guidance in the planes documentation

Quick Start

1. Get the Code

# Clone with git
git clone https://github.com/drandyhaas/KiCadRoutingTools.git
cd KiCadRoutingTools

Or download the ZIP and extract it.

2. Install the Rust Router

python build_router.py

By default this downloads a prebuilt binary for your OS from the project's GitHub Releasesno Rust toolchain required. Prebuilts are published for:

  • Linux x86_64
  • macOS arm64 (Apple Silicon)
  • macOS x86_64 (Intel)
  • Windows x86_64

If a prebuilt isn't available for your platform (e.g. Linux arm64) or the download fails, the script falls back to building locally with cargo.

Building from source (optional)

If you'd rather build locally — or you're on a platform without a prebuilt — install Rust from rustup.rs:

# macOS / Linux
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Windows: Download and run rustup-init.exe from https://rustup.rs/

After installation, restart your terminal or run source ~/.cargo/env, then:

python build_router.py --from-source     # build locally instead of downloading
python build_router.py --tag v0.15.0     # download a specific release
python build_router.py --clean           # remove all build artifacts

3. Choose Your Interface

Option A: KiCad Plugin (Recommended for interactive use)

# Install the plugin
python install_plugin.py

# Then in KiCad: Tools → External Plugins → KiCadRoutingTools

Option B: Claude Code (AI-assisted routing)

Use Claude Code to analyze your PCB and generate a routing plan:

> /plan-pcb-routing kicad_files/my_board.kicad_pcb

Claude will:

  • Analyze your board structure and identify components needing fanout (BGA/QFN/PGA)
  • Detect differential pairs and DDR signals requiring length matching
  • Identify power/ground nets and recommend plane vs trace routing
  • Assess signal speeds and recommend GND return via placement
  • Generate a step-by-step routing plan with explanations
  • Run the commands and verify results

Other useful skills:

> /find-high-speed-nets kicad_files/my_board.kicad_pcb       # Identify high-speed nets via datasheet lookup
> /analyze-power-nets kicad_files/my_board.kicad_pcb         # Identify power nets and track widths
> /identify-diff-pairs kicad_files/my_board.kicad_pcb        # Find diff pairs by pin function, recommend gap/impedance
> /recommend-stackup kicad_files/my_board.kicad_pcb          # Stackup advice for impedance/time-matching accuracy
> /diagnose-routing-failures my_board.kicad_pcb /tmp/route_output.txt  # Root-cause failed routes, get a retry command
> /review-routed-board my_board_routed.kicad_pcb             # Post-route QA: DRC, connectivity, length match, GND vias

See Claude Skills for what each skill does and how they fit together.

All of these are also available inside KiCad without leaving the plugin - see AI assistance in the plugin below.

Option C: Manual Command Line (For scripting and automation)

# Optionally optimize an existing placement for routability (before routing)
python place_optimize.py my_board.kicad_pcb --max-displacement 3

# Fan out a BGA, then tidy decoupling caps off the new vias (issue #130)
python bga_fanout.py my_board.kicad_pcb -c U1 -o fanned.kicad_pcb --clearance 0.1
python place_fanout_clearance.py fanned.kicad_pcb capclean.kicad_pcb --clearance 0.1

# Route all nets
python route.py my_board.kicad_pcb

# Route differential pairs
python route_diff.py my_board.kicad_pcb --nets "*lvds*"

# Create power planes
python route_planes.py my_board.kicad_pcb --nets GND --plane-layers B.Cu

KiCad Plugin

The plugin provides a full graphical interface for all routing features, running directly within KiCad 9 or 10.

KiCad Plugin GUI

AI assistance (Claude tab)

Claude tab: planned steps, controls, and live transcript

With Claude Code installed, the routing dialog gains AI assistance throughout (the plugin spawns claude headless, streams a live transcript, and fills GUI controls from the results):

  • Claude tab - Plan Routing runs /plan-pcb-routing: the plan fills the parameter fields across the tabs and appears as a checkable step list, which Run Selected Steps executes sequentially in-process on the live board with per-step status marks. Review Routed Board and Diagnose Routing Failures give post-route QA and failure root-causing. Model and effort dropdowns control every AI run and persist with the dialog settings.
  • Per-field "Ask Claude" buttons - power nets/widths (Basic tab), stackup check (Layers), differential-pair verification by pin function (Differential tab), net-to-plane layer mappings and GND return via distance (Planes tab).

The full button-to-skill map is in Claude Skills - Plugin GUI Integration. Datasheet-based skills use web lookups and take a few minutes; every run shows a live transcript with cancel.

Installation

Three ways to install:

A. KiCad Plugin and Content Manager (PCM) — the recommended path for end users. Open the PCM from the KiCad main window, find KiCad Routing Tools, and click Install. (The package is in the process of being added to the official repository; once accepted, this will be available out-of-the-box.) On first launch, the plugin checks the Python packages listed in requirements.txt (currently scipy and shapely — KiCad already bundles numpy) and offers a one-click pip install for any that are missing into KiCad's Python.

B. PCM "Install from File…" using the release zip — works today, before the package lands in the official repository. Each GitHub Release ships a ready-to-install PCM package zip named KiCadRoutingTools-<version>.zip (a single cross-platform archive bundling the prebuilt Rust binaries for all platforms — not the auto-generated "Source code (zip)"). To install it:

  1. From the Release's Assets, download KiCadRoutingTools-<version>.zip (e.g. KiCadRoutingTools-0.15.13.zip).
  2. In KiCad, open Plugin and Content Manager from the main window.
  3. Click Install from File… (bottom of the PCM dialog) and select the downloaded zip.
  4. Click Apply Pending Changes, then restart KiCad if prompted.

The plugin appears under Tools → External Plugins in the PCB Editor. The same first-launch scipy/shapely dependency check described in (A) applies. This path keeps the plugin manageable from the PCM (you can update or uninstall it there), unlike the manual install below.

C. Manual install from source — for development or for using the CLI tools as well:

# Install the plugin (copies to KiCad plugins directory)
python install_plugin.py

# For development: create symlink instead of copying
python install_plugin.py --symlink

# Remove the plugin
python install_plugin.py --uninstall

The installer automatically detects your KiCad installation directory (supports KiCad 9.0 and 10.0):

  • macOS: ~/Documents/KiCad/<version>/3rdparty/plugins/
  • Linux: ~/.local/share/kicad/<version>/3rdparty/plugins/
  • Windows: ~/Documents/KiCad/<version>/3rdparty/plugins/

If you previously installed this plugin through the Plugin & Content Manager, that copy sits next to the local install and would shadow it on sys.path (causing stale-code errors). The installer detects any such PCM copy and moves it aside to <kicad-base>/disabled_pcm_plugins/<version>/, leaving it recoverable. Pass --keep-pcm to skip this.

Releasing a new version (maintainers)

The full release flow — version bump, GitHub Release, and the merge request to the official KiCad PCM repository — is documented step by step in docs/release-pipeline.md.

Short version:

  1. Bump VERSION and the versions[] entry in metadata.json.
  2. git tag v0.15.6 && git push --tags — CI builds all 4 platform binaries, packages a single KiCadRoutingTools-<ver>.zip (the PCM validator rejects duplicate version strings, so we ship one cross-platform zip), patches metadata.json with real sha256/size values, and attaches everything to the GitHub Release.
  3. Append the new version to the metadata file in your fork of gitlab.com/kicad/addons/metadata and open an MR. See the docs page for the exact commands.

To build a zip locally for testing:

python package_pcm.py --binary-dir ./path/to/release/artifacts

Usage

  1. Open KiCad (9.0 or later)
  2. Open a PCB in Pcbnew
  3. (Optional) Select one or more nets in the PCB editor first — for example by clicking tracks/pads, or right-clicking a track and choosing Select → All Tracks in Net. Any nets you have selected are automatically pre-checked for routing when the plugin opens.
  4. Go to Tools → External Plugins → KiCadRoutingTools
  5. Configure routing parameters and select (or adjust) the nets to route
  6. Click Route to run the router

Plugin Tabs

Basic Tab:

  • Net selection with filtering and component filtering
  • Nets selected in the PCB editor before opening the plugin are pre-checked automatically (also applies to the Fanout, Planes, and Differential tabs)
  • Option to separate nets by net class (organizes into tabs per class)
  • Track width, clearance, via size/drill from net class or manual override
  • Layer selection with per-layer cost multipliers
  • Options: stub layer swaps, copper text moving, teardrops, power net widths, no-BGA zones
  • Guide corridor - draw a polyline on a User layer (e.g. User.1) and tick "Follow User-layer guide path" to route the selected nets along it (waypoints, avoiding obstacles, packed non-overlapping)
  • Keepout zones - draw one or more closed polygons on a User layer (e.g. User.2) and tick "Keep out of User-layer polygon(s)" to keep routed tracks out of those areas (hard keepout, all routed nets)
  • Clear guide/keepout layers - optional "Clear guide layer after routing" / "Clear keepout layer after routing" checkboxes (unchecked by default) delete the drawn guide/keepout graphics from their User layer after a successful route, so you can draw fresh ones for the next run

Advanced Tab:

  • Swappable nets configuration for target swap optimization
  • Routing parameters: iterations, heuristic weight, rip-up, probe iterations
  • MPS ordering options, direction control, length matching
  • Proximity settings: BGA, stub, track, via proximity costs
  • Debug options

Differential Tab:

  • Differential pair selection with filtering
  • Pair gap, turning radius, setback angle configuration
  • Options: polarity fix, GND vias, intra-pair length matching

Fanout Tab:

  • BGA fanout with exit margin, escape direction, differential pair support
  • Under-pad escape option for dense, fully-populated BGAs the channel router can't escape (issue #122) — see BGA Fanout
  • "Optimize decoupling cap placement" option (off by default) — after fanout, nudges decoupling caps off foreign-net fanout vias and toward same-net balls (issue #130) — see Placement
  • QFN fanout with extension length configuration
  • Net selection for fanout operations

Planes Tab:

  • Net-to-layer assignment for power/ground planes
  • Create planes with via connections to SMD pads
  • Repair disconnected plane regions
  • GND return via placement near signal vias
  • Via size/drill, track width, clearance configuration

Log Tab:

  • Real-time routing output display
  • Color-coded messages (errors, warnings, success)

About Tab:

  • Version information and credits

General Features:

  • Settings persistence (parameters and selections preserved between sessions)
  • Cancel button to stop routing operations mid-progress
  • Results applied directly to the open PCB in KiCad

Command-Line Interface

Net Pattern Syntax

All --nets options support fnmatch-style wildcards and exclusion patterns:

Pattern Description
* All nets
*DATA* Nets containing "DATA"
/* Nets starting with "/" (hierarchical)
Net-(U1-*) Nets matching "Net-(U1-...)"
!GND Exclude net named "GND"
!*VCC* Exclude nets containing "VCC"
"*" "!GND" "!VCC" All nets except GND and VCC

Notes:

  • Exclusion patterns (starting with !) remove matching nets from the result
  • Order matters: include patterns add nets, exclude patterns remove them
  • Nets starting with "unconnected-" are automatically excluded
  • Use quotes around patterns with special characters

Route Nets

# Route all nets (default) - outputs to input_routed.kicad_pcb
python route.py kicad_files/input.kicad_pcb

# Route all nets, overwrite input file
python route.py kicad_files/input.kicad_pcb --overwrite

# Route all nets to a specific output file
python route.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb

# Route specific nets (using --nets option)
python route.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb --nets "Net-(U2A-DATA_0)" "Net-(U2A-DATA_1)"

# Route with wildcard patterns
python route.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb --nets "Net-(U2A-DATA_*)"

# Route all nets on a component (auto-excludes GND/VCC/VDD/unconnected)
python route.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb --component U1

# Route specific patterns on a component (no auto-exclusion)
python route.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb --nets "/DDAT*" --component U1

# Route ALL nets on a component including power (use "*" pattern)
python route.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb --nets "*" --component U1

# Route all nets except GND and VCC (exclusion patterns with ! prefix)
python route.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb --nets "*" "!GND" "!VCC"

# Route differential pairs (use route_diff.py)
python route_diff.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb --nets "*lvds*" --no-bga-zones

# Route with wider tracks for power nets
python route.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb --nets "Net*" \
  --power-nets "*GND*" "*VCC*" "+3.3V" --power-nets-widths 0.4 0.5 0.3 --track-width 0.2

# Typical workflow: create GND plane first, then route all signals
python route_planes.py kicad_files/flat_hierarchy.kicad_pcb --nets GND --plane-layers B.Cu
python route.py kicad_files/flat_hierarchy_routed.kicad_pcb --overwrite

3. Create Power/Ground Planes

# Create GND zone on B.Cu with via connections to all GND pads (outputs to input_routed.kicad_pcb)
python route_planes.py kicad_files/input.kicad_pcb --nets GND --plane-layers B.Cu

# Create GND zone, overwrite input file
python route_planes.py kicad_files/input.kicad_pcb --overwrite --nets GND --plane-layers B.Cu

# Create GND zone to specific output file
python route_planes.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb --nets GND --plane-layers B.Cu

# Create multiple planes at once (each net paired with corresponding plane layer)
python route_planes.py kicad_files/input.kicad_pcb --nets GND +3.3V --plane-layers In1.Cu In2.Cu

# Create VCC plane with larger vias
python route_planes.py kicad_files/input.kicad_pcb --nets VCC --plane-layers In2.Cu --via-size 0.5 --via-drill 0.4

# Rip up blocking nets and automatically re-route them
python route_planes.py kicad_files/input.kicad_pcb --nets GND +3.3V --plane-layers In1.Cu In2.Cu --rip-blocker-nets --reroute-ripped-nets

# Multiple nets sharing same layer via Voronoi partitioning (use | separator)
python route_planes.py kicad_files/input.kicad_pcb --nets GND "VA19|VA11" --plane-layers In4.Cu In5.Cu

# Dry run to see what would be placed
python route_planes.py kicad_files/input.kicad_pcb --nets GND --plane-layers B.Cu --dry-run

3b. Repair Disconnected Plane Regions

After creating power planes, regions may become split by vias and traces from other nets. Use route_disconnected_planes.py to reconnect them:

# Auto-detect all zones in PCB and repair disconnected regions (outputs to input_routed.kicad_pcb)
python route_disconnected_planes.py kicad_files/input.kicad_pcb

# Auto-detect all zones, overwrite input
python route_disconnected_planes.py kicad_files/input.kicad_pcb --overwrite

# Auto-detect all zones to specific output file
python route_disconnected_planes.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb

# Specific nets and layers
python route_disconnected_planes.py kicad_files/input.kicad_pcb --nets GND --plane-layers B.Cu

# Customize track width and clearance
python route_disconnected_planes.py kicad_files/input.kicad_pcb kicad_files/output.kicad_pcb \
    --track-width 0.5 --clearance 0.2

4. Verify Results

# Check for DRC violations (default clearance: 0.2mm)
python check_drc.py kicad_files/output.kicad_pcb

# Cross-check with KiCad's own DRC engine (requires KiCad; --refill-zones avoids
# bogus zone-clearance errors from stale pours - see tests/README.md for details)
kicad-cli pcb drc --refill-zones --format json -o drc.json kicad_files/output.kicad_pcb

# Check connectivity (detects unrouted nets, broken routes, and T-junctions)
python check_connected.py kicad_files/output.kicad_pcb

# Check connectivity for specific nets
python check_connected.py kicad_files/output.kicad_pcb --nets "*DATA*"

# Check connectivity for all nets on a component
python check_connected.py kicad_files/output.kicad_pcb --component U1

# Only check routed nets (skip unrouted net detection)
python check_connected.py kicad_files/output.kicad_pcb --routed-only

# Check for orphan stubs (dead-end traces with no pad/via/trace at the loose end).
# Connection is judged by actual copper extent (via radius, pad size, trace
# half-width), so T-junction taps and copper-overlap joints are not miscounted.
python check_orphan_stubs.py kicad_files/output.kicad_pcb

# Pad-geometry sanity check: flags same-footprint, different-net pads whose copper
# overlaps (a short). A non-zero result almost always means a pad's rotation/size
# is modelled wrong - the usual cause is a QFN/QFP/BGA placed at a non-orthogonal
# angle. The fanout tools run this automatically on their component first; run it
# yourself before fanout (or board-wide) as a standalone check:
python check_pads.py kicad_files/board.kicad_pcb                 # whole board, per footprint
python check_pads.py kicad_files/board.kicad_pcb --component U23 # one footprint
python check_pads.py kicad_files/board.kicad_pcb --cross-footprint  # also across parts

# Flag long non-orthonormal tracks. An on-grid router emits only 0/45/90-degree
# segments; the only legitimate non-orthonormal segment is a short (<=1 grid cell)
# terminal connector to an off-grid pad/ball. Anything longer is a routing defect
# (it can cut diagonally across foreign copper). qfn_fanout escape stubs are
# excluded automatically; bga_fanout's short stub-end jogs clear the 0.25mm default.
python check_orthonormal.py kicad_files/output.kicad_pcb

5. Power Net Analysis

Use the /analyze-power-nets skill to identify power nets and get track width recommendations:

# Ask Claude to analyze your board with datasheet lookup
/analyze-power-nets kicad_files/my_board.kicad_pcb

The skill:

  1. Auto-classifies obvious components (resistors, capacitors, inductors, etc.)
  2. Uses WebSearch to look up datasheets for unknown components (ICs, connectors, transistors)
  3. Classifies each component's role (power source, current sink, pass-through, shunt)
  4. Traces power paths from sinks to sources
  5. Generates ready-to-use --power-nets configurations

See Power Net Analysis for detailed documentation.

6. High-Speed Net Analysis

Use the /find-high-speed-nets skill to identify high-speed nets and get GND return via recommendations:

# Ask Claude to analyze signal speeds with datasheet lookup
/find-high-speed-nets kicad_files/my_board.kicad_pcb

The skill:

  1. Pre-classifies nets by name patterns (DDR, USB, SPI, CLK, etc.)
  2. Pre-classifies components by footprint (FPGA, DDR, PHY, etc.)
  3. Uses WebSearch to look up datasheets for ICs and extract max clock rates and rise times
  4. Traces high-speed signals through series passives (termination resistors, AC coupling caps)
  5. Generates a speed classification (ultra-high/high/medium/low) with recommended --gnd-via-distance

The /plan-pcb-routing skill includes a lightweight version of this analysis (net name and footprint pattern matching only, no datasheet lookup) and automatically includes a GND return via step when GND planes are present. Run /find-high-speed-nets first for more accurate recommendations based on actual component specifications.

7. Integration Tests

# Run full integration test (fanout + routing + checks)
python tests/test_fanout_and_route.py --all

# Quick mode for faster testing
python tests/test_fanout_and_route.py --all --quick

See tests/README.md for detailed documentation of all test scripts.

Documentation

Document Description
Routing Architecture Module structure, obstacle maps, A* algorithm
Python API Using the modules as a library: parser, writer, modification, config, net analysis, impedance — with runnable examples
Configuration Command-line options, GridRouteConfig parameters
Differential Pairs P/N pairing, polarity swaps, via handling
Net Ordering MPS algorithm, inside-out ordering, strategy comparison
Rip-Up and Reroute Blocking analysis, progressive N+1 escalation, reroute loop
Length Matching Trombone meanders, via barrel lengths, DDR auto-grouping, time matching
Bus Routing Bus detection, middle-out ordering, neighbor attraction
Guide Corridor User-layer guide paths, waypoints, best-effort following
Power/Ground Planes Copper zones with automatic via placement
Utilities DRC checker, connectivity checker, fanout generators, layer switcher, DRC-settings fixer
BGA Fanout BGA escape routing generator
QFN Fanout QFN/QFP escape routing generator
Rust Router Building and using the Rust A* module
Visualizer Real-time A* visualization with PyGame
Power Net Analysis Power net detection, AI analysis, track width guidelines
Claude Skills All eight AI skills: routing plans, power/high-speed/diff-pair analysis, stackup, plane mappings, failure diagnosis, board review
Placement Placement optimization for routability
Integration Tests Test scripts and performance benchmarks
Release Pipeline How to tag a release and submit it to the KiCad PCM (maintainers)

Project Structure

KiCadRoutingTools/
├── place_optimize.py         # Main CLI - placement optimization (quench)
├── place_route_loop.py       # Main CLI - router-in-the-loop placement repair
├── route.py                  # Main CLI - single-ended routing
├── route_diff.py             # Main CLI - differential pair routing
├── route_planes.py           # Main CLI - power/ground plane via connections
├── route_disconnected_planes.py  # CLI - repair disconnected plane regions
├── plane_io.py               # Plane I/O utilities (zone extraction, output writing)
├── plane_obstacle_builder.py # Obstacle map building for plane via placement
├── plane_blocker_detection.py # Blocker detection and rip-up for plane vias
├── plane_zone_geometry.py    # Voronoi zone computation for multi-net layers
├── plane_resistance.py       # Plane resistance and current capacity calculations
├── plane_region_connector.py # Detect and route between disconnected plane regions
├── routing_config.py         # GridRouteConfig, GridCoord, DiffPair classes
├── routing_defaults.py       # Default routing parameter values
├── routing_exceptions.py     # Routing exception classes
├── routing_state.py          # RoutingState class - tracks routing progress
├── routing_context.py        # Helper functions for obstacle building
├── routing_common.py         # Shared utilities for route.py and route_diff.py
├── routing_utils.py          # Shared utilities (pos_key, etc.)
├── obstacle_map.py           # Obstacle map building functions
├── obstacle_cache.py         # Net obstacle caching for incremental builds
├── obstacle_costs.py         # Stub/track proximity cost calculations
├── bresenham_utils.py        # Bresenham line-walking utilities for grid operations
│
├── diff_pair_loop.py         # Differential pair routing loop
├── single_ended_loop.py      # Single-ended routing loop
├── reroute_loop.py           # Reroute queue processing
├── phase3_routing.py         # Phase 3 multi-point tap routing
├── diff_pair_routing.py      # Diff pair A* routing implementation
├── single_ended_routing.py   # Single-ended A* routing implementation
│
├── net_ordering.py           # MPS, inside-out, and original ordering
├── net_queries.py            # Net queries (diff pairs, MPS, endpoints)
├── connectivity.py           # Stub endpoints, connected groups
├── layer_swap_optimization.py # Upfront layer swap optimization
├── layer_swap_fallback.py    # Fallback layer swap on failure
├── stub_layer_switching.py   # Stub layer swap utilities
├── mps_layer_swap.py         # MPS-aware layer swap for crossing conflicts
├── polarity_swap.py          # P/N polarity swap handling
├── target_swap.py            # Target assignment optimization
├── rip_up_reroute.py         # Rip-up and reroute logic
├── blocking_analysis.py      # Analyze blocking nets
├── length_matching.py        # Length matching with trombone meanders
│
├── kicad_parser.py           # KiCad .kicad_pcb file parser
├── kicad_writer.py           # KiCad S-expression generator
├── output_writer.py          # Route output and swap application
├── pcb_modification.py       # Add/remove routes from PCB data
├── schematic_updater.py      # Update .kicad_sch files with pad swaps
├── chip_boundary.py          # Chip boundary detection
├── geometry_utils.py         # Shared geometry calculations
├── impedance.py              # Impedance calculation (microstrip/stripline formulas)
├── memory_debug.py           # Memory usage statistics
│
├── check_drc.py              # DRC violation checker
├── check_connected.py        # Connectivity checker (with T-junction detection)
├── check_orphan_stubs.py     # Orphan stub detector
├── check_cycles.py           # Redundant-loop (cycle) + overlapping-via checker
├── fix_kicad_drc_settings.py # Make .kicad_pro DRC constraints consistent with the routed floors (clearance, track/via/drill, hole, edge; courtyard/mask/footprint noise)
├── bga_fanout.py             # BGA fanout CLI wrapper
├── bga_fanout/               # BGA fanout package
│   ├── __init__.py           # Main fanout logic and public API
│   ├── types.py              # Track, BGAGrid, FanoutRoute, Channel, DiffPairPads
│   ├── escape.py             # Escape channel finding and assignment
│   ├── reroute.py            # Collision resolution and rerouting
│   ├── layer_balance.py      # Layer rebalancing for even distribution
│   ├── layer_assignment.py   # Layer assignment for collision avoidance
│   ├── tracks.py             # Track generation and collision detection
│   ├── geometry.py           # 45° stub and jog calculations
│   ├── collision.py          # Low-level collision detection utilities
│   ├── grid.py               # BGA grid analysis
│   ├── diff_pair.py          # Differential pair detection
│   └── constants.py          # Configuration constants
├── qfn_fanout.py             # QFN/QFP fanout CLI wrapper
├── qfn_fanout/               # QFN/QFP fanout package
│   ├── __init__.py           # Main fanout logic and public API
│   ├── layout.py             # Layout analysis functions
│   ├── geometry.py           # Stub position calculations
│   └── types.py              # QFNLayout, PadInfo, FanoutStub
├── list_nets.py              # List nets on a component
├── build_router.py           # Rust module build script (--clean to remove artifacts)
├── startup_checks.py         # Startup checks (Python deps, Rust library version)
│
├── tests/                    # Integration tests
│   ├── test_fanout_and_route.py  # Full integration test (fanout + route)
│   ├── test_kit_route.py         # Pad-to-pad routing test (no fanout)
│   ├── test_flat_hierarchy.py    # 2-layer board with GND plane test
│   ├── test_interf_u.py          # 2-layer board with non-rectangular outline test
│   ├── test_sonde_u.py           # Wide track routing test
│   ├── run_utils.py              # Shared test utilities
│   └── stress/                   # Real-world-board stress-test harness (run_queue.sh) — see tests/README.md
│
├── rust_router/              # Rust A* implementation
├── pygame_visualizer/        # Real-time visualization
├── kicad_routing_plugin/     # KiCad ActionPlugin
│   ├── action_plugin.py      # ActionPlugin entry point
│   ├── swig_gui.py           # Main routing dialog (Basic/Advanced tabs)
│   ├── differential_gui.py   # Differential pair routing tab
│   ├── fanout_gui.py         # BGA/QFN fanout tab and net selection panel
│   ├── planes_gui.py         # Power/ground planes tab
│   ├── about_tab.py          # About tab with version info
│   ├── gui_utils.py          # Shared GUI utilities
│   └── settings_persistence.py  # Save/restore dialog settings between sessions
├── placement/               # Component placement
│   ├── engine.py            # Core placement algorithm
│   ├── parser.py            # Courtyard boundary extraction
│   ├── writer.py            # Footprint position modification
│   └── utility.py           # Shared placement utilities
├── install_plugin.py         # Plugin installer script
├── docs/                     # Documentation
└── .claude/skills/           # Claude Code skills
    ├── analyze-power-nets/   # AI-powered power net analysis skill
    ├── find-high-speed-nets/ # AI-powered high-speed net identification skill
    ├── plan-pcb-routing/     # AI-powered routing plan generation skill (orchestrates the others)
    ├── identify-diff-pairs/  # Datasheet-based diff pair detection skill
    ├── recommend-stackup/    # Stackup review/recommendation skill
    ├── diagnose-routing-failures/  # Failure root-cause and retry skill
    ├── review-routed-board/  # Post-route QA and sign-off skill
    └── stress-test-router/   # Batch stress-test on real-world boards + issue filing (dev/QA)

Module Overview

One-line summaries below; the Python API documentation has full per-module references (signatures, dataclass fields, gotchas) with runnable examples.

Core Routing

Module Purpose
route.py CLI for single-ended routing
route_diff.py CLI for differential pair routing
route_planes.py CLI for power/ground plane via connections
route_disconnected_planes.py CLI for repairing disconnected plane regions
routing_config.py Configuration dataclasses (GridRouteConfig, GridCoord, DiffPair)
routing_state.py RoutingState class tracking progress, results, and PCB modifications
routing_context.py Helper functions for building obstacles and recording success
routing_common.py Shared utilities for route.py and route_diff.py (BGA zones, net resolution, length matching)
routing_utils.py Shared utilities (build_layer_map, iter_pad_blocked_cells)
obstacle_map.py Obstacle map building from PCB data
obstacle_cache.py Net obstacle caching for incremental obstacle map builds
obstacle_costs.py Stub and track proximity cost calculations
bresenham_utils.py Bresenham line-walking utilities for grid-based segment operations
geometry_utils.py Shared geometry calculations (point-to-segment distance, segment intersection, UnionFind)
routing_constants.py Shared constants (default layer stack, power net patterns, tolerances)
terminal_colors.py ANSI color codes for terminal output

Routing Loops

Module Purpose
diff_pair_loop.py Main loop for routing differential pairs
single_ended_loop.py Main loop for routing single-ended nets
reroute_loop.py Processes reroute queue for failed routes
phase3_routing.py Phase 3 multi-point tap routing (connects remaining pads after length matching)
diff_pair_routing.py Differential pair A* with centerline + offset and GND vias
single_ended_routing.py Single-ended net A* routing

Net Analysis

Module Purpose
net_ordering.py MPS, inside-out, and original net ordering strategies
net_queries.py Net queries (diff pair detection, MPS ordering, power net detection, chip pad positions)
connectivity.py Stub endpoints, connected groups, multi-point net detection

Key functions in net_queries.py:

  • identify_power_nets(pcb, patterns, widths) - Pattern-based power net detection for --power-nets CLI option
  • compute_mps_net_ordering(pcb, net_ids) - MPS algorithm for optimal net ordering
  • find_differential_pairs(pcb, patterns) - Detect P/N pairs from net names (suffix-style aware: +/- nets only pair with each other, never with _P/_N nets sharing the same base name)

Key functions in analyze_power_paths.py (used by /analyze-power-nets skill):

  • analyze_pcb(filepath) - Load PCB and extract components for analysis
  • get_components_needing_analysis(components) - Get components requiring AI classification
  • classify_component(components, ref, role, current_ma, notes) - Set component classification
  • trace_power_paths(pcb, components) - Trace current from sinks to sources
  • get_power_net_recommendations(pcb, components, paths) - Get recommended track widths

Optimization

Module Purpose
layer_swap_optimization.py Upfront layer swap optimization before routing
layer_swap_fallback.py Try layer swap when route fails
stub_layer_switching.py Low-level stub layer swap utilities
mps_layer_swap.py MPS-aware layer swap for crossing conflicts
polarity_swap.py P/N polarity swap for differential pairs
target_swap.py Hungarian algorithm for optimal target assignment
rip_up_reroute.py Rip-up blocking routes and retry
blocking_analysis.py Analyze which nets are blocking
length_matching.py Length matching with trombone-style meanders

I/O and Utilities

Module Purpose
kicad_parser.py KiCad .kicad_pcb file parser (extracts stackup, footprint values, pintypes)
kicad_writer.py KiCad S-expression generator
output_writer.py Write routed output with swaps and debug geometry
pcb_modification.py Add/remove routes from PCB data structure
schematic_updater.py Update .kicad_sch files with pad swaps from routing
impedance.py Impedance calculations (microstrip/stripline, width from target Z)
memory_debug.py Memory usage statistics and debugging

Performance

Integration test results (tests/test_fanout_and_route.py):

Stage Nets Time Iterations
FTDI single-ended 47/47 8.6s 319K
LVDS diff pairs (batch 1) 28/28 29.7s 10.2M
LVDS diff pairs (batch 2) 28/28 28.0s 12.0M
DDR diff pairs 5/5 0.3s 25K
DDR single-ended 51/51 6.2s 565K

Rust acceleration provides ~10x speedup vs pure Python.

Common Options

Single-Ended Routing (route.py)

python route.py kicad_files/input.kicad_pcb [output.kicad_pcb] [OPTIONS]

# Output options (default: input_routed.kicad_pcb)
--overwrite, -O         # Overwrite input file instead of creating _routed copy

# Net selection (default: "*" = all nets)
--nets "pattern" ...    # Net names or wildcard patterns to route
                        # Supports exclusion: --nets "*" "!GND" "!VCC" = all except GND/VCC
--component U1          # Route all nets on U1 (auto-excludes GND/VCC/VDD/unconnected unless --nets given)

# Geometry
--track-width 0.3       # Track width (mm), ignored if --impedance specified
--impedance 50          # Target single-ended impedance (ohms), calculates width per layer from stackup
--clearance 0.25        # Track clearance (mm)
--via-size 0.5          # Via diameter (mm)
--via-drill 0.3         # Via drill (mm)

# Power net routing (wider tracks for power/ground)
--power-nets "*GND*" "*VCC*"  # Glob patterns for power nets
--power-nets-widths 0.4 0.5   # Widths in mm for each pattern (must match --power-nets length)
--neckdown-length 2.5         # Narrow track length (mm) from the pads when a failed wide power
                              # route is retried at the default width (neck-down)
--neckdown-taper-length 0.5   # Narrow-to-wide width taper length in mm (0 = abrupt)
--no-power-tap-neckdown       # Disable the neck-down retry of failed wide power routes

# Algorithm
--grid-step 0.1         # Grid resolution (mm). For dense or fine-pitch boards use
                        # --grid-step 0.05: it gives the router room to route legally
                        # around correctly-blocked pads, recovering both completion and
                        # DRC-cleanliness (e.g. castor_pollux: 0.1mm 101 nets vs 0.05mm
                        # 123 nets, both DRC-clean). The coarser the grid, the fewer legal
                        # routes near tight pads.
--via-cost 50           # Via penalty in 0.1mm grid steps (50 = 5mm of path; all cost knobs
                        # are mm-calibrated, so behavior is independent of --grid-step)
--max-iterations 200000      # A* iteration limit
--max-probe-iterations 5000  # Quick probe per direction to detect stuck routes
--heuristic-weight 1.9       # A* greediness (>1 = faster)
--proximity-heuristic-factor 0.02  # Proximity cost estimate (only applied when endpoints in zones, diff pairs use 1/10th)
--turn-cost 1000             # Penalty for direction changes (straighter paths)
--direction-preference-cost 50   # Penalty for non-preferred layer direction (0=disabled)
                                 # Alternates H/V: F.Cu=horizontal, In1.Cu=vertical, etc.
--max-ripup 3                # Max blockers to rip up at once (1-N progressive)
--routing-clearance-margin 1.0   # Multiplier on track-via clearance (1.0 = min DRC, default)
--hole-to-hole-clearance 0.2 # Minimum drill hole edge-to-edge clearance (mm)
--board-edge-clearance 0.0   # Clearance from board edge (0 = use track clearance)

# Strategy
--ordering mps          # mps | inside_out | original
--layers F.Cu B.Cu      # Routing layers (default: 2-layer)
--layer-costs 1.0 3.0   # Per-layer cost multipliers (1.0-1000)
                        # Default: 4+ layers = all 1.0; 2 layers = F.Cu=1.0, B.Cu=3.0
                        # Order matches --layers. Use to prefer certain layers (e.g., keep signals on F.Cu)
--no-bga-zones          # Allow routing through all BGA areas
--no-bga-zones U1 U3    # Allow routing through specific BGAs only (or all if none given)

# Proximity penalties
--stub-proximity-radius 2.0  # Radius around stubs to penalize (mm)
--stub-proximity-cost 0.2    # Cost penalty near stubs (mm equivalent)
--bga-proximity-radius 7.0  # Radius around BGA edges to penalize (mm)
--bga-proximity-cost 0.2     # Cost penalty near BGA edges (mm equivalent)
--track-proximity-distance 2.0  # Radius around routed tracks (mm, same layer)
--track-proximity-cost 0.0   # Cost penalty near tracks (0 = disabled)
--vertical-attraction-radius 1.0  # Radius for cross-layer track attraction (mm)
--vertical-attraction-cost 0.0    # Cost bonus for cross-layer alignment (0 = disabled)
--ripped-route-avoidance-radius 1.0  # Radius around ripped route corridors (mm)
--ripped-route-avoidance-cost 0.1    # Cost penalty for routing through ripped corridors (0 = disabled)

# Bus routing (parallel groups of nets)
# Detects groups of nets with clustered endpoints and routes them together.
# Routes middle net first (guide track), then alternates outward with attraction
# to keep traces parallel. Use --verbose to see routing order and attraction relationships.
--bus                           # Enable bus detection and parallel routing
--bus-detection-radius 5.0      # Max endpoint distance to form bus group (mm)
--bus-attraction-radius 5.0     # Attraction radius from neighbor track (mm)
--bus-attraction-bonus 5000     # Cost bonus for staying parallel to neighbor
--bus-min-nets 2                # Minimum nets to form a bus group

# Guide corridor: route selected nets to follow a polyline drawn on a User layer (issue #7)
--guide-corridor                # Steer routed nets along the drawn guide polyline
--guide-corridor-layer User.1   # User layer the guide polyline is drawn on
--guide-corridor-spacing 0.0    # Max mm between waypoints (0 = drawn vertices only; >0 subdivides)

# Keepout zones: keep routed tracks out of polygons drawn on a User layer (issue #27)
--keepout                       # Keep routed tracks out of the drawn keepout polygons
--keepout-layer User.2          # User layer the keepout polygons are drawn on

# Layer optimization
--no-stub-layer-swap    # Disable stub layer switching

# Target swap optimization
--swappable-nets "*rx*"  # Glob patterns for nets that can have targets swapped
--schematic-dir /path/to/kicad  # Optional: sync pad swaps to .kicad_sch files (disabled by default)
                                # Updates lib_symbols in ALL files containing the symbol
--crossing-penalty 1000  # Penalty for crossing assignments (default: 1000)
--no-crossing-layer-check  # Count crossings regardless of layer (default: same-layer only)
--mps-reverse-rounds     # Route most-conflicting MPS groups first (instead of least)
--mps-layer-swap         # Try layer swaps to resolve MPS crossing conflicts
--mps-segment-intersection  # Force segment intersection method for MPS (auto when no BGAs)

# Length matching (for DDR4 DQ/DQS signals)
--length-match-group auto       # Auto-group DDR4 nets by byte lane (DQ0-7+DQS0, DQ8-15+DQS1, etc)
--length-match-group "pattern1" "pattern2"  # Manual grouping by net patterns
--length-match-tolerance 0.1    # Acceptable length variance within group (mm)
--meander-amplitude 1.0         # Height of meanders perpendicular to trace (mm)

# Time matching (alternative to length matching)
--time-matching                 # Match propagation time instead of length (accounts for layer dielectric)
--time-match-tolerance 1.0      # Acceptable time variance within group (ps)

# Debug
--verbose               # Print detailed diagnostic output
--debug-lines           # Output debug geometry on User layers
--skip-routing          # Skip routing, only do swaps and write debug info
--debug-memory          # Print memory usage statistics during routing
--add-teardrops         # Add teardrop settings to all pads in output file
--stats                 # Print A* search statistics (cells expanded, heuristic efficiency, etc.)

Differential Pair Routing (route_diff.py)

python route_diff.py kicad_files/input.kicad_pcb [output.kicad_pcb] [OPTIONS]

# Output options (default: input_routed.kicad_pcb)
--overwrite, -O         # Overwrite input file instead of creating _routed copy

# Net selection (default: "*" = all nets)
# All nets specified with --nets are treated as differential pairs (P/N naming convention)

# Diff pair specific options
--impedance 100         # Target differential impedance (ohms), calculates width per layer from stackup
--diff-pair-gap 0.101   # P-N gap (mm), also used as spacing for impedance calculation
--diff-pair-centerline-setback  # Setback distance (default: 2x P-N spacing)
--min-turning-radius 0.2      # Min turn radius (mm)
--max-turn-angle 180          # Max cumulative turn (degrees, prevents U-turns)
--max-setback-angle 45        # Max angle for setback search (degrees)
--direction backward    # Route from target to source
--no-gnd-vias           # Disable GND via placement (enabled by default)
--diff-chamfer-extra 1.5      # Chamfer multiplier for diff pair meanders (>1 avoids P/N crossings)
--diff-pair-intra-match       # Match P/N lengths within each diff pair (meander shorter track)

# Layer optimization
--no-stub-layer-swap    # Disable stub layer switching
--can-swap-to-top-layer # Allow swapping stubs to F.Cu (off by default)

# Target/polarity swap with schematic sync
--swappable-nets "*rx*"  # Glob patterns for nets that can have targets swapped
--schematic-dir /path/to/kicad  # Optional: sync pad swaps to .kicad_sch files (disabled by default)
                                # Syncs target swaps (P1_P<->P2_P, P1_N<->P2_N) and polarity swaps (P<->N)
                                # Updates ALL schematic files containing the lib_symbol

# All other options from route.py also apply (geometry, strategy, proximity, length matching, etc.)

Power/Ground Plane Via Connections (route_planes.py)

python route_planes.py kicad_files/input.kicad_pcb [output.kicad_pcb] --nets GND --plane-layers B.Cu [OPTIONS]

# Output options (default: input_routed.kicad_pcb)
--overwrite, -O         # Overwrite input file instead of creating _routed copy

# Required (can specify multiple nets/plane layers)
--nets, -n GND VCC          # Net name(s) for planes (e.g., GND VCC +3.3V)
                            # Use | to share a layer: "VA19|VA11" creates Voronoi-partitioned zones
--plane-layers, -p In1.Cu In2.Cu  # Plane layer(s), one per net (or one per net group)

# Via/trace geometry
--via-size 0.5          # Via outer diameter (mm)
--via-drill 0.3         # Via drill size (mm)
--track-width 0.3       # Track width for via-to-pad connections (mm)
--clearance 0.25        # Clearance (mm)

# Zone options
--zone-clearance 0.2    # Zone clearance from other copper (mm)
--min-thickness 0.1     # Minimum zone copper thickness (mm)

# Algorithm
--grid-step 0.1         # Grid resolution (mm)
--max-search-radius 10.0  # Max radius to search for valid via position (mm)
--max-via-reuse-radius 1.0  # Max radius to prefer reusing existing via (mm)
--close-via-radius 0.5      # Radius to check for nearby vias before placing new one (default: 2.5 * via-size)
--hole-to-hole-clearance 0.2  # Minimum drill hole clearance (mm)
--layers, -l F.Cu In1.Cu In2.Cu B.Cu  # All copper layers for routing and via span
--layer-costs 1.0 1.0 1.0 1.0  # Per-layer cost multipliers (1.0-1000)
                               # Default: 4+ layers = all 1.0; 2 layers = F.Cu=1.0, B.Cu=3.0
--board-edge-clearance 0.5  # Zone clearance from board edge (mm)

# Multi-net plane layers (Voronoi partitioning)
--plane-proximity-radius 2.0  # Proximity radius for routing around other nets' vias (mm)
--plane-proximity-cost 5.0    # Proximity cost for routing around other nets' vias
--plane-track-via-clearance 0.8  # Clearance from MST track center to other nets' via centers (mm)
--voronoi-seed-interval 2.0   # Sample interval for seed points along connection routes (mm)
--plane-max-iterations 200000 # Max A* iterations for plane connection routing

# Blocker rip-up
--rip-blocker-nets      # Rip up nets blocking via placement
--max-rip-nets 3        # Max blocker nets to rip up per pad (default: 3)
--reroute-ripped-nets   # Automatically re-route ripped nets after via placement
--power-nets "*GND*" "*VCC*"  # Glob patterns for power nets (wider tracks when rerouting)
--power-nets-widths 0.4 0.5   # Track widths for each power-net pattern

# Debug
--dry-run               # Analyze without writing output
--verbose, -v           # Print detailed debug messages
--debug-lines           # Draw MST routes on User.1, User.2, etc. per net
--add-teardrops         # Add teardrop settings to all pads in output file

# GND return via placement (for signal integrity)
--add-gnd-vias          # Add GND vias near signal vias for return current paths
--gnd-via-net GND       # Net name for GND vias (default: GND)
--gnd-via-distance 2.0  # Max distance from signal via to place GND via (mm, default: 2.0)

Features:

  • Multi-net support - Process multiple nets in one run (e.g., GND and VCC planes)
  • Voronoi partitioning - Multiple nets can share a single plane layer using | separator (e.g., "VA19|VA11"). Each net's vias get non-overlapping zone polygons. MST edges are routed between all vias using A* pathfinding, with routes sampled as Voronoi seeds to ensure connected zones. Retries with failed nets first (up to 5 iterations)
  • Automatic pad classification - Identifies SMD pads needing vias vs through-hole/zone-layer pads
  • Smart via placement - Places vias at pad center when possible, spirals outward when blocked
  • A* trace routing - Routes traces from offset vias to pads, avoiding all copper layers
  • Via reuse with fallback - Prefers nearby vias within reuse radius, falls back to farther vias if placement fails
  • Blocker rip-up - When via placement/routing fails, identifies blocking nets and temporarily removes them, then retries
  • Automatic re-routing - Optionally re-routes ripped nets after all plane vias are placed
  • Zone creation - Creates copper pour zone. If an existing zone for the same net/layer is present, it is replaced with new parameters (clearance, min_thickness)
  • Resistance analysis - Calculates and displays approximate plane resistance and maximum current capacity (IPC-2152) for each polygon. For multi-net layers, uses the longest MST route path length; for single-net layers, uses the bounding box diagonal. Samples polygon width perpendicular to the current path to estimate effective cross-section. Assumes 1 oz copper and 10°C temperature rise

See Power/Ground Planes for detailed documentation.

Disconnected Plane Region Repair (route_disconnected_planes.py)

After creating power planes, regions may become split by vias and traces from other nets cutting through. This script detects disconnected regions within each plane zone and routes wide, short tracks between them.

python route_disconnected_planes.py kicad_files/input.kicad_pcb [output.kicad_pcb] [OPTIONS]

# Output options (default: input_routed.kicad_pcb)
--overwrite, -O         # Overwrite input file instead of creating _routed copy

# Zone selection (auto-detects all zones if not specified)
--nets, -n GND +3.3V        # Net name(s) to process
--plane-layers, -p B.Cu In1.Cu  # Plane layer(s) to process
--layers, -l F.Cu In1.Cu In2.Cu B.Cu  # Layers available for routing (default: all copper)

# Track width
--max-track-width 2.0       # Maximum track width for connections (mm)
--min-track-width 0.2       # Minimum track width for connections (mm)
--track-width 0.3           # Default track width for routing config (mm)

# Clearance
--clearance 0.25            # Trace-to-trace clearance (mm)
--zone-clearance 0.2        # Zone fill clearance around obstacles (mm)
--track-via-clearance 0.8   # Clearance from tracks to other nets' vias (mm)
--board-edge-clearance 0.5  # Clearance from board edge (mm)
--hole-to-hole-clearance 0.3  # Minimum clearance between drill holes (mm)

# Via options
--via-size 0.5              # Via outer diameter (mm)
--via-drill 0.3             # Via drill diameter (mm)

# Grid
--grid-step 0.1             # Routing grid step (mm)
--analysis-grid-step 0.5    # Grid step for connectivity analysis (coarser = faster)

# Routing
--max-iterations 200000     # Maximum A* iterations per route attempt

# Debug
--dry-run                   # Analyze without writing output
--verbose, -v               # Print detailed debug messages
--debug-lines               # Add debug lines on User.4 layer showing route paths

# DRC settings
--no-fix-drc-settings       # Skip making the output project's DRC rules match the
                            # plane routing floors (done by default; issue #160)
--keep-thermal              # Leave starved_thermal at its severity instead of
                            # demoting it to a warning when fixing DRC settings

Features:

  • Auto-detection - Automatically finds all zones in PCB if nets/layers not specified
  • Per-net processing - Zones with the same net on multiple layers are processed together, reducing redundant routes since vias connect all layers
  • Flood-fill region detection - Uses grid-based flood fill to identify disconnected regions across all zone layers
  • Cross-layer connectivity - Uses vias and through-hole pads to properly track connectivity across multiple zone layers
  • MST-based connections - Connects regions using minimum spanning tree for optimal routing
  • Multi-point routing - Uses ALL anchors (vias/pads) in each region as potential connection points, trying both directions (A->B and B->A) since A* can find different paths depending on direction
  • Wide track routing - Tries track widths from max (2.0mm) down to min (0.2mm), using the widest width that fits without rebuilding obstacle maps
  • Smart via placement - Only adds new vias at layer transitions if no via already exists at that position
  • Hole-to-hole clearance - Respects drill hole clearances when placing new vias
  • Multi-layer routing - Can route through any copper layer to connect regions

Requirements

  • Python 3.7+
  • numpy (pip3 install numpy)
  • scipy (pip3 install scipy) - used for optimal target assignment and Voronoi partitioning
  • shapely (pip3 install shapely) - used for polygon union in multi-net plane layers
  • Rust toolchain — only needed if you build the router from source (python build_router.py --from-source); not required when using the prebuilt binary
  • pygame-ce (optional, for visualizer: pip3 install pygame-ce)

Limitations

  • No push-and-shove (routes around obstacles, doesn't move them)
  • No layer swaps of stubs for multipoint nets (3+ pads)
  • No blind or buried vias
  • No coarse grid assignment before detailed routing to plan overall topology
  • No via cost or other parameter learning/tuning
  • No design rules by region/area support
  • Greedy rip-up routing is sensitive to obstacle perturbation: a ~1% change in blocked cells can swing completion noticeably on dense boards (a finer --grid-step is the usual remedy)

License

MIT License

About

A set of Python/Rust tools to aid routing in KiCad

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors