A fast Rust-accelerated A* autorouter for KiCad PCB files. Available as both a KiCad Plugin with full GUI and a Command-Line Interface for scripting and automation.
- 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.
- 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
- 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 swap - Detects when differential pair P/N polarity differs between source and target pads and automatically swaps target pad net assignments to match. Use
--no-fix-polarityto disable - 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-diris 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
--busflag. Configurable detection radius, attraction radius, and attraction bonus - 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
- 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-matchingto enable. Tolerance specified in picoseconds - 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 - 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-netsskill 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-netsconfigurations. 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, 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.pyscript detects disconnected regions and routes wide, short tracks between them to ensure electrical continuity - 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-viaswith route_planes.py - AI-powered high-speed net analysis - Use the
/find-high-speed-netsskill 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-distancevalues based on the fastest signals on the board. See the GND return via distance guidance in the planes documentation
# Clone with git
git clone https://github.com/drandyhaas/KiCadRoutingTools.git
cd KiCadRoutingToolsOr download the ZIP and extract it.
If you don't have Rust installed, install it 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.
python build_router.pyOption A: KiCad Plugin (Recommended for interactive use)
# Install the plugin
python install_plugin.py
# Then in KiCad: Tools → External Plugins → KiCadRoutingToolsOption 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
Option C: Manual Command Line (For scripting and automation)
# 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.CuThe plugin provides a full graphical interface for all routing features, running directly within KiCad 9+.
# 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 --uninstallThe installer automatically detects your KiCad installation directory:
- macOS:
~/Documents/KiCad/9.0/3rdparty/plugins/ - Linux:
~/.local/share/kicad/9.0/3rdparty/plugins/ - Windows:
~/Documents/KiCad/9.0/3rdparty/plugins/
- Open KiCad 9.0 or later
- Open a PCB in Pcbnew
- Go to Tools → External Plugins → KiCadRoutingTools
- Configure routing parameters and select nets to route
- Click Route to run the router
Basic Tab:
- Net selection with filtering and component filtering
- 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
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
- 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
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 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# 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-runAfter 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# Check for DRC violations (default clearance: 0.2mm)
python check_drc.py 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 (traces ending without proper connection)
python check_orphan_stubs.py kicad_files/output.kicad_pcbUse 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:
- Auto-classifies obvious components (resistors, capacitors, inductors, etc.)
- Uses WebSearch to look up datasheets for unknown components (ICs, connectors, transistors)
- Classifies each component's role (power source, current sink, pass-through, shunt)
- Traces power paths from sinks to sources
- Generates ready-to-use
--power-netsconfigurations
See Power Net Analysis for detailed documentation.
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:
- Pre-classifies nets by name patterns (DDR, USB, SPI, CLK, etc.)
- Pre-classifies components by footprint (FPGA, DDR, PHY, etc.)
- Uses WebSearch to look up datasheets for ICs and extract max clock rates and rise times
- Traces high-speed signals through series passives (termination resistors, AC coupling caps)
- 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.
# 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 --quickSee tests/README.md for detailed documentation of all test scripts.
| Document | Description |
|---|---|
| Routing Architecture | Module structure, obstacle maps, A* algorithm |
| Configuration | Command-line options, GridRouteConfig parameters |
| Differential Pairs | P/N pairing, polarity swaps, via handling |
| Net Ordering | MPS algorithm, inside-out ordering, strategy comparison |
| Power/Ground Planes | Copper zones with automatic via placement |
| Utilities | DRC checker, connectivity checker, fanout generators, layer switcher |
| 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 |
| High-Speed Net Analysis | Signal speed classification, GND return via recommendations |
| Integration Tests | Test scripts and performance benchmarks |
KiCadRoutingTools/
├── 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
├── 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
│
├── 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
├── 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
| 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 |
| 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 |
| 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-netsCLI optioncompute_mps_net_ordering(pcb, net_ids)- MPS algorithm for optimal net orderingfind_differential_pairs(pcb, patterns)- Detect P/N pairs from net names
Key functions in analyze_power_paths.py (used by /analyze-power-nets skill):
analyze_pcb(filepath)- Load PCB and extract components for analysisget_components_needing_analysis(components)- Get components requiring AI classificationclassify_component(components, ref, role, current_ma, notes)- Set component classificationtrace_power_paths(pcb, components)- Trace current from sinks to sourcesget_power_net_recommendations(pcb, components, paths)- Get recommended track widths
| 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 |
| 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 |
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.
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)
# Algorithm
--grid-step 0.1 # Grid resolution (mm)
--via-cost 50 # Via penalty (grid steps)
--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
# 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.)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.)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.
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 pathsFeatures:
- 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
- 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 (for building the router module)
- pygame-ce (optional, for visualizer:
pip3 install pygame-ce)
- 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 user-defined keepout zones
- 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
MIT License


