上传文件至「mxpic_router」

This commit is contained in:
2026-06-15 08:47:31 +00:00
parent 59d432b0bf
commit 38e2d3d7f6
+119 -9
View File
@@ -313,7 +313,7 @@ def _route_bundle_links(links: list, pin_map: dict, Route, warnings: list) -> No
plans.append(plan) plans.append(plan)
by_order[order] = plan by_order[order] = plan
_assign_sbend_lstart_spacing(plans) _assign_bend_route_spacing(plans)
accepted = [] accepted = []
for plan in plans: for plan in plans:
@@ -365,29 +365,78 @@ def _route_bundle_links(links: list, pin_map: dict, Route, warnings: list) -> No
f"{plan['link'].src_inst}:{plan['link'].src_pin} -> " f"{plan['link'].src_inst}:{plan['link'].src_pin} -> "
f"{plan['link'].dst_inst}:{plan['link'].dst_pin}" f"{plan['link'].dst_inst}:{plan['link'].dst_pin}"
) )
if plan.get("route_options", {}).get("length"):
warnings.append(
f"Applied ubend length {plan['route_options']['length']:g}um to "
f"{plan['link'].src_inst}:{plan['link'].src_pin} -> "
f"{plan['link'].dst_inst}:{plan['link'].dst_pin}"
)
_route_link(plan["link"], pin_map, Route, warnings, plan.get("route_options")) _route_link(plan["link"], pin_map, Route, warnings, plan.get("route_options"))
def _assign_sbend_lstart_spacing(plans: list) -> None: def _assign_bend_route_spacing(plans: list) -> None:
groups = {} groups = {}
for plan in plans: for plan in plans:
if not plan.get("automatic"): if not plan.get("automatic"):
continue continue
if _route_method_name_for_pins(plan["pin1"], plan["pin2"]) != "sbend_p2p": method_name = _route_method_name_for_pins(plan["pin1"], plan["pin2"])
if method_name not in {"sbend_p2p", "ubend_p2p"}:
continue continue
key = _sbend_spacing_group_key(plan) key = _bend_spacing_group_key(plan, method_name)
if key is None: if key is None:
continue continue
groups.setdefault(key, []).append(plan) bucket = groups.setdefault(key, {"method": method_name, "plans": []})
bucket["plans"].append(plan)
for group in groups.values(): for bucket in groups.values():
group = bucket["plans"]
if len(group) < 2: if len(group) < 2:
continue continue
axis = _sbend_forward_axis(group[0]) axis = _sbend_forward_axis(group[0])
coord_key = "y" if axis == "horizontal" else "x" coord_key = "y" if axis == "horizontal" else "x"
step = _sbend_lstart_step(group) step = _sbend_lstart_step(group)
for plan, rank in _sbend_lstart_ranks(group, coord_key): if bucket["method"] == "sbend_p2p":
plan["route_options"]["Lstart"] = rank * step ranked_plans = _sbend_lstart_ranks(group, coord_key)
else:
ranked_plans = _ubend_length_ranks(group, coord_key)
for plan, rank in ranked_plans:
if bucket["method"] == "sbend_p2p":
plan["route_options"]["Lstart"] = rank * step
else:
plan["route_options"]["length"] = rank * step
_assign_mixed_bend_route_spacing(plans)
def _assign_mixed_bend_route_spacing(plans: list) -> None:
groups = {}
for plan in plans:
if not plan.get("automatic"):
continue
method_name = _route_method_name_for_pins(plan["pin1"], plan["pin2"])
if method_name not in {"sbend_p2p", "ubend_p2p"}:
continue
key = _mixed_bend_spacing_group_key(plan)
if key is None:
continue
bucket = groups.setdefault(key, {"methods": set(), "plans": []})
bucket["methods"].add(method_name)
bucket["plans"].append(plan)
for bucket in groups.values():
if len(bucket["methods"]) < 2:
continue
group = bucket["plans"]
axis = _sbend_forward_axis(group[0])
coord_key = "y" if axis == "horizontal" else "x"
step = _sbend_lstart_step(group)
for method_name, plan, rank in _mixed_bend_route_ranks(group, coord_key, step):
if method_name == "sbend_p2p":
plan["route_options"]["Lstart"] = rank * step
plan["route_options"].pop("length", None)
else:
plan["route_options"]["length"] = rank * step
plan["route_options"].pop("Lstart", None)
def _sbend_lstart_step(group: list) -> float: def _sbend_lstart_step(group: list) -> float:
@@ -413,13 +462,52 @@ def _sbend_lstart_ranks(group: list, coord_key: str) -> list:
] ]
def _ubend_length_ranks(group: list, coord_key: str) -> list:
spans = [round(abs(_route_coord_delta(plan, coord_key)), 6) for plan in group]
nonzero_spans = [span for span in spans if span > 1e-9]
if nonzero_spans and len(set(nonzero_spans)) > 1:
ordered_spans = sorted(set(spans))
return [(plan, ordered_spans.index(round(abs(_route_coord_delta(plan, coord_key)), 6)) + 1) for plan in group]
center = sum(_route_start_coord(plan, coord_key) for plan in group) / len(group)
distances = sorted({round(abs(_route_start_coord(plan, coord_key) - center), 6) for plan in group})
return [
(plan, distances.index(round(abs(_route_start_coord(plan, coord_key) - center), 6)) + 1)
for plan in group
]
def _mixed_bend_route_ranks(group: list, coord_key: str, step: float) -> list:
ubend_plans = [plan for plan in group if _route_method_name_for_pins(plan["pin1"], plan["pin2"]) == "ubend_p2p"]
sbend_plans = [plan for plan in group if _route_method_name_for_pins(plan["pin1"], plan["pin2"]) == "sbend_p2p"]
ranked = []
ubend_ranked = _ubend_length_ranks(ubend_plans, coord_key)
for plan, rank in ubend_ranked:
ranked.append(("ubend_p2p", plan, rank))
first_sbend_rank = _mixed_first_sbend_rank_after_ubends(ubend_ranked, step)
for plan, rank in _sbend_lstart_ranks(sbend_plans, coord_key):
ranked.append(("sbend_p2p", plan, first_sbend_rank + rank - 1))
return ranked
def _mixed_first_sbend_rank_after_ubends(ubend_ranked: list, step: float) -> int:
if not ubend_ranked:
return 1
max_length = max(rank * step for plan, rank in ubend_ranked)
max_radius = max((_safe_float(plan["link"].radius, 10.0) or 10.0) for plan, rank in ubend_ranked)
total_width = sum((_safe_float(plan["link"].width, 0.5) or 0.5) for plan, rank in ubend_ranked)
spacing_slots = len(ubend_ranked) + 1
ubend_envelope = max_length + max_radius + total_width + spacing_slots * ROUTE_MIN_SPACING
return max(1, math.ceil(ubend_envelope / step))
def _route_coord_delta(plan: dict, coord_key: str) -> float: def _route_coord_delta(plan: dict, coord_key: str) -> float:
start = plan["points"][0] start = plan["points"][0]
end = plan["points"][-1] end = plan["points"][-1]
return float(end[coord_key]) - float(start[coord_key]) return float(end[coord_key]) - float(start[coord_key])
def _sbend_spacing_group_key(plan: dict): def _bend_spacing_group_key(plan: dict, method_name: str):
link = plan["link"] link = plan["link"]
axis = _sbend_forward_axis(plan) axis = _sbend_forward_axis(plan)
main_key = "x" if axis == "horizontal" else "y" main_key = "x" if axis == "horizontal" else "y"
@@ -433,6 +521,27 @@ def _sbend_spacing_group_key(plan: dict):
_sbend_span_bucket(plan["points"][0][main_key]), _sbend_span_bucket(plan["points"][0][main_key]),
_sbend_span_bucket(plan["points"][-1][main_key]), _sbend_span_bucket(plan["points"][-1][main_key]),
) )
return (
method_name,
axis,
_route_direction_sign(main_delta),
route_scope,
str(link.xsection or ""),
_safe_float(link.width, 0.0),
_safe_float(link.radius, 0.0),
)
def _mixed_bend_spacing_group_key(plan: dict):
link = plan["link"]
axis = _sbend_forward_axis(plan)
main_key = "x" if axis == "horizontal" else "y"
main_delta = _route_coord_delta(plan, main_key)
explicit_group = _link_explicit_route_group(link)
if explicit_group:
route_scope = ("explicit", explicit_group)
else:
route_scope = ("start-span", _sbend_span_bucket(plan["points"][0][main_key]))
return ( return (
axis, axis,
_route_direction_sign(main_delta), _route_direction_sign(main_delta),
@@ -1143,6 +1252,7 @@ class _NazcaInterconnectRoute:
width=self._route_width(width), width=self._route_width(width),
radius=self._route_radius(radius), radius=self._route_radius(radius),
xs=self._route_xs(xs), xs=self._route_xs(xs),
length=kwargs.get("length", 0),
arrow=arrow, arrow=arrow,
) )