How you run them depends on how you installed
All 8 demos are starters bundled in the wheel, grouped into nanodevice/, photonics/, passives/, and digital/ categories: klink init <proj> scaffolds them into <proj>/example_template/<category>/ and a pip user runs python example_template/<category>/<name>.py — ebl_wraparound, hallbar, neural_electrode under nanodevice/, gf_mzi_module under photonics/, idc_capacitor, spiral_inductor, saw_idt_filter, baw_fbar_planview under passives/, and fit_device_pnr_lvs, chat_to_netlist_pnr, multilayer_pnr_lvs, padframe_pnr_lvs under digital/ (the cards below give this command directly). The 4 digital/ demos additionally need a running KLayout session (they do live P&R+LVS); from a repo clone you can also run them as python -m examples_klink.public.demos.digital.<name>, which the cards below also give.
python -m … script talking to KLayout over the plugin port. MCP is the layer that lets your agent call klink as resident tools. Both paths use the same pip install klayout-klink.A KLayout "port" is just a session — any port works; none has a special role. Use an empty or test-owned session, not your manual working tab.
The 8 demos at a glance
| Demo | Category | Requires | Measured |
|---|---|---|---|
| EBL wraparound | nanodevice | fully offline | 40 electrodes · 12 patches · 0 violations · 0 overlaps |
| Hall bar | nanodevice | offline (--live optional) | semantic bundle + routed result |
| Neural electrode | nanodevice | live KLayout | 48 ports · 24 nets · overlap 0 · hit 0 |
| Fit device → P&R → LVS | digital P&R | live KLayout | routed 94/94 · LVS match=True · 173 devices |
| Netlist → lint → P&R | digital P&R | live KLayout | lint 0 err · routed 3/3 · LVS match=True |
| Multilayer P&R at scale | digital P&R | live KLayout | routed 405/405 · LVS match=True · 766 devices · ~17s |
| Probe-card padframe | digital P&R | live KLayout | routed 94/94 · LVS match=True · 16 pads connected |
| gdsfactory MZI takeover | photonics | live KLayout + gdsfactory | 6 optical nets · reroute 12 routes · 0 crossings |
1 · EBL nanodevice wraparound fully offline
A parametric electron-beam-lithography wraparound generator. Offline it prints the generated bundle; --live writes to a KLayout session. The fastest path to a first result with no external geometry.
python example_template/nanodevice/ebl_wraparound.py # [--live] [--keep]
# from a repo clone you can also run: python -m examples_klink.public.demos.nanodevice.ebl_wraparound
Reusable core: klink.domains.nanodevice.devices.wraparound.build_wraparound_demo. Copy the demo and edit electrode count / pitch / writefield params — the flow does not change.
2 · Hall bar nanodevice offline (--live)
A parametric Hall-bar generator. Offline it prints the semantic bundle + routed result; --live writes a disposable KLayout cell (deleted unless --keep). It demonstrates the "device generator + delegate to the generic router" loop behind nanodevice.hallbar.
python example_template/nanodevice/hallbar.py # [--live] [--keep]
# from a repo clone you can also run: python -m examples_klink.public.demos.nanodevice.hallbar
Reusable core: tapered-hybrid router + port.mark / anchor.mark. From a HallBarSpec (bar length/width, contact count, pad dims, pitch, gaps) it computes the whole device geometry, then delegates contact→pad routing to the generic router.
3 · Neural-electrode harness live KLayout
A self-contained probe generator: defines pad/via geometry and Port/Anchor resources, then calls the tapered-hybrid router. No GDS, just live Port/Anchor PCells. Use an empty or test-owned session.
python example_template/nanodevice/neural_electrode.py --port <session-port> --elec-rows 4
# from a repo clone you can also run: python -m examples_klink.public.demos.nanodevice.neural_electrode --port <session-port> --elec-rows 4
1/0 + 12×3/0)4 · Fit a device → digital P&R → LVS live KLayout
The full self-contained, IP-free digital flow: fit a parametric device PCell from synthetic exemplar geometry, place it, run detailed routing, and verify with live LVS. Swap in your own harvested exemplar boxes to fit your real device — the flow does not change.
python example_template/digital/fit_device_pnr_lvs.py --port <session-port> # [--draw-only]
# from a repo clone you can also run: python -m examples_klink.public.demos.digital.fit_device_pnr_lvs --port <session-port> # [--draw-only]
Reusable core: map_logic_to_devices(...) → place → FlexDR → live LVS.
5 · Hand-written netlist → lint → P&R → LVS live KLayout
The "describe it in chat, get a verified layout" flow: a 3-stage ring oscillator netlist is written by hand, validated by lint_netlist (every structural mistake gets a fix-it message before any geometry exists), then placed, routed, LVS-verified, and every stage node brought out as a bare labelled trace. Netlists are plain data — an agent (or you) can write one for any topology, no logic synthesizer required.
python example_template/digital/chat_to_netlist_pnr.py --port <session-port>
# from a repo clone you can also run: python -m examples_klink.public.demos.digital.chat_to_netlist_pnr --port <session-port>
6 · Multilayer place & route at scale live KLayout
The scale demo: a bundled 766-device synthetic netlist (a toy 4-bit ALU, 268 gates, netted by an open logic synthesizer, remapped onto this gallery's synthetic fitted devices) is linted, then compared on two example process stacks with the built-in layer-count advisor — the 3-layer public process from the fit-a-device demo, and a 7-layer example stack defined in the demo itself. The advisor prints each stack's core-area cost so you can see why a design this size wants the extra layers. It then places, marks all 20 primary ports (13 in west, 7 out east), and routes with the multilayer engine.
python example_template/digital/multilayer_pnr_lvs.py --port <session-port>
# from a repo clone you can also run: python -m examples_klink.public.demos.digital.multilayer_pnr_lvs --port <session-port>
Copy this file and edit PUBLIC_MULTILAYER for your own layer stack — the flow does not change.
7 · Probe-card-first place & route live KLayout
The reversed-order hardware flow: the probe card / pad ring exists first (positions frozen long ago) and the circuit must meet it — even when the card interior is too small for the whole block. The same synthetic 4-bit adder is linted, then a stand-in 20-pad probe card is fabricated and harvested back with pads_from_gds. A net→pad table assigns all 14 primary ports + VDD + GND; because the interior fits only half the rows, place_grid(forbid_y_bands=…) splits the block half inside / half below, and pdn_split_bands threads one power grid per region bridged by a spine strap.
python example_template/digital/padframe_pnr_lvs.py --port <session-port> # [--no-card]
# from a repo clone you can also run: python -m examples_klink.public.demos.digital.padframe_pnr_lvs --port <session-port> # [--no-card]
--no-card drops the card: every port leaves as a bare labelled wire-end trace at the periphery (inputs west, outputs east), power on the auto-labelled PDN tie rails — routed 94/94, LVS match=True, all 14 stubs CONNECTED. Copy this file and edit the pad table for your own card.
8 · gdsfactory takeover → editable photonic module live KLayout + gdsfactory
A complete thermo-optic MZI — tilted fiber GC → 1×2 MMI splitter → two thermal phase-shifter arms (bottom mirrored) → 2×2 MMI combiner → offset output GCs, plus heater pad rows and a fiber-loopback pair — written as an ordinary gdsfactory script, then taken over by a single import_gf_component call. One persisted net table then holds every kind of net: the script's own optics (re-drawn by klink), the offset output bank restyled to sbend, the tilted GC a Manhattan router can't reach (all_angle), the loopback pair (dubins arcs), and the heater→pad electrical nets on metal. A single photonics.reroute redraws all of them — so after you drag any component in the GUI, one reroute re-routes optics and metal together.
python example_template/photonics/gf_mzi_module.py --port <session-port>
# … drag a component in KLayout …
python example_template/photonics/gf_mzi_module.py --port <session-port> --reroute
# from a repo clone you can also run: python -m examples_klink.public.demos.photonics.gf_mzi_module --port <session-port> [--reroute]
--reroute re-routes from the dragged positions without rebuilding, keeping your edit. Re-running with no flag rebuilds from the gdsfactory source and snaps every component back to its original spot, undoing the drag — a common first-time surprise, so the flag is the fix. (An agent with the MCP tools calls photonics.reroute directly.)Requirements: gdsfactory in the same interpreter that runs it. The demos are pinned to the tested line — pip install "klayout-klink[photonics]" gets a known-good gdsfactory. If gdsfactory already lives in another venv, add klink into that venv and run from there; do not sys.path-hack the repo into a foreign interpreter (that path leads to version mismatch and 1000×-off geometry).
Passive-device geometry templates offline (--live)
Four parametric passive-device geometry templates, starters in the passives/ category: after klink init, run python example_template/passives/<name>.py. Offline by default, each writes a GDS under test_outputs/ and prints a structured self-check summary; --live [--port <session-port>] pushes a disposable cell to a KLayout session instead. Every family marks klink Ports (999/99) on its electrical terminals, so the routing backends work on them out of the box. Each is a geometry template, NOT a validated electrical/acoustic design — tune the numbers for your process and verify with your own models (SAW/BAW make no frequency or material claims).
- IDC capacitor —
python example_template/passives/idc_capacitor.py(defaults, 10 fingers: 2 merged regions, no short, 2 ports) - Square spiral inductor —
python example_template/passives/spiral_inductor.py(defaults, 3 turns: 1 merged region per metal layer, underpass crosses 4 segments, 2 ports) - SAW IDT filter —
python example_template/passives/saw_idt_filter.py(defaults, 12 pairs: 2 merged regions per IDT, 1 per reflector grating, 4 ports) - BAW / FBAR plan view —
python example_template/passives/baw_fbar_planview.py(defaults, 2000 µm² target: no two edges parallel, area error <1%, 2 ports)
Every command supports [--live --port <session-port>].
Feature examples
examples_klink/public/features shows single capabilities, good to learn the API and copy into your project:
- gdsfactory: route to KLayout (
23), route ports (24), net examples (25), component marker (26), width mismatch + auto taper (29), routing zoo (30) — on the opengf.gpdk, same interpreter rule. - Port/Anchor walkthrough (
anchor_port_5_exampleand its_pyavariant). - Router stress: tapered, tapered segments, steiner, damped, plus future/missing-algorithm showcases.
- measurement import, harness/probe generators.
The examples_klink/public/smoke folder has capability smoke demos (draw, PCell zoo, cells & shapes, delete/undo, exec, route run) — not full tutorials, but good to confirm a primitive works.
Public boundaries
The public gallery's contract is open + open-box runnable:
- No NDA / proprietary PDK content.
- No committed private GDS.
- No dev-only PDK module imports.
- Third-party deps handled as ordinary
pip install.
.gitignore blocks *.gds/*.oas by default.