From b266ec6272f21c99c5a4b196e60b9e012d8c8f84 Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Wed, 24 Jun 2026 10:34:23 -0400 Subject: [PATCH] Implemented the resistor "pi" model, which evenly splits the capacitance of a resistor device between the two terminals. If the resistor device model contains the capacitance, then the resistor type should not be included in types that generate parasitics. If not, then the "pi" model is used. The "tee" model is still available using "ext2spice resistor tee on". What this update does is to default to the "pi" model instead of ignoring the capacitance of the resistor type (e.g., "rm1"), and because the capacitance of that node is removed after distributing it between the two terminals, it will no longer produce a "floating" node in the netlist output. --- ext2spice/ext2hier.c | 28 ++++++++------- ext2spice/ext2spice.c | 83 ++++++++++++++++++++++++++++++++++++------- ext2spice/ext2spice.h | 1 + 3 files changed, 86 insertions(+), 26 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index a6bfa79a..e0ab7dbf 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1028,24 +1028,21 @@ spcdevHierVisit( if (sdM != 1.0) fprintf(esSpiceF, " M=%g", sdM); } + else + { + spcdevResPi(hc->hc_hierName, gate->dterm_node->efnode_name->efnn_hier, + source->dterm_node->efnode_name->efnn_hier, + drain->dterm_node->efnode_name->efnn_hier, + "subckt"); + } break; case DEV_RES: if (esDoResistorTee) { - /* There are three ways of handling capacitance */ - /* on resistor networks. One is to ignore it */ - /* (the default; generates "floating" nodes in */ - /* the SPICE output) which is okay for LVS. */ - /* Another way is the Pi network, in which the */ - /* capacitance is split evenly between the */ - /* terminals. Again, the resistor node is left */ - /* floating. The third is the Tee network, in */ - /* which the resistance is split in two parts, */ - /* connecting to a capacitor to ground in the */ - /* middle. This is the best solution but plays */ - /* havoc with LVS. So, the choice is a command */ - /* line option. */ + /* There are two ways of handling resistor */ + /* capacitance to substrate: The Pi model and */ + /* the Tee model (see ext2spice.c). */ esOutputHierResistor(hc, dev, scale, gate, source, has_model, l, w, 2); @@ -1061,6 +1058,11 @@ spcdevHierVisit( { esOutputHierResistor(hc, dev, scale, source, drain, has_model, l, w, 1); + + spcdevResPi(hc->hc_hierName, gate->dterm_node->efnode_name->efnn_hier, + source->dterm_node->efnode_name->efnn_hier, + drain->dterm_node->efnode_name->efnn_hier, + "subckt"); } break; diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 0c3a0094..d048215f 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -2995,8 +2995,15 @@ spcdevVisit( name, esSpiceF); } else if (dev->dev_nterm > 2) + { spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier, name, esSpiceF); + + spcdevResPi(hierName, gate->dterm_node->efnode_name->efnn_hier, + source->dterm_node->efnode_name->efnn_hier, + drain->dterm_node->efnode_name->efnn_hier, + name); + } } else /* class DEV_MSUBCKT */ { @@ -3093,19 +3100,15 @@ spcdevVisit( case DEV_RES: if (esDoResistorTee) { - /* There are three ways of handling capacitance */ - /* on resistor networks. One is to ignore it */ - /* (the default; generates "floating" nodes in */ - /* the SPICE output) which is okay for LVS. */ - /* Another way is the Pi network, in which the */ - /* capacitance is split evenly between the */ - /* terminals. Again, the resistor node is left */ - /* floating. The third is the Tee network, in */ - /* which the resistance is split in two parts, */ - /* connecting to a capacitor to ground in the */ - /* middle. This is the best solution but plays */ - /* havoc with LVS. So, the choice is a command */ - /* line option. */ + /* There are two ways of handling capacitance */ + /* on resistor networks. The default is the Pi */ + /* network, which splits the capacitance of the */ + /* resistor itself evenly between the two */ + /* terminals. The resistor itself is not */ + /* output as a node. The other is the Tee */ + /* network, in which the resistor is divided in */ + /* two, with the capacitance to substrate in */ + /* the middle. */ esOutputResistor(dev, hierName, scale, gate, source, has_model, l, w, 2); @@ -3121,6 +3124,11 @@ spcdevVisit( { esOutputResistor(dev, hierName, scale, source, drain, has_model, l, w, 1); + + spcdevResPi(hierName, gate->dterm_node->efnode_name->efnn_hier, + source->dterm_node->efnode_name->efnn_hier, + drain->dterm_node->efnode_name->efnn_hier, + name); } break; @@ -3851,6 +3859,55 @@ spcnAPHier( return 0; } +/* + * ---------------------------------------------------------------------------- + * + * spcdevResPi -- + * + * Handle a "pi" resistor model: Take the capacitance of the "gate" + * (resistor device layer) to substrate, and split it between the two + * resistor terminals. + * + * Results: + * None. + * + * Side effects: + * Modifies the capacitance values on the terminal and "gate" nodes + * of the resistor device. + * + * ---------------------------------------------------------------------------- + */ + +void +spcdevResPi( + const HierName *prefix, + const HierName *gate_suffix, + const HierName *source_suffix, + const HierName *drain_suffix, + const char *name) +{ + HashEntry *he; + EFNodeName *nngate, *nnsource, *nndrain; + EFCapValue rescap; + + he = EFHNConcatLook(prefix, gate_suffix, name); + if (he == NULL) return; + nngate = (EFNodeName *) HashGetValue(he); + + he = EFHNConcatLook(prefix, drain_suffix, name); + if (he == NULL) return; + nndrain = (EFNodeName *) HashGetValue(he); + + he = EFHNConcatLook(prefix, source_suffix, name); + if (he == NULL) return; + nnsource = (EFNodeName *) HashGetValue(he); + + rescap = nngate->efnn_node->efnode_cap / 2.0; + nnsource->efnn_node->efnode_cap += rescap; + nndrain->efnn_node->efnode_cap += rescap; + nngate->efnn_node->efnode_cap = 0; +} + /* * ---------------------------------------------------------------------------- * diff --git a/ext2spice/ext2spice.h b/ext2spice/ext2spice.h index 2284bfee..9e93c5dd 100644 --- a/ext2spice/ext2spice.h +++ b/ext2spice/ext2spice.h @@ -49,6 +49,7 @@ extern void setDevMult(int i, float f); extern int EFHNSprintf(char *str, HierName *hierName); extern int printSubcktDict(void); extern int spcdevOutNode(const HierName *prefix, const HierName *suffix, const char *name, FILE *outf); +extern void spcdevResPi(const HierName *prefix, const HierName *gate, const HierName *source, const HierName *drain, const char *name); extern int spcnAP(DevTerm *dterm, EFNode *node, int resClass, float scale, char *asterm, char *psterm, float m, FILE *outf, int w); extern int parallelDevs(const devMerge *f1, const devMerge *f2); extern int nodeHspiceName(char *s);