Skip to content

Open port

File: pics/simple_splitter.pic.yml

Error caught: open — port wg_in,o1 is connected in the layout but never promoted to a top-level schematic port.

Error type: LVS.open

Expected: ok=False, error_count=1

import tempfile
from pathlib import Path

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

gf.gpdk.PDK.activate()

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

Schematic

The schematic declares two top-level ports (o2, o3) but omits o1.
wg_in,o1 — the free end of the input waveguide — is left dangling.

schematic = elvis.load_schematics(PIC)
schematic
{'simple_splitter': {'instances': {'mmi': {'component': 'mmi1x2',
    'settings': {}},
   'wg_in': {'component': 'straight', 'settings': {'length': 10}},
   'wg_out1': {'component': 'straight', 'settings': {'length': 10}},
   'wg_out2': {'component': 'straight', 'settings': {'length': 10}}},
  'connections': {'mmi,o2': 'wg_out1,o1',
   'mmi,o3': 'wg_out2,o1',
   'wg_in,o2': 'mmi,o1'},
  'ports': {'o2': 'wg_out1,o2', 'o3': 'wg_out2,o2'},
  'placements': {'mmi': {'x': 0, 'y': 0},
   'wg_in': {'x': -20, 'y': 0},
   'wg_out1': {'x': 15.5, 'y': 0.625},
   'wg_out2': {'x': 15.5, 'y': -0.625}}}}

Build from schematic

c = gf.read.from_yaml(schematic["simple_splitter"])
gds_path = BUILD_GDS / "simple_splitter.gds"
c.write_gds(gds_path)
show(gds_path, netlist=PIC, tools=[Tool.FIT_ALL, Tool.DANGLING_PORTS])
GDS Layout Preview

LVS Results

rdb = elvis.lvs_rdb(gds_path, schematic)
rdb_path = Path(tempfile.gettempdir()) / "simple_splitter.lyrdb"
rdb.save(str(rdb_path))
show(gds_path, lyrdb=rdb_path, netlist=PIC, tools=[Tool.FIT_ALL])
GDS Layout Preview

Open errors in detail:

print(f"ok={rdb.num_items() == 0}, error_count={rdb.num_items()}")
Markdown(elvis.error_summary(rdb))
ok=False, error_count=1
cell error type description
simple_splitter LVS.open Open port: wg_in,o1 is not connected

The Bug: Missing Port in ports:

The schematic ports: block only lists two of the three circuit I/O ports:

ports:
  o2: wg_out1,o2
  o3: wg_out2,o2
  # o1: wg_in,o1   ← missing!

wg_in is a 2-port straight waveguide, so Elvis treats it as transparent routing.
Its free end (wg_in,o1) is reachable from the layout but has no corresponding top-level port in the schematic — Elvis flags it as an open (dangling) port.

Fix

Add the missing entry to ports: in simple_splitter.pic.yml:

ports:
  o1: wg_in,o1   # ← add this
  o2: wg_out1,o2
  o3: wg_out2,o2
schematic["simple_splitter"]["ports"]["o1"] = "wg_in,o1"  # the fix

c2 = gf.read.from_yaml(schematic["simple_splitter"])
c2.write_gds(gds_path)
elvis.lvs_rdb(gds_path, schematic).save(str(rdb_path))
show(gds_path, lyrdb=rdb_path, netlist=PIC, tools=[Tool.FIT_ALL])
GDS Layout Preview

Why it matters

Open ports in optical waveguides can cause back-reflections and indicate an unfinished circuit. Promoting a port is a promise that it will be connected at a higher level of the hierarchy. If an open is intentional use a dedicated Terminator component (even a structurally empty one) with a single port to make the intent explicit.

Tip

Dangling / open / unused ports are such a common issue that we have a special tool in the gds viewer to find them. Use the 'dangling ports' tool in the first layout viewer to view the dangling ports without even having to run LVS.