|
| 1 | +"""Generate the IHP seal ring without KLayout's PCell registry.""" |
| 2 | + |
| 3 | +import importlib.util |
| 4 | +import os |
| 5 | +import pathlib |
| 6 | +import re |
| 7 | +import sys |
| 8 | +import types |
| 9 | + |
| 10 | +import pya |
| 11 | + |
| 12 | + |
| 13 | +croc_root = os.environ["CROC_ROOT"] |
| 14 | +klayout_path = os.environ["KLAYOUT_PATH"] |
| 15 | +pdk = os.environ["CROC_PDK"] |
| 16 | +klayout_python = os.path.join(klayout_path, "python") |
| 17 | +shared_klayout_python = os.path.join( |
| 18 | + croc_root, "ihp13", "sg13g2", "ihp-sg13g2", "libs.tech", "klayout", "python" |
| 19 | +) |
| 20 | +sys.path.extend( |
| 21 | + [ |
| 22 | + klayout_python, |
| 23 | + os.path.join(shared_klayout_python, "pycell4klayout-api", "source", "python"), |
| 24 | + ] |
| 25 | +) |
| 26 | + |
| 27 | +from cni.dlo import PyCellContext |
| 28 | +from cni.tech import Tech |
| 29 | + |
| 30 | + |
| 31 | +if pdk == "sg13cmos5l": |
| 32 | + pcell_package = "sg13cmos5l_pycell_lib" |
| 33 | +elif pdk == "sg13g2": |
| 34 | + pcell_package = "sg13g2_pycell_lib" |
| 35 | +else: |
| 36 | + raise RuntimeError(f"Unsupported Croc PDK: {pdk}") |
| 37 | + |
| 38 | +package_name = f"croc_{pdk}_pcell" |
| 39 | +pcell_root = os.path.join(klayout_python, pcell_package) |
| 40 | +ihp_root = os.path.join(pcell_root, "ihp") |
| 41 | +package = types.ModuleType(package_name) |
| 42 | +package.__path__ = [pcell_root] |
| 43 | +sys.modules[package_name] = package |
| 44 | +ihp_package = types.ModuleType(f"{package_name}.ihp") |
| 45 | +ihp_package.__path__ = [ihp_root] |
| 46 | +sys.modules[ihp_package.__name__] = ihp_package |
| 47 | + |
| 48 | + |
| 49 | +def load_module(name, path): |
| 50 | + spec = importlib.util.spec_from_file_location(name, path) |
| 51 | + module = importlib.util.module_from_spec(spec) |
| 52 | + sys.modules[name] = module |
| 53 | + spec.loader.exec_module(module) |
| 54 | + return module |
| 55 | + |
| 56 | + |
| 57 | +load_module(f"{package_name}.sg13_tech", os.path.join(pcell_root, "sg13_tech.py")) |
| 58 | +sealring_module = load_module( |
| 59 | + f"{package_name}.ihp.sealring_code", os.path.join(ihp_root, "sealring_code.py") |
| 60 | +) |
| 61 | + |
| 62 | +tech = Tech.get("SG13_dev") |
| 63 | +Tech.techInUse = tech.getTechParams()["libName"] |
| 64 | +edge_box = float(re.sub("[a-zA-Z]+", "", tech.getTechParams()["sealring_complete_edgeBox"])) |
| 65 | +layout = pya.Layout(True) |
| 66 | +layout.dbu = 0.001 |
| 67 | +top_cell = layout.create_cell("sealring_top") |
| 68 | +sealring = sealring_module.sealring() |
| 69 | +sealring.setTech(tech) |
| 70 | + |
| 71 | +with PyCellContext(tech, top_cell, sealring): |
| 72 | + sealring.addCellContext(top_cell) |
| 73 | + sealring.setupParams( |
| 74 | + { |
| 75 | + "l": f"{float(width) - 2 * edge_box}u", |
| 76 | + "w": f"{float(height) - 2 * edge_box}u", |
| 77 | + "addLabel": "nil", |
| 78 | + "addSlit": "nil", |
| 79 | + "edgeBox": f"{edge_box}u", |
| 80 | + } |
| 81 | + ) |
| 82 | + sealring.genLayout() |
| 83 | + |
| 84 | +pathlib.Path(output).parent.mkdir(parents=True, exist_ok=True) |
| 85 | +options = pya.SaveLayoutOptions() |
| 86 | +options.write_context_info = False |
| 87 | +layout.write(output, options) |
0 commit comments