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:
parent
fa80458d80
commit
bdc0325901
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue