Netlist extractor YAML

Netlist extractor YAML#

Any component can extract its netlist with get_netlist

While gf.read.from_yaml converts a YAML Dict into a Component

get_netlist converts Component into a YAML Dict

import gdsfactory as gf
import yaml
c = gf.components.mzi()
c.plot()
../_images/744b12ed8438d739cb1677232cac6d772afba73592f8f895146116f6be89f904.png
c.plot_netlist()
<networkx.classes.graph.Graph at 0x7f64bd467c50>
../_images/4c30c834f7353cd719f86b0810bcd81690fc56c67424accb8777ccb994b5402b.png
c = gf.components.ring_single()
c.plot()
../_images/718b7608fc5cc2b02e655d0c8e6cd145f7fd81011e4b78178707c06acc26c353.png
c.plot_netlist()
<networkx.classes.graph.Graph at 0x7f64bd4727b0>
../_images/eee137246e6117964d6bcb29fbfc8bc7e4c23a46e18ad9b57a34efbbc1194659.png
n = c.get_netlist()
netlist_string = c.write_netlist(n)
n = yaml.safe_load(netlist_string)
i = list(n["instances"].keys())
i
['bend_euler',
 'bend_euler2',
 'coupler_ring',
 'straight',
 'straight2',
 'straight3']
instance_name0 = i[0]
n["instances"][instance_name0]["settings"]
{'allow_min_radius_violation': False,
 'angle': 90,
 'angular_step': None,
 'cross_section': 'strip',
 'layer': None,
 'npoints': None,
 'p': 0.5,
 'radius': None,
 'width': None,
 'with_arc_floorplan': True}

Instance names#

By default get netlist names each instance with the name of the reference

@gf.cell
def mzi_with_bend_automatic_naming():
    c = gf.Component()
    mzi = c.add_ref(gf.components.mzi())
    bend = c.add_ref(gf.components.bend_euler())
    bend.connect("o1", mzi.ports["o2"])
    return c


c = mzi_with_bend_automatic_naming()
c.plot_netlist()
/home/runner/work/gplugins/gplugins/.venv/lib/python3.12/site-packages/gdsfactory/component.py:577: UserWarning: Unconnected ports: ['bend_euler,o2', 'mzi,o1']
  return get_netlist(
<networkx.classes.graph.Graph at 0x7f64bd0d8170>
../_images/3be37ab580f8246d454f5110e936ab2a9d0fe892eb73e3ce7dbaa6da144f1d51.png
@gf.cell
def mzi_with_bend_deterministic_names_using_alias():
    c = gf.Component()
    mzi = c.add_ref(gf.components.mzi(), name="my_mzi")
    bend = c.add_ref(gf.components.bend_euler(), name="my_bend")
    bend.connect("o1", mzi.ports["o2"])
    return c


c = mzi_with_bend_deterministic_names_using_alias()
c.plot_netlist()
/home/runner/work/gplugins/gplugins/.venv/lib/python3.12/site-packages/gdsfactory/component.py:577: UserWarning: Unconnected ports: ['my_bend,o2', 'my_mzi,o1']
  return get_netlist(
<networkx.classes.graph.Graph at 0x7f64bd0eb3b0>
../_images/f67fa5d605c061d49ac0486794c09bc716f20e9c2b256758b22db3ee5b2e2439.png
c = gf.components.mzi()
c.plot()
../_images/744b12ed8438d739cb1677232cac6d772afba73592f8f895146116f6be89f904.png
c = gf.components.mzi()
n = c.get_netlist()
print(c.get_netlist().keys())
dict_keys(['instances', 'placements', 'ports', 'nets'])
c.plot_netlist()
<networkx.classes.graph.Graph at 0x7f64bd44b110>
../_images/4c30c834f7353cd719f86b0810bcd81690fc56c67424accb8777ccb994b5402b.png
n.keys()
dict_keys(['instances', 'placements', 'ports', 'nets'])

warnings#

Lets make a connectivity error, for example connecting ports on the wrong layer

@gf.cell
def mmi_with_bend():
    c = gf.Component()
    mmi = c.add_ref(gf.components.mmi1x2(), name="mmi")
    bend = c.add_ref(gf.components.bend_euler(layer=(2, 0)), name="bend")
    bend.connect("o1", mmi.ports["o2"], allow_layer_mismatch=True)
    return c


c = mmi_with_bend()
c.plot()
../_images/9242e6f744fcdb37a1cc99092b7008f99a2933939b5b951b963d221b6316cc1a.png
n = c.get_netlist()
/home/runner/work/gplugins/gplugins/.venv/lib/python3.12/site-packages/gdsfactory/component.py:577: UserWarning: Unconnected ports: ['bend,o2', 'mmi,o1', 'mmi,o3']
  return get_netlist(
print(n.get("warnings", {}))
{}
c.plot_netlist()
<networkx.classes.graph.Graph at 0x7f64bd01c4a0>
../_images/3909ffe0ddb50e1ab26a73c0c2d2a4de7dc8c18b62d3d1def09edfa6bf351bfd.png

get_netlist_recursive#

When you do get_netlist() for a component it will only show connections for the instances that belong to that component. So despite having a lot of connections, it will show only the meaningful connections for that component. For example, a ring has a ring_coupler. If you want to dig deeper, the connections that made that ring coupler are still available.

get_netlist_recursive() returns a recursive netlist.

c = gf.components.ring_single()
c.plot()
../_images/718b7608fc5cc2b02e655d0c8e6cd145f7fd81011e4b78178707c06acc26c353.png
c.plot_netlist()
<networkx.classes.graph.Graph at 0x7f64bcf07500>
../_images/eee137246e6117964d6bcb29fbfc8bc7e4c23a46e18ad9b57a34efbbc1194659.png
c = gf.components.ring_double()
c.plot()
../_images/64faa5e42a340035205ff93369d80be6ea684031bf687f79c54fc91af14521b4.png
c.plot_netlist()
<networkx.classes.graph.Graph at 0x7f64bd473da0>
../_images/1dca68f4b36f98bbf3fc926738b098af9fc0effb4c9f3aa068e49bb9e6e6d15c.png
c = gf.components.mzit()
c.plot()
../_images/fa531dc74f061cfacf599a5b4372bdca7d1da32bc804ed834bcd00b8efbb11f1.png
c.plot_netlist()
<networkx.classes.graph.Graph at 0x7f64bd4a9760>
../_images/91111de802918338c3b54276a51ef0a1b0c8bf2b904854a6df960d3c7dfc4ec4.png
coupler_lengths = (10, 20, 30)
coupler_gaps = (0.1, 0.2, 0.3)
delta_lengths = (10, 100)

c = gf.components.mzi_lattice(
    coupler_lengths=coupler_lengths,
    coupler_gaps=coupler_gaps,
    delta_lengths=delta_lengths,
)
c.plot()
../_images/3506336ced28cc04af04b221ce4e0c2d3ffb8e66c239c1c7c8557a45a073faea.png
c.plot_netlist()
<networkx.classes.graph.Graph at 0x7f64bd050ef0>
../_images/e80e8e0b6055be8e415c40750ffe26734a77b7e94964b55e7403bae48a439453.png
coupler_lengths = (10, 20, 30, 40)
coupler_gaps = (0.1, 0.2, 0.4, 0.5)
delta_lengths = (10, 100, 200)

c = gf.components.mzi_lattice(
    coupler_lengths=coupler_lengths,
    coupler_gaps=coupler_gaps,
    delta_lengths=delta_lengths,
)
c.plot()
../_images/b434a3e78efaabf7a47fe0b55ffcf02f934f83f014224862e5c909b696988055.png
n = c.get_netlist()
c.plot_netlist()
<networkx.classes.graph.Graph at 0x7f64bced7c50>
../_images/b8bd553196b166b0302fb88108cb912164eb89f2810fa4af4bf8968f8d00f1b2.png
n_recursive = c.get_netlist(recursive=True)
n_recursive.keys()
dict_keys(['mzi_lattice', 'mzi', 'mzi2', 'mzi3'])

Placement information is accumulated, and connections and ports are mapped, respectively, to the ports of the unique instances or the component top level ports. This can be plotted:

c.plot_netlist(with_labels=False)  # labels get cluttered
<networkx.classes.graph.Graph at 0x7f64bd0db290>
../_images/c16d9633f16c6604dae2c392e1540b32788a00b0bdfa45213cbfef27de3b527e.png