Extended the use of "ext2spice resistor tee on" to include

DEV_RSUBCKT as well as (previously implemented) DEV_RES.  The
handling of DEV_RSUBCKT includes checking if the subcircuit has
a substrate pin, and zeroing the capacitance to substrate for the
resistor node, under the assumption that the parasitics are part of
the resistor subcircuit model.
This commit is contained in:
R. Timothy Edwards 2026-05-09 20:05:52 -04:00
parent fa80458d80
commit bdc0325901
3 changed files with 127 additions and 7 deletions

View File

@ -1 +1 @@
8.3.639
8.3.640

View File

@ -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:

View File

@ -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)
{