Added a text file that explains the bsimbulk PMOS wiring fix.

This commit is contained in:
Justin Fisher 2026-06-01 14:43:21 +02:00
parent 39a5ea338b
commit 0246ba761a
1 changed files with 17 additions and 0 deletions

View File

@ -0,0 +1,17 @@
This branch (jfisher/bsimbulk-osdi-parsing) is built on top of jfisher/osdi-fixes and adds a small set of changes I needed for ngspice to correctly load an OSDI BSIM-BULK model and wire it up with the right number of terminals.
There are two commits on top of the osdi-fixes branch.
The first commit tells ngspice that a .model line with level=77 means "use the bsimbulk OSDI device". Before this change, level=77 ended up with INPmodType = -1 and the model card got registered with an invalid type. I also added bsimbulk to the model-type allowlist in INP2M() so the M-prefixed MOSFET instance lines using a BSIM-BULK model don't get rejected with "incorrect model type". (The original fix in my main work tree also touched inpgmod.c for multi-bin support - that piece is unrelated to the wiring demonstration here so I left it out.)
The second commit is a bug demonstration. The function model_numnodes() in src/spicelib/parser/inp2m.c returns the expected number of terminals for a given model type. Without an entry for bsimbulk and bsimcmg_va it falls through to the default "return 4", so the parser sets up only 4 GENnode slots on the instance. The OSDI runtime then reads its 5-port descriptor but port 5 doesn't exist, so it effectively rewires the body (or temperature) terminal to whatever happens to be in that memory slot.
What this looks like in simulation: a PMOS body diode forward-biased through the supply rail. A simple CMOS inverter draws amps in steady state and fails to switch rail-to-rail. Build the binary at the first commit and you can see the bad behaviour; build it at the second commit and the wiring is correct.
I also added bsimcmg_va to the model-type allowlist in INP2M() for consistency - same five-node BSIM-CMG OSDI device, same reasoning.
A note on the 5th pin. It's a thermal node, not just a temperature input. The model injects its own power dissipation as a current out of the node, and reads the resulting voltage back as a temperature rise above ambient (1 V at the thermal node = +1 K). So whatever you wire to T affects the device's actual operating temperature. You'd typically attach a thermal RC network (Rth to set steady-state degrees-per-watt, Cth to set thermal time-constant) or just short T to ground if you don't care about self-heating in this particular run. Leaving T floating gives a singular matrix during OP solve.
For the basic wiring demonstration on this branch the right move is to short T to ground on each device - that pins V(T) = 0 (ambient) and takes the self-heating dynamics out of the picture, so what we're testing is purely whether the body terminal lands on the actual body node instead of whatever stale value was in the OSDI node_mapping slot 5. Verifying self-heating with a real Rth/Cth is a separate test for another day.
Justin.