feat: KiCad plugin fixes, zone/keepout extraction, board viewer improvements#17
Open
RolandWa wants to merge 34 commits intobbenchoff:mainfrom
Open
feat: KiCad plugin fixes, zone/keepout extraction, board viewer improvements#17RolandWa wants to merge 34 commits intobbenchoff:mainfrom
RolandWa wants to merge 34 commits intobbenchoff:mainfrom
Conversation
…plugin path - Add swig_init.py: SWIG ActionPlugin that registers toolbar button and launches main.py as subprocess in plugin mode (kipy auto-discovers IPC socket, no KICAD_API_SOCKET env var needed) - Cross-platform support: per-platform Python exe, kicad bin dir, 3rdparty site-packages detection (Windows/Linux/macOS) - Set QT_PLUGIN_PATH so PyQt6 finds platform plugins in subprocess env - Windows: set PYTHONHOME, PYTHONUTF8, PATH from kicad-cmd.bat pattern - Rewrite build.py: deploy to KiCad 3rdparty, ZIP for PCM, OneDrive lock resilience (incremental clean, fallback ZIP naming) - Lazy imports in __init__.py files to avoid pcbnew crash at module load - Add debug logging to main.py and kicad_plugin.py for plugin launch
- rich_kicad_interface.py: correct IPC API attribute access for tracks/vias, nm->mm conversion, BoardLayer enum name mapping (BL_F_Cu -> F.Cu), new _extract_vias() method - main_window.py: normalize BL_* layer names in paint loop, RoundCap/RoundJoin pen for track rendering - .gitignore: exclude copy_to_kicad.ps1 (local dev tool only) Co-authored-by: RolandW <RolandW@users.noreply.github.com>
- rich_kicad_interface.py: implement _extract_zones() using KiCad IPC API board.get_zones(); skips rule areas (logged by name); extracts outline and filled_polygons per layer with nm->mm conversion and BL_* layer name mapping; logs skip reasons for rule area zones - main_window.py: add _draw_zones() with semi-transparent layer-colored fills respecting visible_layers checkbox; wired into paint loop under show_zones toggle - DRC extraction: downgrade 'No module named kicad' from WARNING to INFO - Orphaned pads: downgrade WARNING to DEBUG, clean up message prefix Co-authored-by: RolandW <RolandW@users.noreply.github.com>
… them - rich_kicad_interface: _extract_zones() returns (zones, keepouts) tuple; rule areas extracted with full constraint flags from rule_area_settings proto - board.py: added keepouts: List[Dict] field to Board domain model - kicad_plugin: store board_data; attach board.keepouts before routing - unified_pathfinder: add _apply_keepout_obstacles(board) method with vectorised point-in-polygon test (ray casting); blocks track edges when keepout_tracks=True and via edges when keepout_vias=True; called at end of initialize_graph(); add module-level _points_in_polygon() numpy helper Co-authored-by: RolandW
Paint event now calls _draw_keepouts() when show_keepouts=True. New _draw_keepouts() renders each keepout outline as a dashed red semi-transparent polygon, respecting layer visibility. Previously the checkbox toggled the flag but triggered no drawing because no _draw_keepouts() method or call existed. Co-authored-by: RolandW
Right-clicking inside a keepout area now shows a popup with:
- Keepout name and affected layers
- Per-constraint status with check/cross mark:
No Tracks / No Vias / No Copper Fills / No Pads / No Footprints
Uses ray-casting PIP test (_point_in_polygon) against keepout outline
after converting screen coords -> world (mm) coords via _screen_to_world().
Clicking outside any keepout shows nothing.
Co-authored-by: RolandW
_draw_tracks, _draw_vias, _draw_zones were logging at INFO level on every paint event (~50ms), flooding the log with hundreds of lines per session. Downgraded to DEBUG: called/completed summaries, VIEWPORT DEBUG, COORD VERIFY, TRACK COORDS, TRACK DRAWN, TRACK LAYER FILTERED messages. Genuine warnings (invalid data, transform failures) remain at WARNING. Co-authored-by: RolandW
build.py --deploy and ZIP builds were missing orthoroute.json (the runtime config file). Added it to the extra-files copy loop and to the required-files validation list so a broken build fails fast. Co-authored-by: RolandW
- Build: corrected ZIP name, noted orthoroute.json now included and validated - KiCad integration: document IPC data extraction (tracks/vias/zones/keepouts), fix plugin folder name (underscores not dots), point to plugin logs, add dev-sync workflow (copy_to_kicad.ps1) - Key files table: add rich_kicad_interface, main_window, board.py - Routing: document _apply_keepout_obstacles() keepout enforcement - PCB viewer: add display features table and right-click keepout menu docs - Keepout rule areas: full data structure reference section - Common pitfalls: add log-spam regression note - Project status: mark track/via/zone/keepout work as complete Also fix .gitignore: .github/ was accidentally listed under 'Generated documentation', preventing copilot-instructions.md from being tracked. Co-authored-by: RolandW
- 3,311 GPU paths profiled across 40 iterations - GPU Dijkstra kernel: 16ms avg (5% of per-net time) - Python->CUDA MULTI-LAUNCH loop: ~296ms avg (95% of per-net time) - PERSISTENT KERNEL already compiled but not activated — fix is bbenchoff#1 priority - Via rebuild (_rebuild_via_usage_from_committed): 275ms avg, 1% of total - Expected speedup if persistent kernel activated: 10-20x (44min -> 3-5min) Updated docs/optimization/: - OPTIMIZATION_QUICK_REF.md: corrected priority table, GPU architecture notes - optimization_baseline_2026-04-03.md: GPU analysis section, revised roadmap - README.md: corrected targets and phases
…t persistent kernel fix - All 210 logger.info() calls converted to logger.debug() - [GPU-SEEDS] Path found in X iterations promoted to WARNING (key timing metric) - Result: log size 861MB -> ~10-20MB per run - Document why _enable_persistent_kernel = False: persistent kernel lacks allowed_bitmap param (owner-aware node filtering) needed to prevent routing through other nets' pad nodes fix: add uint32* allowed_bitmap + bitmap_words to CUDA PTX + IN_BITMAP check expected speedup: 20x per net, 48min -> ~3min total run
- Add allowed_bitmap (uint32*), bitmap_words, use_bitmap params to persistent_sssp_kernel PTX -- owner-aware node filtering now works - IN_BITMAP check in inner loop matches wavefront_expand_all kernel - launch_persistent_kernel() updated to accept/pass bitmap params - _enable_persistent_kernel = True (was False since v1) - Bump _persistent_kernel_version to 3 (forces recompile) Verified on TestBackplane.kicad_pcb: 512/512 nets converged, 0 overuse, 70 iterations Run time: 25 min (was 47.9 min) -- 2x speedup Per-net kernel GPU time: 3-24ms (was 306ms multi-launch) Per-iteration wall time: ~20s (was ~39s) Note: Python bitmap construction overhead ~50ms/net limits full 20x gain
- Run time: 47.9min -> 25min (2x speedup, 70 iters, 512/512 converged) - New bottleneck: Python bitmap construction ~50ms/net (65% of per-net) int(seed) loop causes ~100 GPU->CPU syncs before kernel launch Fix: cp.scatter_add vectorized bitmap set (one kernel call) Expected gain: 25min -> ~8-10min (3-4x additional speedup) - Mark MULTI-LAUNCH overhead as DONE in priority table
…edup) - cuda_dijkstra.py: skip cp.asarray() if allowed_bitmap already CuPy - cuda_dijkstra.py: fix cupyx.scatter_add bitmap OR corruption (build zero force_mask then OR into roi_bitmaps to avoid bit-flip on existing bits) - unified_pathfinder.py: add node_owner_gpu (CuPy mirror of node_owner) - unified_pathfinder.py: sync node_owner_gpu once per iter in _rebuild_node_owner - unified_pathfinder.py: batch-write to node_owner_gpu in _mark_via_barrel_ownership_for_path - unified_pathfinder.py: _build_owner_bitmap_for_fullgraph builds bitmap entirely on GPU (no CPU computation, no PCIe upload) when node_owner_gpu available - unified_pathfinder.py: CPU fallback uses reshape+matmul instead of np.add.at - docs: record run history (runs 3+4), no-improvement findings, mystery 70-100ms gap documented, profiling plan added
- _path_to_edges: replace nested Python loops + per-call GPU->CPU transfer with cached CPU arrays (_indptr_cpu/_indices_cpu) and NumPy broadcast broadcast matrix search. 21.6ms -> 0.12ms avg per call (~180x) - commit_path: replace per-element GPU indexing loop with cupyx.scatter_add (GPU) / np.add.at (CPU) batch scatter. 6.6ms -> 0.73ms avg per call (~9x) - Combined per-net Python overhead reduced from ~28ms to ~0.85ms - Profiling: _path_to_edges 5126 calls, 616ms total (was 73s for same calls) - New bottleneck: _rebuild_via_usage_from_committed at 211ms/iter
- init_logging() respects ORTHO_DEBUG (was hardcoded DEBUG) - File log: WARNING normal / DEBUG when ORTHO_DEBUG=1 - Console: always WARNING - Screenshots: disabled by default, enabled with ORTHO_DEBUG=1 - image.save() offloaded to daemon thread (eliminates 6s inter-iter stall) - setup_logging(): removed duplicate component_levels loop, added dead-code note - performance_utils.profile_time: no-op unless ORTHO_DEBUG=1 - unified_pathfinder: removed @profile_time decorators (controlled via env var now) - [ROUTING START] + iter=/total= timing added to normal-mode log - README + copilot-instructions updated with ORTHO_DEBUG documentation
- Contributing.md: full spec for headless routing regression test - Read-only board (never modify TestBoards/TestBackplane.kicad_pcb) - Golden metrics: nets_routed, overuse_edges exact-or-better - Iterations: +-10% tolerance (non-deterministic router) - Timing: <=110% of golden (no performance regression) - Stores baseline in tests/golden_metrics.json (committed to repo) - Skeleton test code in tests/test_regression_backplane.py - --export-metrics flag needed in main.py CLI - copilot-instructions.md: added to Needs Work list
…ts arg, remove invalid .board attr
…ly in normal mode
…rence tests/README.md
…r OrthoRoute dev workflow
…un (512/512 nets, 65 iters, 717s)
…log path, iter regex, GPU golden metrics
…lt fallback, log_path picks largest file
… baseline
- conftest.py: _parse_lattice_from_log() parses 'Lattice: NxNxN = N nodes' WARNING;
log_lattice fixture exposes it session-wide
- test_backplane.py: TestLatticeSize group (4 tests)
- test_lattice_nodes: HARD FAIL if nodes != golden_board[lattice_nodes] (446,472)
- test_lattice_layers: HARD FAIL if layers != golden_board[copper_layers] (18)
- test_lattice_dimensions_reported: SOFT WARN on zero dims
- test_lattice_node_product: SOFT WARN if cols*rows*layers != reported nodes
- docs/optimization/optimization_baseline_2026-04-05.md: Apr-5 run 717.5s (12min),
4x faster than Apr-3 baseline
- Regression: 14 -> 18 passing, 25 skipping, 0 failing
conftest.py - _parse_routing_result_from_log now extracts: - [CLEAN] All nets routed with zero overuse -> clean_zero_overuse flag - ROUTING COMPLETE: All N nets routed ... -> routing_complete_banner flag - [FINAL] Edge routing converged (N barrel) -> final_barrel_conflicts count - Applied N tracks and N vias to KiCad -> tracks_written / vias_written Convergence is now driven by hard [CLEAN]/ROUTING COMPLETE markers, not just the [ITER N] CONVERGED flag. test_backplane.py - TestRoutingQuality gets 2 new SOFT WARN tests: - test_routing_complete_banner: checks ROUTING COMPLETE line present - test_clean_zero_overuse: checks [CLEAN] All nets... line present Results: 45 passed, 0 skipped (was 18 passed, 25 skipped)
- Two-run comparison table (run1 golden ref vs run2 confirmed log) - PERSISTENT kernel confirmed in run2 (run_20260405_223659.log line 383) - Full 67-iter convergence trend: iter 1-6, 10, 20, 30, 40, 50, 60-67 with nets_active, overuse edges, barrel conflicts, iter/total time - Key observations: warm-up, pres_fac cap at 64, net exclusion/retry pattern, barrel floor at 379, final sprint at <5s/iter - Regression test table updated: 45 passing (was 18), added lattice group
added 4 commits
April 10, 2026 14:27
Unit tests added: - test_edge_accountant.py - PathFinder edge cost and congestion tracking - test_pathfinding.py - Dijkstra pathfinding methods (52 failing - mock issues) - test_real_global_grid.py - Grid coordinate conversion and validation - test_roi_extraction.py - Region of interest extraction (20 failing - mock issues) - test_rrg.py - Routing resource graph data structures - test_via_conflicts.py - Via barrel conflict detection (16 failing - mock issues) - test_smoke.py - Quick smoke tests for regression suite Test results: 115 passing, 52 failing (all failures due to improper mocking) See test_failure_analysis.md for detailed analysis. Optimization baseline updates: - Added optimization_baseline_2026-04-08.md documenting latest routing run - Updated README.md with performance regression analysis (17.5 min vs 11.96 min best) - Updated OPTIMIZATION_QUICK_REF.md with current status and investigation priorities Performance summary: - April 8 run: 17.5 min (67 iterations, 15.7s avg) - 46% regression vs April 5 - All 512 nets routed successfully with zero overuse - Barrel conflicts: 359 (19% improvement) - Investigation needed: verify GPU persistent kernel usage and profile overhead
- Add 167 unit tests (all passing) - Add 63 regression tests validating against golden result - Document golden result: April 10, 2026 (512/512 nets, zero overuse, 18.4 min) - Create tests/run_golden_regression.md with test documentation - Update golden_board.json and golden_metrics.json with validated baselines - Add docs/optimization/golden_result_2026-04-10.md with complete metrics Test Results: - 167/167 unit tests passing - 47/63 regression tests passing (16 expected skips/fails) - All routing quality metrics validated against golden baseline - GPU hardware functional (NVIDIA Compute Capability 75)
- Create scripts/analyze_log.py: Standalone log parser for routing metrics extraction and golden comparison - Create scripts/optimize_and_validate.ps1: PowerShell automation wrapper for full optimization cycle - Create scripts/README.md: Comprehensive documentation for automation scripts - Create tests/regression/smoke_metrics.json: Golden thresholds for smoke test (100 nets, 4 layers) - Create docs/optimization/optimization_workflow.md: Complete optimization workflow guide (800+ lines) - Create docs/optimization/baseline_template.md: Standardized template for future optimization baselines - Extend launch_kicad_debug.ps1: Add -RunValidation flag for post-KiCad smoke test - Extend copy_to_kicad.ps1: Add -Validate switch for deployment validation - Update optimization docs: Add workflow references to QUICK_REF, README, golden_result_2026-04-10 - Update historical baselines: Add workflow tool references to 2026-04-03, 04-05, 04-08 Workflow enables fast iterative optimization: make change → sync → smoke test (30s) → analyze → commit Exit codes: 0=PASS, 1=FAIL routing, 2=WARN regression, 3=ERROR environment Smoke test becomes primary validation checkpoint (middle complexity: 100 nets vs 512 backplane)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR brings seven commits that fix the KiCad plugin connection layer, improve
the PCB board viewer, and add full keepout rule area support across extraction,
visualization, and routing enforcement.
KiCad plugin fixes
with fallback scan
proto layer names (
BL_F_Cu->F.Cu)RoundCap/RoundJoinpen caps matching KiCad's styleCopper zone extraction and rendering
_extract_zones()readsboard.get_zones()via IPC, collecting both thezone outline and per-layer
filled_polygons(post-pour fills)_draw_zones()renders filled polygons with semi-transparent layer-coloredfills and respects per-layer visibility checkboxes
Keepout rule area support
Extraction (
rich_kicad_interface.py)_extract_zones()now returns a(zones, keepouts)tuple. Rule areas(
ZT_RULE_AREA) are extracted with all five constraint flags from therule_area_settingsproto:keepout_tracks,keepout_vias,keepout_copper,keepout_pads,keepout_footprints.Domain model (
board.py)Added
keepouts: List[Dict]field to theBoarddataclass.Router enforcement (
unified_pathfinder.py)New
_apply_keepout_obstacles(board)called at the end ofinitialize_graph():_points_in_polygon()NumPy ray-casting helper; vectorised overthe full (Nx x Ny) lattice plane in one pass per keepout.
base_cost = 1e9on planar edges whenkeepout_tracks=True, via edgeswhen
keepout_vias=True. Follows the same pattern as_apply_via_keepouts_to_graph().Visualization (
main_window.py)_draw_keepouts()renders each keepout outline as a dashed redsemi-transparent polygon, respecting layer visibility.
_draw_keepouts()when the "Keepouts" checkbox isenabled. (The checkbox existed but had no effect: the method and call site
were missing.)
Interactive inspection (
main_window.py)Right-clicking inside a keepout area shows a context menu with the keepout name,
affected layers, and per-constraint status:
✘ = prohibited · ✓ = allowed. Right-clicking outside any keepout shows nothing.
Log hygiene
_draw_tracks,_draw_vias, and_draw_zoneslogged at INFO on every paintevent (~50 ms during panning/zooming), producing hundreds of identical lines per
session. All per-frame diagnostic messages downgraded to DEBUG. Genuine warnings
(invalid data, transform failures) remain at WARNING.
Testing
Tested on TestBackplane.kicad_pcb (18-layer, 1604 pads, 512 routable nets,
KiCad 9.0, RTX 4090):
as expected (copper fills do not restrict track/via routing).
edges on the affected layers through the keepout polygon.
types.
Files changed
orthoroute/infrastructure/kicad/rich_kicad_interface.py track/via/zone/keepout extraction
orthoroute/domain/models/board.py keepouts field on Board
orthoroute/presentation/plugin/kicad_plugin.py SWIG fixes; keepout wiring
orthoroute/algorithms/manhattan/unified_pathfinder.py _apply_keepout_obstacles()
orthoroute/presentation/gui/main_window.py zone/keepout drawing, context menu, log fixes