Check via footprints lazily in the grid search

Profiling the rc4 sense board at resolution 2 put half the time in
_via_placeable: every expanded cell checked a 5x5 via footprint on both
layers, for vias the search almost never takes. Queue a layer change as a
candidate and check its footprint (memoised per search) only when it is
popped. A check can only rule a via out, never make it cheaper, so this
cannot change which route is found.
This commit is contained in:
2026-09-27 11:41:42 -06:00
parent 67c6c205f1
commit 83b2248a97
+24 -4
View File
@@ -376,8 +376,26 @@ class GridRouter:
g_score[s] = self._stub_cost(conn.a, s)
heapq.heappush(open_heap, (g_score[s] + self._h(s, goal_cell), s))
# Via footprints are checked lazily: a layer change goes on the heap as
# a candidate and is checked only if it is popped. Most never are (a
# via costs a lot), and the check is the single most expensive thing
# the search does. A check can only rule a via out, never make it
# cheaper, so deferring it cannot change which route is found.
via_ok: dict[Cell, bool] = {}
while open_heap:
_, current = heapq.heappop(open_heap)
entry = heapq.heappop(open_heap)
if len(entry) == 4: # a deferred via: (f, target, g, source)
_, target, g_via, source = entry
if g_via >= g_score.get(target, math.inf):
continue
cell = (target[0], target[1])
ok = via_ok.get(cell)
if ok is None:
ok = via_ok[cell] = self._via_placeable(cell, net_no, conns)
if ok:
self._relax(source, target, g_via, goal_cell, g_score, came_from, open_heap)
continue
current = entry[1]
if current in goals:
return _reconstruct(came_from, current)
cx, cy, cl = current
@@ -397,13 +415,15 @@ class GridRouter:
self._relax(
current, nxt, base + step + enter, goal_cell, g_score, came_from, open_heap
)
if len(self.layers) > 1 and self._via_placeable((cx, cy), net_no, conns):
if len(self.layers) > 1:
g_via = base + self.via_cost
for layer in self.layers:
if layer == cl:
continue
nxt = (cx, cy, layer)
self._relax(
current, nxt, base + self.via_cost, goal_cell, g_score, came_from, open_heap
if g_via < g_score.get(nxt, math.inf):
heapq.heappush(
open_heap, (g_via + self._h(nxt, goal_cell), nxt, g_via, current)
)
return None