"""Vias keep hole-to-hole spacing, even within one net.""" from __future__ import annotations import itertools import math from freeroute.dsn import parse_dsn from freeroute.route.pipeline import route_dsn_board_exact # four GND pads 0.5 mm apart over a GND plane: each drops a via to the plane _DSN = """(pcb holes (parser) (resolution um 10) (unit um) (structure (layer F.Cu (type signal)) (layer In1.Cu (type power)) (layer In2.Cu (type power)) (layer B.Cu (type signal)) (boundary (path pcb 0 0 0 20000 0 20000 -20000 0 -20000 0 0)) (plane GND (polygon In1.Cu 0 500 -500 19500 -500 19500 -19500 500 -19500 500 -500)) (via "Via[0-3]_500:300_um") (rule (width 150) (clearance 150))) (placement (component S (place G1 9000 -10000 front 0) (place G2 9500 -10000 front 0) (place G3 10000 -10000 front 0) (place G4 10500 -10000 front 0))) (library (image S (pin smd 1 0 0)) (padstack smd (shape (rect F.Cu -150 -300 150 300)) (attach off)) (padstack "Via[0-3]_500:300_um" (shape (circle F.Cu 500)) (shape (circle B.Cu 500)) (attach off))) (network (net GND (pins G1-1 G2-1 G3-1 G4-1))))""" def test_a_nets_own_vias_keep_hole_to_hole_spacing(): dsn = parse_dsn(_DSN) exact, scale, _ = route_dsn_board_exact(dsn, resolution=2) assert exact.result.failed == [] vias = exact.result.vias[1] assert len(set(vias)) == len(vias), "a via written twice" need = (300 + 250) * scale # drill + 0.25 mm, centre to centre 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" 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"