"""Pins of a 1.27 mm pitch row routed at 1.0 mm (the RN2483 module on the TTN Enschede mote). A trace centre has to stay within 0.06 mm of a pin's centreline to pass its neighbours, which no grid column hits, so a route leaves each pin straight along that line and only jogs to its column once past the pads. FreeRouting routes this row in full the same way.""" from __future__ import annotations import pytest from rpmroute.board import build_board from rpmroute.board.items import Pin from rpmroute.dsn import parse_dsn from rpmroute.geometry import IntPoint from rpmroute.route.grid_router import GridRouter from rpmroute.route.pipeline import route_dsn_board_exact def _row(x0: int, pins: int = 6, skew: int = 3000) -> str: places = " ".join(f"(place R{i} {x0 + 1270 * i} -5000 front 0)" for i in range(pins)) places += " " + " ".join( f"(place T{i} {x0 + 1270 * i + skew} -15000 front 0)" for i in range(pins) ) nets = " ".join(f"(net N{i} (pins R{i}-1 T{i}-1))" for i in range(pins)) return f"""(pcb t (parser) (resolution um 10) (unit um) (structure (layer F.Cu (type signal)) (layer B.Cu (type signal)) (boundary (path pcb 0 0 0 30000 0 30000 -20000 0 -20000 0 0)) (via "Via[0-1]_600:400_um") (rule (width 1000) (clearance 200))) (placement (component P {places})) (library (image P (pin pad 1 0 0)) (padstack pad (shape (rect F.Cu -508 -762 508 762)) (attach off)) (padstack "Via[0-1]_600:400_um" (shape (circle F.Cu 600)) (shape (circle B.Cu 600)) (attach off))) (network {nets}))""" @pytest.mark.parametrize("x0", [5000, 5150, 5300]) def test_every_pin_of_a_row_leaves_straight_and_routes(x0): # three offsets of the row against the grid; before, 2 or 3 of 6 routed result, _, _ = route_dsn_board_exact(parse_dsn(_row(x0)), resolution=2) assert len(result.routed_net_numbers) == 6 assert result.drc_clean def test_a_walled_in_pin_may_escape_to_the_column_either_side(): # two pins side by side leaving the same way can then jog apart board = build_board(parse_dsn(_row(5000))) router = GridRouter(board, trace_width=10000, clearance=2000, orthogonal=True, resolution=2) router._conns = router._build_connections() pin = next( p for p in board.get_items() if isinstance(p, Pin) and p.location == IntPoint(50000 + 2 * 12700, -50000) ) net = pin.net_nos[0] cx, cy = router._cell_of(pin.location) nodes = router._escape_nodes(pin, net, router._conns, [0], (cx, cy)) columns = {x for x, y, _ in nodes if y != cy} assert {cx - 1, cx, cx + 1} <= columns