Fixed a bug when using acm=2.

This commit is contained in:
pnenzi 2004-08-09 17:05:45 +00:00
parent f41b7d2e49
commit c3064d0b26
2 changed files with 157 additions and 144 deletions

View File

@ -2,7 +2,14 @@
* Updated and corrected test files in "tests" directory. Added
"examples" directory.
* src/spicelib/devices/bsim3/b3set.c: Added Dietmar Warning patch
to solve a bug that shows up when acm=2 was used. From Dietmar's
mail:
if we use the acm=2 option we must set the nrd and nrs
defaults to 0.
2004-07-08 Paolo Nenzi <p.nenzi@ieee.org>
* Applied Al Niessner <Al.Niessner@jpl.nasa.gov> negabyte patch

View File

@ -28,7 +28,7 @@
int
BSIM3setup (SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
int *states)
int *states)
{
BSIM3model *model = (BSIM3model*)inModel;
BSIM3instance *here;
@ -53,35 +53,35 @@ IFuid tmpName;
if (!model->BSIM3capModGiven)
model->BSIM3capMod = 3;
if (!model->BSIM3acmModGiven)
model->BSIM3acmMod = 0;
model->BSIM3acmMod = 0;
if (!model->BSIM3noiModGiven)
model->BSIM3noiMod = 1;
/* If the user does not provide the model revision,
* we always choose the most recent.
*/
if (!model->BSIM3versionGiven)
model->BSIM3version = "3.2.4";
/* If the user does not provide the model revision,
* we always choose the most recent.
*/
if (!model->BSIM3versionGiven)
model->BSIM3version = "3.2.4";
/* I have added below the code that translate model string
* into an integer. This trick is meant to speed up the
* revision testing instruction, since comparing integer
* is faster than comparing strings.
* Paolo Nenzi 2002
*/
if (!strcmp (model->BSIM3version, "3.2.4"))
model->BSIM3intVersion = BSIM3V324;
else if (!strcmp (model->BSIM3version, "3.2.3"))
model->BSIM3intVersion = BSIM3V323;
else if (!strcmp (model->BSIM3version, "3.2.2"))
model->BSIM3intVersion = BSIM3V322;
else if (!strcmp (model->BSIM3version, "3.2"))
model->BSIM3intVersion = BSIM3V32;
else
model->BSIM3intVersion = BSIM3V3OLD;
/* BSIM3V3OLD is a placeholder for pre 3.2 revision
* This model should not be used for pre 3.2 models.
*/
/* I have added below the code that translate model string
* into an integer. This trick is meant to speed up the
* revision testing instruction, since comparing integer
* is faster than comparing strings.
* Paolo Nenzi 2002
*/
if (!strcmp (model->BSIM3version, "3.2.4"))
model->BSIM3intVersion = BSIM3V324;
else if (!strcmp (model->BSIM3version, "3.2.3"))
model->BSIM3intVersion = BSIM3V323;
else if (!strcmp (model->BSIM3version, "3.2.2"))
model->BSIM3intVersion = BSIM3V322;
else if (!strcmp (model->BSIM3version, "3.2"))
model->BSIM3intVersion = BSIM3V32;
else
model->BSIM3intVersion = BSIM3V3OLD;
/* BSIM3V3OLD is a placeholder for pre 3.2 revision
* This model should not be used for pre 3.2 models.
*/
if (!model->BSIM3toxGiven)
model->BSIM3tox = 150.0e-10;
@ -90,15 +90,15 @@ IFuid tmpName;
model->BSIM3toxm = model->BSIM3tox;
if (!model->BSIM3cdscGiven)
model->BSIM3cdsc = 2.4e-4; /* unit Q/V/m^2 */
model->BSIM3cdsc = 2.4e-4; /* unit Q/V/m^2 */
if (!model->BSIM3cdscbGiven)
model->BSIM3cdscb = 0.0; /* unit Q/V/m^2 */
if (!model->BSIM3cdscdGiven)
model->BSIM3cdscd = 0.0; /* unit Q/V/m^2 */
model->BSIM3cdscb = 0.0; /* unit Q/V/m^2 */
if (!model->BSIM3cdscdGiven)
model->BSIM3cdscd = 0.0; /* unit Q/V/m^2 */
if (!model->BSIM3citGiven)
model->BSIM3cit = 0.0; /* unit Q/V/m^2 */
model->BSIM3cit = 0.0; /* unit Q/V/m^2 */
if (!model->BSIM3nfactorGiven)
model->BSIM3nfactor = 1;
model->BSIM3nfactor = 1;
if (!model->BSIM3xjGiven)
model->BSIM3xj = .15e-6;
if (!model->BSIM3vsatGiven)
@ -122,9 +122,9 @@ IFuid tmpName;
if (!model->BSIM3ngateGiven)
model->BSIM3ngate = 0; /* unit 1/cm3 */
if (!model->BSIM3vbmGiven)
model->BSIM3vbm = -3.0;
model->BSIM3vbm = -3.0;
if (!model->BSIM3xtGiven)
model->BSIM3xt = 1.55e-7;
model->BSIM3xt = 1.55e-7;
if (!model->BSIM3kt1Given)
model->BSIM3kt1 = -0.11; /* unit V */
if (!model->BSIM3kt1lGiven)
@ -174,9 +174,9 @@ IFuid tmpName;
if (!model->BSIM3u0Given)
model->BSIM3u0 = (model->BSIM3type == NMOS) ? 0.067 : 0.025;
if (!model->BSIM3uteGiven)
model->BSIM3ute = -1.5;
model->BSIM3ute = -1.5;
if (!model->BSIM3voffGiven)
model->BSIM3voff = -0.08;
model->BSIM3voff = -0.08;
if (!model->BSIM3deltaGiven)
model->BSIM3delta = 0.01;
if (!model->BSIM3rdswGiven)
@ -262,31 +262,31 @@ IFuid tmpName;
/* acm model */
if (!model->BSIM3hdifGiven)
model->BSIM3hdif = 0.0;
model->BSIM3hdif = 0.0;
if (!model->BSIM3ldifGiven)
model->BSIM3ldif = 0.0;
model->BSIM3ldif = 0.0;
if (!model->BSIM3ldGiven)
model->BSIM3ld = 0.0;
model->BSIM3ld = 0.0;
if (!model->BSIM3rdGiven)
model->BSIM3rd = 0.0;
model->BSIM3rd = 0.0;
if (!model->BSIM3rsGiven)
model->BSIM3rs = 0.0;
model->BSIM3rs = 0.0;
if (!model->BSIM3rdcGiven)
model->BSIM3rdc = 0.0;
model->BSIM3rdc = 0.0;
if (!model->BSIM3rscGiven)
model->BSIM3rsc = 0.0;
model->BSIM3rsc = 0.0;
/* Length dependence */
/* Length dependence */
if (!model->BSIM3lcdscGiven)
model->BSIM3lcdsc = 0.0;
model->BSIM3lcdsc = 0.0;
if (!model->BSIM3lcdscbGiven)
model->BSIM3lcdscb = 0.0;
if (!model->BSIM3lcdscdGiven)
model->BSIM3lcdscd = 0.0;
model->BSIM3lcdscb = 0.0;
if (!model->BSIM3lcdscdGiven)
model->BSIM3lcdscd = 0.0;
if (!model->BSIM3lcitGiven)
model->BSIM3lcit = 0.0;
model->BSIM3lcit = 0.0;
if (!model->BSIM3lnfactorGiven)
model->BSIM3lnfactor = 0.0;
model->BSIM3lnfactor = 0.0;
if (!model->BSIM3lxjGiven)
model->BSIM3lxj = 0.0;
if (!model->BSIM3lvsatGiven)
@ -310,9 +310,9 @@ IFuid tmpName;
if (!model->BSIM3lngateGiven)
model->BSIM3lngate = 0.0;
if (!model->BSIM3lvbmGiven)
model->BSIM3lvbm = 0.0;
model->BSIM3lvbm = 0.0;
if (!model->BSIM3lxtGiven)
model->BSIM3lxt = 0.0;
model->BSIM3lxt = 0.0;
if (!model->BSIM3lkt1Given)
model->BSIM3lkt1 = 0.0;
if (!model->BSIM3lkt1lGiven)
@ -360,9 +360,9 @@ IFuid tmpName;
if (!model->BSIM3lu0Given)
model->BSIM3lu0 = 0.0;
if (!model->BSIM3luteGiven)
model->BSIM3lute = 0.0;
model->BSIM3lute = 0.0;
if (!model->BSIM3lvoffGiven)
model->BSIM3lvoff = 0.0;
model->BSIM3lvoff = 0.0;
if (!model->BSIM3ldeltaGiven)
model->BSIM3ldelta = 0.0;
if (!model->BSIM3lrdswGiven)
@ -435,17 +435,17 @@ IFuid tmpName;
if (!model->BSIM3lvoffcvGiven)
model->BSIM3lvoffcv = 0.0;
/* Width dependence */
/* Width dependence */
if (!model->BSIM3wcdscGiven)
model->BSIM3wcdsc = 0.0;
model->BSIM3wcdsc = 0.0;
if (!model->BSIM3wcdscbGiven)
model->BSIM3wcdscb = 0.0;
if (!model->BSIM3wcdscdGiven)
model->BSIM3wcdscd = 0.0;
model->BSIM3wcdscb = 0.0;
if (!model->BSIM3wcdscdGiven)
model->BSIM3wcdscd = 0.0;
if (!model->BSIM3wcitGiven)
model->BSIM3wcit = 0.0;
model->BSIM3wcit = 0.0;
if (!model->BSIM3wnfactorGiven)
model->BSIM3wnfactor = 0.0;
model->BSIM3wnfactor = 0.0;
if (!model->BSIM3wxjGiven)
model->BSIM3wxj = 0.0;
if (!model->BSIM3wvsatGiven)
@ -469,9 +469,9 @@ IFuid tmpName;
if (!model->BSIM3wngateGiven)
model->BSIM3wngate = 0.0;
if (!model->BSIM3wvbmGiven)
model->BSIM3wvbm = 0.0;
model->BSIM3wvbm = 0.0;
if (!model->BSIM3wxtGiven)
model->BSIM3wxt = 0.0;
model->BSIM3wxt = 0.0;
if (!model->BSIM3wkt1Given)
model->BSIM3wkt1 = 0.0;
if (!model->BSIM3wkt1lGiven)
@ -519,9 +519,9 @@ IFuid tmpName;
if (!model->BSIM3wu0Given)
model->BSIM3wu0 = 0.0;
if (!model->BSIM3wuteGiven)
model->BSIM3wute = 0.0;
model->BSIM3wute = 0.0;
if (!model->BSIM3wvoffGiven)
model->BSIM3wvoff = 0.0;
model->BSIM3wvoff = 0.0;
if (!model->BSIM3wdeltaGiven)
model->BSIM3wdelta = 0.0;
if (!model->BSIM3wrdswGiven)
@ -594,17 +594,17 @@ IFuid tmpName;
if (!model->BSIM3wvoffcvGiven)
model->BSIM3wvoffcv = 0.0;
/* Cross-term dependence */
/* Cross-term dependence */
if (!model->BSIM3pcdscGiven)
model->BSIM3pcdsc = 0.0;
model->BSIM3pcdsc = 0.0;
if (!model->BSIM3pcdscbGiven)
model->BSIM3pcdscb = 0.0;
if (!model->BSIM3pcdscdGiven)
model->BSIM3pcdscd = 0.0;
model->BSIM3pcdscb = 0.0;
if (!model->BSIM3pcdscdGiven)
model->BSIM3pcdscd = 0.0;
if (!model->BSIM3pcitGiven)
model->BSIM3pcit = 0.0;
model->BSIM3pcit = 0.0;
if (!model->BSIM3pnfactorGiven)
model->BSIM3pnfactor = 0.0;
model->BSIM3pnfactor = 0.0;
if (!model->BSIM3pxjGiven)
model->BSIM3pxj = 0.0;
if (!model->BSIM3pvsatGiven)
@ -629,9 +629,9 @@ IFuid tmpName;
if (!model->BSIM3pngateGiven)
model->BSIM3pngate = 0.0;
if (!model->BSIM3pvbmGiven)
model->BSIM3pvbm = 0.0;
model->BSIM3pvbm = 0.0;
if (!model->BSIM3pxtGiven)
model->BSIM3pxt = 0.0;
model->BSIM3pxt = 0.0;
if (!model->BSIM3pkt1Given)
model->BSIM3pkt1 = 0.0;
if (!model->BSIM3pkt1lGiven)
@ -679,9 +679,9 @@ IFuid tmpName;
if (!model->BSIM3pu0Given)
model->BSIM3pu0 = 0.0;
if (!model->BSIM3puteGiven)
model->BSIM3pute = 0.0;
model->BSIM3pute = 0.0;
if (!model->BSIM3pvoffGiven)
model->BSIM3pvoff = 0.0;
model->BSIM3pvoff = 0.0;
if (!model->BSIM3pdeltaGiven)
model->BSIM3pdelta = 0.0;
if (!model->BSIM3prdswGiven)
@ -756,7 +756,9 @@ IFuid tmpName;
/* unit degree celcius */
if (!model->BSIM3tnomGiven)
model->BSIM3tnom = ckt->CKTnomTemp;
model->BSIM3tnom = ckt->CKTnomTemp;
/* else
model->BSIM3tnom = model->BSIM3tnom + 273.15; */
if (!model->BSIM3LintGiven)
model->BSIM3Lint = 0.0;
if (!model->BSIM3LlGiven)
@ -807,33 +809,33 @@ IFuid tmpName;
model->BSIM3dlc = model->BSIM3Lint;
if (!model->BSIM3xlGiven)
model->BSIM3xl = 0.0;
model->BSIM3xl = 0.0;
if (!model->BSIM3xwGiven)
model->BSIM3xw = 0.0;
model->BSIM3xw = 0.0;
if (!model->BSIM3cfGiven)
if (!model->BSIM3cfGiven)
model->BSIM3cf = 2.0 * EPSOX / PI
* log(1.0 + 0.4e-6 / model->BSIM3tox);
* log(1.0 + 0.4e-6 / model->BSIM3tox);
if (!model->BSIM3cgdoGiven)
{ if (model->BSIM3dlcGiven && (model->BSIM3dlc > 0.0))
{ model->BSIM3cgdo = model->BSIM3dlc * model->BSIM3cox
- model->BSIM3cgdl ;
}
else
model->BSIM3cgdo = 0.6 * model->BSIM3xj * model->BSIM3cox;
}
{ if (model->BSIM3dlcGiven && (model->BSIM3dlc > 0.0))
{ model->BSIM3cgdo = model->BSIM3dlc * model->BSIM3cox
- model->BSIM3cgdl ;
}
else
model->BSIM3cgdo = 0.6 * model->BSIM3xj * model->BSIM3cox;
}
if (!model->BSIM3cgsoGiven)
{ if (model->BSIM3dlcGiven && (model->BSIM3dlc > 0.0))
{ model->BSIM3cgso = model->BSIM3dlc * model->BSIM3cox
- model->BSIM3cgsl ;
}
else
model->BSIM3cgso = 0.6 * model->BSIM3xj * model->BSIM3cox;
}
{ if (model->BSIM3dlcGiven && (model->BSIM3dlc > 0.0))
{ model->BSIM3cgso = model->BSIM3dlc * model->BSIM3cox
- model->BSIM3cgsl ;
}
else
model->BSIM3cgso = 0.6 * model->BSIM3xj * model->BSIM3cox;
}
if (!model->BSIM3cgboGiven)
{ model->BSIM3cgbo = 2.0 * model->BSIM3dwc * model->BSIM3cox;
}
{ model->BSIM3cgbo = 2.0 * model->BSIM3dwc * model->BSIM3cox;
}
if (!model->BSIM3xpartGiven)
model->BSIM3xpart = 0.0;
if (!model->BSIM3sheetResistanceGiven)
@ -865,24 +867,24 @@ IFuid tmpName;
if (!model->BSIM3jctTempExponentGiven)
model->BSIM3jctTempExponent = 3.0;
if (!model->BSIM3oxideTrapDensityAGiven)
{ if (model->BSIM3type == NMOS)
{ if (model->BSIM3type == NMOS)
model->BSIM3oxideTrapDensityA = 1e20;
else
model->BSIM3oxideTrapDensityA=9.9e18;
}
}
if (!model->BSIM3oxideTrapDensityBGiven)
{ if (model->BSIM3type == NMOS)
{ if (model->BSIM3type == NMOS)
model->BSIM3oxideTrapDensityB = 5e4;
else
model->BSIM3oxideTrapDensityB = 2.4e3;
}
}
if (!model->BSIM3oxideTrapDensityCGiven)
{ if (model->BSIM3type == NMOS)
{ if (model->BSIM3type == NMOS)
model->BSIM3oxideTrapDensityC = -1.4e-12;
else
model->BSIM3oxideTrapDensityC = 1.4e-12;
}
}
if (!model->BSIM3emGiven)
model->BSIM3em = 4.1e7; /* V/m */
if (!model->BSIM3efGiven)
@ -894,13 +896,13 @@ IFuid tmpName;
/* loop through all the instances of the model */
for (here = model->BSIM3instances; here != NULL ;
here=here->BSIM3nextInstance)
{
if (here->BSIM3owner == ARCHme)
{
/* allocate a chunk of the state vector */
here->BSIM3states = *states;
*states += BSIM3numStates;
}
{
if (here->BSIM3owner == ARCHme)
{
/* allocate a chunk of the state vector */
here->BSIM3states = *states;
*states += BSIM3numStates;
}
/* perform the parameter defaulting */
if (!here->BSIM3drainAreaGiven)
@ -908,7 +910,10 @@ IFuid tmpName;
if (!here->BSIM3drainPerimeterGiven)
here->BSIM3drainPerimeter = 0.0;
if (!here->BSIM3drainSquaresGiven)
here->BSIM3drainSquares = 1.0;
if (model->BSIM3acmMod == 0)
here->BSIM3drainSquares = 1.0;
else
here->BSIM3drainSquares = 0.0;
if (!here->BSIM3icVBSGiven)
here->BSIM3icVBS = 0.0;
if (!here->BSIM3icVDSGiven)
@ -922,30 +927,32 @@ IFuid tmpName;
if (!here->BSIM3sourcePerimeterGiven)
here->BSIM3sourcePerimeter = 0.0;
if (!here->BSIM3sourceSquaresGiven)
here->BSIM3sourceSquares = 1.0;
if (model->BSIM3acmMod == 0)
here->BSIM3sourceSquares = 1.0;
else
here->BSIM3sourceSquares = 0.0;
if (!here->BSIM3wGiven)
here->BSIM3w = 5.0e-6;
if (!here->BSIM3nqsModGiven)
here->BSIM3nqsMod = 0;
if (!here->BSIM3mGiven)
here->BSIM3m = 1;
if (!here->BSIM3mGiven)
here->BSIM3m = 1;
/* process drain series resistance */
if ( ((model->BSIM3sheetResistance > 0.0) &&
(here->BSIM3drainSquares > 0.0) && (here->BSIM3dNodePrime == 0))
||((model->BSIM3sheetResistance > 0.0) &&
(model->BSIM3hdif > 0.0) && (here->BSIM3dNodePrime == 0))
||((model->BSIM3rd > 0.0) &&
(model->BSIM3ldif > 0.0) && (here->BSIM3dNodePrime == 0))
||((model->BSIM3rd > 0.0) &&
(model->BSIM3ld > 0.0) && (here->BSIM3dNodePrime == 0))
||((model->BSIM3rsc > 0.0) && (here->BSIM3dNodePrime == 0))
if ( ((model->BSIM3sheetResistance > 0.0) &&
(here->BSIM3drainSquares > 0.0) && (here->BSIM3dNodePrime == 0))
||((model->BSIM3sheetResistance > 0.0) &&
(model->BSIM3hdif > 0.0) && (here->BSIM3dNodePrime == 0))
||((model->BSIM3rd > 0.0) &&
(model->BSIM3ldif > 0.0) && (here->BSIM3dNodePrime == 0))
||((model->BSIM3rd > 0.0) &&
(model->BSIM3ld > 0.0) && (here->BSIM3dNodePrime == 0))
||((model->BSIM3rsc > 0.0) && (here->BSIM3dNodePrime == 0))
)
{ error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"drain");
{ error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"drain");
if(error) return(error);
here->BSIM3dNodePrime = tmp->number;
here->BSIM3dNodePrime = tmp->number;
if (ckt->CKTcopyNodesets) {
if (CKTinst2Node(ckt,here,1,(void **)tmpNode,&tmpName)==OK) {
if (tmpNode[0]->nsGiven) {
@ -954,24 +961,23 @@ IFuid tmpName;
}
}
}
}
else
{ here->BSIM3dNodePrime = here->BSIM3dNode;
else
{ here->BSIM3dNodePrime = here->BSIM3dNode;
}
/* process source series resistance */
if ( ((model->BSIM3sheetResistance > 0.0) &&
(here->BSIM3sourceSquares > 0.0) && (here->BSIM3sNodePrime == 0))
||((model->BSIM3sheetResistance > 0.0) &&
(model->BSIM3hdif > 0.0) && (here->BSIM3sNodePrime == 0))
||((model->BSIM3rs > 0.0) &&
(model->BSIM3ldif > 0.0) && (here->BSIM3sNodePrime == 0))
||((model->BSIM3rs > 0.0) &&
(model->BSIM3ld > 0.0) && (here->BSIM3sNodePrime == 0))
||((model->BSIM3rsc > 0.0) && (here->BSIM3sNodePrime == 0))
if ( ((model->BSIM3sheetResistance > 0.0) &&
(here->BSIM3sourceSquares > 0.0) && (here->BSIM3sNodePrime == 0))
||((model->BSIM3sheetResistance > 0.0) &&
(model->BSIM3hdif > 0.0) && (here->BSIM3sNodePrime == 0))
||((model->BSIM3rs > 0.0) &&
(model->BSIM3ldif > 0.0) && (here->BSIM3sNodePrime == 0))
||((model->BSIM3rs > 0.0) &&
(model->BSIM3ld > 0.0) && (here->BSIM3sNodePrime == 0))
||((model->BSIM3rsc > 0.0) && (here->BSIM3sNodePrime == 0))
)
{ error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"source");
{ error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"source");
if(error) return(error);
here->BSIM3sNodePrime = tmp->number;
@ -985,19 +991,19 @@ IFuid tmpName;
}
}
else
{ here->BSIM3sNodePrime = here->BSIM3sNode;
else
{ here->BSIM3sNodePrime = here->BSIM3sNode;
}
/* internal charge node */
if ((here->BSIM3nqsMod) && (here->BSIM3qNode == 0))
{ error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"charge");
{ error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"charge");
if(error) return(error);
here->BSIM3qNode = tmp->number;
}
else
{ here->BSIM3qNode = 0;
else
{ here->BSIM3qNode = 0;
}
/* set Sparse Matrix Pointers */