import argparse import os import shutil from copy import deepcopy from pathlib import Path from typing import Any, Dict import yaml from mxpic.technologies.manifest_loader import TECHNOLOGIES_ROOT SILTERRA_EOM1_MANIFEST = TECHNOLOGIES_ROOT / "silterra" / "EMO1_2ML_CU.yml" def build_silterra_eom1_manifest() -> Dict[str, Any]: """Load the Silterra EOM1 manifest consumed by mxpic_EDA.""" return _build_export_manifest(SILTERRA_EOM1_MANIFEST) def _build_export_manifest(manifest_path: Path) -> Dict[str, Any]: with manifest_path.open("r", encoding="utf-8") as file: manifest = yaml.safe_load(file) or {} manifest = deepcopy(manifest) manifest["layers"] = _export_layers(manifest.get("layers", {})) return manifest def _export_layers(layers: Dict[str, Any]) -> Dict[str, Any]: exported = {} for name, entry in layers.items(): exported_entry = dict(entry) layer = exported_entry.pop("layer") exported_entry["layer"] = int(layer[0]) exported_entry["datatype"] = int(layer[1]) exported[name] = exported_entry return exported def export_manifests(destination_root: str) -> None: """Export supported technology manifests into an EDA PDK root.""" for manifest_path in _manifest_paths(): _export_manifest(manifest_path, destination_root) def _manifest_paths() -> list[Path]: return sorted( path for path in TECHNOLOGIES_ROOT.glob("*/*.yml") if path.is_file() ) def _export_manifest(manifest_path: Path, destination_root: str) -> None: manifest = _build_export_manifest(manifest_path) technology_dir = Path(destination_root) / manifest["foundry"] / manifest["technology"] technology_dir.mkdir(parents=True, exist_ok=True) _copy_material_files(manifest, manifest_path.parent, technology_dir) output_path = technology_dir / "technology.yml" with output_path.open("w", encoding="utf-8") as file: yaml.safe_dump(manifest, file, sort_keys=False, allow_unicode=True) def _copy_material_files(manifest: Dict[str, Any], source_dir: Path, technology_dir: Path) -> None: for material in manifest.get("materials", {}).values(): data_file = material.get("data_file") if not data_file: continue source = source_dir / data_file if not source.exists(): continue target = technology_dir / data_file target.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(source, target) def main() -> None: parser = argparse.ArgumentParser(description="Export mxpic technology manifests for mxpic_EDA.") parser.add_argument( "--dest", default=os.path.abspath(os.path.join(os.getcwd(), "..", "mxpic_EDAX", "mxpic", "PDKs")), help="Destination mxpic_EDA PDK root.", ) args = parser.parse_args() export_manifests(os.path.abspath(args.dest)) if __name__ == "__main__": main()