Skip to content

Array instances

File: pics/simple_array.pic.yml

Error caught: short + net + open — two routes connecting pad arrays cross each other, causing a geometric short, a missing-net group derived from that short, and dangling ports on the pads that aren't routed.

Expected: ok=False, error_count=9 (2 shorts + 1 missing_in_schematic net group + 6 opens for unrouted pads)

import tempfile
from copy import deepcopy
from pathlib import Path

import elvis
import gdsfactory as gf
from IPython.display import Markdown, display
from kwasm import Tool, show

gf.gpdk.PDK.activate()

PICS = Path("../pics")
BUILD_GDS = Path("../build/gds")
BUILD_GDS.mkdir(parents=True, exist_ok=True)
PIC = PICS / "simple_array.pic.yml"

Schematic

Two rows of 5 pads each, 200 µm column pitch. Routes connect selected ports across the two arrays — but they cross each other, causing a short.

schematic = elvis.load_schematics(PIC)
schematic
{'simple_array': {'instances': {'pads': {'component': 'pad',
    'settings': {},
    'array': {'columns': 5,
     'rows': 1,
     'column_pitch': 200.0,
     'row_pitch': 100.0}},
   'pads2': {'component': 'pad',
    'settings': {},
    'array': {'columns': 5,
     'rows': 1,
     'column_pitch': 200.0,
     'row_pitch': 100.0}}},
  'routes': {'elec1': {'links': {'pads<1.0>,e4': 'pads2<3.0>,e2'},
    'routing_strategy': 'route_bundle_electrical',
    'settings': {'allow_layer_mismatch': False,
     'allow_type_mismatch': False,
     'allow_width_mismatch': False}},
   'elec2': {'links': {'pads<3.0>,e4': 'pads2<0.0>,e2'},
    'routing_strategy': 'route_bundle_electrical',
    'settings': {'allow_layer_mismatch': False,
     'allow_type_mismatch': False,
     'allow_width_mismatch': False}}},
  'ports': {},
  'placements': {'pads': {'x': 0, 'y': 0, 'dx': -96.428, 'dy': -26.49},
   'pads2': {'x': -96.4280014038086,
    'y': -26.489999771118164,
    'dx': -0.0,
    'dy': -515.322,
    'rotation': 0,
    'mirror': False}}}}

Build from schematic

gds_path = BUILD_GDS / "simple_array.gds"
c = gf.read.from_yaml(schematic["simple_array"])
c.write_gds(gds_path)
show(
    gds_path,
    netlist=PIC,
    tools=[Tool.RULER, Tool.CLEAR_ALL, Tool.TOP_PORTS, Tool.INSTANCE_PORTS],
)
GDS Layout Preview

Tip: Use instance-ports to see all 20 port positions (5 pads × 4 ports × 2 arrays). The ruler can verify the 200µm column pitch.

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()) / "simple_array.lyrdb"
rdb.save(str(lyrdb))
show(
    gds_path,
    lyrdb=lyrdb,
    netlist=PIC,
    tools=[Tool.SELECT, Tool.RULER, Tool.CLEAR_ALL],
)
GDS Layout Preview

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.

Errors in detail:

print(f"ok={rdb.num_items() == 0}, error_count={rdb.num_items()}")
Markdown(elvis.error_summary(rdb))
ok=False, error_count=9
cell error type description
simple_array LVS.net.missing_in_schematic Net {pads<1.0>,{pad,e1,e2,e3,e4}; pads<3.0>,{pad,e1,e2,e3,e4}; pads2<0.0>,{pad,e1,e2,e3,e4}; pads2<3.0>,{pad,e1,e2,e3,e4}} in layout but not in schematic
simple_array LVS.open Open port: pads<2.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.open Open port: pads2<1.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.open Open port: pads<0.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.open Open port: pads2<2.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.open Open port: pads<4.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.open Open port: pads2<4.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.short Geometric short between 'pads<1.0>,e4 -> pads2<3.0>,e2' and 'pads<3.0>,e4 -> ...' (1 location)
simple_array LVS.short Geometric short between 'pads<1.0>,e4 -> pads2<3.0>,e2' and 'pads2<0.0>,e2 -> ...' (1 location)

Fix

Uncross the routes in simple_array.pic.yml — swap the right-hand sides of the two links so each route's source and destination columns line up in the same order on both arrays:

routes:
  elec1:
    links:
      pads<1.0>,e4: pads2<0.0>,e2   # was pads2<3.0>,e2
  elec2:
    links:
      pads<3.0>,e4: pads2<3.0>,e2   # was pads2<0.0>,e2

Below we deepcopy the schematic, apply the swap, and re-run LVS:

schematic_fixed = deepcopy(schematic)
routes = schematic_fixed["simple_array"]["routes"]

# Swap the right-hand sides of the two routes
elec1_target = routes["elec1"]["links"]["pads<1.0>,e4"]
elec2_target = routes["elec2"]["links"]["pads<3.0>,e4"]
routes["elec1"]["links"]["pads<1.0>,e4"] = elec2_target
routes["elec2"]["links"]["pads<3.0>,e4"] = elec1_target

c_fixed = gf.read.from_yaml(schematic_fixed["simple_array"])
c_fixed.write_gds(gds_path)
rdb_fixed = elvis.lvs_rdb(
    gds_path,
    schematic_fixed,
    short_layers=[(49, 0)],
    equivalent_ports={"pad": ["pad", "e1", "e2", "e3", "e4"]},
)
rdb_fixed.save(str(lyrdb))
display(show(gds_path, lyrdb=lyrdb, netlist=PIC, tools=[Tool.FIT_ALL]))

print(f"ok={rdb_fixed.num_items() == 0}, error_count={rdb_fixed.num_items()}")
Markdown(elvis.error_summary(rdb_fixed))
GDS Layout Preview
ok=False, error_count=6
cell error type description
simple_array LVS.open Open port: pads2<4.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.open Open port: pads2<2.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.open Open port: pads2<1.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.open Open port: pads<0.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.open Open port: pads<4.0>,{pad,e1,e2,e3,e4} is not connected
simple_array LVS.open Open port: pads<2.0>,{pad,e1,e2,e3,e4} is not connected

The 2 shorts and the merged LVS.net.missing_in_schematic group are gone — the topology now matches what the schematic declared. The 6 remaining LVS.open errors are simply the unrouted pads (out of 10 total, only 4 are wired up in this demo); they're orthogonal to the crossing-routes bug and would be there even without the fix.

Why it matters

Crossed routes in pad arrays create shorts that are nearly impossible to spot in a layout viewer — the X-shaped crossing looks intentional. Elvis's AREF expansion unpacks the array into individual pad instances and then checks each route chain for polygon overlap, finding the hidden cross-wiring before it causes a circuit failure.