"""--negotiate: PathFinder-style rounds on the empty board before routing.""" from __future__ import annotations from pathlib import Path import pytest from rpmroute.board import build_board from rpmroute.dsn import parse_dsn from rpmroute.route.grid_router import GridRouter from rpmroute.route.pipeline import _rule_clearance_dsn, _rule_width_dsn, route_dsn_board FIXTURES = Path(__file__).resolve().parent.parent / "dsn" / "fixtures" def _router(name, negotiate): dsn = parse_dsn((FIXTURES / name).read_text()) s = dsn.resolution.value return GridRouter( build_board(dsn), trace_width=round(_rule_width_dsn(dsn) * s), clearance=round(_rule_clearance_dsn(dsn) * s), negotiate=negotiate, ) def test_negotiation_leaves_the_board_empty_and_the_ends_as_they_were(): router = _router("true_density.dsn", 3) conns = router._conns = router._build_connections() ends = [(c.a_end, c.b_end) for c in conns] router._negotiate(list(conns), conns) assert router._history # a dense board has contested cells assert not router._cell_owner and not router._halo and not router._via_claims assert not any(c.routed for c in conns) assert [(c.a_end, c.b_end) for c in conns] == ends assert router._present is None def test_sharing_is_priced_only_for_other_nets(): router = _router("true_density.dsn", 1) node = (3, 4, 0) router._history[node] = 2.0 router._present, router._present_cost = {node: {7: 1, 9: 2}}, 0.5 assert router._congestion(node, 7) == pytest.approx(2.5) # one other net assert router._congestion(node, 5) == pytest.approx(3.0) # two other nets router._present = None assert router._congestion(node, 5) == pytest.approx(2.0) # history only, after @pytest.mark.parametrize("name", ["ripup_needed.dsn", "true_density.dsn", "kicad_routable.dsn"]) def test_negotiated_routing_keeps_the_occupancy_honest(name): """Only routed connections hold cells afterwards, as without negotiation.""" router = _router(name, 3) router.route() conns = router._conns assert all(conns[i].routed for i in router._cell_owner.values()) assert all(conns[i].routed for claims in router._halo.values() for i in claims) def test_option_reaches_the_router_and_is_off_by_default(): text = (FIXTURES / "kicad_routable.dsn").read_text() plain, _, _ = route_dsn_board(parse_dsn(text)) again, _, _ = route_dsn_board(parse_dsn(text), negotiate=0) assert plain.unrouted == again.unrouted