Hole spacing also from through-hole pads and fixed vias
A route could drop a via next to (or onto) a through-hole pad of its own net, where it changes layer for free, and a via reusing a fixed via's cell came out a little off the fixed via's centre, beside it. No via now goes within hole spacing of a through-hole pad of any net; a via in a pad is checked exactly against every via and hole; and a routed via on a fixed via of its net is not written. charge-sense: 4 hole_to_hole to 0; flight controller: 2 to 0, unconnected unchanged.
This commit is contained in:
@@ -257,6 +257,7 @@ class GridRouter:
|
||||
# an own-net via at the very same cell, which it simply reuses.
|
||||
drill = via_drill if via_drill else 2 * self.via_half
|
||||
need = drill + max(hole_to_hole, 0)
|
||||
self._via_drill, self._hole_gap, self._hole_need = drill, max(hole_to_hole, 0), need
|
||||
reach = math.ceil(need / self.step)
|
||||
self._hole_offsets = [
|
||||
(dx, dy)
|
||||
@@ -265,6 +266,7 @@ class GridRouter:
|
||||
if (dx or dy) and math.hypot(dx, dy) * self.step < need
|
||||
]
|
||||
self._via_nets: dict[Cell, dict[int, int]] = {} # routed via centres
|
||||
self._via_centres: list[IntPoint] | None = None # cache for _hole_clear_at
|
||||
self._fixed_vias: dict[Cell, int] = {}
|
||||
self._fixed_via_points: set[tuple[int, IntPoint]] = set()
|
||||
|
||||
@@ -299,6 +301,21 @@ class GridRouter:
|
||||
if isinstance(item, Via) and item.fixed and item.net_nos:
|
||||
self._fixed_vias[self._cell_of(item.location)] = item.net_nos[0]
|
||||
self._fixed_via_points.add((item.net_nos[0], item.location))
|
||||
# Through-hole pads have holes too, and a route changes layer at one
|
||||
# for free, so no via (of any net) goes within hole spacing of one.
|
||||
# The DSN has no drill for a pad; its smaller half size stands in.
|
||||
self._tht_holes: list[tuple[IntPoint, int]] = []
|
||||
self._tht_block: set[Cell] = set()
|
||||
for pin in board.get_pins():
|
||||
if pin.shape is None or sum(1 for layer in pin.layers if layer in self.layers) < 2:
|
||||
continue
|
||||
box = pin.shape.bounding_box()
|
||||
radius = min(box.ur.x - box.ll.x, box.ur.y - box.ll.y) // 2
|
||||
reach = radius + self._via_drill // 2 + self._hole_gap
|
||||
self._tht_holes.append((pin.location, reach))
|
||||
ring = IntBox(pin.location.x, pin.location.y, pin.location.x, pin.location.y)
|
||||
for cell in self._cells_in_box(ring, reach):
|
||||
self._tht_block.add(cell)
|
||||
|
||||
# --- grid helpers -------------------------------------------------------
|
||||
|
||||
@@ -524,7 +541,10 @@ class GridRouter:
|
||||
return nets
|
||||
|
||||
def _holes_clear(self, cell: Cell, net_no: int) -> bool:
|
||||
"""No via centre within hole-to-hole reach, but an own-net one here."""
|
||||
"""No via centre within hole-to-hole reach, but an own-net one here,
|
||||
and no through-hole pad's hole within reach at all."""
|
||||
if cell in self._tht_block:
|
||||
return False
|
||||
if self._via_nets_at(cell) - {net_no}:
|
||||
return False
|
||||
cx, cy = cell
|
||||
@@ -717,7 +737,23 @@ class GridRouter:
|
||||
]
|
||||
copper += [(box, net) for net, _, box in self.board.get_fixed_copper()]
|
||||
self._static_copper = copper
|
||||
return not any(net != net_no and box.overlaps(grown) for box, net in self._static_copper)
|
||||
if any(net != net_no and box.overlaps(grown) for box, net in self._static_copper):
|
||||
return False
|
||||
return self._hole_clear_at(point)
|
||||
|
||||
def _hole_clear_at(self, point: IntPoint) -> bool:
|
||||
"""Hole spacing measured exactly from ``point`` to every via and
|
||||
through-hole pad (a via moved into a pad is not on its cell's centre)."""
|
||||
need = self._hole_need
|
||||
if self._via_centres is None: # rebuilt only after vias change
|
||||
self._via_centres = [loc for _net, loc in self._fixed_via_points] + [
|
||||
self._cell_center(c) for c, count in self._via_nets.items() if any(count.values())
|
||||
]
|
||||
if any(math.hypot(c.x - point.x, c.y - point.y) < need for c in self._via_centres):
|
||||
return False
|
||||
return not any(
|
||||
math.hypot(loc.x - point.x, loc.y - point.y) < reach for loc, reach in self._tht_holes
|
||||
)
|
||||
|
||||
def _stub_cells(self, pin_location: IntPoint, cell: Cell, half: int | None = None) -> list[Cell]:
|
||||
"""Cells where another net's trace would come too close to the stub."""
|
||||
@@ -993,6 +1029,8 @@ class GridRouter:
|
||||
for cell in conn.via_cells:
|
||||
count = self._via_nets.setdefault(cell, {})
|
||||
count[conn.net_no] = count.get(conn.net_no, 0) + 1
|
||||
if conn.via_cells:
|
||||
self._via_centres = None
|
||||
for cell, layer in conn.trace_cells:
|
||||
self._cell_owner[(*cell, layer)] = conn.index
|
||||
conn.half = half = self._conn_half(conn)
|
||||
@@ -1071,6 +1109,8 @@ class GridRouter:
|
||||
count = self._via_nets.get(cell)
|
||||
if count and count.get(conn.net_no):
|
||||
count[conn.net_no] -= 1
|
||||
if conn.via_cells:
|
||||
self._via_centres = None
|
||||
conn.via_cells = []
|
||||
conn.wires = []
|
||||
conn.vias = []
|
||||
|
||||
Reference in New Issue
Block a user