Write each plane via once in the exact engine's output too
The exact engine rebuilds its output from each connection's own vias, so connections sharing a plane via each wrote a copy: th-eda's flight controller had 71 spots carrying 2 to 4 vias of one net. Vias are now written once per net and spot, and never on a via already on the board.
This commit is contained in:
@@ -31,7 +31,7 @@ from dataclasses import dataclass, field
|
|||||||
import math
|
import math
|
||||||
|
|
||||||
from freeroute.board.board import BasicBoard
|
from freeroute.board.board import BasicBoard
|
||||||
from freeroute.board.items import Pin
|
from freeroute.board.items import Pin, Via
|
||||||
from freeroute.board.search_tree import ShapeSearchTree, TreeShape
|
from freeroute.board.search_tree import ShapeSearchTree, TreeShape
|
||||||
from freeroute.geometry import (
|
from freeroute.geometry import (
|
||||||
IntBox,
|
IntBox,
|
||||||
@@ -178,6 +178,11 @@ def route_board_exact(
|
|||||||
|
|
||||||
via_layers = frozenset(signal_layers)
|
via_layers = frozenset(signal_layers)
|
||||||
accepted: dict[int, _Accepted] = {}
|
accepted: dict[int, _Accepted] = {}
|
||||||
|
fixed_vias = {
|
||||||
|
(item.net_nos[0], item.location)
|
||||||
|
for item in board.get_items()
|
||||||
|
if isinstance(item, Via) and item.fixed and item.net_nos
|
||||||
|
}
|
||||||
|
|
||||||
# Verify connection by connection, so one conflicting segment of a
|
# Verify connection by connection, so one conflicting segment of a
|
||||||
# 25-pin supply net costs that one connection, not the whole net.
|
# 25-pin supply net costs that one connection, not the whole net.
|
||||||
@@ -207,7 +212,11 @@ def route_board_exact(
|
|||||||
if acc is None:
|
if acc is None:
|
||||||
acc = accepted[net_no] = _Accepted(wires=[], vias=[])
|
acc = accepted[net_no] = _Accepted(wires=[], vias=[])
|
||||||
acc.wires.extend(wires)
|
acc.wires.extend(wires)
|
||||||
acc.vias.extend(vias)
|
# connections of one net that end on the same plane cell share its
|
||||||
|
# via: write it once, and never on top of a via already on the board
|
||||||
|
acc.vias.extend(
|
||||||
|
v for v in dict.fromkeys(vias) if v not in acc.vias and (net_no, v) not in fixed_vias
|
||||||
|
)
|
||||||
for box, box_layers in boxes:
|
for box, box_layers in boxes:
|
||||||
oid = next(owner)
|
oid = next(owner)
|
||||||
tree.insert(TreeShape(oid, net_no, box_layers, box, routed=True))
|
tree.insert(TreeShape(oid, net_no, box_layers, box, routed=True))
|
||||||
|
|||||||
@@ -34,3 +34,23 @@ def test_a_nets_own_vias_keep_hole_to_hole_spacing():
|
|||||||
need = (300 + 250) * scale # drill + 0.25 mm, centre to centre
|
need = (300 + 250) * scale # drill + 0.25 mm, centre to centre
|
||||||
for a, b in itertools.combinations(vias, 2):
|
for a, b in itertools.combinations(vias, 2):
|
||||||
assert math.hypot(a.x - b.x, a.y - b.y) >= need, f"vias at {a} and {b} too close"
|
assert math.hypot(a.x - b.x, a.y - b.y) >= need, f"vias at {a} and {b} too close"
|
||||||
|
|
||||||
|
|
||||||
|
def test_connections_sharing_a_plane_via_write_it_once():
|
||||||
|
# eight GND pads 0.4 mm apart: the hole spacing makes several of them
|
||||||
|
# end on the same plane via, which must come out once, not once each
|
||||||
|
pads = " ".join(f"(place G{i} {9000 + 400 * i} -10000 front 0)" for i in range(8))
|
||||||
|
pins = " ".join(f"G{i}-1" for i in range(8))
|
||||||
|
dsn = parse_dsn(
|
||||||
|
_DSN.replace(
|
||||||
|
"(place G1 9000 -10000 front 0) (place G2 9500 -10000 front 0)\n"
|
||||||
|
" (place G3 10000 -10000 front 0) (place G4 10500 -10000 front 0)",
|
||||||
|
pads,
|
||||||
|
)
|
||||||
|
.replace("(pins G1-1 G2-1 G3-1 G4-1)", f"(pins {pins})")
|
||||||
|
.replace("(rect F.Cu -150 -300 150 300)", "(rect F.Cu -125 -300 125 300)")
|
||||||
|
)
|
||||||
|
exact, _scale, _ = route_dsn_board_exact(dsn, resolution=2)
|
||||||
|
vias = exact.result.vias[1]
|
||||||
|
assert len(vias) < 8, "no via is shared, so this board no longer tests sharing"
|
||||||
|
assert len(set(vias)) == len(vias), "a shared via written more than once"
|
||||||
|
|||||||
Reference in New Issue
Block a user