Route 45-degree traces on the exact track (opt-in diagonal mode)
Add diagonal=True to the exact router: after orthogonal routing, each 2-pin net is retried as the shortest exactly-clean octilinear (0/45/90/135-degree) trace. A dropped net is recovered; an orthogonal route is replaced only when the diagonal is strictly shorter. Candidates are the direct 45-degree segment or the two diagonal-plus-axis two-benders; each segment's diagonal copper is covered by the exact octagon and its clearance checked with clearance_conflict_shape, so a trace fits a diagonal corridor the bounding-box cover would reject. Endpoints stay on the pads; diagonal copper is stored with its exact octagon so later nets clear it precisely; same-net copper is ignored during the check so the candidate is verified against every other net before the orthogonal copper is ripped. With diagonal=False the pass is skipped and output is byte-for-byte the orthogonal router. Threaded through route_dsn_board_exact / build_exact_routing_result / route(engine="exact").
This commit is contained in:
@@ -111,11 +111,13 @@ def route_dsn_board_exact(
|
||||
max_passes: int = 10,
|
||||
rip_up: bool = True,
|
||||
shove: bool = False,
|
||||
diagonal: bool = False,
|
||||
) -> tuple[ExactRouteResult, int, list[str]]:
|
||||
"""Route a parsed :class:`DsnBoard` with the exact-geometry (orthogonal,
|
||||
DRC-verified) track; return the exact result, the scale, and layer names.
|
||||
``shove`` enables moving existing traces aside to recover dropped nets;
|
||||
``rip_up`` toggles the underlying grid's rip-up-and-retry."""
|
||||
``rip_up`` toggles the underlying grid's rip-up-and-retry; ``diagonal`` enables
|
||||
the 45-degree recovery pass for still-dropped 2-pin nets."""
|
||||
board = build_board(dsn)
|
||||
scale = max(dsn.resolution.value, 1)
|
||||
width_board = round(_rule_width_dsn(dsn) * scale)
|
||||
@@ -128,15 +130,18 @@ def route_dsn_board_exact(
|
||||
max_passes=max_passes,
|
||||
rip_up=rip_up,
|
||||
shove=shove,
|
||||
diagonal=diagonal,
|
||||
)
|
||||
return exact, scale, [layer.name for layer in dsn.layers]
|
||||
|
||||
|
||||
def build_exact_routing_result(
|
||||
dsn: DsnBoard, *, layers: list[int] | None = None, shove: bool = False
|
||||
dsn: DsnBoard, *, layers: list[int] | None = None, shove: bool = False, diagonal: bool = False
|
||||
) -> RoutingResult:
|
||||
"""Route ``dsn`` (exact track) and convert to a DSN-unit RoutingResult."""
|
||||
exact, scale, layer_names = route_dsn_board_exact(dsn, layers=layers, shove=shove)
|
||||
exact, scale, layer_names = route_dsn_board_exact(
|
||||
dsn, layers=layers, shove=shove, diagonal=diagonal
|
||||
)
|
||||
return _to_routing_result(exact.result, dsn, scale, layer_names)
|
||||
|
||||
|
||||
@@ -177,6 +182,7 @@ def route(
|
||||
engine: str = "grid",
|
||||
shove: bool = False,
|
||||
pack: bool = False,
|
||||
diagonal: bool = False,
|
||||
) -> str:
|
||||
"""Route a Specctra DSN string and return the routed SES string.
|
||||
|
||||
@@ -190,7 +196,7 @@ def route(
|
||||
"""
|
||||
dsn = parse_dsn(dsn_text)
|
||||
if engine == "exact":
|
||||
result = build_exact_routing_result(dsn, layers=layers, shove=shove)
|
||||
result = build_exact_routing_result(dsn, layers=layers, shove=shove, diagonal=diagonal)
|
||||
elif engine == "room":
|
||||
result = build_rooms_routing_result(dsn, layers=layers, shove=shove, pack=pack)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user