CODEX revised with following function: 1. GDS building, 2. different user group with different authority.
This commit is contained in:
+59
-2
@@ -1,5 +1,6 @@
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, List
|
||||
|
||||
@@ -16,13 +17,34 @@ class BuildResult:
|
||||
warnings: List[str] = field(default_factory=list)
|
||||
|
||||
|
||||
def build_project_gds(project_dir: str, output_path: str, pdk_public_root: str) -> BuildResult:
|
||||
def build_project_gds(
|
||||
project_dir: str,
|
||||
output_path: str,
|
||||
pdk_public_root: str,
|
||||
technology_manifest_path: str = None,
|
||||
prefer_full_gds: bool = False,
|
||||
) -> BuildResult:
|
||||
"""Build a hierarchical project GDS from saved cell YAML files."""
|
||||
cells = _load_project_cells(project_dir)
|
||||
if not cells:
|
||||
raise ValueError("No saved cell YAML files found for this project")
|
||||
|
||||
registry = PdkRegistry(pdk_public_root)
|
||||
try:
|
||||
return _build_with_mxpic_router(
|
||||
project_dir,
|
||||
output_path,
|
||||
pdk_public_root,
|
||||
technology_manifest_path,
|
||||
prefer_full_gds,
|
||||
)
|
||||
except ImportError as router_error:
|
||||
if _cells_have_links(cells):
|
||||
raise RuntimeError(
|
||||
"Routed Build GDS requires mxpic_router, nazca, and mxpic_forge when layout links are present. "
|
||||
f"Router import failed: {router_error}"
|
||||
) from router_error
|
||||
|
||||
registry = PdkRegistry(pdk_public_root, prefer_full_gds=prefer_full_gds)
|
||||
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||
|
||||
try:
|
||||
@@ -37,6 +59,33 @@ def build_project_gds(project_dir: str, output_path: str, pdk_public_root: str)
|
||||
) from nazca_error
|
||||
|
||||
|
||||
def _build_with_mxpic_router(
|
||||
project_dir: str,
|
||||
output_path: str,
|
||||
pdk_root: str,
|
||||
technology_manifest_path: str,
|
||||
prefer_full_gds: bool,
|
||||
) -> BuildResult:
|
||||
router_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "mxpic_router"))
|
||||
if os.path.isdir(router_root) and router_root not in sys.path:
|
||||
sys.path.insert(0, router_root)
|
||||
from mxpic_router import build_project_gds as build_routed_project_gds
|
||||
|
||||
result = build_routed_project_gds(
|
||||
project_dir=project_dir,
|
||||
output_path=output_path,
|
||||
pdk_root=pdk_root,
|
||||
technology_manifest_path=technology_manifest_path,
|
||||
prefer_full_gds=prefer_full_gds,
|
||||
)
|
||||
return BuildResult(
|
||||
output_path=result.get("output_path", output_path),
|
||||
engine=result.get("engine", "mxpic_router"),
|
||||
cells_built=result.get("cells_built", []),
|
||||
warnings=result.get("warnings", []),
|
||||
)
|
||||
|
||||
|
||||
def _load_project_cells(project_dir: str) -> Dict[str, dict]:
|
||||
cells = {}
|
||||
for filename in sorted(os.listdir(project_dir)):
|
||||
@@ -56,6 +105,14 @@ def _ordered_cell_names(cells: Dict[str, dict]) -> List[str]:
|
||||
return composites + projects
|
||||
|
||||
|
||||
def _cells_have_links(cells: Dict[str, dict]) -> bool:
|
||||
for data in cells.values():
|
||||
for bundle in (data.get("bundles") or {}).values():
|
||||
if bundle.get("links"):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _build_with_gdstk(cells: Dict[str, dict], output_path: str, registry: PdkRegistry) -> BuildResult:
|
||||
import gdstk
|
||||
|
||||
|
||||
Reference in New Issue
Block a user