mirror of
https://github.com/TinyTapeout/tt-support-tools.git
synced 2026-11-03 04:36:09 +01:00
feat(precheck): add analog pin check for ihp-sg13g2
This commit is contained in:
+28
-21
@@ -17,10 +17,9 @@ from klayout_tools import parse_lyp_layers
|
||||
from pin_check import pin_check
|
||||
from precheck_failure import PrecheckFailure
|
||||
from tech_data import (
|
||||
analog_pin_pos,
|
||||
analog_pin_rects,
|
||||
boundary_layer,
|
||||
forbidden_layers,
|
||||
layer_map,
|
||||
lyp_filename,
|
||||
tech_names,
|
||||
valid_layers,
|
||||
@@ -261,42 +260,50 @@ def analog_pin_check(
|
||||
if is_analog:
|
||||
lib = gdstk.read_gds(gds)
|
||||
top = lib.top_level()[0]
|
||||
met4 = top.copy("test_met4")
|
||||
met4.flatten()
|
||||
met4.filter([layer_map[tech]["met4"]], False)
|
||||
via3 = top.copy("test_via3")
|
||||
via3.flatten()
|
||||
via3.filter([layer_map[tech]["via3"]], False)
|
||||
filtered = {}
|
||||
|
||||
for pin in range(8):
|
||||
x = analog_pin_pos[tech](pin, uses_3v3)
|
||||
pin_over = gdstk.rectangle((x, 0), (x + 0.9, 1.0))
|
||||
pin_around = gdstk.boolean(
|
||||
gdstk.offset(pin_over, 0.5), gdstk.offset(pin_over, 0.1), "not"
|
||||
for pin, (rect, pin_layer, via_layers) in enumerate(
|
||||
analog_pin_rects(tech, uses_3v3)
|
||||
):
|
||||
for layer in [pin_layer] + via_layers:
|
||||
if layer not in filtered:
|
||||
i = len(filtered)
|
||||
lf = top.copy(f"test_lf_{i}")
|
||||
lf.flatten()
|
||||
lf.filter([layer], False)
|
||||
filtered[layer] = lf
|
||||
|
||||
pin_rect = gdstk.rectangle(*rect)
|
||||
pin_ring = gdstk.boolean(
|
||||
gdstk.offset(pin_rect, 0.5), gdstk.offset(pin_rect, 0.1), "not"
|
||||
)
|
||||
|
||||
via3_over = gdstk.boolean(via3.polygons, pin_over, "and")
|
||||
met4_around = gdstk.boolean(met4.polygons, pin_around, "and")
|
||||
connected = bool(via3_over) or bool(met4_around)
|
||||
pin_layer_polygons = filtered[pin_layer].polygons
|
||||
connected = bool(gdstk.boolean(pin_layer_polygons, pin_ring, "and"))
|
||||
for via_layer in via_layers:
|
||||
via_layer_polygons = filtered[via_layer].polygons
|
||||
connected = connected or bool(
|
||||
gdstk.boolean(via_layer_polygons, pin_rect, "and")
|
||||
)
|
||||
|
||||
expected_pc = pin < analog_pins
|
||||
expected_pd = bool(pinout.get(f"ua[{pin}]", ""))
|
||||
|
||||
if connected and not expected_pc:
|
||||
raise PrecheckFailure(
|
||||
f"Analog pin `ua[{pin}]` is connected to some metal but `analog_pins` is set to {analog_pins} in `info.yaml`. Either increase `analog_pins` to at least {pin+1}, or remove any metal4 or via3 adjacent to `ua[{pin}]`."
|
||||
f"Analog pin `ua[{pin}]` is connected to some metal but `analog_pins` is set to {analog_pins} in `info.yaml`. Either increase `analog_pins` to at least {pin+1}, or remove any metal or via adjacent to `ua[{pin}]`."
|
||||
)
|
||||
elif connected and not expected_pd:
|
||||
raise PrecheckFailure(
|
||||
f"Analog pin `ua[{pin}]` is connected to some metal but the description of `ua[{pin}]` in the pinout section of `info.yaml` is empty. Either add a description or remove any metal4 or via3 adjacent to `ua[{pin}]`."
|
||||
f"Analog pin `ua[{pin}]` is connected to some metal but the description of `ua[{pin}]` in the pinout section of `info.yaml` is empty. Either add a description or remove any metal or via adjacent to `ua[{pin}]`."
|
||||
)
|
||||
elif not connected and expected_pc:
|
||||
raise PrecheckFailure(
|
||||
f"Analog pin `ua[{pin}]` is not connected to any adjacent metal but `analog_pins` is set to {analog_pins} in `info.yaml`. Either wire up `ua[{pin}]` to your design using metal4 or via3, or decrease `analog_pins` to {pin}."
|
||||
f"Analog pin `ua[{pin}]` is not connected to any adjacent metal but `analog_pins` is set to {analog_pins} in `info.yaml`. Either wire up `ua[{pin}]` to your design or decrease `analog_pins` to {pin}."
|
||||
)
|
||||
elif not connected and expected_pd:
|
||||
raise PrecheckFailure(
|
||||
f"Analog pin `ua[{pin}]` is not connected to any adjacent metal but the description of `ua[{pin}]` in the pinout section of `info.yaml` is non-empty. Either wire up `ua[{pin}]` to your design using metal4 or via3, or remove the description for the disconnected pin."
|
||||
f"Analog pin `ua[{pin}]` is not connected to any adjacent metal but the description of `ua[{pin}]` in the pinout section of `info.yaml` is non-empty. Either wire up `ua[{pin}]` to your design or remove the description for the disconnected pin."
|
||||
)
|
||||
|
||||
|
||||
@@ -437,7 +444,7 @@ def main():
|
||||
"check": lambda: analog_pin_check(
|
||||
gds_file, tech, is_analog, uses_3v3, analog_pins, pinout
|
||||
),
|
||||
"techs": ["sky130A"],
|
||||
"techs": ["sky130A", "ihp-sg13g2"],
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
+29
-12
@@ -1,3 +1,5 @@
|
||||
tech_names = ["sky130A", "ihp-sg13g2", "gf180mcuD"]
|
||||
|
||||
# fmt: off
|
||||
valid_layers_sky130A = [
|
||||
'cldntm.mask', 'ldntm.drawing', 'cncm.mask', 'ctunm.mask', 'cnwm.mask', 'cnsm.mask', 'cfom.drawing', 'cfom.maskAdd',
|
||||
@@ -93,15 +95,34 @@ valid_layers_gf180mcuD = [
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
# layers used for the analog pin check
|
||||
layer_map_sky130A = {
|
||||
"met4": (71, 20),
|
||||
"via3": (70, 44),
|
||||
}
|
||||
|
||||
|
||||
def analog_pin_pos_sky130A(pin_number: int, uses_3v3: bool):
|
||||
return 151.81 - 19.32 * pin_number - (15.64 if uses_3v3 else 0)
|
||||
def analog_pin_rects(tech: str, uses_3v3: bool):
|
||||
if tech == "sky130A":
|
||||
pin_layer = (71, 20) # met4
|
||||
via_layers = [(70, 44)] # via3
|
||||
for pin_number in range(8):
|
||||
if uses_3v3:
|
||||
x1, y1 = 136.17 - 19.32 * pin_number, 0.0
|
||||
else:
|
||||
x1, y1 = 151.81 - 19.32 * pin_number, 0.0
|
||||
x2, y2 = x1 + 0.9, y1 + 1.0
|
||||
rect = ((x1, y1), (x2, y2))
|
||||
yield (rect, pin_layer, via_layers)
|
||||
elif tech == "ihp-sg13g2":
|
||||
pin_layer = (126, 0) # TopMetal1
|
||||
via_layers = [(125, 0)] # TopVia1
|
||||
for pin_number in range(8):
|
||||
if uses_3v3:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
x1, y1 = 190.165 - 24.48 * pin_number, 0.0
|
||||
x2, y2 = x1 + 1.75, y1 + 2.0
|
||||
rect = ((x1, y1), (x2, y2))
|
||||
yield (rect, pin_layer, via_layers)
|
||||
elif tech in tech_names:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
raise ValueError(f"unexpected tech {tech}")
|
||||
|
||||
|
||||
valid_layers = {
|
||||
@@ -109,8 +130,6 @@ valid_layers = {
|
||||
"ihp-sg13g2": valid_layers_ihp_sg13g2,
|
||||
"gf180mcuD": valid_layers_gf180mcuD,
|
||||
}
|
||||
layer_map = {"sky130A": layer_map_sky130A}
|
||||
analog_pin_pos = {"sky130A": analog_pin_pos_sky130A}
|
||||
lyp_filename = {
|
||||
"sky130A": "sky130A.lyp",
|
||||
"ihp-sg13g2": "sg13g2.lyp",
|
||||
@@ -165,5 +184,3 @@ boundary_layer = {
|
||||
"ihp-sg13g2": "prBoundary.boundary",
|
||||
"gf180mcuD": "PR_bndry",
|
||||
}
|
||||
|
||||
tech_names = ["sky130A", "ihp-sg13g2", "gf180mcuD"]
|
||||
|
||||
Reference in New Issue
Block a user