GDS Generation

The last stage of Flow A: turning a routed, timing/function-verified netlist into an actual GDSII layout, via KLayout.

Why this isn’t just “open the DEF in KLayout”

A routed DEF only carries abstract cell outlines from the LEF — not the real Sky130 standard-cell polygons. Producing a true GDS means merging the PDK’s own standard-cell GDS shapes into the DEF’s placement/routing, using a proper LEF/DEF → GDS layer map. This flow does that with KLayout’s stream_out.py script (from the LibreLane/OpenLane project — see Flow A: Overview for the reference-flow context), driven headless through KLayout’s own Python bindings (pya).

That’s a different thing from the apt-installed KLayout package: the .deb gives you the KLayout application (GUI + klayout binary), which does not expose pya to the system python3. Scripted DEF/LEF/GDS automation needs the separate klayout pip package instead, in its own venv.

One-time setup

python3 -m venv ~/klayout-venv
source ~/klayout-venv/bin/activate
pip install klayout click

mkdir -p ~/thesis/tools/klayout-scripts
wget -O ~/thesis/tools/klayout-scripts/stream_out.py \
  https://raw.githubusercontent.com/The-OpenROAD-Project/OpenLane/master/scripts/klayout/stream_out.py

Verify:

python3 -c "import pya; print(pya.__file__)"

Warning

Do not create this venv from a terminal that has oss-cad-suite/environment sourced. oss-cad-suite ships its own bundled python3 (under oss-cad-suite/py3bin/), which shadows the system one on PATH and breaks python3 -m venv’s pip bootstrap (ensurepip ... exit status 127). Check which python3 first; if it resolves into oss-cad-suite/..., invoke the system interpreter explicitly instead (/usr/bin/python3.11 -m venv ~/klayout-venv). Keep this venv’s terminal separate from the one that sources oss-cad-suite/environment going forward — the two environments’ Python setups conflict on PATH.

Running it

Via the Makefile (recommended — reads top_design/proj_name straight out of yosys_common.tcl for you):

source ~/klayout-venv/bin/activate     # NOT oss-cad-suite/environment
make gds

Or directly:

chmod +x scripts/gen_gds.sh
./scripts/gen_gds.sh

Either way, this needs $PDK_ROOT/$PDK exported as usual, and <proj_name>_placed.def already produced by pnr.tcl (despite the “_placed” name, this file already contains full routing — write_def runs after detailed_route, not merely after placement). Output: <proj_name>.gds in the project root.

Override the stream_out.py location if it isn’t at the default path above:

STREAM_OUT_PY=/path/to/stream_out.py ./scripts/gen_gds.sh

Verifying the output

Open it in the KLayout GUI (the apt-installed KLayout is fine for viewing — no Python bindings needed just to look):

deactivate
source ~/thesis/tools/oss-cad-suite/environment   # or plain `klayout` if on PATH
klayout <proj_name>.gds

Sanity-check visually: a sane die/core rectangle, visible multi-layer metal routing (not just bare standard-cell boxes), and a non-trivial file size (ls -lh <proj_name>.gds) — a near-empty GDS despite a [INFO] Done. message would suggest a silent merge problem.

The script itself prints [INFO] Checking for missing GDS... near the end — All LEF cells have matching GDS cells. is the expected PASS. A has no matching GDS cell error means some cell used in the mapped netlist isn’t in the PDK’s standard-cell GDS library, and should be treated as a failed run, not a warning.

PDK file locations

gen_gds.sh expects the ciel/open_pdks layout used so far: $PDK_ROOT/$PDK/libs.tech/klayout/tech/{<PDK>.lyt,<PDK>.lyp,<PDK>.map}. This subpath has varied across PDK tooling versions — if the script reports a missing PDK file, confirm the real layout first:

find "$PDK_ROOT/$PDK/libs.tech/klayout" -maxdepth 3 -type f

Status

Implemented and validated for GDSII generation via gen_gds.sh/stream_out.py. Not yet implemented: DRC and LVS against the generated GDS — see the status note in Running Flow A on Your Own SV Design.