Design Rule Check¶
After finalizing the physical layout of the 800G transceiver chip, the Design Rule Check (DRC) serves as the critical bridge between digital design and physical manufacturing. Even a visually perfect layout can contain microscopic violations—such as traces that are too narrow or elements placed too close together—that would lead to total device failure during the lithography and etching processes at the foundry.
This notebook checks the chip layout against the SiEPIC_EBeam process requirements with drc_check. Because drc_check exports the component and runs the KLayout DRC engine from Python, we can programmatically identify “un-manufacturable” geometries, generate visual error markers, and iteratively refine the design.
The following sections run the DRC deck on the chip, draw the violations on a dedicated error layer for quick debugging, and check the corrected layout.
First we build the chip layout.
[1]:
%%capture
%run Chip_Layout.ipynb
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Progress: 100%
Run the design rule check¶
drc_check takes the component and the DRC runset (rule deck). It exports pic to GDSII, runs KLayout in batch mode, and returns a DRCResults object with the markers of every rule. The runset compares every polygon in the design against rules such as minimum widths, spacing and enclosure requirements. For more information see the DRC
guide.
[2]:
# Export the chip, run the SiEPIC EBeam runset through KLayout and load the markers
results = pf.drc_check(pic, "SiEPIC_EBeam.drc")
KLayout DRC finished in 6 s
Inspect the results¶
The summary lists the number of markers of each rule, which shows quickly which layers or rules (for example, Metal 2) cause issues before looking at the layout itself.
[3]:
print(results)
print(f"DRC clean: {results.is_clean}")
DRC results summary
--------------------------------
Total violations: 149
Violations by category:
Devices: 0
Boundary: 0
Si_width: 0
Si_space: 0
SiN_width: 0
SiN_space: 0
M1_width: 0
M1_space: 0
M2_width: 96
M2_space: 53
MLOpen_width: 0
MLOpen_space: 0
M2_M1_overlap: 0
SiEPIC-1a: 0
DT_Metal_separation: 0
DRC clean: False
Add violation markers to the layout¶
To make the errors actionable, we draw a box around each marker on an Errors layer. The markers go into a new component that holds a reference to the chip, so pic itself is left untouched. Each marker is given in the coordinates of the cell it was found in, and results.in_top_cell moves it into the chip’s coordinates.
Marker display limit: for readability, only the first 10 violations per category are drawn. The full violation list is still available in
results; this limit only affects the layout view.
[4]:
# New top cell with the chip and a layer of violation markers on top
chip_with_markers = pf.Component("800G_2xFR4 DRC")
chip_with_markers.add(pf.Reference(pic))
# Readability cap: draw only the first N violations per category
max_markers_per_category = 10
for category in results.categories:
for marker in results[category].markers[:max_markers_per_category]:
# Edge-pair markers (width, space) carry two edges; polygon markers a hull
marker = results.in_top_cell(marker)
if isinstance(marker, pf.verification.EdgePairMarker):
points = [p for edge in marker.edge_pair for p in edge]
else:
points = marker.hull
# Box around the marker, padded by 0.5 µm so thin markers stay visible
xs, ys = zip(*points)
box = pf.Rectangle(
(min(xs) - 0.5, min(ys) - 0.5), (max(xs) + 0.5, max(ys) + 0.5)
)
chip_with_markers.add("Errors", box)
# Label each box with the rule name
center = sum(box.bounds()) / 2
label = pf.Label(category[:10], center, anchor="o", scaling=2.0)
chip_with_markers.add("Text", label)
Visualize and resolve violations¶
We use the LiveViewer to inspect the violations. Zooming in on the boxes of the Errors layer shows the exact locations of the failures.
The check reports violations of ‘M2_width’ and ‘M2_space’. To resolve them, the trace width is increased to 10.0 µm, so the metal traces meet the foundry’s minimum manufacturing requirements. After applying this fix, the DRC confirms the layout is clean.
[5]:
from photonforge.live_viewer import LiveViewer
viewer = LiveViewer()
viewer(chip_with_markers)
LiveViewer started at http://127.0.0.1:40469. Call its 'stop()' method to free the port.
[5]:
[6]:
# Widen the M2 traces and check the updated chip again
pic.update(trace_width=10.0)
results = pf.drc_check(pic, "SiEPIC_EBeam.drc")
print(f"DRC clean: {results.is_clean}")
KLayout DRC finished in 6 s
DRC clean: True
[7]:
viewer(pic)
[7]:
Notes¶
Violation markers are drawn on the Errors layer of
chip_with_markers.Labels show the violation category (first 10 characters).
Zoom in on the LiveViewer to see individual violations.
After we run DRC we might need to adjust some of the dimensions and iterate on the design to make sure it is manufacturable.