Magic 8.3.681, PDK ihp-sg13g2 1.0.1, kpex 0.3.15, in IIC-OSIC-TOOLS. Current master 8.3.683 behaves the same where checked.
We built a PEX regression suite of 63 metal-only dummy layouts whose parasitics follow from libs.tech/magic/ihp-sg13g2-extract.tech by hand, so every extracted value has a closed-form expected value. It lives in ihp-sg13g2/pex_bench of iic-jku/open-pdks-regression-tests, and make pex-bench-defects reproduces every case below in about 25 seconds. The full write-up with all tables is in pex_bench/report/.
The models themselves are exact. Area capacitance, perimeter capacitance, sheet resistance and contact resistance reproduce the deck to six digits on all seven metals and all four via types, including 1/n scaling for parallel cuts. Everything below is about what happens around them.
Happy to split this into separate issues if you prefer, and happy to run any experiment on the bench.
| # |
Finding |
Status |
| 1 |
Sidewall capacitance is half the tech-file coefficient |
Regression in 8.3.679 |
| 2 |
ext2spice hierarchy on moves a net's substrate capacitance onto other nets |
|
| 3 |
A non-zero extresist mindelay drops resistor arms and leaves ports unconnected |
|
| 4 |
Unbranched nets get no resistance unless threshold and mindelay are both 0 |
|
| 5 |
extract no coupling discards inter-net capacitance instead of grounding it |
|
| - |
full-RC double-counts coupling capacitance |
Already open as #550, confirmation below |
1. Sidewall capacitance is half the tech-file coefficient (regression in 8.3.679)
Two Metal1 wires, 0.5 um wide, 50 um long, separation swept. The deck line is
defaultsidewall allm1 metal1 28.735 -0.057
| separation [um] |
coefficient x L / (s + offset) |
magic emits |
converged FasterCap |
| 0.2 |
10.0472 |
4.7892 |
6.2195 |
| 0.4 |
4.1888 |
2.0525 |
3.6468 |
| 0.8 |
1.9337 |
0.9578 |
2.0777 |
| 1.6 |
0.9311 |
0.4635 |
1.0585 |
| 3.2 |
0.4571 |
0.2281 |
0.4364 |
Exactly 0.5 * coefficient * L / (s + offset) at all five spacings, to five digits. Writing 57.470 in the deck instead returns 1.91567 fF at 0.8 um against 1.93371 expected, so the single application of the 0.5 is the whole of the effect. The explicit sidewall keyword behaves identically to defaultsidewall.
This arrived in 51522d6 (2026-08-02, 8.3.678 to 8.3.679), which added the halving in ExtCouple.c with this comment:
Important! The sidewall coeffient is correct for the coupling between edges, but both edges will be checked, causing a double-count, so each edge should contribute half of the total.
On two parallel wires the second edge is not checked, so the halving is never undone. c81b995 later moved the halving to the tech-file parser without changing the result, so it is not a fix, and master still halves.
Before 8.3.679 there was no halving anywhere, so a deck carrying capiche's coefficients extracted the full value. The same layout and the same PDK therefore give half the sidewall coupling in 8.3.679 that they gave in 8.3.678.
That the open-PDK coefficients are the full value rather than a pre-halved one is stated in the same commit message:
This measure was taken because the open PDK values generated by "capiche" were not halving the value, so I either change magic or I change all the tech files.
Two independent checks that the full value is intended. KLayout's kpex reads the identical coefficients for this PDK (sidewall 28.735, offset -0.057) and its 2.5D engine emits the full value at every spacing; the two tools agree to six digits on areacap and perimc, and differ by exactly two only here (they also differ on overlap, by 1.4 % on adjacent layers, which is the halo split covered at the end and is a separate matter). And the FasterCap column above is a mesh-converged solve on the same stack (raw-matrix asymmetry 0.03 % to 0.16 %): magic sits below it at every spacing by 23 % to 56 %, while the full coefficient straddles it, which is what a fitted 1/(s+off) form does against a curve of a different shape.
Minor and separate: the offset is rounded to whole lambda, so the deck's -0.057 um is applied as -0.05 um. That is worth 4.7 % at 0.2 um spacing and nothing above 1 um.
2. ext2spice hierarchy on moves a net's substrate capacitance onto other nets
One sg13g2_inv_1 standard cell with a 0.5 x 200 um Metal2 wire added on its gate net A, reached through one Via1 in the pin. By the deck that wire is worth about 15.8 fF to substrate and there is nothing else in the layout it could belong to. Flattened, extract all, ext2spice cthresh 0.01.
ext2spice hierarchy off:
C3 Y VSS 0.16752f
C4 A VSS 15.9216f <- the wire, on the net it is drawn on
C5 VDD VSS 0.13605f
ext2spice hierarchy on, same layout:
C3 Y VSS 8.12832f <- 0.16752 + 7.9608
C4 VDD VSS 8.09685f <- 0.13605 + 7.9608
<- A has no capacitance at all; 2 x 7.9608 = 15.9216
The wire's entire capacitance leaves the net it belongs to and lands in two exact halves on the output and the supply.
On a larger cell the total is not even conserved: on a 176-transistor macro, hierarchy on loses 40.5 fF of 288.9 fF, all of it substrate capacitance, with five nets left at exactly zero. Every coupling capacitor is unchanged in both cases. Device-less layouts are unaffected, so this only appears once the layout contains devices.
Worth flagging because ext2spice lvs sets hierarchy on, so a flow that starts from that shortcut and then re-enables capacitance with ext2spice cthresh <value> is affected without the user choosing hierarchical output. Setting hierarchy on alone reproduces it exactly, and ext2spice lvs followed by ext2spice hierarchy off restores the full total; the shortcut's other effects (global off, blackbox on, subcircuit top auto, format ngspice) each make no difference on their own.
3. A non-zero extresist mindelay drops resistor arms and leaves ports unconnected
One Metal1 net shaped as a cross: four arms of 199.5, 199.5, 299.5 and 199 um meeting at one junction, a port at the end of each arm, nothing else in the layout.
With extresist threshold 0, minres 0, mindelay 0 the network is correct:
.subckt cross_m1 w e s n
R0 n.n0 e 32.9345 # 299.5 um at 110 mOhm/sq = 32.945
R1 n.n0 s 21.9565
R2 w n.n0 21.9565
R3 n.n0 n 21.8245
.ends
With mindelay 1 (threshold 10000, minres 1000):
.subckt cross_m1 w e s n
R0 n s 21.9565
R1 w n 21.9565
.ends
Two problems. Port e is declared and appears in no element, so it is a floating node in simulation. Port n is silently aliased onto the junction, so its 21.82 Ohm arm reads zero. A three-arm tee behaves the same way, losing a 32.93 Ohm arm.
Any non-zero mindelay does this and the value does not matter: 1, 2 and 10 behave alike. minres, which is documented as the network simplification control, is innocent here: it merges nothing at 1000 mOhm on 11 Ohm arms, as expected.
4. Unbranched nets get no resistance unless threshold and mindelay are both 0
A 1 um wide, 1000 um long Metal1 wire is 110 Ohm with 114 fF to substrate, an RC delay of 12.6 ps. It extracts as an ideal short at any non-zero threshold, including 1 mOhm, and adding a third port in the middle changes nothing. The log shows
Nets extracted: 1 (0.333333)
Nets output: 0 (0.000000)
so the resistance is computed and then discarded. With threshold 0 and mindelay 0 it comes out correct at R0 l r 109.891 against a hand value of 109.89.
On a branched net the threshold behaves exactly as documented: the network survives at threshold 10000 and disappears at 100000, bracketing that net's real 10.96 Ohm. So the gating looks specific to nets without a junction.
This is the case that matters most in practice: point-to-point routes, a clock spine feeding one sink, supply stubs, any long wire between exactly two things.
5. extract no coupling discards inter-net capacitance instead of grounding it
Two parallel Metal1 wires, 0.5 um wide, 50 um long, 0.2 um apart.
With coupling (extract all):
C0 a b 4.78917f
C1 b sub 3.06954f
C2 a sub 3.06954f
With extract no coupling:
C0 b sub 4.87346f
C1 a sub 4.87346f
4.87346 fF is exactly what one of these wires extracts on its own with no neighbour in the layout at all. So the neighbour is not being referred to ground, it is being ignored: the coupling is dropped, and the shielding it applies to the substrate fringe is dropped with it. Each wire should carry 3.06954 + 4.78917 = 7.859 fF if the neighbour is treated as an AC ground, and carries 4.873 fF instead.
On the same 176-transistor macro, extract no coupling emits four capacitors in total, all output-to-VSS; VDD and every input net come out with no parasitic capacitance at all, against 42.2 fF of real wiring capacitance on each input in the coupled run. Total is 166.5 fF against 248.4 fF coupled.
Confirmation of #550 (full-RC double-counts coupling capacitance)
Not a new report, and no reproduction case was attached there, so here is one with numbers.
Two parallel Metal1 wires, 0.5 um wide, 200 um long, 0.2 um apart, each with a short stub so both nets branch and qualify for resistance extraction. C-coupled reference:
C0 s1 s0 19.1567f <- coupling
C1 s1 sub 14.0930f
C2 s0 sub 14.0930f
Full RC (threshold 10000, minres 1000, mindelay 0, extract do resistance, ext2spice extresist on):
R0..R5 <- correct, arm values within 0.1 %
C0 s1 s0 19.1567f <- the coupling capacitor is still here
C1 s1 w# 15.00077f
C2 b1 w# 4.35815f
C3 a1 w# 4.37121f
C8 s1.n0 w# 9.51957f
The four substrate capacitors of net s1 sum to 33.2497 fF, which is exactly 14.0930 + 19.1567: the true substrate capacitance plus the whole of the coupling, spread over the RC nodes, while the coupling element is also emitted. Node s0 therefore carries 52.4 fF where the correct answer is 33.25 fF. On two coupled wires with no resistor network at all it reads 7.85871 = 3.06954 + 4.78917 on each node, to the last digit.
On the 176-transistor macro the total goes from 248.4 fF to 510.8 fF, and the output node from 35.8 fF to 60.8 fF, an over-estimate of 70 %.
One more, weaker, for completeness
A 10 x 10 um TopMetal1 plate centred on a 30 x 30 um Metal1 plate, so the upper plate is fully covered and its edges are 10 um inside the lower plate's outline:
|
top to bottom |
top to substrate |
top to far field |
| magic |
1.6024 |
0.7957 |
no such node |
| kpex 2.5D, same coefficients, no halo split |
2.3178 |
none |
no such node |
| FasterCap |
2.2861 |
0.1267 |
0.3809 |
The halo split sends 0.80 fF of the upper plate's edge charge to the substrate, against the 0.51 fF the field solve puts outside the plate-to-plate path, and takes it out of the plate-to-plate coupling, which is then 30 % low. On adjacent layers the two models agree within 1.4 % and it does not matter, and on TopMetal2 over TopMetal1 magic is the closer of the two, so this looks like a deep-stack effect rather than a problem with the halo model as such. Mentioning it only because it falls out of the same table; it may belong with #183.
Magic 8.3.681, PDK ihp-sg13g2 1.0.1, kpex 0.3.15, in IIC-OSIC-TOOLS. Current master 8.3.683 behaves the same where checked.
We built a PEX regression suite of 63 metal-only dummy layouts whose parasitics follow from
libs.tech/magic/ihp-sg13g2-extract.techby hand, so every extracted value has a closed-form expected value. It lives inihp-sg13g2/pex_benchofiic-jku/open-pdks-regression-tests, andmake pex-bench-defectsreproduces every case below in about 25 seconds. The full write-up with all tables is inpex_bench/report/.The models themselves are exact. Area capacitance, perimeter capacitance, sheet resistance and contact resistance reproduce the deck to six digits on all seven metals and all four via types, including 1/n scaling for parallel cuts. Everything below is about what happens around them.
Happy to split this into separate issues if you prefer, and happy to run any experiment on the bench.
ext2spice hierarchy onmoves a net's substrate capacitance onto other netsextresist mindelaydrops resistor arms and leaves ports unconnectedthresholdandmindelayare both 0extract no couplingdiscards inter-net capacitance instead of grounding it1. Sidewall capacitance is half the tech-file coefficient (regression in 8.3.679)
Two Metal1 wires, 0.5 um wide, 50 um long, separation swept. The deck line is
Exactly
0.5 * coefficient * L / (s + offset)at all five spacings, to five digits. Writing57.470in the deck instead returns 1.91567 fF at 0.8 um against 1.93371 expected, so the single application of the 0.5 is the whole of the effect. The explicitsidewallkeyword behaves identically todefaultsidewall.This arrived in 51522d6 (2026-08-02, 8.3.678 to 8.3.679), which added the halving in
ExtCouple.cwith this comment:On two parallel wires the second edge is not checked, so the halving is never undone. c81b995 later moved the halving to the tech-file parser without changing the result, so it is not a fix, and master still halves.
Before 8.3.679 there was no halving anywhere, so a deck carrying capiche's coefficients extracted the full value. The same layout and the same PDK therefore give half the sidewall coupling in 8.3.679 that they gave in 8.3.678.
That the open-PDK coefficients are the full value rather than a pre-halved one is stated in the same commit message:
Two independent checks that the full value is intended. KLayout's kpex reads the identical coefficients for this PDK (
sidewall 28.735, offset -0.057) and its 2.5D engine emits the full value at every spacing; the two tools agree to six digits onareacapandperimc, and differ by exactly two only here (they also differ onoverlap, by 1.4 % on adjacent layers, which is the halo split covered at the end and is a separate matter). And the FasterCap column above is a mesh-converged solve on the same stack (raw-matrix asymmetry 0.03 % to 0.16 %): magic sits below it at every spacing by 23 % to 56 %, while the full coefficient straddles it, which is what a fitted1/(s+off)form does against a curve of a different shape.Minor and separate: the offset is rounded to whole lambda, so the deck's
-0.057um is applied as-0.05um. That is worth 4.7 % at 0.2 um spacing and nothing above 1 um.2.
ext2spice hierarchy onmoves a net's substrate capacitance onto other netsOne
sg13g2_inv_1standard cell with a 0.5 x 200 um Metal2 wire added on its gate netA, reached through one Via1 in the pin. By the deck that wire is worth about 15.8 fF to substrate and there is nothing else in the layout it could belong to. Flattened,extract all,ext2spice cthresh 0.01.ext2spice hierarchy off:ext2spice hierarchy on, same layout:The wire's entire capacitance leaves the net it belongs to and lands in two exact halves on the output and the supply.
On a larger cell the total is not even conserved: on a 176-transistor macro, hierarchy on loses 40.5 fF of 288.9 fF, all of it substrate capacitance, with five nets left at exactly zero. Every coupling capacitor is unchanged in both cases. Device-less layouts are unaffected, so this only appears once the layout contains devices.
Worth flagging because
ext2spice lvssetshierarchy on, so a flow that starts from that shortcut and then re-enables capacitance withext2spice cthresh <value>is affected without the user choosing hierarchical output. Settinghierarchy onalone reproduces it exactly, andext2spice lvsfollowed byext2spice hierarchy offrestores the full total; the shortcut's other effects (global off,blackbox on,subcircuit top auto,format ngspice) each make no difference on their own.3. A non-zero
extresist mindelaydrops resistor arms and leaves ports unconnectedOne Metal1 net shaped as a cross: four arms of 199.5, 199.5, 299.5 and 199 um meeting at one junction, a port at the end of each arm, nothing else in the layout.
With
extresist threshold 0,minres 0,mindelay 0the network is correct:With
mindelay 1(threshold 10000, minres 1000):Two problems. Port
eis declared and appears in no element, so it is a floating node in simulation. Portnis silently aliased onto the junction, so its 21.82 Ohm arm reads zero. A three-arm tee behaves the same way, losing a 32.93 Ohm arm.Any non-zero
mindelaydoes this and the value does not matter: 1, 2 and 10 behave alike.minres, which is documented as the network simplification control, is innocent here: it merges nothing at 1000 mOhm on 11 Ohm arms, as expected.4. Unbranched nets get no resistance unless
thresholdandmindelayare both 0A 1 um wide, 1000 um long Metal1 wire is 110 Ohm with 114 fF to substrate, an RC delay of 12.6 ps. It extracts as an ideal short at any non-zero threshold, including 1 mOhm, and adding a third port in the middle changes nothing. The log shows
so the resistance is computed and then discarded. With
threshold 0andmindelay 0it comes out correct atR0 l r 109.891against a hand value of 109.89.On a branched net the threshold behaves exactly as documented: the network survives at
threshold 10000and disappears at 100000, bracketing that net's real 10.96 Ohm. So the gating looks specific to nets without a junction.This is the case that matters most in practice: point-to-point routes, a clock spine feeding one sink, supply stubs, any long wire between exactly two things.
5.
extract no couplingdiscards inter-net capacitance instead of grounding itTwo parallel Metal1 wires, 0.5 um wide, 50 um long, 0.2 um apart.
With coupling (
extract all):With
extract no coupling:4.87346 fF is exactly what one of these wires extracts on its own with no neighbour in the layout at all. So the neighbour is not being referred to ground, it is being ignored: the coupling is dropped, and the shielding it applies to the substrate fringe is dropped with it. Each wire should carry 3.06954 + 4.78917 = 7.859 fF if the neighbour is treated as an AC ground, and carries 4.873 fF instead.
On the same 176-transistor macro,
extract no couplingemits four capacitors in total, all output-to-VSS; VDD and every input net come out with no parasitic capacitance at all, against 42.2 fF of real wiring capacitance on each input in the coupled run. Total is 166.5 fF against 248.4 fF coupled.Confirmation of #550 (full-RC double-counts coupling capacitance)
Not a new report, and no reproduction case was attached there, so here is one with numbers.
Two parallel Metal1 wires, 0.5 um wide, 200 um long, 0.2 um apart, each with a short stub so both nets branch and qualify for resistance extraction. C-coupled reference:
Full RC (
threshold 10000,minres 1000,mindelay 0,extract do resistance,ext2spice extresist on):The four substrate capacitors of net
s1sum to 33.2497 fF, which is exactly 14.0930 + 19.1567: the true substrate capacitance plus the whole of the coupling, spread over the RC nodes, while the coupling element is also emitted. Nodes0therefore carries 52.4 fF where the correct answer is 33.25 fF. On two coupled wires with no resistor network at all it reads7.85871 = 3.06954 + 4.78917on each node, to the last digit.On the 176-transistor macro the total goes from 248.4 fF to 510.8 fF, and the output node from 35.8 fF to 60.8 fF, an over-estimate of 70 %.
One more, weaker, for completeness
A 10 x 10 um TopMetal1 plate centred on a 30 x 30 um Metal1 plate, so the upper plate is fully covered and its edges are 10 um inside the lower plate's outline:
The halo split sends 0.80 fF of the upper plate's edge charge to the substrate, against the 0.51 fF the field solve puts outside the plate-to-plate path, and takes it out of the plate-to-plate coupling, which is then 30 % low. On adjacent layers the two models agree within 1.4 % and it does not matter, and on TopMetal2 over TopMetal1 magic is the closer of the two, so this looks like a deep-stack effect rather than a problem with the halo model as such. Mentioning it only because it falls out of the same table; it may belong with #183.