feat(precheck): add pin checks

Checks for missing or invalid pins, wrong pin dimensions or layers.
This commit is contained in:
htfab
2024-05-01 00:55:53 +03:00
committed by Uri Shaked
parent 51e5747c09
commit 97e65e74f6
5 changed files with 419 additions and 4 deletions
+122
View File
@@ -1,4 +1,6 @@
import os
import subprocess
import textwrap
import klayout.db as pya
import klayout_tools
@@ -105,6 +107,102 @@ def gds_invalid_macro_name(tmp_path_factory: pytest.TempPathFactory):
return str(gds_file)
def generate_analog_example(
tcl_file: str,
gds_file: str,
lef_file: str,
toplevel: str,
vpwr_layer: str,
vpwr_box: str,
vgnd_layer: str,
vgnd_box: str,
):
with open(tcl_file, "w") as f:
f.write(
textwrap.dedent(
f"""
def read ../def/analog/tt_block_1x2_pg_ana.def
cellname rename tt_um_template {toplevel}
# VPWR
box {vpwr_box}
paint {vpwr_layer}
label VPWR FreeSans {vpwr_layer}
port VPWR make n
port VPWR use power
port VPWR class bidirectional
port conn n s e w
# VGND
box {vgnd_box}
paint {vgnd_layer}
label VGND FreeSans {vgnd_layer}
port VGND make n
port VGND use ground
port VGND class bidirectional
port conn n s e w
# Export
gds write {gds_file}
lef write {lef_file} -pinonly
"""
)
)
magic = subprocess.run(
[
"magic",
"-noconsole",
"-dnull",
"-rcfile",
f"{PDK_ROOT}/{PDK_NAME}/libs.tech/magic/{PDK_NAME}.magicrc",
tcl_file,
],
)
assert magic.returncode == 0
@pytest.fixture(scope="session")
def gds_lef_analog_example(tmp_path_factory: pytest.TempPathFactory):
"""Creates a GDS and LEF using the 1x2 analog template."""
tcl_file = tmp_path_factory.mktemp("tcl") / "TEST_analog_example.tcl"
gds_file = tmp_path_factory.mktemp("gds") / "TEST_analog_example.gds"
lef_file = tmp_path_factory.mktemp("lef") / "TEST_analog_example.lef"
generate_analog_example(
str(tcl_file),
str(gds_file),
str(lef_file),
"TEST_analog_example",
"met4",
"100 500 250 22076",
"met4",
"4900 500 5050 22076",
)
return str(gds_file), str(lef_file)
@pytest.fixture(scope="session")
def gds_lef_analog_wrong_vgnd(tmp_path_factory: pytest.TempPathFactory):
"""Creates a GDS and LEF using the 1x2 analog template, with wrong VGND layer & dimensions."""
tcl_file = tmp_path_factory.mktemp("tcl") / "TEST_analog_wrong_vgnd.tcl"
gds_file = tmp_path_factory.mktemp("gds") / "TEST_analog_wrong_vgnd.gds"
lef_file = tmp_path_factory.mktemp("lef") / "TEST_analog_wrong_vgnd.lef"
generate_analog_example(
str(tcl_file),
str(gds_file),
str(lef_file),
"TEST_analog_wrong_vgnd",
"met4",
"100 500 250 22076",
"met3",
"4900 500 5250 12076",
)
return str(gds_file), str(lef_file)
def test_magic_drc_pass(gds_valid: str):
precheck.magic_drc(gds_valid, "TEST_valid")
@@ -166,3 +264,27 @@ def test_klayout_zero_area_drc_pass(gds_valid: str):
def test_klayout_zero_area_drc_fail(gds_zero_area: str):
with pytest.raises(precheck.PrecheckFailure, match="Klayout zero_area failed"):
precheck.klayout_zero_area(gds_zero_area)
def test_pin_analog_example(gds_lef_analog_example: tuple[str, str]):
gds_file, lef_file = gds_lef_analog_example
precheck.pin_check(
gds_file,
lef_file,
"../def/analog/tt_block_1x2_pg_ana.def",
"TEST_analog_example",
)
def test_pin_analog_wrong_vgnd(gds_lef_analog_wrong_vgnd: tuple[str, str]):
with pytest.raises(
precheck.PrecheckFailure,
match="Some ports are missing or have wrong dimensions",
):
gds_file, lef_file = gds_lef_analog_wrong_vgnd
precheck.pin_check(
gds_file,
lef_file,
"../def/analog/tt_block_1x2_pg_ana.def",
"TEST_analog_wrong_vgnd",
)