diff --git a/VERSION b/VERSION index d15f068e..979d2895 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.639 +8.3.640 diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index f66ed9ff..b0f38d3c 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -844,6 +844,8 @@ spcdevHierVisit( case DEV_DSUBCKT: case DEV_MSUBCKT: fprintf(esSpiceF, "%d", esSbckNum++); + if ((dev->dev_class == DEV_RSUBCKT) && esDoResistorTee) + fprintf(esSpiceF, "A"); break; default: fprintf(esSpiceF, "%d", esDevNum++); @@ -920,16 +922,27 @@ spcdevHierVisit( else if (dev->dev_class != DEV_MSUBCKT) { if (dev->dev_nterm > 1) - spcdevOutNode(hc->hc_hierName, source->dterm_node->efnode_name->efnn_hier, + spcdevOutNode(hc->hc_hierName, + source->dterm_node->efnode_name->efnn_hier, "subckt", esSpiceF); - if (dev->dev_nterm > 2) - spcdevOutNode(hc->hc_hierName, drain->dterm_node->efnode_name->efnn_hier, + if ((dev->dev_class == DEV_RSUBCKT) && esDoResistorTee) + { + /* Handle resistor "tee" model */ + spcdevOutNode(hc->hc_hierName, + gate->dterm_node->efnode_name->efnn_hier, + "subckt", esSpiceF); + l /= 2; /* Halve the resistor length for each side */ + } + else if (dev->dev_nterm > 2) + spcdevOutNode(hc->hc_hierName, + drain->dterm_node->efnode_name->efnn_hier, "subckt", esSpiceF); } else /* class DEV_MSUBCKT */ { if (dev->dev_nterm > 2) - spcdevOutNode(hc->hc_hierName, source->dterm_node->efnode_name->efnn_hier, + spcdevOutNode(hc->hc_hierName, + source->dterm_node->efnode_name->efnn_hier, "subckt", esSpiceF); } /* The following only applies to DEV_SUBCKT and DEV_VERILOGA, which */ @@ -967,6 +980,54 @@ spcdevHierVisit( spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE); if (sdM != 1.0) fprintf(esSpiceF, " M=%g", sdM); + + if ((dev->dev_class == DEV_RSUBCKT) && esDoResistorTee) + { + /* Repeat everything above for the second half of the "tee" resistor */ + fprintf(esSpiceF, "\n%c%dB", devchar, esSbckNum - 1); + + spcdevOutNode(hc->hc_hierName, + gate->dterm_node->efnode_name->efnn_hier, + "subckt", esSpiceF); + spcdevOutNode(hc->hc_hierName, + drain->dterm_node->efnode_name->efnn_hier, + "subckt", esSpiceF); + + /* Get the device parameters now, and check if the substrate is */ + /* passed as a parameter rather than as a node. */ + + plist = efGetDeviceParams(EFDevTypes[dev->dev_type]); + for (pptr = plist; pptr != NULL; pptr = pptr->parm_next) + if (pptr->parm_type[0] == 's') + break; + + if ((pptr == NULL) && subnode) + { + EFNode *dnode; + + fprintf(esSpiceF, " "); + subnodeFlat = spcdevSubstrate(hc->hc_hierName, + subnode->efnode_name->efnn_hier, + dev->dev_type, esSpiceF); + + /* If a tee resistor subcircuit has a substrate pin, then the + * parasitic capacitance to substrate should be assumed to be + * part of the resistor subcircuit model, and so the parasitic + * to substrate on the "gate" node should be forced to zero. + */ + dnode = GetHierNode(hc, gate->dterm_node->efnode_name->efnn_hier); + dnode->efnode_cap = 0; + } + /* Support for CDL format */ + if (esFormat == CDL) fprintf(esSpiceF, " /"); + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + /* Write all requested parameters to the subcircuit call. */ + sdM = getCurDevMult(); + spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + } break; case DEV_RES: diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index ea00d46b..45a6696c 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -2901,13 +2901,17 @@ spcdevVisit( case DEV_VOLT: fprintf(esSpiceF, "%d", esVoltNum++); break; + case DEV_RSUBCKT: case DEV_SUBCKT: case DEV_VERILOGA: - case DEV_RSUBCKT: case DEV_CSUBCKT: case DEV_DSUBCKT: case DEV_MSUBCKT: fprintf(esSpiceF, "%d", esSbckNum++); + if ((dev->dev_class == DEV_RSUBCKT) && esDoResistorTee) + /* For resistor tee networks, use, e.g., */ + /* "X1A" and "X1B", for clarity */ + fprintf(esSpiceF, "A"); break; default: fprintf(esSpiceF, "%d", esDevNum++); @@ -2982,7 +2986,15 @@ spcdevVisit( if (dev->dev_nterm > 1) spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, name, esSpiceF); - if (dev->dev_nterm > 2) + if ((dev->dev_class == DEV_RSUBCKT) && esDoResistorTee) + { + l /= 2; /* Halve the resistor. Note that this may introduce + * error if l is an odd value. + */ + spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + } + else if (dev->dev_nterm > 2) spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier, name, esSpiceF); } @@ -3031,6 +3043,53 @@ spcdevVisit( fprintf(esSpiceF, " M=%g", sdM); break; + if (dev->dev_class == DEV_RSUBCKT && esDoResistorTee) + { + /* Write the second half of the "Tee" resistor when + * the resistor is type DEV_RSUBCKT and not DEV_RES. + */ + fprintf(esSpiceF, "\n%c%dB", devchar, esSbckNum - 1); + + spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + + /* Get the device parameters now, and check if the substrate is */ + /* passed as a parameter rather than as a node. */ + + plist = efGetDeviceParams(EFDevTypes[dev->dev_type]); + for (pptr = plist; pptr != NULL; pptr = pptr->parm_next) + if (pptr->parm_type[0] == 's') + break; + + if ((pptr == NULL) && subnode) + { + fprintf(esSpiceF, " "); + subnodeFlat = spcdevSubstrate(hierName, + subnode->efnode_name->efnn_hier, + dev->dev_type, esSpiceF); + + /* There is a substrate pin on the resistor subcircuit, so assume + * that the substrate cap is part of the subcircuit model, and + * zero it. + */ + gate->dterm_node->efnode_cap = 0; + } + + /* CDL format support: Output a slash followed by a space. */ + if (esFormat == CDL) fprintf(esSpiceF, " /"); + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + /* Write all requested parameters to the subcircuit call. */ + + sdM = getCurDevMult(); + spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + } + break; + case DEV_RES: if (esDoResistorTee) {