Merge pull request 'Removing mxpic_forge from dependency' (#2) from main into pengkun_main #3

Merged
PotatoMaxwell merged 16 commits from pengkun_main into qinyue_main 2026-06-10 11:34:17 +00:00
Showing only changes of commit f367fd4fc6 - Show all commits
+275
View File
@@ -254,6 +254,281 @@ class EdaRouterPinsContractTest(unittest.TestCase):
"strt_bend_strt_p2p",
)
def test_route_spacing_detection_handles_crossing_and_endpoint_exceptions(self):
from mxpic_router.builder import (
ROUTE_ENDPOINT_SPACING_IGNORE,
ROUTE_MIN_SPACING,
_first_spacing_adjusted_route,
_orthogonal_elbow,
_polyline_spacing,
_route_spacing_reference_points,
_route_spacing_check_points,
_spacing_offsets,
_spacing_adjusted_route_points,
)
from mxpic_router.eda_loader import LinkSpec
class FakePin:
def __init__(self, x, y, angle):
self.x = x
self.y = y
self.a = angle
self.assertGreaterEqual(
_polyline_spacing(
[{"x": 0, "y": 0}, {"x": 100, "y": 0}],
[{"x": 0, "y": 12}, {"x": 100, "y": 12}],
),
ROUTE_MIN_SPACING,
)
self.assertLess(
_polyline_spacing(
[{"x": 0, "y": 0}, {"x": 100, "y": 0}],
[{"x": 50, "y": -20}, {"x": 50, "y": 20}],
),
ROUTE_MIN_SPACING,
)
device_plan = {
"link": LinkSpec(src_inst="mmi1", src_pin="o1", dst_inst="mmi2", dst_pin="i1"),
"points": [{"x": 0, "y": 0}, {"x": 100, "y": 0}],
}
nearby_port_plan = {
"link": LinkSpec(src_inst="port_1", src_pin="io1", dst_inst="mmi2", dst_pin="i1"),
"points": [{"x": 0, "y": 5}, {"x": 100, "y": 5}],
}
device_check_points = _route_spacing_check_points(device_plan)
nearby_port_check_points = _route_spacing_check_points(nearby_port_plan)
self.assertEqual(device_check_points[0], {"x": ROUTE_ENDPOINT_SPACING_IGNORE, "y": 0.0})
self.assertEqual(nearby_port_check_points[0], {"x": ROUTE_ENDPOINT_SPACING_IGNORE, "y": 5.0})
self.assertLess(_polyline_spacing(device_check_points, nearby_port_check_points), ROUTE_MIN_SPACING)
adjusted = _spacing_adjusted_route_points(
LinkSpec(width=0.5, radius=10),
FakePin(0, 0, 0),
FakePin(100, 0, 180),
offset=ROUTE_MIN_SPACING,
)
self.assertEqual(adjusted[0], {"x": 0.0, "y": 0.0})
self.assertEqual(adjusted[-1], {"x": 100.0, "y": 0.0})
self.assertEqual(adjusted[2]["y"], ROUTE_MIN_SPACING)
self.assertEqual(adjusted[3]["y"], ROUTE_MIN_SPACING)
current_plan = {
"link": LinkSpec(src_inst="a", src_pin="o1", dst_inst="b", dst_pin="i1"),
"pin1": FakePin(0, 5, 0),
"pin2": FakePin(100, 5, 180),
"points": [{"x": 0, "y": 5}, {"x": 100, "y": 5}],
}
accepted_below = [{
"check_points": [{"x": 10, "y": 0}, {"x": 90, "y": 0}],
}]
accepted_above = [{
"check_points": [{"x": 10, "y": 10}, {"x": 90, "y": 10}],
}]
self.assertEqual(_spacing_offsets(current_plan, accepted_below)[0], ROUTE_MIN_SPACING / 2.0)
self.assertEqual(_spacing_offsets(current_plan, accepted_above)[0], -ROUTE_MIN_SPACING / 2.0)
adjusted_from_close_route = _first_spacing_adjusted_route(current_plan, accepted_below)
self.assertIsNotNone(adjusted_from_close_route)
self.assertEqual(adjusted_from_close_route["points"][2]["y"], 10.0)
elbow = _orthogonal_elbow({"x": 0, "y": 0}, 0, {"x": 20, "y": 30}, 270)
self.assertEqual(elbow, {"x": 20.0, "y": 0.0})
reference = _route_spacing_reference_points(
LinkSpec(),
FakePin(0, 0, 0),
FakePin(20, 30, 270),
)
self.assertEqual(reference, [{"x": 0.0, "y": 0.0}, {"x": 20.0, "y": 0.0}, {"x": 20.0, "y": 30.0}])
def test_automatic_p2p_spacing_detection_does_not_change_geometry_by_default(self):
from mxpic_router.builder import _route_bundle_links
from mxpic_router.eda_loader import LinkSpec
class FakePin:
def __init__(self, x, y, angle):
self.x = x
self.y = y
self.a = angle
class FakeRoute:
calls = []
def __init__(self, **kwargs):
pass
def sbend_p2p(self, **kwargs):
self.calls.append(("sbend_p2p", kwargs))
return self
def strt_p2p(self, **kwargs):
self.calls.append(("strt_p2p", kwargs))
return self
def strt_bend_strt_p2p(self, **kwargs):
self.calls.append(("strt_bend_strt_p2p", kwargs))
return self
def put(self):
self.calls.append(("put", {}))
FakeRoute.calls = []
links = [
LinkSpec(src_inst="mmi1", src_pin="b1", dst_inst="port_1", dst_pin="io1"),
LinkSpec(src_inst="mmi2", src_pin="b1", dst_inst="port_1", dst_pin="io2"),
]
pin_map = {
("mmi1", "b1"): FakePin(0, 0, 0),
("port_1", "io1"): FakePin(100, 0, 180),
("mmi2", "b1"): FakePin(0, 5, 0),
("port_1", "io2"): FakePin(100, 5, 180),
}
warnings = []
_route_bundle_links(links, pin_map, FakeRoute, warnings)
self.assertEqual([call[0] for call in FakeRoute.calls], ["sbend_p2p", "put", "sbend_p2p", "put"])
self.assertTrue(any("Detected route spacing below 10um" in warning for warning in warnings))
self.assertEqual(FakeRoute.calls[0][1]["Lstart"], 10.5)
self.assertEqual(FakeRoute.calls[2][1]["Lstart"], 10.5)
call_names = [call[0] for call in FakeRoute.calls]
self.assertNotIn("strt_bend_strt_p2p", call_names)
self.assertNotIn("strt_p2p", call_names)
def test_sbend_lstart_spacing_uses_whole_bundle_inner_outer_order(self):
from mxpic_router.builder import _route_bundle_links
from mxpic_router.eda_loader import LinkSpec
class FakePin:
def __init__(self, x, y, angle):
self.x = x
self.y = y
self.a = angle
class FakeRoute:
calls = []
def __init__(self, **kwargs):
pass
def sbend_p2p(self, **kwargs):
self.calls.append(("sbend_p2p", kwargs))
return self
def put(self):
self.calls.append(("put", {}))
FakeRoute.calls = []
links = [
LinkSpec(src_inst="mmi_top", src_pin="b1", dst_inst="port_top", dst_pin="io1", width=0.5, radius=10),
LinkSpec(src_inst="mmi_top", src_pin="b2", dst_inst="port_mid_top", dst_pin="io1", width=0.5, radius=10),
LinkSpec(src_inst="mmi_bot", src_pin="b1", dst_inst="port_mid_bot", dst_pin="io1", width=0.5, radius=10),
LinkSpec(src_inst="mmi_bot", src_pin="b2", dst_inst="port_bot", dst_pin="io1", width=0.5, radius=10),
]
pin_map = {
("mmi_top", "b1"): FakePin(0, 12, 0),
("port_top", "io1"): FakePin(100, 12, 180),
("mmi_top", "b2"): FakePin(0, 4, 0),
("port_mid_top", "io1"): FakePin(100, 4, 180),
("mmi_bot", "b1"): FakePin(0, -4, 0),
("port_mid_bot", "io1"): FakePin(100, -4, 180),
("mmi_bot", "b2"): FakePin(0, -12, 0),
("port_bot", "io1"): FakePin(100, -12, 180),
}
_route_bundle_links(links, pin_map, FakeRoute, [])
lstarts = [call[1]["Lstart"] for call in FakeRoute.calls if call[0] == "sbend_p2p"]
self.assertEqual(lstarts, [21.0, 10.5, 10.5, 21.0])
def test_sbend_lstart_spacing_uses_monotonic_order_for_same_direction_fanout(self):
from mxpic_router.builder import _route_bundle_links
from mxpic_router.eda_loader import LinkSpec
class FakePin:
def __init__(self, x, y, angle):
self.x = x
self.y = y
self.a = angle
class FakeRoute:
calls = []
def __init__(self, **kwargs):
pass
def sbend_p2p(self, **kwargs):
self.calls.append(("sbend_p2p", kwargs))
return self
def put(self):
self.calls.append(("put", {}))
FakeRoute.calls = []
links = [
LinkSpec(src_inst="mmi1", src_pin="b1", dst_inst="port1", dst_pin="io1", width=0.5, radius=10),
LinkSpec(src_inst="mmi1", src_pin="b2", dst_inst="port2", dst_pin="io1", width=0.5, radius=10),
LinkSpec(src_inst="mmi2", src_pin="b1", dst_inst="port3", dst_pin="io1", width=0.5, radius=10),
LinkSpec(src_inst="mmi2", src_pin="b2", dst_inst="port4", dst_pin="io1", width=0.5, radius=10),
]
pin_map = {
("mmi1", "b1"): FakePin(0, 40, 0),
("port1", "io1"): FakePin(100, 20, 180),
("mmi1", "b2"): FakePin(0, 32, 0),
("port2", "io1"): FakePin(100, 12, 180),
("mmi2", "b1"): FakePin(0, 24, 0),
("port3", "io1"): FakePin(100, 4, 180),
("mmi2", "b2"): FakePin(0, 16, 0),
("port4", "io1"): FakePin(100, -4, 180),
}
_route_bundle_links(links, pin_map, FakeRoute, [])
lstarts = [call[1]["Lstart"] for call in FakeRoute.calls if call[0] == "sbend_p2p"]
self.assertEqual(lstarts, [42.0, 31.5, 21.0, 10.5])
def test_sbend_lstart_step_includes_route_width(self):
from mxpic_router.builder import _route_bundle_links
from mxpic_router.eda_loader import LinkSpec
class FakePin:
def __init__(self, x, y, angle):
self.x = x
self.y = y
self.a = angle
class FakeRoute:
calls = []
def __init__(self, **kwargs):
pass
def sbend_p2p(self, **kwargs):
self.calls.append(("sbend_p2p", kwargs))
return self
def put(self):
self.calls.append(("put", {}))
FakeRoute.calls = []
links = [
LinkSpec(src_inst="r1", src_pin="b1", dst_inst="p1", dst_pin="io1", width=40, radius=10),
LinkSpec(src_inst="r2", src_pin="b1", dst_inst="p2", dst_pin="io1", width=40, radius=10),
]
pin_map = {
("r1", "b1"): FakePin(0, 0, 0),
("p1", "io1"): FakePin(100, 0, 180),
("r2", "b1"): FakePin(0, 100, 0),
("p2", "io1"): FakePin(100, 100, 180),
}
_route_bundle_links(links, pin_map, FakeRoute, [])
lstarts = [call[1]["Lstart"] for call in FakeRoute.calls if call[0] == "sbend_p2p"]
self.assertEqual(lstarts, [50.0, 50.0])
def test_route_backend_falls_back_to_nazca_interconnect_when_forge_is_absent(self):
import mxpic_router.builder as builder