Electrical Short (Through Hierarchy)¶
File: pics/two_elec.pic.yml + pics/elec.pic.yml
Error caught: short + net.missing_in_schematic — the routing wires inside each elec instance cross on the same metal layer, and the two instances are placed so their wires also overlap. Three geometric shorts transitively tie six pad ports onto a single electrical net that the schematic doesn't declare.
Error type: LVS.short
Expected: ok=False, error_count=4 (3 shorts + 1 missing_in_schematic net group)
import tempfile
from copy import deepcopy
from pathlib import Path
import elvis
import gdsfactory as gf
from gdsfactory.gpdk import PDK
from IPython.display import Markdown
from kwasm import Tool, show
PDK.activate()
PICS = Path("../pics")
BUILD_GDS = Path("../build/gds")
BUILD_GDS.mkdir(parents=True, exist_ok=True)
PIC_UP = PICS / "two_elec.pic.yml"
PIC_DOWN = PICS / "elec.pic.yml"
Schematic¶
two_elec.pic.yml places two elec instances. instance1 is rotated 90° — observe how its ports rotate accordingly. elec.pic.yml routes four pads in two pairs on the same metal layer.
{'two_elec': {'instances': {'instance1': {'component': 'elec', 'settings': {}},
'instance2': {'component': 'elec', 'settings': {}}},
'ports': {},
'placements': {'instance1': {'x': 0,
'y': 0,
'dx': 491.989,
'dy': -104.859,
'rotation': 90,
'mirror': False},
'instance2': {'x': 100,
'y': 0,
'dx': 267.46,
'dy': 53.93,
'rotation': 0,
'mirror': False}}},
'elec': {'instances': {'pad1': {'component': 'pad', 'settings': {}},
'pad2': {'component': 'pad', 'settings': {}},
'pad3': {'component': 'pad', 'settings': {}},
'pad4': {'component': 'pad', 'settings': {}}},
'routes': {'electrical': {'links': {'pad1,e3': 'pad2,e1'},
'routing_strategy': 'route_bundle_electrical',
'settings': {'allow_layer_mismatch': False,
'allow_type_mismatch': False,
'allow_width_mismatch': False}},
'electrical2': {'links': {'pad3,e3': 'pad4,e3'},
'routing_strategy': 'route_bundle_electrical',
'settings': {'allow_layer_mismatch': False,
'allow_type_mismatch': False,
'allow_width_mismatch': False,
'radius': 10}}},
'ports': {},
'placements': {'pad1': {'x': 0, 'y': 0, 'dx': -98.125, 'dy': -19.273},
'pad2': {'x': 0,
'y': 0,
'dx': 349.71,
'dy': -394.94,
'rotation': 0,
'mirror': False},
'pad3': {'x': -98.125,
'y': -19.273,
'dx': -97.005,
'dy': -423.277,
'rotation': 0,
'mirror': False},
'pad4': {'x': 0,
'y': 0,
'dx': 137.75,
'dy': -124.39,
'rotation': 0,
'mirror': False}}}}
Build from schematic¶
# for the top-level to work the lower levels needs to be registered.
# tools like gdsfactoryplus do this automatically for you.
if "elec" not in PDK.cells:
elec = gf.read.from_yaml(schematic["elec"], name="elec")
PDK.cells["elec"] = lambda: elec
c = gf.read.from_yaml(schematic["two_elec"], name="two_elec")
gds_path = BUILD_GDS / "two_elec.gds"
c.write_gds(gds_path)
show(gds_path, tools=[Tool.FIT_ALL])
LVS Results¶
rdb = elvis.lvs_rdb(
gds_path,
schematic,
short_layers=[(49, 0)],
equivalent_ports={"pad": ["pad", "e1", "e2", "e3", "e4"]},
)
lyrdb = Path(tempfile.gettempdir()) / "two_elec.lyrdb"
rdb.save(str(lyrdb))
show(gds_path, lyrdb=lyrdb, tools=[Tool.FIT_ALL])
flags used
The above LVS function is called with the following flags
- short_layers=[(49, 0)]
- equivalent_ports={'pad': ["pad", "e1", "e2", "e3", "e4"]}
this can also be pre-configured.
The three LVS.short errors transitively tie six pad ports (across both elec instances) onto a single electrical net that the schematic doesn't declare. Elvis reports that as one LVS.net.missing_in_schematic group error — rendered with set notation {instance1~pad2,{pad,e1,e2,e3,e4}; instance1~pad4,{pad,e1,e2,e3,e4}; instance2~pad1,{pad,e1,e2,e3,e4}; …}. The underlying cross-pairs (25 × 6 = many) are listed in the rdb item's comment field. (See notebook 09 for the equivalent-port and net-group merge steps explained in isolation.)
print(f"ok={rdb.num_items() == 0}, error_count={rdb.num_items()}")
Markdown(elvis.error_summary(rdb))
ok=False, error_count=4
| cell | error type | description |
|---|---|---|
| two_elec | LVS.net.missing_in_schematic | Net {instance2~pad2,{pad,e1,e2,e3,e4}; instance2~pad4,{pad,e1,e2,e3,e4}; instance2~pad1,{pad,e1,e2,e3,e4}; instance1~pad2,{pad,e1,e2,e3,e4}; instance1~pad4,{pad,e1,e2,e3,e4}; instance2~pad3,{pad,e1,e2,e3,e4}; instance1~pad1,{pad,e1,e2,e3,e4}; instance1~pad3,{pad,e1,e2,e3,e4}} in layout but not in schematic |
| two_elec | LVS.short | Geometric short between 'instance2~pad4,e3 -> instance2~pad3,e3' and 'instance1~pad2,e1 -> instance1~pad1,e3' (1 location) |
| two_elec | LVS.short | Geometric short between 'instance2~pad4,e3 -> instance2~pad3,e3' and 'instance2~pad1,e3 -> instance2~pad2,e1' (1 location) |
| two_elec | LVS.short | Geometric short between 'instance1~pad2,e1 -> instance1~pad1,e3' and 'instance1~pad3,e3 -> instance1~pad4,e3' (1 location) |
Fix¶
There are obviously two sets of errors here:
- The LVS errors on the lower hierarchy are reported, we can't fix those in this hierarchy (see the "Electrical Short" example for that)
- On this hierarchy, the two instances are overlapping. We can fix that by moving
instance2.
schematic2 = deepcopy(schematic)
schematic2["two_elec"]["placements"]["instance1"]["dx"] += 500
c = gf.read.from_yaml(schematic2["two_elec"], name="two_elec2")
c.write_gds(gds_path)
rdb = elvis.lvs_rdb(
gds_path,
schematic,
short_layers=[(49, 0)],
equivalent_ports={"pad": ["pad", "e1", "e2", "e3", "e4"]},
)
rdb.save(str(lyrdb))
show(gds_path, lyrdb=lyrdb, tools=[Tool.FIT_ALL])
print(f"ok={rdb.num_items() == 0}, error_count={rdb.num_items()}")
Markdown(elvis.error_summary(rdb))
ok=False, error_count=4
| cell | error type | description |
|---|---|---|
| two_elec | LVS.net.missing_in_schematic | Net {instance1~pad1,{pad,e1,e2,e3,e4}; instance1~pad3,{pad,e1,e2,e3,e4}; instance1~pad4,{pad,e1,e2,e3,e4}; instance1~pad2,{pad,e1,e2,e3,e4}} in layout but not in schematic |
| two_elec | LVS.net.missing_in_schematic | Net {instance2~pad1,{pad,e1,e2,e3,e4}; instance2~pad4,{pad,e1,e2,e3,e4}; instance2~pad2,{pad,e1,e2,e3,e4}; instance2~pad3,{pad,e1,e2,e3,e4}} in layout but not in schematic |
| two_elec | LVS.short | Geometric short between 'instance1~pad2,e1 -> instance1~pad1,e3' and 'instance1~pad4,e3 -> instance1~pad3,e3' (1 location) |
| two_elec | LVS.short | Geometric short between 'instance2~pad2,e1 -> instance2~pad1,e3' and 'instance2~pad3,e3 -> instance2~pad4,e3' (1 location) |
Note
Even though the error count did not go down we did remove the short on this hierarchy level, which is what we care about. Our fix also separates the nets of the underlying instances. Those instances have problems of their own, which we show how to fix in the first "Electrical Short" discussion