62 lines
2.3 KiB
Python
62 lines
2.3 KiB
Python
# -----------------------------------------------------------------------------
|
|
# Description: Routed layout preview helpers that invoke the routing/build flow and return preview artifacts.
|
|
# Inside functions: create_routed_layout_svg, layout_has_links
|
|
# Developer : Qin Yue @ 2026
|
|
# Organization : OptiHK Limited
|
|
# -----------------------------------------------------------------------------
|
|
import os
|
|
import tempfile
|
|
|
|
import yaml
|
|
|
|
from router_dependency import require_router_stack
|
|
|
|
|
|
def create_routed_layout_svg(
|
|
yaml_content: str,
|
|
output_path: str,
|
|
pdk_root: str,
|
|
project_dir: str,
|
|
technology_manifest_path: str = None,
|
|
prefer_full_gds: bool = False,
|
|
) -> str:
|
|
"""Create an SVG preview from routed GDS geometry generated by mxpic_router."""
|
|
require_router_stack(require_gdstk=True)
|
|
import gdstk
|
|
|
|
layout = yaml.safe_load(yaml_content) or {}
|
|
cell_name = str(layout.get("name") or "layout")
|
|
from mxpic_router import build_project_gds
|
|
|
|
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
|
# Build into a temporary GDS first, then convert the generated top cell into
|
|
# the SVG preview consumed by the canvas.
|
|
with tempfile.TemporaryDirectory(prefix="mxpic_routed_preview_") as temp_dir:
|
|
temp_gds = os.path.join(temp_dir, f"{cell_name}.gds")
|
|
build_project_gds(
|
|
project_dir=project_dir,
|
|
output_path=temp_gds,
|
|
pdk_root=pdk_root,
|
|
technology_manifest_path=technology_manifest_path,
|
|
prefer_full_gds=prefer_full_gds,
|
|
target_cell_name=cell_name,
|
|
)
|
|
library = gdstk.read_gds(temp_gds)
|
|
top_cells = library.top_level()
|
|
if not top_cells:
|
|
raise RuntimeError("Routed preview GDS has no top-level cell")
|
|
top_cells[0].write_svg(output_path)
|
|
return output_path
|
|
|
|
|
|
def layout_has_links(yaml_content: str) -> bool:
|
|
"""Detect whether a layout YAML document contains routed bundle links."""
|
|
layout = yaml.safe_load(yaml_content) or {}
|
|
# Any bundle link means preview generation must use the routed builder
|
|
# instead of simple component placement.
|
|
for bundle in (layout.get("bundles") or {}).values():
|
|
links = bundle.get("links") or []
|
|
if links:
|
|
return True
|
|
return False
|