Skip to content

Skip parasitic extraction in the Magic LVS script - #320

Merged
mguthaus merged 1 commit into
VLSIDA:devfrom
TheAnimatrix:magic-lvs-connectivity-extract
Oct 13, 2026
Merged

mguthaus merged 1 commit into
VLSIDA:devfrom
TheAnimatrix:magic-lvs-connectivity-extract

Conversation

@TheAnimatrix

Copy link
Copy Markdown

The Magic script that extracts the layout netlist for LVS runs extract all with capacitance, coupling and resistance extraction on. ext2spice then throws all of that away (cthresh infinite, rthresh infinite), so netgen never sees it. On large sky130 arrays the parasitic extraction is most of the runtime and looks like a hang. That matches #248 (2 KB SRAM stuck in run_ext for a day) and probably #165.

This adds extract no capacitance, extract no coupling and extract no resistance before extract all in write_drc_script. Transistor extraction, extract unique all and port matching are unchanged. PEX writes its own scripts and is not affected.

Where we hit it

sky130 1rw1r macro, 64 words x 32 bits, OpenRAM v1.2.48, Magic 8.3.363 from the conda environment. The LVS job timed out while the bitcell array .ext was an incomplete 81 MiB. Rerunning extraction and LVS on the same saved Magic hierarchy with this change took 119 s at 837 MiB peak RSS. The array .ext was 3.9 MiB and netgen matched uniquely, 1694 devices and 1319 nets on both sides. A copy with one PMOS disconnected on purpose still failed LVS.

Tests on dev (3608704)

Run before and after the change with Magic 8.3.363, netgen and ngspice from the conda environment, and sky130_fd_bd_sram at the commit in the Makefile (fc63b128). Each test gave the same result both times.

Test sky130 scn4m_subm
04_pinv_1x pass pass
04_pnand2 pass pass
05_bitcell_array LVS mismatch before and after pass
05_bitcell_array_1rw_1r LVS mismatch before and after pass
08_wordline_driver_array pass pass
14_replica_bitcell_array_bothrbl_1rw_1r LVS mismatch before and after error before and after
15_local_bitcell_array_bothrbl_1rw_1r error before and after error before and after
18_port_data_nomux_1rw_1r pass pass
19_single_bank_nomux_1rw_1r pass pass
20_sram_1bank_nomux_1rw_1r pass pass

For 20_sram_1bank_nomux_1rw_1r on sky130 I kept the temp directory from both runs. Both match uniquely with 512 devices, and sram.ext.err has the same messages. Total .ext size went from 7.9 MB to 1.4 MB. The extracted sram.spice differs only in subcircuit port order and in transistor ad/as/pd/ps, which are now 0. The netgen lvs command is the only reader of that file.

I did not run the full regression or freepdk45.

ext2spice drops capacitance and resistance for LVS anyway (cthresh/rthresh infinite), so extracting them only costs runtime. On large sky130 arrays that extraction can run for hours.
@TheAnimatrix

Copy link
Copy Markdown
Author

Linking #245. That 16 KB sky130 run sat in extraction for a month on magic 8.3.363, and it is the same failure mode this PR is about: the parasitic passes dominate on large bitcell arrays and look like a hang.

Numbers from our side, all magic 8.3.363, netgen from the conda env:

  • 64 x 32 1rw1r: without this change the LVS job timed out with an incomplete 81 MiB bitcell_array .ext. With it, extraction + LVS finished in 119 s, 837 MiB peak RSS, netgen unique match.
  • 640 x 16 1rw1r (10,240 bitcells, words_per_row 4): with this change, DRC 0, LVS unique match, whole verification about 1 h.
  • 2048 x 32 1rw1r (65,536 bitcells, words_per_row 8): still stalls even with this change. Magic writes the 65,536 use lines of the bitcell_array .ext within minutes, then stays at 100% of one core for 4.5 h+ without writing a single merge line. Memory is flat at about 4 GB, so it is not the swap explanation given in Runtime  #245.

So this PR removes the parasitic cost, but there is a second, size-dependent cost in the subcell connectivity phase of the parent-cell extraction that #245 most likely hit as well. Profiling it now, will report in #245.

@TheAnimatrix TheAnimatrix mentioned this pull request Oct 13, 2026
@mguthaus
mguthaus merged commit de5614a into VLSIDA:dev Oct 13, 2026
@mguthaus

Copy link
Copy Markdown
Collaborator

Merged. Thanks — the writeup made this easy to check, and I was able to reproduce the mechanism independently.

I confirmed the reasoning in the code: write_drc_script() emits two scripts, and the three new lines land only in run_ext.sh. run_drc.sh is a separate Magic invocation, so DRC is untouched. run_ext.sh already sets ext2spice cthresh infinite and rthresh infinite (magic.py:146-147), so every parasitic that was being extracted was then discarded. And the extracted <cell>.spice has exactly one reader — write_lvs_script() hands it to netgen. run_pex() goes through write_script_pex_rule(), which is an independent Magic session doing its own gds read + extract with default options, so PEX still gets full parasitics. Using the same pre prefix as the surrounding lines was the right call too.

extract no capacitance|coupling|resistance is accepted by both Magic 8.3.363 and 8.3.629 here.

Measured on scn4m_subm (A/B in two worktrees, DRC and LVS both run):

design extract time before after .ext before after DRC LVS
20_sram_1bank_nomux_1rw_1r — — 1.33 MB 0.59 MB 0 / 0 match uniquely both
128 words x 16 16.0 s 11.0 s 4.55 MB 2.00 MB 0 / 0 0 errors both
256 words x 16 28.0 s 18.0 s 7.54 MB 3.17 MB 0 / 0 0 errors both

Device and net counts in the netgen report are identical before and after, and the saving grows with array size (-31% then -36% on extraction, ~-57% on .ext), which lines up with your sky130 result being far more dramatic.

Full regression on freepdk45 + scn4m_subm (30 tests incl. every Magic/netgen DRC+LVS test in my set): identical pass/fail to dev.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants