Files
mxpic_EDA/backend/routed_layout_preview.py
2026-06-10 19:10:59 +08:00

74 lines
2.8 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 layout_files import load_layout_cell_files, write_layout_cells_to_directory
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:
staged_project_dir = os.path.join(temp_dir, "project")
saved_cells, _warnings = load_layout_cell_files(project_dir)
staged_cells = [cell for cell in saved_cells if cell["name"] != cell_name]
staged_cells.append({
"filename": f"{cell_name}.yml",
"name": cell_name,
"data": layout,
"content": yaml_content,
})
write_layout_cells_to_directory(staged_cells, staged_project_dir)
temp_gds = os.path.join(temp_dir, f"{cell_name}.gds")
build_project_gds(
project_dir=staged_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