Klayout Design Rule Checking (DRC)

Klayout Design Rule Checking (DRC)#

Your device can be fabricated correctly when it meets the Design Rule Checks (DRC) from the foundry, you can write DRC rules from gdsfactory and customize the shortcut to run the checks in Klayout.

Here are some rules explained in repo generic DRC technology and video

rules1

try:
  import google.colab
  is_running_on_colab = True
  !pip install gdsfactory gplugins > /dev/null
  
except ImportError:
  is_running_on_colab = False
import gdsfactory as gf
from gdsfactory.component import Component
from gdsfactory.generic_tech import LAYER
from gdsfactory.typings import Float2, Layer

from gplugins.klayout.drc.write_drc import (
    check_area,
    check_density,
    check_enclosing,
    check_separation,
    check_space,
    check_width,
    write_drc_deck_macro,
)

gf.CONF.display_type = "klayout"
help(write_drc_deck_macro)
Help on function write_drc_deck_macro in module gplugins.klayout.drc.write_drc:

write_drc_deck_macro(rules: 'list[str]', layers: 'dict[str, Layer] | None' = None, name: 'str' = 'generic', filepath: 'PathType | None' = None, shortcut: 'str' = 'Ctrl+Shift+D', mode: 'str' = 'tiled', threads: 'int' = 4, tile_size: 'int' = 500, tile_borders: 'int | None' = None) -> 'str'
    Write KLayout DRC macro.
    
    You can customize the shortcut to run the DRC macro from the Klayout GUI.
    
    Args:
        rules: list of rules.
        layers: layer definitions can be dict or dataclass.
        name: drc rule deck name.
        filepath: Optional macro path (defaults to .klayout/drc/name.lydrc).
        shortcut: to run macro from KLayout GUI.
        mode: tiled, default or deep (hierarchical).
        threads: number of threads.
        tile_size: in um for tile mode.
        tile_borders: sides for each. Defaults None to automatic.
    
    .. code::
    
        import gdsfactory as gf
        from gplugins.klayout.drc.write_drc import (
            write_drc_deck_macro,
            check_enclosing,
            check_width,
            check_space,
            check_separation,
            check_area,
            check_density,
        )
        from gdsfactory.generic_tech import LAYER
        rules = [
            check_width(layer="WG", value=0.2),
            check_space(layer="WG", value=0.2),
            check_separation(layer1="HEATER", layer2="M1", value=1.0),
            check_enclosing(layer1="VIAC", layer2="M1", value=0.2),
            check_area(layer="WG", min_area_um2=0.05),
            check_density(
                layer="WG", layer_floorplan="FLOORPLAN", min_density=0.5, max_density=0.6
            ),
            check_not_inside(layer="VIAC", not_inside="NPP"),
        ]
    
        drc_check_deck = write_drc_deck_macro(rules=rules, layers=LAYER, mode="tiled")
        print(drc_check_deck)
rules = [
    check_width(layer="WG", value=0.2),
    check_space(layer="WG", value=0.2),
    check_width(layer="M1", value=1),
    check_width(layer="M2", value=2),
    check_space(layer="M2", value=2),
    check_separation(layer1="HEATER", layer2="M1", value=1.0),
    check_enclosing(layer1="M1", layer2="VIAC", value=0.2),
    check_area(layer="WG", min_area_um2=0.05),
    check_density(
        layer="WG", layer_floorplan="FLOORPLAN", min_density=0.5, max_density=0.6
    ),
]

drc_check_deck = write_drc_deck_macro(
    rules=rules,
    layers=LAYER,
    shortcut="Ctrl+Shift+D",
)
Wrote DRC deck to '/home/runner/.klayout/drc/generic.lydrc' with shortcut 'Ctrl+Shift+D'

Lets create some DRC errors and check them on klayout.

layer = LAYER.WG


@gf.cell
def width_min(size: Float2 = (0.1, 0.1)) -> Component:
    return gf.components.rectangle(size=size, layer=layer)


@gf.cell
def area_min() -> Component:
    size = (0.2, 0.2)
    return gf.components.rectangle(size=size, layer=layer)


@gf.cell
def gap_min(gap: float = 0.1) -> Component:
    c = gf.Component()
    r1 = c << gf.components.rectangle(size=(1, 1), layer=layer)
    r2 = c << gf.components.rectangle(size=(1, 1), layer=layer)
    r1.xmax = 0
    r2.xmin = gap
    return c


@gf.cell
def separation(
    gap: float = 0.1, layer1: Layer = LAYER.HEATER, layer2: Layer = LAYER.M1
) -> Component:
    c = gf.Component()
    r1 = c << gf.components.rectangle(size=(1, 1), layer=layer1)
    r2 = c << gf.components.rectangle(size=(1, 1), layer=layer2)
    r1.xmax = 0
    r2.xmin = gap
    return c


@gf.cell
def enclosing(
    enclosing: float = 0.1, layer1: Layer = LAYER.VIAC, layer2: Layer = LAYER.M1
) -> Component:
    """Layer1 must be enclosed by layer2 by value.

    checks if layer1 encloses (is bigger than) layer2 by value
    """
    w1 = 1
    w2 = w1 + enclosing
    c = gf.Component()
    c << gf.components.rectangle(size=(w1, w1), layer=layer1, centered=True)
    r2 = c << gf.components.rectangle(size=(w2, w2), layer=layer2, centered=True)
    r2.movex(0.5)
    return c


@gf.cell
def snapping_error(gap: float = 1e-3) -> Component:
    c = gf.Component()
    r1 = c << gf.components.rectangle(size=(1, 1), layer=layer)
    r2 = c << gf.components.rectangle(size=(1, 1), layer=layer)
    r1.xmax = 0
    r2.xmin = gap
    return c


@gf.cell
def errors() -> Component:
    components = [width_min(), gap_min(), separation(), enclosing()]
    c = gf.pack(components, spacing=1.5)
    c = gf.add_padding_container(c[0], layers=(LAYER.FLOORPLAN,), default=5)
    return c


c = errors()
c.show()  # show in klayout
c.plot()
2024-03-09 00:43:59.160 | WARNING  | gdsfactory.klive:show:49 - UserWarning: Could not connect to klive server. Is klayout open and klive plugin installed?
2024-03-09 00:43:59.262 | INFO     | gdsfactory.technology.layer_views:to_lyp:1017 - LayerViews written to '/tmp/gdsfactory/errors.lyp'.
/opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/gdsfactory/klive.py:49: UserWarning: Could not connect to klive server. Is klayout open and klive plugin installed?
  warnings.warn(
../_images/c7486344694805e3743bdb46638e7d03f8a7616c25aac11753403f3d1c45c62f.png

Klayout connectivity checks#

You can you can to check for component overlap and unconnected pins using klayout DRC.

The easiest way is to write all the pins on the same layer and define the allowed pin widths. This will check for disconnected pins or ports with width mismatch.

import gplugins.klayout.drc.write_connectivity as wc

nm = 1e-3

rules = [
    wc.write_connectivity_checks(pin_widths=[0.5, 0.9, 0.45], pin_layer=LAYER.PORT)
]
script = wc.write_drc_deck_macro(rules=rules, layers=None)
Wrote DRC deck to '/home/runner/.klayout/drc/generic.lydrc' with shortcut 'Ctrl+Shift+D'

You can also define the connectivity checks per section

connectivity_checks = [
    wc.ConnectivyCheck(cross_section="xs_sc", pin_length=1 * nm, pin_layer=(1, 10)),
    wc.ConnectivyCheck(
        cross_section="xs_sc_auto_widen", pin_length=1 * nm, pin_layer=(1, 10)
    ),
]
rules = [
    wc.write_connectivity_checks_per_section(connectivity_checks=connectivity_checks),
]
script = wc.write_drc_deck_macro(rules=rules, layers=None)
Wrote DRC deck to '/home/runner/.klayout/drc/generic.lydrc' with shortcut 'Ctrl+Shift+D'