Module 8: Physical Verification ยท 8.2 Layout vs. Schematic

Running Netgen: Extracting a Netlist From Layout

In the previous article we saw why DRC cannot catch a short or an open. In this article we run the check that can. LVS stands for Layout Versus Schematic, but in a digital flow the “schematic” is a netlist, and it is worth being precise about which one.

It is not the netlist Yosys wrote in Module 2. Since then the flow has changed the netlist several times: CTS added clock buffers, the resizer added and resized cells during placement and in the ECO of Module 7, OpenLane inserted tap, decap and filler cells, and antenna diodes may be added later in this module. The netlist LVS compares against is the final, powered gate-level netlist that OpenLane writes at the end of the flow, the one that describes what the tools believe they built, including the power connections of every cell.

That gives a two-part guarantee. LVS checks that the layout matches the final netlist. Whether the final netlist still does the same thing as your RTL is a separate question, answered by gate-level simulation or formal equivalence checking, and the netlist changes made by the tools (buffers, resizing) are designed to preserve function. Keep the two apart in your head and a lot of LVS confusion disappears.

An LVS run has two steps. First extract a netlist from the layout, working out the circuit the shapes actually implement. Then compare it with the final netlist.

Step one: extract a netlist from the layout

Magic can walk the layout’s geometry and reconstruct the circuit from which shapes touch which, through which vias and contacts, on which layers:

magic -dnull -noconsole \
      -rcfile "$PDK_ROOT/sky130A/libs.tech/magic/sky130A.magicrc" <<'EOF'
gds read runs/uart_full/results/final/gds/uart_top.gds
load uart_top
select top cell
extract do local
extract all
ext2spice lvs
ext2spice -o uart_extracted.spice
quit -noprompt
EOF
  • extract all walks the geometry and writes Magic’s .ext description of every device and every electrical node.
  • ext2spice lvs sets the SPICE writer up for LVS: hierarchical, with each standard cell as a subcircuit, matching how the gate-level netlist is organised.
  • ext2spice -o writes the extracted netlist.

Extraction is doing real work here, not reformatting. It infers “this polysilicon crossing this diffusion forms a transistor, and this contact connects its source to that net” purely from geometry and layer rules. It is the flow run backwards.

Step two: run Netgen

Netgen takes two netlists and decides whether they describe the same circuit, allowing internal nets to have different names:

netgen -batch lvs \
  "uart_extracted.spice uart_top" \
  "runs/uart_full/results/final/verilog/gl/uart_top.v uart_top" \
  "$PDK_ROOT/sky130A/libs.tech/netgen/sky130A_setup.tcl" \
  uart_lvs.report

Each quoted argument is a “file cell” pair. Netgen needs to know which cell in each file is the top of the comparison, since either file can contain many cells. The second file is the final powered netlist from OpenLane; the exact path and name differ a little between OpenLane versions, so use the one from your run. The setup file tells Netgen how to treat SKY130’s devices and standard cells, for example which pins are power and how parallel transistors can be combined.

Reading a clean report

When the layout and the netlist match, the end of uart_lvs.report looks something like this (trimmed):

Subcircuit summary:
Circuit 1: uart_top                         |Circuit 2: uart_top
--------------------------------------------|--------------------------------------------
sky130_fd_sc_hd__dfxtp_2 (96)               |sky130_fd_sc_hd__dfxtp_2 (96)
sky130_fd_sc_hd__nand2_1 (143)              |sky130_fd_sc_hd__nand2_1 (143)
sky130_fd_sc_hd__xor2_4 (1)                 |sky130_fd_sc_hd__xor2_4 (1)
sky130_fd_sc_hd__buf_6 (1)                  |sky130_fd_sc_hd__buf_6 (1)
...                                         |...
Number of devices: 1406                     |Number of devices: 1406
Number of nets: 1842                        |Number of nets: 1842
--------------------------------------------------------------------------------------------
Netlists match uniquely.

Cell pin lists are equivalent.
Device classes uart_top and uart_top are equivalent.

Final result: Circuits match uniquely.

A passing report confirms several separate things, and it is worth being precise because each one could have gone wrong:

  1. The same number of devices and nets. Nothing was dropped or duplicated between the netlist and the layout.
  2. The same count of each cell type. Not just 1406 devices in total, but the same breakdown by cell. This catches a case where the totals happen to agree but the mix is wrong. Notice the xor2_4 and buf_6 from the Module 7 ECO: they are in both netlists, because the final netlist was written after the ECO.
  3. The same pins on the top cell. The interface, clk, rst_n, rx, tx and so on, lines up exactly, and no pin has been renamed, swapped or left unconnected.
  4. “Match uniquely”. Netgen did not just find some correspondence between the two circuits. It found exactly one. If a structure could be matched in more than one way, Netgen says so, because ambiguity means it could not fully confirm the connections.
What LVS confirms What it does not confirm
The layout has the same devices and the same connectivity as the final netlist That the netlist is functionally correct (simulation and equivalence checking)
No short, open or substituted cell was introduced by the physical implementation Timing (STA’s job)
The top-level pins match by name and connection Manufacturability (DRC’s job)

The ambiguity point trips people up the first time they see an LVS failure that is not an obvious short or open. A perfectly good layout can be flagged if a symmetrical structure, say two identical parallel buffers with interchangeable inputs, allows more than one valid matching. That is usually not a real bug, and Netgen can normally resolve it once a few nets are matched by name, but you have to be able to tell the difference. The next article works on exactly that skill.

Hands-on: sanity-check the extraction, not just the comparison

Before trusting any LVS result, check that the extraction produced something sensible. A known failure is an extraction that silently drops part of the design, a macro for instance, and then “matches” a netlist that was generated with the same part missing. Count the cell instances inside the top-level subcircuit of the extracted netlist and compare with the report:

awk '/^\.subckt uart_top/ {on=1; next} /^\.ends/ {on=0} on && /^X/ {n++} END {print n}' \
    uart_extracted.spice

The count should match the device total in the report and your expectations for the design. If it is wildly different, something went wrong in extraction, and the comparison result means nothing until that is fixed.

Practice Exercise

LVS against the final netlist passes. A colleague then compares the final netlist with the synthesis netlist from Module 2 and notices that the final one has dozens of extra cells (clock buffers, tap and decap cells, one buf_6) and one XOR that is xor2_4 instead of xor2_2. Does this mean LVS missed something?

Solution

No. LVS compared the layout with the final netlist, and they match: every extra cell and the resized XOR exist in both. The differences from the synthesis netlist are the expected results of the flow: CTS clock buffers, tap and decap cells for the physical rows, and the buffer and resize from the Module 7 ECO.

The colleague’s question is still a good one, but it belongs to a different check. Whether the final netlist does the same thing as the synthesis netlist is a matter for gate-level simulation or formal equivalence checking. The tool changes are designed to preserve function, but a manual edit or a tool bug might not, and LVS by itself would never notice, because it only compares the layout with the netlist it is given. This is also why, whenever a change is made directly to the layout (as in the Module 10 debugging project), the netlist has to be regenerated from the same change, or LVS is comparing against the wrong reference.

A clean match is the easy case. In the next article we break the UART on purpose, remove a single via, and learn to read what kind of mismatch it causes from the Netgen report alone.

โ† Why a DRC-Clean Layout Can Still Be Functionally Wrong Diagnosing a Real LVS Mismatch โ†’