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.
This commit is contained in:
parent
338b3899bf
commit
b266ec6272
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue