Compare commits

...
Author SHA1 Message Date
rsp2k 33de21ba0e Route with the exact engine by default; warn when an engine does not check
The grid engine was the default and its copper is not checked against exact
shapes: a full reroute of the Labrador lid with no flags came out with 15
tracks_crossing and 87 clearance violations under KiCad's DRC while the
report listed only unrouted connections. The exact engine (what mckicad and
every benchmark already use) is now the default, and grid or room runs end
with a warning that their output needs a DRC.
2026-10-07 18:37:33 -06:00
rsp2k 3b29edc624 Merge feat/rename-rpmroute: the router is now rpmroute (freeroute kept as an alias) 2026-10-07 17:35:56 -06:00
2 changed files with 33 additions and 9 deletions
+16 -4
View File
@@ -94,11 +94,12 @@ def build_parser() -> argparse.ArgumentParser:
parser.add_argument(
"--engine",
choices=sorted(ENGINE_OPTIONS),
default="grid",
default="exact",
help=(
"routing track: grid (default; multi-layer rip-up maze, highest coverage), "
"exact (orthogonal, exact-geometry DRC-verified output), "
"room (continuous expansion rooms, routes off-grid channels)"
"routing track: exact (default; every route checked against exact pad and "
"copper shapes, DRC-clean output), grid (quick maze on the grid alone: its "
"copper is NOT clearance-checked and can short), room (continuous expansion "
"rooms, routes off-grid channels; not clearance-checked either)"
),
)
parser.add_argument(
@@ -386,6 +387,17 @@ def main(argv: list[str] | None = None) -> int:
for net, a, b, zone in in_zone:
print(f" {net}: {a} to {b} (both in zone {zone})", file=sys.stderr)
if args.engine != "exact":
# These engines route on approximations and do not check the copper
# they write against exact shapes: a board can come out with shorts
# that this report would otherwise never mention.
print(
f"rpmroute: WARNING: the {args.engine} engine does not check its copper for "
"clearance or shorts; run KiCad's DRC on the result, or route with "
"--engine exact (the default)",
file=sys.stderr,
)
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
f.write(ses_text)
+17 -5
View File
@@ -71,13 +71,25 @@ def test_cli_every_engine_routes_a_fixture(engine, tmp_path):
assert "(wire" in text
def test_cli_default_engine_is_grid(tmp_path):
"""The default must stay grid — the drop-in JAR replacement behaviour."""
def test_cli_default_engine_is_exact(tmp_path):
"""The default is the engine that checks its copper: grid output can short
and say nothing (a user routing with no flags shipped 15 crossings)."""
default = tmp_path / "default.ses"
grid = tmp_path / "grid.ses"
exact = tmp_path / "exact.ses"
assert main([str(FIXTURE), "-do", str(default)]) == 0
assert main([str(FIXTURE), "--engine", "grid", "-do", str(grid)]) == 0
assert default.read_text() == grid.read_text()
assert main([str(FIXTURE), "--engine", "exact", "-do", str(exact)]) == 0
assert default.read_text() == exact.read_text()
@pytest.mark.parametrize("engine", ["grid", "room"])
def test_unchecked_engines_say_so(tmp_path, capsys, engine):
assert main([str(FIXTURE), "--engine", engine, "-do", str(tmp_path / "out.ses")]) == 0
assert "does not check its copper" in capsys.readouterr().err
def test_the_exact_engine_does_not_warn(tmp_path, capsys):
assert main([str(FIXTURE), "-do", str(tmp_path / "out.ses")]) == 0
assert "WARNING" not in capsys.readouterr().err
def test_cli_room_pack_routes(tmp_path):