Count on a zone's connectivity only when no track can cross it
A zone outline is where copper may go, not where it ends up: on the rc4 sense board the board-wide GND pours break into islands around other nets' tracks, and treating every pad inside them as connected left 28 GND islands unjoined (63 unconnected against 42 without zones). Trust a zone only when a no-tracks rule area covers it on its layer, as the power stage's pours are covered; route the rest with tracks as before. rc4, exact engine, resolution 2: power stage 5 unconnected (JAR 12), sense board 41 (JAR 32), no DRC errors on either.
This commit is contained in:
@@ -506,6 +506,23 @@ class GridRouter:
|
|||||||
self._zone_cells[key] = sorted(set(nodes))
|
self._zone_cells[key] = sorted(set(nodes))
|
||||||
return self._zone_cells[key]
|
return self._zone_cells[key]
|
||||||
|
|
||||||
|
def _zone_is_solid(self, zone, coverage: float = 0.95) -> bool:
|
||||||
|
"""Whether a zone's fill can be trusted to be one piece of copper.
|
||||||
|
|
||||||
|
A zone outline is where copper may go, not where it will be: other
|
||||||
|
nets' tracks through a board-wide pour break its fill into islands,
|
||||||
|
and a pad inside the outline need not reach the rest of the net. It
|
||||||
|
is safe to count on only when no track can cross it, which is what a
|
||||||
|
no-tracks rule area over the zone guarantees (the rc4 power pours).
|
||||||
|
Otherwise the zone is left out and its pads are routed with tracks.
|
||||||
|
"""
|
||||||
|
cells = [cell for tile in zone.tiles for cell in self._cells_in_box(tile.bounding_box(), 0)
|
||||||
|
if zone.polygon.contains(self._cell_center(cell))]
|
||||||
|
if not cells:
|
||||||
|
return False
|
||||||
|
covered = sum((*cell, zone.layer) in self._keepout for cell in cells)
|
||||||
|
return covered >= coverage * len(cells)
|
||||||
|
|
||||||
def _group_ends(self, group, net_no: int, conns) -> dict[Node, Pin | None]:
|
def _group_ends(self, group, net_no: int, conns) -> dict[Node, Pin | None]:
|
||||||
"""End nodes of a group, each mapped to its pin (None for a zone cell)."""
|
"""End nodes of a group, each mapped to its pin (None for a zone cell)."""
|
||||||
ends: dict[Node, Pin | None] = {}
|
ends: dict[Node, Pin | None] = {}
|
||||||
@@ -693,7 +710,7 @@ class GridRouter:
|
|||||||
pins_by_net = self._pins_by_net()
|
pins_by_net = self._pins_by_net()
|
||||||
zones_by_net: dict[int, list] = {}
|
zones_by_net: dict[int, list] = {}
|
||||||
for zone in self.board.get_conduction_areas():
|
for zone in self.board.get_conduction_areas():
|
||||||
if zone.layer in self.layers and zone.net_nos:
|
if zone.layer in self.layers and zone.net_nos and self._zone_is_solid(zone):
|
||||||
zones_by_net.setdefault(zone.net_nos[0], []).append(zone)
|
zones_by_net.setdefault(zone.net_nos[0], []).append(zone)
|
||||||
conns: list[_Connection] = []
|
conns: list[_Connection] = []
|
||||||
nets = set(pins_by_net) | set(zones_by_net)
|
nets = set(pins_by_net) | set(zones_by_net)
|
||||||
|
|||||||
@@ -138,3 +138,13 @@ def test_a_pad_reaches_a_zone_under_a_no_tracks_area_by_a_via():
|
|||||||
if layer == f_cu: # no track runs inside the no-tracks area
|
if layer == f_cu: # no track runs inside the no-tracks area
|
||||||
assert not any(t.contains(p) and not t.bounding_box().is_empty()
|
assert not any(t.contains(p) and not t.bounding_box().is_empty()
|
||||||
for t in pour.tiles for p in pts[1:-1])
|
for t in pour.tiles for p in pts[1:-1])
|
||||||
|
|
||||||
|
|
||||||
|
def test_a_pour_other_nets_can_cross_is_not_trusted_to_connect():
|
||||||
|
# the same zone with no no-tracks area over it: its fill could be split by
|
||||||
|
# other nets' tracks, so its pads are joined by routing, not assumed
|
||||||
|
places = "(place P1 5500 -7000 front 0) (place P2 8500 -7000 front 0)"
|
||||||
|
dsn = parse_dsn(_dsn(f"(component P {places})", "(net N (pins P1-1 P2-1))", _ZONE))
|
||||||
|
result, _, _ = route_dsn_board_exact(dsn)
|
||||||
|
net = next(iter(result.routed_net_numbers))
|
||||||
|
assert result.result.wires.get(net) # P1 and P2 got a track between them
|
||||||
|
|||||||
Reference in New Issue
Block a user