Skip to content
UW-ASICPublic

About

GPU-Accelerated DRC, LVS, PEX, & ERC checks that attempts to match propietary-quality

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

GPurify

CI Nightly Open issues Rust 2021

Physical verification for integrated circuits: DRC, LVS, ERC and PEX, in one tool.

Most verification tools tell you how many violations they found. The number you actually need is a different one: how much of your chip did the tool look at? An empty violation table and a run that never executed produce the same report, and a tool that cannot tell those apart will eventually sign off a chip it did not check. GPurify reports both. Every rule says whether it ran and how many shapes it examined, and a run that could not check everything you asked it to check does not pass.

Status

Domain Implemented Expressible Partial Missing
DRC 56 6 44 0
LVS 31 1 15 1
ERC 64 4 13 0
PEX 9 0 7 0
Flow 2 0 8 0

Each row of docs/check-catalog.tsv is one check a commercial verification tool performs, with its public source. Expressible means the existing rule kinds can write it; partial rows say what is still missing; work not yet started is in the issues. The table is recomputed from the catalog by tests/doc_counts.rs, so it cannot drift.

Every check is tested against an answer derived independently of the code (hand-worked values, closed forms, published examples), and wherever an open-source tool performs the same check, against that tool too:

Checked against What
KLayout design rules on the corpus, every exhaustive fixture and random layouts (rectilinear, 45-degree, any angle); antenna ratios; layout XOR; fill
Foundry KLayout decks the shipped sky130, gf180mcu and IHP SG13G2 decks, rule by rule, on the foundries' test structures and standard cells
Netgen LVS on every small circuit with every single fault, black boxes, multi-die stacks
Magic analytical resistance and capacitance
FastCap, FastHenry field-solved capacitance and inductance
OpenROAD antenna (check_antennas), IR drop and currents (PDNSim), route-level extraction (OpenRCX), LEF/DEF reading
Yosys floating gates
ngspice Liberty timing and power tables

The KLayout, foundry and open-tool comparisons run nightly; fuzzing (10 input formats), mutation testing and a coverage floor run with them. How each is set up is in docs/testing-plan.md.

Install

cargo build --release

The binary lands at target/release/gpurify. Any stable Rust toolchain builds it; nix develop gives you a pinned one.

Run a check

gpurify drc my_layout.gds --deck my_process.deck
rules:
  met1.min_width: ran, examined 1 shapes, found 1 violations
  met1.min_edge_length: ran, examined 4 shapes, found 2 violations
  met1.min_spacing: ran, examined 0 shapes, found 0 violations
  met1.min_area: ran, examined 1 shapes, found 0 violations
  off_grid: ran, examined 4 shapes, found 0 violations
  diff.li.max_distance_to_tap: skipped, the layer it names holds no geometry, examined 0 shapes, found 0 violations
  ...
violations: 4
  met1.min_width error layer 7 at (40 nm, 500 nm) measured 80 nm against limit 100 nm on shape 0
  met1.min_edge_length error layer 7 at (40 nm, 0 nm) measured 80 nm against limit 100 nm on shape 0
summary:
  drc: ran
  erc: not selected
  lvs: not selected
  pex: not selected
  1 rules skipped
  22 rules clean
  4 violations: 4 errors, 0 warnings

Read 1 rules skipped before you read the violation count. One rule skipped means one rule did not look at your layout, and the run does not pass even though nothing was found.

Command What it checks Extra input
drc Design rules: widths, spacings, areas, density none
erc Electrical rules: antenna, ties, shorts, power grid --intent <file> for some rules
lvs Layout against your schematic a reference netlist, required
pex Parasitic resistance and capacitance --quasistatic <net>… to field-solve a net; the deck's report lines for point-to-point and net-to-net figures
all Everything a missing input marks its check skipped, never passed
lib Nothing: writes a hard macro's Liberty .lib per corner, and its Verilog blackbox --spec <file>, which also states the accuracy, and --output-dir <dir>; ngspice above interface accuracy
xor Two layouts against each other, layer by layer a second layout: gpurify xor <layout> <other> --deck <deck>
fill Nothing: writes the layout with density fill added, then reports DRC on it the deck's fill lines; gpurify fill <layout> <output.gds> --deck <deck>
enhance Nothing: writes the layout with redundant cuts and widened straps, then reports DRC on it the deck's via_redundancy rules and widen lines; gpurify enhance <layout> <output.gds> --deck <deck>
system Several dies as one assembly: bump bonding, LVS and system ESD a system file and netlist: gpurify system <stack.json> --reference <netlist>
compare Two parasitic netlists (SPEF or DSPF), net by net gpurify compare <reference> <candidate> [--spec <compare.json>], the spec stating the tolerance (default 5 %); no layout or deck

The only choice made on the command line is --quasistatic; the rest are input and output files and --format. Settings that shape a run live with what they describe: the deck (report lines, temperature, layers to skip), lib's macro spec (accuracy) and compare's spec (tolerance). Every option, the report format and the design intent file are described in docs/usage.md.

The exit code is 0 only when every check you selected ran and passed. Anything else is 1: violations found, a rule skipped, an input missing, a file it could not read. There is no exit code that means "mostly fine".

Describing your process

A deck is a plain-text description of your process: layers, connectivity, devices, the parasitic stack and the rules.

grid 5nm
layer met1 = gds(68, 20)
layer via1 = gds(68, 44)

rule m1.1 width(met1) >= 140nm
rule m1.2 space(met1) >= 140nm
rule m1.6 area(met1)  >= 0.083um2
rule via.4a enclosure(via1, met1) >= 55nm

It is strict. Every parameter must be written out, every number carries its unit, and a typo is an error with a line and column, never a rule that silently does nothing. There are 82 design-rule kinds and 57 electrical-rule kinds. docs/deck.md covers the language and every rule.

Four decks ship in pdks/, each citing the rule manual release its numbers come from and using the foundry's rule ids:

File Drawn layers Rules Devices
ihp_sg13g2 75 465 12
gf180mcu 56 328 27
sky130 74 302 30
generic_finfet (ASAP7) 45 239 0

From Rust, each is also compiled into the library as a constant (gpurify::pdks::SKY130 and so on), so a tool built on GPurify reads the same deck instead of a copy. None has been compared against foundry signoff. What each leaves out is listed at the end of the deck and in docs/limitations.md.

The same input gives the same file

The same inputs produce a byte-identical report on every run. The test suite holds every corpus report as a golden file and runs each twice, and each field solve on one thread and on many, failing on any byte that differs. A report that differs from itself cannot be diffed against yesterday's, so you could not tell a fixed violation from one that merely vanished.

Accuracy

GPurify is tested against 167 GDSII cells, drawn with sky130 layer names on a synthetic deck, each containing a deliberate defect at a known coordinate with a measurement worked out by hand. All 167 agree with their expected answer. The shipped foundry decks are tested separately, on hand-drawn layouts at each rule's limit, and nightly against the foundries' own KLayout decks on their test structures and standard cells; every difference is recorded rule by rule in docs/xcheck/.

DRC   ██████████████████████████████████████  94
ERC   ████████████                            30
PEX   ███████████                             27
LVS   ██████                                  16

Expected answers were derived from the geometry and the physics first, then compared against the previous implementation's output. 117 agree, so two independent routes reached the same number. 27 disagree, and each records which side is wrong and why.

The test that matters

Per-rule accounting closes a hole most suites have. In the previous implementation, 45 of 94 design-rule cases asserted only that nothing was found, so a rule that never executed passed all 45 of them:

Cases that would still pass if the rule never ran

before  ████████████████████████  45 of 94   (48%)
now     ▏                          0 of 94   (0%)

Not every passing test proves the same amount

A suite that reports only pass or fail flatters itself, so each case carries a grade for how much evidence is behind it:

strong       ███████████████████████████████████  123   the rule ran, had real geometry to look at, and the measurement came close to the limit
underivable  ███                                   11   nothing in the test data determines the answer
blocked      ███                                    9   the expected answer is sound but the tool cannot currently reach it
vacuous      ██                                     7   the rule ran but never came close to the limit
skipped      ██                                     7   the rule reported skipped, and a clean count here would be a lie
weak         ██                                     7   nothing to check, for a legitimate reason
refused      █                                      3   the rule correctly refuses this input rather than guessing

Nearly three quarters genuinely discriminates. The rest is accounted for by name, which is not the same as being counted as a pass.

Checked against KLayout

An independent reference matters more than our own suite, so 43 of the 94 design-rule cases were re-run through KLayout 0.30.8, using the nine rule families whose semantics map onto KLayout region operations. Both tools are scored against the same physics-derived answer, independent of either:

GPurify  ███████████████████████████████████████████  43 / 43
KLayout  ██████████████████████████████████████████   42 / 43

That was not GPurify being more correct. The one difference was DRC_MW_DIAG_FAIL, a shape drawn at 45 degrees: KLayout measured it at 80.6 nm against a 100 nm limit and flagged it, correctly, while GPurify, then rectilinear-only, refused the input and scored the point only because refusing was the documented expectation. GPurify now measures that shape too (80 nm, floored), and the case expects the measurement.

On the other 42, two independently written tools reach the same number.

Speed

Whether a tool falls over on a large design is the question worth asking. Across 1,000 then 10,000 then 100,000 polygons, the cost per polygon falls rather than climbs:

                          1k        10k       100k
building the layout     283.5      300.6      113.9   ns per polygon
extracting nets         759.5      564.0      358.1
finding shape pairs      22.4       16.3        6.5

Ten times the input costs this much more time:

building the layout      10.6×  then   3.8×
extracting nets           7.4×  then   6.3×
finding shape pairs       7.3×  then   4.0×

linear would be          10.0×        10.0×
quadratic would be      100.0×       100.0×

Nothing here is quadratic, which is the failure mode that makes a tool unusable on a real chip rather than merely slow.

Against KLayout

Same rule (min_width, 100 nm, one layer), same files, both tools single threaded, median of five runs, identical violation counts at every size. The layouts were written by KLayout itself, so this is reproducible without any file GPurify prepared for itself:

              KLayout    GPurify     end to end
   1,000 pt    1061 ms     4.7 ms        226x
  10,000 pt    1083 ms    13.0 ms         83x
 100,000 pt    1309 ms    72.4 ms         18x
1,000,000 pt   3653 ms   661.9 ms        5.5x

Most of that gap is not the checking. KLayout pays about 1,056 ms of Ruby and Qt startup per invocation, measured with an empty script, against GPurify's 3.8 ms floor. Subtract each tool's own floor and only the geometry work is left:

 100,000 pt   KLayout 253 ms   GPurify  68.5 ms   3.7x
1,000,000 pt  KLayout 2597 ms  GPurify 658.1 ms   3.9x

So the honest number is about four times faster on the actual checking, with a much larger margin per invocation in a scripted flow that starts the tool once per cell. At a thousand polygons neither tool is doing enough work to measure.

This is one rule on synthetic rectilinear layout. It does not exercise KLayout's hierarchical or tiled modes and is not a claim about its DRC engine in general. KLayout's DRC is a programmable Ruby DSL, so it can express rules a fixed vocabulary of rule kinds cannot; a rule count is not a comparison between the two.

Everything above is one release build on an Intel i9-14900HX. These timings are recorded, not enforced; what is enforced is their shape. The nightly tier times the engine on one generated layout at 1, 4 and 16 times a base size and fails if the cost per polygon at 16 times is over three times the base's (tests/scaling.rs), so a path that grows faster than the input fails a build whatever the machine. cargo run --release --example bench_all reprints the tables on your own machine, including a per-rule breakdown of which rule costs what.

What it cannot do yet

This is a working tool that has not been proven against foundry signoff on production silicon. Do not tape out on its verdict alone. On a layout with edges at 45 degrees or any other angle, width, notch, space, area, hole area, edge length, forbidden shapes, inside, contains and enclosure are measured; the other rules refuse such a layer. Several rules measure less than a foundry deck does, and the shipped decks are incomplete. docs/limitations.md lists every known gap.

There is no licence file yet.

Documentation

File What is in it
docs/usage.md Commands, options, reading the report, design intent, parasitics.
docs/deck.md Writing a deck, and what every rule checks.
docs/liberty.md Liberty for a hard macro: accuracy levels, the macro spec, how each number is measured.
docs/limitations.md What GPurify cannot check yet.
docs/check-catalog.tsv, docs/check-sources.md Every check a commercial tool performs, its public source and GPurify's status.
docs/klayout-mirror.md How each rule kind maps onto KLayout, and where the two differ.
docs/testing-plan.md How GPurify is tested: oracles, tiers, findings.
tests/fixtures/README.md The test corpus and how each expected answer was derived.
cargo test --workspace                    # the test suite, golden reports included
cargo run --release --example bench_all   # the timing tables above

About

GPU-Accelerated DRC, LVS, PEX, & ERC checks that attempts to match propietary-quality

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages