You've already forked OrthoRoute
mirror of
https://github.com/bbenchoff/OrthoRoute.git
synced 2026-08-21 22:09:17 +00:00
189 lines
5.3 KiB
Python
189 lines
5.3 KiB
Python
"""Tests for benchmark result accounting."""
|
|
|
|
from types import SimpleNamespace
|
|
|
|
from benchmarks.metrics import collect_route_metrics
|
|
|
|
|
|
class _Accounting:
|
|
def compute_overuse(self, _router):
|
|
return 0, 0
|
|
|
|
|
|
def _net(name, pad_count):
|
|
return SimpleNamespace(
|
|
name=name,
|
|
id=name,
|
|
pads=[object() for _ in range(pad_count)],
|
|
)
|
|
|
|
|
|
def test_metrics_exclude_single_pin_nets_from_completion():
|
|
board = SimpleNamespace(
|
|
name="parsed-backplane",
|
|
layer_count=2,
|
|
nets=[
|
|
_net("ROUTED", 2),
|
|
_net("TRIVIAL", 2),
|
|
_net("NO_CONNECT", 1),
|
|
],
|
|
)
|
|
router = SimpleNamespace(
|
|
lattice=SimpleNamespace(
|
|
x_steps=2, y_steps=2, layers=2, num_nodes=8, pitch=0.4,
|
|
),
|
|
net_paths={"ROUTED": [0, 1, 5], "TRIVIAL": [2]},
|
|
accounting=_Accounting(),
|
|
iteration=3,
|
|
_excluded_nets=set(),
|
|
)
|
|
|
|
metrics = collect_route_metrics(router, board)
|
|
|
|
assert metrics["board"]["nets"] == 3
|
|
assert metrics["board"]["routable_nets"] == 2
|
|
assert metrics["board"]["singleton_nets"] == 1
|
|
assert metrics["completion"] == {
|
|
"routed_nets": 1,
|
|
"trivial_nets": 1,
|
|
"completed_nets": 2,
|
|
"total_nets": 2,
|
|
"excluded_nets": 0,
|
|
"excluded_net_ids": [],
|
|
"unrouted_net_ids": [],
|
|
"complete": True,
|
|
}
|
|
assert metrics["copper"]["wirelength_mm"] == 0.4
|
|
assert metrics["copper"]["via_transitions"] == 1
|
|
assert metrics["copper"]["via_layer_steps"] == 1
|
|
assert metrics["copper"]["layers_used"] == [0]
|
|
|
|
|
|
def test_metrics_coalesce_adjacent_layer_hops_into_one_via():
|
|
board = SimpleNamespace(
|
|
name="multi-hop-via",
|
|
layer_count=4,
|
|
nets=[_net("ROUTED", 2)],
|
|
)
|
|
# plane=4: 0→4→8 is one z run at xy=0, then a lateral step on z=2.
|
|
router = SimpleNamespace(
|
|
lattice=SimpleNamespace(
|
|
x_steps=2, y_steps=2, layers=4, num_nodes=16, pitch=0.4,
|
|
),
|
|
net_paths={"ROUTED": [0, 4, 8, 9]},
|
|
accounting=_Accounting(),
|
|
iteration=1,
|
|
_excluded_nets=set(),
|
|
)
|
|
|
|
copper = collect_route_metrics(router, board)["copper"]
|
|
|
|
assert copper["via_transitions"] == 1
|
|
assert copper["via_layer_steps"] == 2
|
|
|
|
|
|
def test_metrics_count_wrong_way_steps():
|
|
board = SimpleNamespace(
|
|
name="guided",
|
|
layer_count=3,
|
|
nets=[_net("ROUTED", 2)],
|
|
)
|
|
lattice = SimpleNamespace(
|
|
x_steps=3,
|
|
y_steps=3,
|
|
layers=3,
|
|
num_nodes=27,
|
|
pitch=0.4,
|
|
get_legal_axis=lambda layer: "h" if layer == 1 else "v",
|
|
)
|
|
router = SimpleNamespace(
|
|
lattice=lattice,
|
|
# z=1: one preferred +X step, then one wrong-way +Y step.
|
|
net_paths={"ROUTED": [9, 10, 13]},
|
|
accounting=_Accounting(),
|
|
iteration=1,
|
|
_excluded_nets=set(),
|
|
)
|
|
|
|
copper = collect_route_metrics(router, board)["copper"]
|
|
|
|
assert copper["preferred_steps_per_layer"] == {"1": 1}
|
|
assert copper["wrong_way_steps_per_layer"] == {"1": 1}
|
|
assert copper["wrong_way_steps"] == 1
|
|
|
|
|
|
def test_metrics_report_excluded_and_unrouted_ids():
|
|
board = SimpleNamespace(
|
|
name="partial",
|
|
layer_count=2,
|
|
nets=[_net("DONE", 2), _net("DROPPED", 2)],
|
|
)
|
|
router = SimpleNamespace(
|
|
lattice=SimpleNamespace(
|
|
x_steps=2, y_steps=2, layers=2, num_nodes=8, pitch=0.4,
|
|
),
|
|
net_paths={"DONE": [0, 1], "DROPPED": []},
|
|
accounting=_Accounting(),
|
|
iteration=5,
|
|
_excluded_nets={"DROPPED"},
|
|
)
|
|
|
|
completion = collect_route_metrics(router, board)["completion"]
|
|
|
|
assert completion["complete"] is False
|
|
assert completion["excluded_net_ids"] == ["DROPPED"]
|
|
assert completion["unrouted_net_ids"] == ["DROPPED"]
|
|
|
|
|
|
def test_metrics_reject_barrel_conflicts():
|
|
board = SimpleNamespace(
|
|
name="shorted",
|
|
layer_count=2,
|
|
nets=[_net("ROUTED", 2)],
|
|
)
|
|
router = SimpleNamespace(
|
|
lattice=SimpleNamespace(
|
|
x_steps=2, y_steps=2, layers=2,
|
|
num_nodes=8, pitch=0.4,
|
|
),
|
|
net_paths={"ROUTED": [0, 1]},
|
|
accounting=_Accounting(),
|
|
iteration=2,
|
|
_excluded_nets=set(),
|
|
_last_barrel_conflict_count=3,
|
|
_last_path_node_conflict_count=1,
|
|
_last_portal_grid_conflict_count=2,
|
|
)
|
|
|
|
metrics = collect_route_metrics(router, board)
|
|
|
|
assert metrics["completion"]["complete"] is False
|
|
assert metrics["convergence"]["barrel_conflicts"] == 3
|
|
assert metrics["convergence"]["path_node_conflicts"] == 1
|
|
assert metrics["convergence"]["portal_grid_conflicts"] == 2
|
|
|
|
|
|
def test_metrics_reject_shared_path_nodes_independently():
|
|
board = SimpleNamespace(
|
|
name="crossed",
|
|
layer_count=2,
|
|
nets=[_net("ROUTED", 2)],
|
|
)
|
|
router = SimpleNamespace(
|
|
lattice=SimpleNamespace(
|
|
x_steps=2, y_steps=2, layers=2,
|
|
num_nodes=8, pitch=0.4,
|
|
),
|
|
net_paths={"ROUTED": [0, 1]},
|
|
accounting=_Accounting(),
|
|
iteration=2,
|
|
_excluded_nets=set(),
|
|
_last_barrel_conflict_count=0,
|
|
_last_path_node_conflict_count=1,
|
|
)
|
|
|
|
metrics = collect_route_metrics(router, board)
|
|
|
|
assert metrics["completion"]["complete"] is False
|
|
assert metrics["convergence"]["path_node_conflicts"] == 1
|