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:
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user