Technolgy file archetecture revised with dictionary input method
This commit is contained in:
@@ -1,127 +1,84 @@
|
||||
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]:
|
||||
"""Build the Silterra EOM1 manifest consumed by mxpic_EDA."""
|
||||
layers = {
|
||||
"WG_HM": {"layer": 275, "datatype": 0},
|
||||
"WG_STRIP": {"layer": 101, "datatype": 251},
|
||||
"WG_LOWRIB": {"layer": 100, "datatype": 90},
|
||||
"WG_SRIB": {"layer": 100, "datatype": 90},
|
||||
"WG_HIGHRIB": {"layer": 232, "datatype": 0},
|
||||
"HEATER": {"layer": 29, "datatype": 30},
|
||||
"CT_SI": {"layer": 268, "datatype": 0},
|
||||
"CT_GE": {"layer": 35, "datatype": 0},
|
||||
"UTV": {"layer": 172, "datatype": 0},
|
||||
"RDL_VIA": {"layer": 194, "datatype": 0},
|
||||
"UTM": {"layer": 173, "datatype": 0},
|
||||
"UTM2": {"layer": 197, "datatype": 0},
|
||||
"RDL_MET": {"layer": 195, "datatype": 0},
|
||||
"PAD_ELE": {"layer": 100, "datatype": 170},
|
||||
"PAD_OPTICAL": {"layer": 100, "datatype": 160},
|
||||
"PAD_AL": {"layer": 145, "datatype": 0},
|
||||
"WG_N": {"layer": 263, "datatype": 0},
|
||||
"SiN_Rib_WG": {"layer": 63, "datatype": 30},
|
||||
"SSIN0": {"layer": 283, "datatype": 0},
|
||||
"SSIN1": {"layer": 289, "datatype": 0},
|
||||
"SSIN2": {"layer": 290, "datatype": 0},
|
||||
"SSIN3": {"layer": 291, "datatype": 0},
|
||||
"EXCLUSION": {"layer": 57, "datatype": 0},
|
||||
"SALICIDE": {"layer": 128, "datatype": 60},
|
||||
"DM_EXL": {"layer": 23, "datatype": 0},
|
||||
"DM_EXL_FE": {"layer": 23, "datatype": 40},
|
||||
"DM_EXL_BE": {"layer": 23, "datatype": 41},
|
||||
"OXIDE_FACET": {"layer": 90, "datatype": 0},
|
||||
"DT": {"layer": 404, "datatype": 0},
|
||||
"P": {"layer": 256, "datatype": 0},
|
||||
"N": {"layer": 257, "datatype": 0},
|
||||
"PP": {"layer": 258, "datatype": 0},
|
||||
"NP": {"layer": 259, "datatype": 0},
|
||||
"PPP": {"layer": 260, "datatype": 0},
|
||||
"NPP": {"layer": 261, "datatype": 0},
|
||||
"PD_SIPP": {"layer": 100, "datatype": 140},
|
||||
"PD_SINP": {"layer": 100, "datatype": 150},
|
||||
}
|
||||
"""Load the Silterra EOM1 manifest consumed by mxpic_EDA."""
|
||||
return _build_export_manifest(SILTERRA_EOM1_MANIFEST)
|
||||
|
||||
return {
|
||||
"schema_version": "1.0.0",
|
||||
"foundry": "Silterra",
|
||||
"technology": "EMO1_2ML_CU_Al_RDL",
|
||||
"source_class": "mxpic.foundries.Silterra.EOM1_2ML_CU_RDL",
|
||||
"constants": {
|
||||
"STD_SMWG_WIDTH": 0.45,
|
||||
"SLAB_GROWTH": 2,
|
||||
"W_METAL_MIN": 5,
|
||||
"SPACING_HEATER_MIN": 2,
|
||||
"SPACING_METAL_MIN": 4,
|
||||
"W_HEATER_MIN": 3,
|
||||
},
|
||||
"layers": layers,
|
||||
"routing_types": ["euler_bend", "standard_bend"],
|
||||
"defaults": {
|
||||
"xsection": "strip",
|
||||
"family": "optical",
|
||||
"width": 0.45,
|
||||
"radius": 10,
|
||||
"routing_type": "euler_bend",
|
||||
},
|
||||
"xsections": {
|
||||
"strip": {
|
||||
"family": "optical",
|
||||
"default_width": 0.45,
|
||||
"default_radius": 10,
|
||||
"layers": [
|
||||
{"layer": "WG_HM", "growx": 0, "growy": 0},
|
||||
{"layer": "WG_STRIP", "growx": 4, "growy": 4},
|
||||
],
|
||||
},
|
||||
"rib_low": {
|
||||
"family": "optical",
|
||||
"default_width": 0.45,
|
||||
"default_radius": 10,
|
||||
"layers": [
|
||||
{"layer": "WG_HM", "growx": 0, "growy": 0},
|
||||
{"layer": "WG_SRIB", "growx": 3, "growy": 3},
|
||||
{"layer": "WG_STRIP", "leftedge": [-0.5, -3], "rightedge": [-0.5, -3.5]},
|
||||
{"layer": "WG_STRIP", "leftedge": [0.5, 3.5], "rightedge": [0.5, 3]},
|
||||
],
|
||||
},
|
||||
"metal_1": {
|
||||
"family": "electrical",
|
||||
"default_width": 5,
|
||||
"default_radius": 10,
|
||||
"layers": [
|
||||
{"layer": "UTM", "growx": 0, "growy": 0},
|
||||
{"layer": "SSIN0", "growx": 2.5, "growy": 2.5},
|
||||
],
|
||||
},
|
||||
"metal_2": {
|
||||
"family": "electrical",
|
||||
"default_width": 5,
|
||||
"default_radius": 10,
|
||||
"layers": [
|
||||
{"layer": "UTM2", "growx": 0, "growy": 0},
|
||||
{"layer": "SSIN1", "growx": 2.5, "growy": 2.5},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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."""
|
||||
manifest = build_silterra_eom1_manifest()
|
||||
technology_dir = os.path.join(destination_root, manifest["foundry"], manifest["technology"])
|
||||
os.makedirs(technology_dir, exist_ok=True)
|
||||
output_path = os.path.join(technology_dir, "technology.yml")
|
||||
with open(output_path, "w", encoding="utf-8") as file:
|
||||
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(
|
||||
|
||||
Reference in New Issue
Block a user