ordec.layout.klayout — KLayout integration (DRC/LVS)
This module integrates the external KLayout tool for DRC and LVS. It runs KLayout in batch mode (run()) and parses its result files back into ORDB subgraphs: XML result databases (RDB) into DrcReport (parse_rdb()), and LVS databases (LVSDB) into LvsReport (parse_lvsdb()). PDK-specific entry points such as ordec.lib.ihp130.run_drc and ordec.lib.ihp130.run_lvs build on these functions.
For LVS, ORDeC supplies KLayout with two inputs that are generated from the same Cell hierarchy: a SPICE netlist of the schematic (via Netlister) and a GDS file of the layout (via write_gds), both named through one shared Directory (see Cell name matching below).
Hierarchical LVS and KLayout’s align
KLayout’s netlist comparer works hierarchically: it pairs up circuits (layout cells extracted from the GDS vs. .subckt definitions from the schematic netlist) and compares each pair in isolation, treating instances of already-paired subcircuits as opaque building blocks. Circuits are paired by name (case-insensitively). Each compared pair appears as one LvsCircuitPair in the parsed LvsReport.
This pairing only works when both sides have the same hierarchy. To handle differing hierarchies, the LVS deck invokes KLayout’s align step before the comparison. align finds all circuits that have no same-named counterpart on the other side and flattens them, i.e. inlines their contents into their parent circuits. (The top cell of the layout is excepted: if it has no schematic counterpart, align raises an error instead.)
For hierarchical LVS, this has the following consequences:
Cells that exist on both sides (same name) are compared pair by pair, keeping the comparison hierarchical and the report structured.
Cells that exist on one side only are flattened away. This covers leaf device cells (e.g. resistor or MOSFET layout cells, whose devices appear directly inside the parent
.subckton the schematic side), but also deliberately different hierarchy cuts: a flat layout can be compared against a hierarchical schematic and vice versa, and even two hierarchies with shifted cell boundaries compare clean as long as they are electrically equivalent after flattening.Objects of flattened circuits appear in the report under dotted hierarchical names (e.g. device
B1.A1.R1= resistorr1inside instancea1inside instanceb1).Flattening can make structurally identical subcircuits (e.g. two parallel instances of the same cell) topologically symmetric; KLayout then matches the affected nets in an arbitrary but valid way and flags them as ambiguous matches, which
parse_lvsdb()represents asLvsStatus.MatchWarning(not as a mismatch).
tests/lib/lvs_example_hier.ord together with tests/test_ihp130_lvs_hier.py exercises all of these cases.
Cell name matching
Because align and the circuit pairing operate purely on names, LVS is only correct if the netlist and GDS names agree exactly: the schematic and layout of one cell must be paired, and views of different cells must never be. ORDeC’s Directory guarantees this name matching in both directions — two circuits are name-matched by KLayout if and only if they belong to the same cell:
Same cell ⇒ same name. A
Cellsubclass with a given (normalized) parameter set is a singleton, andrun_lvsuses a singleDirectoryfor both netlisting and GDS writing.Directory.name_subgraph()names a subgraph after its cell, memoized per cell object, so the.subcktforA().symboland the GDS cell forA().layoutreceive the identical string. As a guard, registering a second, different subgraph of the same kind under one cell raises an error.Different cells ⇒ different names. All top-level names live in one namespace per
Directory; name collisions (e.g. equal class names from different modules) are resolved by appending number suffixes, so two distinct cells can never receive the same string. Since Directory names contain onlya-z,0-9and_, they are also distinct under KLayout’s case-insensitive name normalization.
Note that both directions hold within one Directory, i.e. within one run_lvs invocation — which is sufficient for the name-based pairing, since KLayout sees exactly the netlist and GDS produced by that one directory. Collision suffixes depend on naming order, so names are not guaranteed to be stable across separate runs.
Functions
- ordec.layout.klayout.run(script, cwd, **kwargs)
Run KLayout script ‘script’ in directory ‘cwd’ with provided keyword args.
- ordec.layout.klayout.parse_rdb(filename, report: DrcReport, directory: Directory = None)
Parse a KLayout XML result database file (RDB), appending the parsed violations into the given DrcReport subgraph.
- Parameters:
filename – Path to the .lyrdb file.
report – Existing DrcReport to append parsed violations into. The checked Layout is taken from report.ref_layout.
directory – Optional Directory for looking up cell names to LayoutInstances. If not provided, DrcItem.cell will be None.
RDB format documentation: https://www.klayout.de/rdb_format.html
- ordec.layout.klayout.parse_rdb_value(value_str: str)
Parse an RDB <value> string into a (tag, kind, payload) tuple.
The grammar covers the full value space accepted by KLayout’s own reader; see RdbValueTransformer for the payload shape of each kind. Raises LarkError if the string is not a valid RDB value.
- ordec.layout.klayout.parse_lvsdb(filename, layout: Layout, schematic: Schematic, directory=None) LvsReport
Parse a KLayout LVS database file (.lvsdb) into an LvsReport subgraph.
- Parameters:
filename – Path to the .lvsdb file.
layout – The Layout subgraph that was checked. Becomes ref_layout of the report and of the top-level LvsCircuitPair. May be None.
schematic – The Schematic subgraph that was compared against. Becomes ref_schematic analogously. May be None.
directory – Optional Directory used during netlisting and GDS export. If given, it is used to resolve subcircuit pairs to their Layout/Schematic subgraphs and item names to ORDB nodes; without it, only the raw LVSDB names are reported.
- Returns:
LvsReport subgraph with all parsed comparison results.
LVSDB format. The format is only documented in the KLayout sources, of which this repository keeps a copy:
experiments/klayout/src/db/db/dbLayoutVsSchematicFormatDefs.hdefines the LVSDB top level,experiments/klayout/src/db/db/dbLayoutToNetlistFormatDefs.hdefines the embedded netlist sections (shared with L2N databases).
An LVSDB file is a tree of parenthesized s-expressions. Every element type has a long and a short key (e.g.
circuitandX); KLayout writes short keys, this parser accepts both. After the magic line#%lvsdb-klayout, the file has three top-level sections:J(...) layout: netlist extracted from the GDS H(...) reference: netlist read from the SPICE file Z(...) xref: comparison results (pairing + status)
Keys relevant to this parser (long form in parentheses):
Key
Meaning
W(top) top cell name, in the layout/reference sections
U(unit) database unit in µm
X(circuit) circuit; inside a circuit,
Xwith a numeric first element is a subcircuit instanceN(net) net definition: id, then optional
Iand geometryP(pin) pin definition: id, then optional
ID(device) device: id, device class, then
I/E/YI(name) name of the enclosing net/device/pin/subcircuit
E(param) device parameter, e.g.
E(l 0.5)Y(location) device/instance location in database units
Lin the xref section: (log) message log of a circuit pair; in the netlist sections: (layer) layer definition!
M(entry) one log message inside
L(...)B(description) message text inside
M(...)Pitfalls:
Short keys are context-dependent:
His the reference section at the top level but a message inside netlist sections,Jis the layout section at the top level but a text label in net geometry,Xmay be a circuit, a subcircuit instance or the nomatch status, andLis a log in the xref section but a layer in the netlist sections.Absent values (unpaired ids, missing names) are written as
().In xref items, pin ids are 0-based, while pin definitions in the netlist sections use 1-based ids.
In the layout section, devices and subcircuit instances are usually unnamed (GDS structure references carry no instance names) and only identified by their location (
Y). In the reference section, names come from the SPICE netlist and are upper-cased.
Status codes (used for circuit pairs and xref items alike):
Code
Long form
Meaning
1match
objects were paired and compare clean
0mismatch
objects were paired, but their comparison failed
Xnomatch
no counterpart found on the other side
Wwarning
matched with warning: for devices, parameters deviate (an LVS error); for nets, pins and subcircuits, the match was ambiguous (harmless)
Sskipped
comparison skipped
Annotated example (shortened, from a hierarchical resistor design):
#%lvsdb-klayout J( # layout netlist (extracted from GDS) W(c_hier) # top cell U(0.001) # database unit in µm L(l6 '6/0') # layer definition ("L" = layer here!) X(a_default # circuit = extracted cell "a_default" N(1 I(x) # net 1, named "x", with geometry: R(l6 (70 3620) (360 160)) # rect on layer l6 J(l26 x (-180 -80)) # text label ("J" = text here!) ) P(1 I(x)) # pin 1, named "x" D(1 D$rsil$1 # device 1 of device class "D$rsil$1", Y(-5 2995) # unnamed, at location (-5, 2995) E(w 0.5) E(l 0.5) # device parameters T(rsil_1 5) # terminal "rsil_1" connects to net 5 ) X(1 a_default Y(0 0) # subcircuit instance 1 of "a_default" P(0 4) # instance pin 0 connects to net 4 ) ) ) H( # reference netlist (from SPICE) X(A_DEFAULT # names are upper-cased SPICE names N(1 I(X)) D(1 RSIL I(R1) ...) # devices/subcircuits are named here X(1 A_DEFAULT I(A1) ...) ) ) Z( # comparison results X(a_default A_DEFAULT 1 # circuit pair: layout circuit, Z( # reference circuit, status N(5 5 1) # item xref: layout id, reference id, P(0 0 1) # status (pin ids 0-based here!) D(3 1 1) X(1 1 1) ) ) )A real specimen of this format is kept at
tests/lvsdb/c_hier.lvsdb;tests/test_parse_lvsdb.pyparses it to pin down this parser’s behavior independently of KLayout.