Keep a route's own vias apart while it is searched
Committed vias were checked for hole spacing, but a route's own vias are not committed until it is done, so a route hopping layers (more of them on 6 layers) could put two of its vias 0.41 mm apart, as th-eda's 6-layer flight controller showed. A via is now also checked against layer changes earlier on its own route.
This commit is contained in:
@@ -538,6 +538,26 @@ class GridRouter:
|
|||||||
return False
|
return False
|
||||||
return self._holes_clear(cell, net_no)
|
return self._holes_clear(cell, net_no)
|
||||||
|
|
||||||
|
def _near_path_via(self, node: Node, cell: Cell, came_from: dict) -> bool:
|
||||||
|
"""A layer change earlier on the route that reaches ``node`` sits
|
||||||
|
within hole spacing of ``cell`` (and is not the same through via).
|
||||||
|
Committed vias are checked elsewhere; a route's own are not yet
|
||||||
|
committed while it is searched. Looks back far enough to cover the
|
||||||
|
hole spacing twice over, not along the whole route."""
|
||||||
|
limit = 4 * (math.ceil(self._hole_need / self.step) + 1)
|
||||||
|
need = self._hole_need / self.step
|
||||||
|
steps = 0
|
||||||
|
while node in came_from and steps < limit:
|
||||||
|
prev = came_from[node]
|
||||||
|
changes_layer = prev[:2] == node[:2] and prev[2] != node[2]
|
||||||
|
if changes_layer and node[:2] != cell and (
|
||||||
|
math.hypot(node[0] - cell[0], node[1] - cell[1]) < need
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
node = prev
|
||||||
|
steps += 1
|
||||||
|
return False
|
||||||
|
|
||||||
def _via_nets_at(self, cell: Cell) -> set[int]:
|
def _via_nets_at(self, cell: Cell) -> set[int]:
|
||||||
nets = {net for net, n in self._via_nets.get(cell, {}).items() if n > 0}
|
nets = {net for net, n in self._via_nets.get(cell, {}).items() if n > 0}
|
||||||
fixed = self._fixed_vias.get(cell)
|
fixed = self._fixed_vias.get(cell)
|
||||||
@@ -664,6 +684,8 @@ class GridRouter:
|
|||||||
pin = ends.get(node)
|
pin = ends.get(node)
|
||||||
if ok and isinstance(pin, Pin) and self._walled(node):
|
if ok and isinstance(pin, Pin) and self._walled(node):
|
||||||
ok = self._via_fits_at(pin.location, net_no)
|
ok = self._via_fits_at(pin.location, net_no)
|
||||||
|
if ok and self._near_path_via(source, cell, came_from):
|
||||||
|
ok = False # too close to a via earlier on this same route
|
||||||
if ok:
|
if ok:
|
||||||
self._relax(source, target, g_via, goal_cell, g_score, came_from, open_heap)
|
self._relax(source, target, g_via, goal_cell, g_score, came_from, open_heap)
|
||||||
continue
|
continue
|
||||||
@@ -675,6 +697,8 @@ class GridRouter:
|
|||||||
ok = via_ok.get(cell)
|
ok = via_ok.get(cell)
|
||||||
if ok is None:
|
if ok is None:
|
||||||
ok = via_ok[cell] = self._via_placeable(cell, net_no, conns)
|
ok = via_ok[cell] = self._via_placeable(cell, net_no, conns)
|
||||||
|
if ok and self._near_path_via(current, cell, came_from):
|
||||||
|
ok = False
|
||||||
else:
|
else:
|
||||||
ok = True
|
ok = True
|
||||||
if ok:
|
if ok:
|
||||||
|
|||||||
@@ -124,3 +124,13 @@ def test_hole_spacing_from_a_fixed_via_is_measured_from_where_it_really_is():
|
|||||||
assert not router._holes_clear(cell, 1), f"{d / s:.0f} um from the fixed via"
|
assert not router._holes_clear(cell, 1), f"{d / s:.0f} um from the fixed via"
|
||||||
elif 560 * s < d < 700 * s and cell not in router._tht_block:
|
elif 560 * s < d < 700 * s and cell not in router._tht_block:
|
||||||
assert router._holes_clear(cell, 1)
|
assert router._holes_clear(cell, 1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_a_route_keeps_its_own_vias_apart():
|
||||||
|
# a route that changed layer at (10, 10) may not change layer again one
|
||||||
|
# cell away; the same cell is the same through via, and far is fine
|
||||||
|
router, _s = _router(_THT)
|
||||||
|
came_from = {(10, 10, 1): (10, 10, 0), (11, 10, 1): (10, 10, 1), (12, 10, 1): (11, 10, 1)}
|
||||||
|
assert router._near_path_via((12, 10, 1), (11, 10), came_from)
|
||||||
|
assert not router._near_path_via((12, 10, 1), (10, 10), came_from)
|
||||||
|
assert not router._near_path_via((12, 10, 1), (40, 10), came_from)
|
||||||
|
|||||||
Reference in New Issue
Block a user