Merge branch 'pre-master' of ssh://git.code.sf.net/p/ngspice/ngspice into pre-master
This commit is contained in:
commit
c9b3144d79
|
|
@ -16,6 +16,7 @@ Author: 1985 Thomas L. Quarles
|
|||
double DEVlimvds(double,double);
|
||||
double DEVpnjlim(double,double,double,double,int*);
|
||||
double DEVfetlim(double,double,double);
|
||||
double DEVlimitlog(double, double, double, int*);
|
||||
void DEVcmeyer(double,double,double,double,double,double,double,double,double,
|
||||
double,double,double*,double*,double*,double,double,double,double);
|
||||
void DEVqmeyer(double,double,double,double,double,double*,double*,double*,
|
||||
|
|
|
|||
|
|
@ -154,6 +154,10 @@ IFparm BJTmPTable[] = { /* model parameters */
|
|||
OPU("excessphasefactor",BJT_MOD_EXCESSPHASEFACTOR,IF_REAL, "Excess phase fact."),
|
||||
IOP("iss", BJT_MOD_ISS, IF_REAL, "Substrate Jct. Saturation Current"),
|
||||
IOP("ns", BJT_MOD_NS, IF_REAL, "Substrate current emission coefficient"),
|
||||
IOP("rco", BJT_MOD_RCO, IF_REAL, "Intrinsic coll. resistance"),
|
||||
IOP("vo", BJT_MOD_VO, IF_REAL, "Epi drift saturation voltage"),
|
||||
IOP("gamma", BJT_MOD_GAMMA, IF_REAL, "Epi doping parameter"),
|
||||
IOP("qco", BJT_MOD_QCO, IF_REAL, "Epi Charge parameter"),
|
||||
IOP("tlev", BJT_MOD_TLEV, IF_INTEGER, "Temperature equation selector"),
|
||||
IOP("tlevc", BJT_MOD_TLEVC, IF_INTEGER, "Temperature equation selector"),
|
||||
IOP("tbf1", BJT_MOD_TBF1, IF_REAL, "BF 1. temperature coefficient"),
|
||||
|
|
@ -216,6 +220,10 @@ IFparm BJTmPTable[] = { /* model parameters */
|
|||
IOP("tise2", BJT_MOD_TISE2, IF_REAL, "ISE 2. temperature coefficient"),
|
||||
IOP("tisc1", BJT_MOD_TISC1, IF_REAL, "ISC 1. temperature coefficient"),
|
||||
IOP("tisc2", BJT_MOD_TISC2, IF_REAL, "ISC 2. temperature coefficient"),
|
||||
IOP("quasimod", BJT_MOD_QUASIMOD, IF_INTEGER, "Temperature equation selector"),
|
||||
IOP("vg", BJT_MOD_EGQS, IF_REAL, "Energy gap for QS temp. dependency"),
|
||||
IOP("cn", BJT_MOD_XRCI, IF_REAL, "Temperature exponent of RCI"),
|
||||
IOP("d", BJT_MOD_XD, IF_REAL, "Temperature exponent of VO"),
|
||||
IOP("vbe_max", BJT_MOD_VBE_MAX, IF_REAL, "maximum voltage B-E junction"),
|
||||
IOP("vbc_max", BJT_MOD_VBC_MAX, IF_REAL, "maximum voltage B-C junction"),
|
||||
IOP("vce_max", BJT_MOD_VCE_MAX, IF_REAL, "maximum voltage C-E branch")
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ BJTacLoad(GENmodel *inModel, CKTcircuit *ckt)
|
|||
double xcsub;
|
||||
double xcmcb;
|
||||
double m;
|
||||
double Irci_Vrci, Irci_Vbci, Irci_Vbcx, xcbcx;
|
||||
|
||||
for( ; model != NULL; model = BJTnextModel(model)) {
|
||||
for( here = BJTinstances(model); here!= NULL;
|
||||
|
|
@ -49,6 +50,9 @@ BJTacLoad(GENmodel *inModel, CKTcircuit *ckt)
|
|||
gmu= *(ckt->CKTstate0 + here->BJTgmu);
|
||||
gm= *(ckt->CKTstate0 + here->BJTgm);
|
||||
go= *(ckt->CKTstate0 + here->BJTgo);
|
||||
Irci_Vrci = *(ckt->CKTstate0 + here->BJTirci_Vrci);
|
||||
Irci_Vbci = *(ckt->CKTstate0 + here->BJTirci_Vbci);
|
||||
Irci_Vbcx = *(ckt->CKTstate0 + here->BJTirci_Vbcx);
|
||||
xgm=0;
|
||||
td=model->BJTexcessPhaseFactor;
|
||||
if(td != 0) {
|
||||
|
|
@ -63,21 +67,24 @@ BJTacLoad(GENmodel *inModel, CKTcircuit *ckt)
|
|||
xcbx= *(ckt->CKTstate0 + here->BJTcqbx) * ckt->CKTomega;
|
||||
xcsub= *(ckt->CKTstate0 + here->BJTcqsub) * ckt->CKTomega;
|
||||
xcmcb= *(ckt->CKTstate0 + here->BJTcexbc) * ckt->CKTomega;
|
||||
xcbcx= *(ckt->CKTstate0 + here->BJTcqbcx) * ckt->CKTomega;
|
||||
|
||||
*(here->BJTcolColPtr) += m * (gcpr);
|
||||
*(here->BJTbaseBasePtr) += m * (gx);
|
||||
*(here->BJTbaseBasePtr + 1) += m * (xcbx);
|
||||
*(here->BJTemitEmitPtr) += m * (gepr);
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * (gmu+go+gcpr);
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * (gmu+go);
|
||||
*(here->BJTcollCXcollCXPtr) += m * (gcpr);
|
||||
*(here->BJTcolPrimeColPrimePtr + 1) += m * (xcmu+xcbx);
|
||||
*(here->BJTsubstConSubstConPtr + 1) += m * (xcsub);
|
||||
*(here->BJTbasePrimeBasePrimePtr) += m * (gx+gpi+gmu);
|
||||
*(here->BJTbasePrimeBasePrimePtr + 1) += m * (xcpi+xcmu+xcmcb);
|
||||
*(here->BJTemitPrimeEmitPrimePtr) += m * (gpi+gepr+gm+go);
|
||||
*(here->BJTemitPrimeEmitPrimePtr + 1) += m * (xcpi+xgm);
|
||||
*(here->BJTcolColPrimePtr) += m * (-gcpr);
|
||||
*(here->BJTcollCollCXPtr) += m * (-gcpr);
|
||||
*(here->BJTbaseBasePrimePtr) += m * (-gx);
|
||||
*(here->BJTemitEmitPrimePtr) += m * (-gepr);
|
||||
*(here->BJTcolPrimeColPtr) += m * (-gcpr);
|
||||
*(here->BJTcollCXCollPtr) += m * (-gcpr);
|
||||
*(here->BJTcolPrimeBasePrimePtr) += m * (-gmu+gm);
|
||||
*(here->BJTcolPrimeBasePrimePtr + 1) += m * (-xcmu+xgm);
|
||||
*(here->BJTcolPrimeEmitPrimePtr) += m * (-gm-go);
|
||||
|
|
@ -97,6 +104,24 @@ BJTacLoad(GENmodel *inModel, CKTcircuit *ckt)
|
|||
*(here->BJTsubstSubstConPtr + 1) += m * (-xcsub);
|
||||
*(here->BJTbaseColPrimePtr + 1) += m * (-xcbx);
|
||||
*(here->BJTcolPrimeBasePtr + 1) += m * (-xcbx);
|
||||
if (model->BJTintCollResistGiven) {
|
||||
*(here->BJTcollCXcollCXPtr) += m * Irci_Vrci;
|
||||
*(here->BJTcollCXColPrimePtr) += m * -Irci_Vrci;
|
||||
*(here->BJTcollCXBasePrimePtr) += m * Irci_Vbci;
|
||||
*(here->BJTcollCXColPrimePtr) += m * -Irci_Vbci;
|
||||
*(here->BJTcollCXBasePrimePtr) += m * Irci_Vbcx;
|
||||
*(here->BJTcollCXcollCXPtr) += m * -Irci_Vbcx;
|
||||
*(here->BJTcolPrimeCollCXPtr) += m * -Irci_Vrci;
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * Irci_Vrci;
|
||||
*(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbci;
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * Irci_Vbci;
|
||||
*(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbcx;
|
||||
*(here->BJTcolPrimeCollCXPtr) += m * Irci_Vbcx;
|
||||
*(here->BJTbasePrimeBasePrimePtr + 1) += m * xcbcx;
|
||||
*(here->BJTcollCXcollCXPtr + 1) += m * xcbcx;
|
||||
*(here->BJTbasePrimeCollCXPtr + 1) += m * -xcbcx;
|
||||
*(here->BJTcollCXBasePrimePtr + 1) += m * -xcbcx;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ BJTask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalue
|
|||
case BJT_QUEST_COLPRIMENODE:
|
||||
value->iValue = here->BJTcolPrimeNode;
|
||||
return(OK);
|
||||
case BJT_QUEST_COLLCXNODE:
|
||||
value->iValue = here->BJTcollCXNode;
|
||||
return(OK);
|
||||
case BJT_QUEST_BASEPRIMENODE:
|
||||
value->iValue = here->BJTbasePrimeNode;
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -27,9 +27,10 @@ BJTconvTest(GENmodel *inModel, CKTcircuit *ckt)
|
|||
double cbhat;
|
||||
double vbe;
|
||||
double vbc;
|
||||
double vbcx;
|
||||
double delvbe;
|
||||
double delvbc;
|
||||
|
||||
double delvbcx;
|
||||
|
||||
|
||||
for( ; model != NULL; model = BJTnextModel(model)) {
|
||||
|
|
@ -41,8 +42,12 @@ BJTconvTest(GENmodel *inModel, CKTcircuit *ckt)
|
|||
vbc=model->BJTtype*(
|
||||
*(ckt->CKTrhsOld+here->BJTbasePrimeNode)-
|
||||
*(ckt->CKTrhsOld+here->BJTcolPrimeNode));
|
||||
vbcx=model->BJTtype*(
|
||||
*(ckt->CKTrhsOld+here->BJTbasePrimeNode)-
|
||||
*(ckt->CKTrhsOld+here->BJTcollCXNode));
|
||||
delvbe=vbe- *(ckt->CKTstate0 + here->BJTvbe);
|
||||
delvbc=vbc- *(ckt->CKTstate0 + here->BJTvbc);
|
||||
delvbcx=vbcx- *(ckt->CKTstate0 + here->BJTvbcx);
|
||||
cchat= *(ckt->CKTstate0 + here->BJTcc)+(*(ckt->CKTstate0 +
|
||||
here->BJTgm)+ *(ckt->CKTstate0 + here->BJTgo))*delvbe-
|
||||
(*(ckt->CKTstate0 + here->BJTgo)+*(ckt->CKTstate0 +
|
||||
|
|
@ -58,14 +63,14 @@ BJTconvTest(GENmodel *inModel, CKTcircuit *ckt)
|
|||
tol=ckt->CKTreltol*MAX(fabs(cchat),fabs(cc))+ckt->CKTabstol;
|
||||
if (fabs(cchat-cc) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) here;
|
||||
ckt->CKTtroubleElt = (GENinstance *) here;
|
||||
return(OK); /* no reason to continue - we've failed... */
|
||||
} else {
|
||||
tol=ckt->CKTreltol*MAX(fabs(cbhat),fabs(cb))+
|
||||
ckt->CKTabstol;
|
||||
if (fabs(cbhat-cb) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) here;
|
||||
ckt->CKTtroubleElt = (GENinstance *) here;
|
||||
return(OK); /* no reason to continue - we've failed... */
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ typedef struct sBJTinstance {
|
|||
const int BJTbaseNode; /* number of base node of bjt */
|
||||
const int BJTemitNode; /* number of emitter node of bjt */
|
||||
const int BJTsubstNode; /* number of substrate node of bjt */
|
||||
int BJTcollCXNode; /* number of internal collector node of bjt */
|
||||
int BJTcolPrimeNode; /* number of internal collector node of bjt */
|
||||
int BJTbasePrimeNode; /* number of internal base node of bjt */
|
||||
int BJTemitPrimeNode; /* number of internal emitter node of bjt */
|
||||
|
|
@ -100,15 +101,18 @@ typedef struct sBJTinstance {
|
|||
double BJTtjunctionExpBC; /* temperature adjusted MJC */
|
||||
double BJTtjunctionExpSub; /* temperature adjusted MJS */
|
||||
double BJTtemissionCoeffS; /* temperature adjusted NS */
|
||||
double BJTtintCollResist; /* temperature adjusted QS RO */
|
||||
double BJTtepiSatVoltage; /* temperature adjusted QS VO */
|
||||
double BJTtepiDoping; /* temperature adjusted QS GAMMA */
|
||||
|
||||
double *BJTcolColPrimePtr; /* pointer to sparse matrix at
|
||||
* (collector,collector prime) */
|
||||
double *BJTcollCollCXPtr; /* pointer to sparse matrix at
|
||||
* (collector,collector cx) */
|
||||
double *BJTbaseBasePrimePtr; /* pointer to sparse matrix at
|
||||
* (base,base prime) */
|
||||
double *BJTemitEmitPrimePtr; /* pointer to sparse matrix at
|
||||
* (emitter,emitter prime) */
|
||||
double *BJTcolPrimeColPtr; /* pointer to sparse matrix at
|
||||
* (collector prime,collector) */
|
||||
double *BJTcollCXCollPtr; /* pointer to sparse matrix at
|
||||
* (collector cx,collector) */
|
||||
double *BJTcolPrimeBasePrimePtr; /* pointer to sparse matrix at
|
||||
* (collector prime,base prime) */
|
||||
double *BJTcolPrimeEmitPrimePtr; /* pointer to sparse matrix at
|
||||
|
|
@ -153,6 +157,17 @@ typedef struct sBJTinstance {
|
|||
double *BJTcolPrimeBasePtr; /* pointer to sparse matrix at
|
||||
* (collector prime,base) */
|
||||
|
||||
double *BJTcollCXcollCXPtr; /* pointer to sparse matrix at
|
||||
* (collector cx,collector cx) */
|
||||
double *BJTcollCXBasePrimePtr; /* pointer to sparse matrix at
|
||||
* (collector cx,base prime) */
|
||||
double *BJTbasePrimeCollCXPtr; /* pointer to sparse matrix at
|
||||
* (base prime,collector cx) */
|
||||
double *BJTcolPrimeCollCXPtr; /* pointer to sparse matrix at
|
||||
* (collector prime,collector cx) */
|
||||
double *BJTcollCXColPrimePtr; /* pointer to sparse matrix at
|
||||
* (collector cx,base prime) */
|
||||
|
||||
unsigned BJToff :1; /* 'off' flag for bjt */
|
||||
unsigned BJTtempGiven :1; /* temperature given for bjt instance*/
|
||||
unsigned BJTdtempGiven :1; /* delta temperature given for bjt instance*/
|
||||
|
|
@ -171,6 +186,7 @@ typedef struct sBJTinstance {
|
|||
double BJTcapbc;
|
||||
double BJTcapsub;
|
||||
double BJTcapbx;
|
||||
double BJTcapbcx;
|
||||
double *BJTsens;
|
||||
|
||||
#define BJTsenGpi BJTsens /* stores the perturbed values of gpi */
|
||||
|
|
@ -297,29 +313,39 @@ typedef struct sBJTinstance {
|
|||
/* entries in the state vector for bjt: */
|
||||
#define BJTvbe BJTstate
|
||||
#define BJTvbc BJTstate+1
|
||||
#define BJTcc BJTstate+2
|
||||
#define BJTcb BJTstate+3
|
||||
#define BJTgpi BJTstate+4
|
||||
#define BJTgmu BJTstate+5
|
||||
#define BJTgm BJTstate+6
|
||||
#define BJTgo BJTstate+7
|
||||
#define BJTqbe BJTstate+8
|
||||
#define BJTcqbe BJTstate+9
|
||||
#define BJTqbc BJTstate+10
|
||||
#define BJTcqbc BJTstate+11
|
||||
#define BJTqsub BJTstate+12
|
||||
#define BJTcqsub BJTstate+13
|
||||
#define BJTqbx BJTstate+14
|
||||
#define BJTcqbx BJTstate+15
|
||||
#define BJTgx BJTstate+16
|
||||
#define BJTcexbc BJTstate+17
|
||||
#define BJTgeqcb BJTstate+18
|
||||
#define BJTgcsub BJTstate+19
|
||||
#define BJTgeqbx BJTstate+20
|
||||
#define BJTvsub BJTstate+21
|
||||
#define BJTcdsub BJTstate+22
|
||||
#define BJTgdsub BJTstate+23
|
||||
#define BJTnumStates 24
|
||||
#define BJTvbcx BJTstate+2
|
||||
#define BJTvrci BJTstate+3
|
||||
#define BJTcc BJTstate+4
|
||||
#define BJTcb BJTstate+5
|
||||
#define BJTgpi BJTstate+6
|
||||
#define BJTgmu BJTstate+7
|
||||
#define BJTgm BJTstate+8
|
||||
#define BJTgo BJTstate+9
|
||||
#define BJTqbe BJTstate+10
|
||||
#define BJTcqbe BJTstate+11
|
||||
#define BJTqbc BJTstate+12
|
||||
#define BJTcqbc BJTstate+13
|
||||
#define BJTqsub BJTstate+14
|
||||
#define BJTcqsub BJTstate+15
|
||||
#define BJTqbx BJTstate+16
|
||||
#define BJTcqbx BJTstate+17
|
||||
#define BJTgx BJTstate+18
|
||||
#define BJTcexbc BJTstate+19
|
||||
#define BJTgeqcb BJTstate+20
|
||||
#define BJTgcsub BJTstate+21
|
||||
#define BJTgeqbx BJTstate+22
|
||||
#define BJTvsub BJTstate+23
|
||||
#define BJTcdsub BJTstate+24
|
||||
#define BJTgdsub BJTstate+25
|
||||
#define BJTirci BJTstate+26
|
||||
#define BJTirci_Vrci BJTstate+27
|
||||
#define BJTirci_Vbci BJTstate+28
|
||||
#define BJTirci_Vbcx BJTstate+29
|
||||
#define BJTqbcx BJTstate+30
|
||||
#define BJTcqbcx BJTstate+31
|
||||
#define BJTgbcx BJTstate+32
|
||||
|
||||
#define BJTnumStates 33
|
||||
|
||||
#define BJTsensxpbe BJTstate+24 /* charge sensitivities and their
|
||||
derivatives. +25 for the derivatives -
|
||||
|
|
@ -388,6 +414,10 @@ typedef struct sBJTmodel { /* model structure for a bjt */
|
|||
double BJTfNexp;
|
||||
double BJTsubSatCur; /* input - don't use */
|
||||
double BJTemissionCoeffS;
|
||||
double BJTintCollResist;
|
||||
double BJTepiSatVoltage;
|
||||
double BJTepiDoping;
|
||||
double BJTepiCharge;
|
||||
int BJTtlev;
|
||||
int BJTtlevc;
|
||||
double BJTtbf1;
|
||||
|
|
@ -459,6 +489,10 @@ typedef struct sBJTmodel { /* model structure for a bjt */
|
|||
double BJTtise2;
|
||||
double BJTtisc1;
|
||||
double BJTtisc2;
|
||||
int BJTquasimod;
|
||||
double BJTenergyGapQS;
|
||||
double BJTtempExpRCI;
|
||||
double BJTtempExpVO;
|
||||
double BJTvbeMax; /* maximum voltage over B-E junction */
|
||||
double BJTvbcMax; /* maximum voltage over B-C junction */
|
||||
double BJTvceMax; /* maximum voltage over C-E branch */
|
||||
|
|
@ -509,6 +543,10 @@ typedef struct sBJTmodel { /* model structure for a bjt */
|
|||
unsigned BJTfNexpGiven :1;
|
||||
unsigned BJTsubSatCurGiven : 1;
|
||||
unsigned BJTemissionCoeffSGiven : 1;
|
||||
unsigned BJTintCollResistGiven : 1;
|
||||
unsigned BJTepiSatVoltageGiven : 1;
|
||||
unsigned BJTepiDopingGiven : 1;
|
||||
unsigned BJTepiChargeGiven : 1;
|
||||
unsigned BJTtlevGiven : 1;
|
||||
unsigned BJTtlevcGiven : 1;
|
||||
unsigned BJTtbf1Given : 1;
|
||||
|
|
@ -568,6 +606,10 @@ typedef struct sBJTmodel { /* model structure for a bjt */
|
|||
unsigned BJTtise2Given : 1;
|
||||
unsigned BJTtisc1Given : 1;
|
||||
unsigned BJTtisc2Given : 1;
|
||||
unsigned BJTquasimodGiven : 1;
|
||||
unsigned BJTenergyGapQSGiven : 1;
|
||||
unsigned BJTtempExpRCIGiven : 1;
|
||||
unsigned BJTtempExpVOGiven : 1;
|
||||
unsigned BJTvbeMaxGiven : 1;
|
||||
unsigned BJTvbcMaxGiven : 1;
|
||||
unsigned BJTvceMaxGiven : 1;
|
||||
|
|
@ -650,6 +692,10 @@ enum {
|
|||
BJT_MOD_KF,
|
||||
BJT_MOD_ISS,
|
||||
BJT_MOD_NS,
|
||||
BJT_MOD_RCO,
|
||||
BJT_MOD_VO,
|
||||
BJT_MOD_GAMMA,
|
||||
BJT_MOD_QCO,
|
||||
BJT_MOD_TNOM,
|
||||
BJT_MOD_TLEV,
|
||||
BJT_MOD_TLEVC,
|
||||
|
|
@ -711,6 +757,10 @@ enum {
|
|||
BJT_MOD_TISE2,
|
||||
BJT_MOD_TISC1,
|
||||
BJT_MOD_TISC2,
|
||||
BJT_MOD_QUASIMOD,
|
||||
BJT_MOD_EGQS,
|
||||
BJT_MOD_XRCI,
|
||||
BJT_MOD_XD,
|
||||
BJT_MOD_VBE_MAX,
|
||||
BJT_MOD_VBC_MAX,
|
||||
BJT_MOD_VCE_MAX,
|
||||
|
|
@ -723,6 +773,7 @@ enum {
|
|||
BJT_QUEST_BASENODE,
|
||||
BJT_QUEST_EMITNODE,
|
||||
BJT_QUEST_SUBSTNODE,
|
||||
BJT_QUEST_COLLCXNODE,
|
||||
BJT_QUEST_COLPRIMENODE,
|
||||
BJT_QUEST_BASEPRIMENODE,
|
||||
BJT_QUEST_EMITPRIMENODE,
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
double czbxf2;
|
||||
double czsub;
|
||||
double delvbc;
|
||||
double delvbcx;
|
||||
double delvbe;
|
||||
double denom;
|
||||
double dqbdvc;
|
||||
|
|
@ -111,6 +112,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
double tf;
|
||||
double tr;
|
||||
double vbc;
|
||||
double vbcx;
|
||||
double vbe;
|
||||
double vbx=0.0;
|
||||
double vce;
|
||||
|
|
@ -137,6 +139,9 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
int error;
|
||||
int SenCond=0;
|
||||
double m;
|
||||
double vrci=0.0, delvrci;
|
||||
double Irci=0.0, Irci_Vrci=0.0, Irci_Vbci=0.0, Irci_Vbcx=0.0;
|
||||
double Qbci=0.0, Qbci_Vbci=0.0, Qbcx, Qbcx_Vbcx=0.0, gbcx, cbcx;
|
||||
|
||||
/* loop through all the models */
|
||||
for( ; model != NULL; model = BJTnextModel(model)) {
|
||||
|
|
@ -159,12 +164,13 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
SenCond = here->BJTsenPertFlag;
|
||||
}
|
||||
|
||||
|
||||
gcsub=0;
|
||||
ceqsub=0;
|
||||
geqbx=0;
|
||||
ceqbx=0;
|
||||
geqcb=0;
|
||||
gbcx=0;
|
||||
cbcx=0;
|
||||
/*
|
||||
* dc model paramters
|
||||
*/
|
||||
|
|
@ -195,6 +201,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
(ckt->CKTmode & MODEINITTRAN)) {
|
||||
vbe = *(ckt->CKTstate1 + here->BJTvbe);
|
||||
vbc = *(ckt->CKTstate1 + here->BJTvbc);
|
||||
vbcx = *(ckt->CKTstate1 + here->BJTvbcx);
|
||||
vrci = *(ckt->CKTstate1 + here->BJTvrci);
|
||||
vbx=model->BJTtype*(
|
||||
*(ckt->CKTrhsOp+here->BJTbaseNode)-
|
||||
*(ckt->CKTrhsOp+here->BJTcolPrimeNode));
|
||||
|
|
@ -205,6 +213,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
else{
|
||||
vbe = *(ckt->CKTstate0 + here->BJTvbe);
|
||||
vbc = *(ckt->CKTstate0 + here->BJTvbc);
|
||||
vbcx = *(ckt->CKTstate0 + here->BJTvbcx);
|
||||
vrci = *(ckt->CKTstate0 + here->BJTvrci);
|
||||
if((ckt->CKTsenInfo->SENmode == DCSEN)||
|
||||
(ckt->CKTsenInfo->SENmode == TRANSEN)){
|
||||
vbx=model->BJTtype*(
|
||||
|
|
@ -233,6 +243,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
if(ckt->CKTmode & MODEINITSMSIG) {
|
||||
vbe= *(ckt->CKTstate0 + here->BJTvbe);
|
||||
vbc= *(ckt->CKTstate0 + here->BJTvbc);
|
||||
vbcx= *(ckt->CKTstate0 + here->BJTvbcx);
|
||||
vrci = *(ckt->CKTstate0 + here->BJTvrci);
|
||||
vbx=model->BJTtype*(
|
||||
*(ckt->CKTrhsOld+here->BJTbaseNode)-
|
||||
*(ckt->CKTrhsOld+here->BJTcolPrimeNode));
|
||||
|
|
@ -242,6 +254,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
} else if(ckt->CKTmode & MODEINITTRAN) {
|
||||
vbe = *(ckt->CKTstate1 + here->BJTvbe);
|
||||
vbc = *(ckt->CKTstate1 + here->BJTvbc);
|
||||
vbcx = *(ckt->CKTstate1 + here->BJTvbcx);
|
||||
vrci = *(ckt->CKTstate1 + here->BJTvrci);
|
||||
vbx=model->BJTtype*(
|
||||
*(ckt->CKTrhsOld+here->BJTbaseNode)-
|
||||
*(ckt->CKTrhsOld+here->BJTcolPrimeNode));
|
||||
|
|
@ -256,20 +270,23 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)){
|
||||
vbe=model->BJTtype*here->BJTicVBE;
|
||||
vce=model->BJTtype*here->BJTicVCE;
|
||||
vbc=vbe-vce;
|
||||
vbc=vbcx=vbe-vce;
|
||||
vbx=vbc;
|
||||
vsub=0;
|
||||
vrci=0.0;
|
||||
} else if((ckt->CKTmode & MODEINITJCT) && (here->BJToff==0)) {
|
||||
vbe=here->BJTtVcrit;
|
||||
vbc=0;
|
||||
vbc=vbcx=0;
|
||||
/* ERROR: need to initialize VSUB, VBX here */
|
||||
vsub=vbx=0;
|
||||
vrci=0.0;
|
||||
} else if((ckt->CKTmode & MODEINITJCT) ||
|
||||
( (ckt->CKTmode & MODEINITFIX) && (here->BJToff!=0))) {
|
||||
vbe=0;
|
||||
vbc=0;
|
||||
vbc=vbcx=0;
|
||||
/* ERROR: need to initialize VSUB, VBX here */
|
||||
vsub=vbx=0;
|
||||
vrci=0.0;
|
||||
} else {
|
||||
#ifndef PREDICTOR
|
||||
if(ckt->CKTmode & MODEINITPRED) {
|
||||
|
|
@ -282,6 +299,14 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
*(ckt->CKTstate1 + here->BJTvbc);
|
||||
vbc = (1+xfact)**(ckt->CKTstate1 + here->BJTvbc)-
|
||||
xfact* *(ckt->CKTstate2 + here->BJTvbc);
|
||||
*(ckt->CKTstate0 + here->BJTvbcx) =
|
||||
*(ckt->CKTstate1 + here->BJTvbcx);
|
||||
vbcx = (1+xfact)**(ckt->CKTstate1 + here->BJTvbcx)-
|
||||
xfact* *(ckt->CKTstate2 + here->BJTvbcx);
|
||||
*(ckt->CKTstate0 + here->BJTvrci) =
|
||||
*(ckt->CKTstate1 + here->BJTvrci);
|
||||
vrci = (1+xfact) * *(ckt->CKTstate1 + here->BJTvrci)-
|
||||
xfact * *(ckt->CKTstate2 + here->BJTvrci);
|
||||
*(ckt->CKTstate0 + here->BJTcc) =
|
||||
*(ckt->CKTstate1 + here->BJTcc);
|
||||
*(ckt->CKTstate0 + here->BJTcb) =
|
||||
|
|
@ -296,10 +321,18 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
*(ckt->CKTstate1 + here->BJTgo);
|
||||
*(ckt->CKTstate0 + here->BJTgx) =
|
||||
*(ckt->CKTstate1 + here->BJTgx);
|
||||
*(ckt->CKTstate0 + here->BJTvsub) =
|
||||
*(ckt->CKTstate0 + here->BJTvsub) =
|
||||
*(ckt->CKTstate1 + here->BJTvsub);
|
||||
vsub = (1+xfact)**(ckt->CKTstate1 + here->BJTvsub)-
|
||||
xfact* *(ckt->CKTstate2 + here->BJTvsub);
|
||||
*(ckt->CKTstate0 + here->BJTirci) =
|
||||
*(ckt->CKTstate1 + here->BJTirci);
|
||||
*(ckt->CKTstate0 + here->BJTirci_Vrci) =
|
||||
*(ckt->CKTstate1 + here->BJTirci_Vrci);
|
||||
*(ckt->CKTstate0 + here->BJTirci_Vbci) =
|
||||
*(ckt->CKTstate1 + here->BJTirci_Vbci);
|
||||
*(ckt->CKTstate0 + here->BJTirci_Vbcx) =
|
||||
*(ckt->CKTstate1 + here->BJTirci_Vbcx);
|
||||
} else {
|
||||
#endif /* PREDICTOR */
|
||||
/*
|
||||
|
|
@ -311,6 +344,12 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
vbc=model->BJTtype*(
|
||||
*(ckt->CKTrhsOld+here->BJTbasePrimeNode)-
|
||||
*(ckt->CKTrhsOld+here->BJTcolPrimeNode));
|
||||
vbcx=model->BJTtype*(
|
||||
*(ckt->CKTrhsOld+here->BJTbasePrimeNode)-
|
||||
*(ckt->CKTrhsOld+here->BJTcollCXNode));
|
||||
vrci=model->BJTtype*(
|
||||
*(ckt->CKTrhsOld+here->BJTcollCXNode)-
|
||||
*(ckt->CKTrhsOld+here->BJTcolPrimeNode));
|
||||
vsub=model->BJTtype*model->BJTsubs*(
|
||||
*(ckt->CKTrhsOld+here->BJTsubstNode)-
|
||||
*(ckt->CKTrhsOld+here->BJTsubstConNode));
|
||||
|
|
@ -319,6 +358,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
#endif /* PREDICTOR */
|
||||
delvbe=vbe- *(ckt->CKTstate0 + here->BJTvbe);
|
||||
delvbc=vbc- *(ckt->CKTstate0 + here->BJTvbc);
|
||||
delvbcx=vbcx- *(ckt->CKTstate0 + here->BJTvbcx);
|
||||
delvrci = vrci - *(ckt->CKTstate0 + here->BJTvrci);
|
||||
vbx=model->BJTtype*(
|
||||
*(ckt->CKTrhsOld+here->BJTbaseNode)-
|
||||
*(ckt->CKTrhsOld+here->BJTcolPrimeNode));
|
||||
|
|
@ -348,6 +389,12 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
if( (fabs(delvbc) < ckt->CKTreltol*MAX(fabs(vbc),
|
||||
fabs(*(ckt->CKTstate0 + here->BJTvbc)))+
|
||||
ckt->CKTvoltTol) )
|
||||
if( (fabs(delvbcx) < ckt->CKTreltol*MAX(fabs(vbcx),
|
||||
fabs(*(ckt->CKTstate0 + here->BJTvbcx)))+
|
||||
ckt->CKTvoltTol) )
|
||||
if( (fabs(delvrci) < ckt->CKTreltol*MAX(fabs(vrci),
|
||||
fabs(*(ckt->CKTstate0 + here->BJTvrci)))+
|
||||
ckt->CKTvoltTol) )
|
||||
if( (fabs(cchat-*(ckt->CKTstate0 + here->BJTcc)) <
|
||||
ckt->CKTreltol* MAX(fabs(cchat),
|
||||
fabs(*(ckt->CKTstate0 + here->BJTcc)))+
|
||||
|
|
@ -361,6 +408,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
*/
|
||||
vbe = *(ckt->CKTstate0 + here->BJTvbe);
|
||||
vbc = *(ckt->CKTstate0 + here->BJTvbc);
|
||||
vbcx = *(ckt->CKTstate0 + here->BJTvbcx);
|
||||
vrci = *(ckt->CKTstate0 + here->BJTvrci);
|
||||
cc = *(ckt->CKTstate0 + here->BJTcc);
|
||||
cb = *(ckt->CKTstate0 + here->BJTcb);
|
||||
gpi = *(ckt->CKTstate0 + here->BJTgpi);
|
||||
|
|
@ -374,6 +423,12 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
vsub = *(ckt->CKTstate0 + here->BJTvsub);
|
||||
gdsub = *(ckt->CKTstate0 + here->BJTgdsub);
|
||||
cdsub = *(ckt->CKTstate0 + here->BJTcdsub);
|
||||
Irci = *(ckt->CKTstate0 + here->BJTirci);
|
||||
Irci_Vrci = *(ckt->CKTstate0 + here->BJTirci_Vrci);
|
||||
Irci_Vbci = *(ckt->CKTstate0 + here->BJTirci_Vbci);
|
||||
Irci_Vbcx = *(ckt->CKTstate0 + here->BJTirci_Vbcx);
|
||||
gbcx = *(ckt->CKTstate0 + here->BJTgbcx);
|
||||
cbcx = *(ckt->CKTstate0 + here->BJTcqbcx);
|
||||
goto load;
|
||||
}
|
||||
#endif /*NOBYPASS*/
|
||||
|
|
@ -389,6 +444,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
vsub = DEVpnjlim(vsub,*(ckt->CKTstate0 + here->BJTvsub),vt,
|
||||
here->BJTtSubVcrit,&ichk1);
|
||||
if (ichk1 == 1) icheck=1;
|
||||
vrci = vbc - vbcx; /* in case vbc was limited */
|
||||
}
|
||||
/*
|
||||
* determine dc current and derivitives
|
||||
|
|
@ -465,6 +521,65 @@ next1: vtn=vt*here->BJTtemissionCoeffF;
|
|||
gdsub = csubsat*evsub/vts + ckt->CKTgmin;
|
||||
cdsub = csubsat*(evsub-1) + ckt->CKTgmin*vsub;
|
||||
}
|
||||
|
||||
/*
|
||||
* Kull's Quasi-Saturation model
|
||||
*/
|
||||
if (model->BJTintCollResistGiven) {
|
||||
double Kbci,Kbci_Vbci,Kbcx,Kbcx_Vbcx;
|
||||
double rKp1,rKp1_Vbci,rKp1_Vbcx,xvar1,xvar1_Vbci,xvar1_Vbcx;
|
||||
double Vcorr,Vcorr_Vbci,Vcorr_Vbcx,Iohm,Iohm_Vrci,Iohm_Vbci,Iohm_Vbcx;
|
||||
double quot,quot_Vrci;
|
||||
if (vrci > 0.) {
|
||||
Kbci = sqrt(1+here->BJTtepiDoping*exp(vbc/vt));
|
||||
Kbci_Vbci = here->BJTtepiDoping*exp(vbc/vt)/(2*vt*Kbci);
|
||||
Kbcx = sqrt(1+here->BJTtepiDoping*exp(vbcx/vt));
|
||||
Kbcx_Vbcx = here->BJTtepiDoping*exp(vbcx/vt)/(2*vt*Kbcx);
|
||||
|
||||
rKp1 = (1+Kbci)/(1+Kbcx);
|
||||
rKp1_Vbci = Kbci_Vbci/(1+Kbci);
|
||||
rKp1_Vbcx = -(1+Kbci)*Kbcx_Vbcx/((Kbcx+1)*(Kbcx+1));
|
||||
xvar1 = log(rKp1);
|
||||
xvar1_Vbci = rKp1_Vbci/rKp1;
|
||||
xvar1_Vbcx = rKp1_Vbcx/rKp1;
|
||||
|
||||
Vcorr = vt*(Kbci - Kbcx - xvar1);
|
||||
Vcorr_Vbci = vt*(Kbci_Vbci - xvar1_Vbci);
|
||||
Vcorr_Vbcx = vt*(-Kbcx_Vbcx - xvar1_Vbcx);
|
||||
|
||||
Iohm = (vrci+Vcorr)/here->BJTtintCollResist;
|
||||
Iohm_Vrci = 1/here->BJTtintCollResist;
|
||||
Iohm_Vbci = Vcorr_Vbci/here->BJTtintCollResist;
|
||||
Iohm_Vbcx = Vcorr_Vbcx/here->BJTtintCollResist;
|
||||
|
||||
quot = 1+fabs(vrci)/here->BJTtepiSatVoltage;
|
||||
quot_Vrci = vrci/(here->BJTtepiSatVoltage*fabs(vrci));
|
||||
|
||||
Irci = Iohm/quot + ckt->CKTgmin*vrci;
|
||||
Irci_Vrci = Iohm_Vrci/quot-Iohm*quot_Vrci/(quot*quot) + ckt->CKTgmin;
|
||||
Irci_Vbci = Iohm_Vbci/quot;
|
||||
Irci_Vbcx = Iohm_Vbcx/quot;
|
||||
|
||||
Qbci = model->BJTepiCharge*Kbci;
|
||||
Qbci_Vbci = model->BJTepiCharge*Kbci_Vbci;
|
||||
Qbcx = model->BJTepiCharge*Kbcx;
|
||||
Qbcx_Vbcx = model->BJTepiCharge*Kbcx_Vbcx;
|
||||
*(ckt->CKTstate0 + here->BJTqbcx) = Qbcx;
|
||||
here->BJTcapbcx = Qbcx_Vbcx;
|
||||
} else {
|
||||
Irci = vrci/here->BJTtintCollResist + ckt->CKTgmin*vrci;
|
||||
Irci_Vrci = 1/here->BJTtintCollResist + ckt->CKTgmin;
|
||||
Irci_Vbci = 0.0;
|
||||
Irci_Vbcx = 0.0;
|
||||
|
||||
Qbci = 0.0;
|
||||
Qbci_Vbci = 0.0;
|
||||
Qbcx = 0.0;
|
||||
Qbcx_Vbcx = 0.0;
|
||||
*(ckt->CKTstate0 + here->BJTqbcx) = Qbcx;
|
||||
here->BJTcapbcx = Qbcx_Vbcx;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* determine base charge terms
|
||||
*/
|
||||
|
|
@ -548,7 +663,7 @@ next1: vtn=vt*here->BJTtemissionCoeffF;
|
|||
cdis=model->BJTbaseFractionBCcap;
|
||||
if (model->BJTsubs == VERTICAL)
|
||||
ctot=here->BJTtBCcap*here->BJTareab;
|
||||
else
|
||||
else
|
||||
ctot=here->BJTtBCcap*here->BJTareac;
|
||||
czbc=ctot*cdis;
|
||||
czbx=ctot-czbc;
|
||||
|
|
@ -641,6 +756,11 @@ next1: vtn=vt*here->BJTtemissionCoeffF;
|
|||
}
|
||||
here->BJTcapbe = capbe;
|
||||
here->BJTcapbc = capbc;
|
||||
if (model->BJTintCollResistGiven) {
|
||||
*(ckt->CKTstate0 + here->BJTqbc) += Qbci;
|
||||
here->BJTcapbc += Qbci_Vbci;
|
||||
capbc += Qbci_Vbci;
|
||||
}
|
||||
here->BJTcapsub = capsub;
|
||||
here->BJTcapbx = capbx;
|
||||
|
||||
|
|
@ -655,6 +775,7 @@ next1: vtn=vt*here->BJTtemissionCoeffF;
|
|||
*(ckt->CKTstate0 + here->BJTcqsub) = capsub;
|
||||
*(ckt->CKTstate0 + here->BJTcqbx) = capbx;
|
||||
*(ckt->CKTstate0 + here->BJTcexbc) = geqcb;
|
||||
*(ckt->CKTstate0 + here->BJTcqbcx) = Qbcx_Vbcx;
|
||||
if(SenCond){
|
||||
*(ckt->CKTstate0 + here->BJTcc) = cc;
|
||||
*(ckt->CKTstate0 + here->BJTcb) = cb;
|
||||
|
|
@ -663,6 +784,9 @@ next1: vtn=vt*here->BJTtemissionCoeffF;
|
|||
*(ckt->CKTstate0 + here->BJTgm) = gm;
|
||||
*(ckt->CKTstate0 + here->BJTgo) = go;
|
||||
*(ckt->CKTstate0 + here->BJTgx) = gx;
|
||||
*(ckt->CKTstate0 + here->BJTirci_Vrci) = Irci_Vrci;
|
||||
*(ckt->CKTstate0 + here->BJTirci_Vbci) = Irci_Vbci;
|
||||
*(ckt->CKTstate0 + here->BJTirci_Vbcx) = Irci_Vbcx;
|
||||
*(ckt->CKTstate0 + here->BJTgcsub) = gcsub;
|
||||
*(ckt->CKTstate0 + here->BJTgeqbx) = geqbx;
|
||||
}
|
||||
|
|
@ -697,6 +821,8 @@ next1: vtn=vt*here->BJTtemissionCoeffF;
|
|||
*(ckt->CKTstate0 + here->BJTqbx) ;
|
||||
*(ckt->CKTstate1 + here->BJTqsub) =
|
||||
*(ckt->CKTstate0 + here->BJTqsub) ;
|
||||
*(ckt->CKTstate1 + here->BJTqbcx) =
|
||||
*(ckt->CKTstate0 + here->BJTqbcx) ;
|
||||
}
|
||||
error = NIintegrate(ckt,&geq,&ceq,capbe,here->BJTqbe);
|
||||
if(error) return(error);
|
||||
|
|
@ -708,11 +834,19 @@ next1: vtn=vt*here->BJTtemissionCoeffF;
|
|||
gmu=gmu+geq;
|
||||
cb=cb+*(ckt->CKTstate0 + here->BJTcqbc);
|
||||
cc=cc-*(ckt->CKTstate0 + here->BJTcqbc);
|
||||
if (model->BJTintCollResistGiven) {
|
||||
error = NIintegrate(ckt,&geq,&ceq,Qbcx_Vbcx,here->BJTqbcx);
|
||||
if(error) return(error);
|
||||
gbcx = geq;
|
||||
cbcx = *(ckt->CKTstate0 + here->BJTcqbcx);
|
||||
}
|
||||
if(ckt->CKTmode & MODEINITTRAN) {
|
||||
*(ckt->CKTstate1 + here->BJTcqbe) =
|
||||
*(ckt->CKTstate0 + here->BJTcqbe);
|
||||
*(ckt->CKTstate1 + here->BJTcqbc) =
|
||||
*(ckt->CKTstate0 + here->BJTcqbc);
|
||||
*(ckt->CKTstate1 + here->BJTcqbcx) =
|
||||
*(ckt->CKTstate0 + here->BJTcqbcx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -747,6 +881,8 @@ next1: vtn=vt*here->BJTtemissionCoeffF;
|
|||
next2:
|
||||
*(ckt->CKTstate0 + here->BJTvbe) = vbe;
|
||||
*(ckt->CKTstate0 + here->BJTvbc) = vbc;
|
||||
*(ckt->CKTstate0 + here->BJTvbcx) = vbcx;
|
||||
*(ckt->CKTstate0 + here->BJTvrci) = vrci;
|
||||
*(ckt->CKTstate0 + here->BJTcc) = cc;
|
||||
*(ckt->CKTstate0 + here->BJTcb) = cb;
|
||||
*(ckt->CKTstate0 + here->BJTgpi) = gpi;
|
||||
|
|
@ -760,6 +896,10 @@ next2:
|
|||
*(ckt->CKTstate0 + here->BJTvsub) = vsub;
|
||||
*(ckt->CKTstate0 + here->BJTgdsub) = gdsub;
|
||||
*(ckt->CKTstate0 + here->BJTcdsub) = cdsub;
|
||||
*(ckt->CKTstate0 + here->BJTirci) = Irci;
|
||||
*(ckt->CKTstate0 + here->BJTirci_Vrci) = Irci_Vrci;
|
||||
*(ckt->CKTstate0 + here->BJTirci_Vbci) = Irci_Vbci;
|
||||
*(ckt->CKTstate0 + here->BJTirci_Vbcx) = Irci_Vbcx;
|
||||
|
||||
/* Do not load the Jacobian and the rhs if
|
||||
perturbation is being carried out */
|
||||
|
|
@ -795,14 +935,15 @@ load:
|
|||
*(here->BJTcolColPtr) += m * (gcpr);
|
||||
*(here->BJTbaseBasePtr) += m * (gx+geqbx);
|
||||
*(here->BJTemitEmitPtr) += m * (gepr);
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * (gmu+go+gcpr+geqbx);
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * (gmu+go+geqbx);
|
||||
*(here->BJTcollCXcollCXPtr) += m * (gcpr);
|
||||
*(here->BJTsubstConSubstConPtr) += m * (geqsub);
|
||||
*(here->BJTbasePrimeBasePrimePtr) += m * (gx +gpi+gmu+geqcb);
|
||||
*(here->BJTemitPrimeEmitPrimePtr) += m * (gpi+gepr+gm+go);
|
||||
*(here->BJTcolColPrimePtr) += m * (-gcpr);
|
||||
*(here->BJTcollCollCXPtr) += m * (-gcpr);
|
||||
*(here->BJTbaseBasePrimePtr) += m * (-gx);
|
||||
*(here->BJTemitEmitPrimePtr) += m * (-gepr);
|
||||
*(here->BJTcolPrimeColPtr) += m * (-gcpr);
|
||||
*(here->BJTcollCXCollPtr) += m * (-gcpr);
|
||||
*(here->BJTcolPrimeBasePrimePtr) += m * (-gmu+gm);
|
||||
*(here->BJTcolPrimeEmitPrimePtr) += m * (-gm-go);
|
||||
*(here->BJTbasePrimeBasePtr) += m * (-gx);
|
||||
|
|
@ -816,6 +957,34 @@ load:
|
|||
*(here->BJTsubstSubstConPtr) += m * (-geqsub);
|
||||
*(here->BJTbaseColPrimePtr) += m * (-geqbx);
|
||||
*(here->BJTcolPrimeBasePtr) += m * (-geqbx);
|
||||
/*
|
||||
c Stamp element: Irci
|
||||
*/
|
||||
if (model->BJTintCollResistGiven) {
|
||||
double rhs_current = model->BJTtype * m * (Irci - Irci_Vrci*vrci - Irci_Vbci*vbc - Irci_Vbcx*vbcx);
|
||||
*(ckt->CKTrhs + here->BJTcollCXNode) += -rhs_current;
|
||||
*(here->BJTcollCXcollCXPtr) += m * Irci_Vrci;
|
||||
*(here->BJTcollCXColPrimePtr) += m * -Irci_Vrci;
|
||||
*(here->BJTcollCXBasePrimePtr) += m * Irci_Vbci;
|
||||
*(here->BJTcollCXColPrimePtr) += m * -Irci_Vbci;
|
||||
*(here->BJTcollCXBasePrimePtr) += m * Irci_Vbcx;
|
||||
*(here->BJTcollCXcollCXPtr) += m * -Irci_Vbcx;
|
||||
*(ckt->CKTrhs + here->BJTcolPrimeNode) += rhs_current;
|
||||
*(here->BJTcolPrimeCollCXPtr) += m * -Irci_Vrci;
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * Irci_Vrci;
|
||||
*(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbci;
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * Irci_Vbci;
|
||||
*(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbcx;
|
||||
*(here->BJTcolPrimeCollCXPtr) += m * Irci_Vbcx;
|
||||
|
||||
*(ckt->CKTrhs + here->BJTbasePrimeNode) += m * -cbcx;
|
||||
*(ckt->CKTrhs + here->BJTcollCXNode) += m * cbcx;
|
||||
*(here->BJTbasePrimeBasePrimePtr) += m * gbcx;
|
||||
*(here->BJTcollCXcollCXPtr) += m * gbcx;
|
||||
*(here->BJTbasePrimeCollCXPtr) += m * -gbcx;
|
||||
*(here->BJTcollCXBasePrimePtr) += m * -gbcx;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -201,6 +201,18 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value)
|
|||
case BJT_MOD_NS:
|
||||
value->rValue = here->BJTemissionCoeffS;
|
||||
return(OK);
|
||||
case BJT_MOD_RCO:
|
||||
value->rValue = here->BJTintCollResist;
|
||||
return(OK);
|
||||
case BJT_MOD_VO:
|
||||
value->rValue = here->BJTepiSatVoltage;
|
||||
return(OK);
|
||||
case BJT_MOD_GAMMA:
|
||||
value->rValue = here->BJTepiDoping;
|
||||
return(OK);
|
||||
case BJT_MOD_QCO:
|
||||
value->rValue = here->BJTepiCharge;
|
||||
return(OK);
|
||||
case BJT_MOD_TLEV:
|
||||
value->iValue = here->BJTtlev;
|
||||
return(OK);
|
||||
|
|
@ -378,6 +390,18 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value)
|
|||
case BJT_MOD_TISC2:
|
||||
value->rValue = here->BJTtisc2;
|
||||
return(OK);
|
||||
case BJT_MOD_QUASIMOD:
|
||||
value->iValue = here->BJTquasimod;
|
||||
return(OK);
|
||||
case BJT_MOD_EGQS:
|
||||
value->rValue = here->BJTenergyGapQS;
|
||||
return(OK);
|
||||
case BJT_MOD_XRCI:
|
||||
value->rValue = here->BJTtempExpRCI;
|
||||
return(OK);
|
||||
case BJT_MOD_XD:
|
||||
value->rValue = here->BJTtempExpVO;
|
||||
return(OK);
|
||||
case BJT_MOD_VBE_MAX:
|
||||
value->rValue = here->BJTvbeMax;
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -218,6 +218,22 @@ BJTmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
mods->BJTemissionCoeffS = value->rValue;
|
||||
mods->BJTemissionCoeffSGiven = TRUE;
|
||||
break;
|
||||
case BJT_MOD_RCO:
|
||||
mods->BJTintCollResist = value->rValue;
|
||||
mods->BJTintCollResistGiven = TRUE;
|
||||
break;
|
||||
case BJT_MOD_VO:
|
||||
mods->BJTepiSatVoltage = value->rValue;
|
||||
mods->BJTepiSatVoltageGiven = TRUE;
|
||||
break;
|
||||
case BJT_MOD_GAMMA:
|
||||
mods->BJTepiDoping = value->rValue;
|
||||
mods->BJTepiDopingGiven = TRUE;
|
||||
break;
|
||||
case BJT_MOD_QCO:
|
||||
mods->BJTepiCharge = value->rValue;
|
||||
mods->BJTepiChargeGiven = TRUE;
|
||||
break;
|
||||
case BJT_MOD_TLEV:
|
||||
mods->BJTtlev = value->iValue;
|
||||
mods->BJTtlevGiven = TRUE;
|
||||
|
|
@ -454,6 +470,22 @@ BJTmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
mods->BJTtisc2 = value->rValue;
|
||||
mods->BJTtisc2Given = TRUE;
|
||||
break;
|
||||
case BJT_MOD_QUASIMOD:
|
||||
mods->BJTquasimod = value->iValue;
|
||||
mods->BJTquasimodGiven = TRUE;
|
||||
break;
|
||||
case BJT_MOD_EGQS:
|
||||
mods->BJTenergyGapQS = value->rValue;
|
||||
mods->BJTenergyGapQSGiven = TRUE;
|
||||
break;
|
||||
case BJT_MOD_XRCI:
|
||||
mods->BJTtempExpRCI = value->rValue;
|
||||
mods->BJTtempExpRCIGiven = TRUE;
|
||||
break;
|
||||
case BJT_MOD_XD:
|
||||
mods->BJTtempExpVO = value->rValue;
|
||||
mods->BJTtempExpVOGiven = TRUE;
|
||||
break;
|
||||
case BJT_MOD_VBE_MAX:
|
||||
mods->BJTvbeMax = value->rValue;
|
||||
mods->BJTvbeMaxGiven = TRUE;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ for (model=firstModel; model != NULL; model=BJTnextModel(model)) {
|
|||
|
||||
case N_DENS:
|
||||
NevalSrc(&noizDens[BJTRCNOIZ],&lnNdens[BJTRCNOIZ],
|
||||
ckt,THERMNOISE,inst->BJTcolPrimeNode,inst->BJTcolNode,
|
||||
ckt,THERMNOISE,inst->BJTcollCXNode,inst->BJTcolNode,
|
||||
inst->BJTtcollectorConduct * inst->BJTarea * inst->BJTm);
|
||||
|
||||
NevalSrc(&noizDens[BJTRBNOIZ],&lnNdens[BJTRBNOIZ],
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ BJTpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
|
|||
double xcsub;
|
||||
double xcmcb;
|
||||
double m;
|
||||
double Irci_Vrci, Irci_Vbci, Irci_Vbcx, xcbcx;
|
||||
|
||||
for( ; model != NULL; model = BJTnextModel(model)) {
|
||||
for( here = BJTinstances(model); here!= NULL;
|
||||
|
|
@ -45,6 +46,9 @@ BJTpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
|
|||
gmu= *(ckt->CKTstate0 + here->BJTgmu);
|
||||
gm= *(ckt->CKTstate0 + here->BJTgm);
|
||||
go= *(ckt->CKTstate0 + here->BJTgo);
|
||||
Irci_Vrci = *(ckt->CKTstate0 + here->BJTirci_Vrci);
|
||||
Irci_Vbci = *(ckt->CKTstate0 + here->BJTirci_Vbci);
|
||||
Irci_Vbcx = *(ckt->CKTstate0 + here->BJTirci_Vbcx);
|
||||
xgm=0;
|
||||
gx= *(ckt->CKTstate0 + here->BJTgx);
|
||||
xcpi= *(ckt->CKTstate0 + here->BJTcqbe);
|
||||
|
|
@ -52,13 +56,15 @@ BJTpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
|
|||
xcbx= *(ckt->CKTstate0 + here->BJTcqbx);
|
||||
xcsub= *(ckt->CKTstate0 + here->BJTcqsub);
|
||||
xcmcb= *(ckt->CKTstate0 + here->BJTcexbc);
|
||||
xcbcx= *(ckt->CKTstate0 + here->BJTcqbcx);
|
||||
|
||||
*(here->BJTcolColPtr) += m * (gcpr);
|
||||
*(here->BJTbaseBasePtr) += m * ((gx) + (xcbx) * (s->real));
|
||||
*(here->BJTbaseBasePtr + 1) += m * ((xcbx) * (s->imag));
|
||||
*(here->BJTemitEmitPtr) += m * (gepr);
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * ((gmu+go+gcpr) + (xcmu+xcbx) * (s->real));
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * ((gmu+go) + (xcmu+xcbx) * (s->real));
|
||||
*(here->BJTcolPrimeColPrimePtr + 1) += m * ((xcmu+xcbx) * (s->imag));
|
||||
*(here->BJTcollCXcollCXPtr) += m * (gcpr);
|
||||
|
||||
*(here->BJTsubstConSubstConPtr) += m * (xcsub)* (s->real);
|
||||
*(here->BJTsubstConSubstConPtr + 1) += m * (xcsub)* (s->imag);
|
||||
|
|
@ -67,10 +73,10 @@ BJTpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
|
|||
*(here->BJTbasePrimeBasePrimePtr + 1) += m * ((xcpi+xcmu+xcmcb) * (s->imag));
|
||||
*(here->BJTemitPrimeEmitPrimePtr) += m * ((gpi+gepr+gm+go) + (xcpi+xgm) * (s->real));
|
||||
*(here->BJTemitPrimeEmitPrimePtr + 1) += m * ((xcpi+xgm) * (s->imag));
|
||||
*(here->BJTcolColPrimePtr) += m * (-gcpr);
|
||||
*(here->BJTcollCollCXPtr) += m * (-gcpr);
|
||||
*(here->BJTbaseBasePrimePtr) += m * (-gx);
|
||||
*(here->BJTemitEmitPrimePtr) += m * (-gepr);
|
||||
*(here->BJTcolPrimeColPtr) += m * (-gcpr);
|
||||
*(here->BJTcollCXCollPtr) += m * (-gcpr);
|
||||
*(here->BJTcolPrimeBasePrimePtr) += m * ((-gmu+gm) + (-xcmu+xgm) * (s->real));
|
||||
*(here->BJTcolPrimeBasePrimePtr + 1) += m * ((-xcmu+xgm) * (s->imag));
|
||||
*(here->BJTcolPrimeEmitPrimePtr) += m * ((-gm-go) + (-xgm) * (s->real));
|
||||
|
|
@ -95,6 +101,28 @@ BJTpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
|
|||
*(here->BJTbaseColPrimePtr + 1) += m * ((-xcbx) * (s->imag));
|
||||
*(here->BJTcolPrimeBasePtr) += m * ((-xcbx) * (s->real));
|
||||
*(here->BJTcolPrimeBasePtr + 1) += m * ((-xcbx) * (s->imag));
|
||||
if (model->BJTintCollResistGiven) {
|
||||
*(here->BJTcollCXcollCXPtr) += m * Irci_Vrci;
|
||||
*(here->BJTcollCXColPrimePtr) += m * -Irci_Vrci;
|
||||
*(here->BJTcollCXBasePrimePtr) += m * Irci_Vbci;
|
||||
*(here->BJTcollCXColPrimePtr) += m * -Irci_Vbci;
|
||||
*(here->BJTcollCXBasePrimePtr) += m * Irci_Vbcx;
|
||||
*(here->BJTcollCXcollCXPtr) += m * -Irci_Vbcx;
|
||||
*(here->BJTcolPrimeCollCXPtr) += m * -Irci_Vrci;
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * Irci_Vrci;
|
||||
*(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbci;
|
||||
*(here->BJTcolPrimeColPrimePtr) += m * Irci_Vbci;
|
||||
*(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbcx;
|
||||
*(here->BJTcolPrimeCollCXPtr) += m * Irci_Vbcx;
|
||||
*(here->BJTbasePrimeBasePrimePtr) += m * xcbcx * (s->real);
|
||||
*(here->BJTbasePrimeBasePrimePtr + 1) += m * xcbcx * (s->imag);
|
||||
*(here->BJTcollCXcollCXPtr) += m * xcbcx * (s->real);
|
||||
*(here->BJTcollCXcollCXPtr + 1) += m * xcbcx * (s->imag);
|
||||
*(here->BJTbasePrimeCollCXPtr) += m * -xcbcx * (s->real);
|
||||
*(here->BJTbasePrimeCollCXPtr + 1) += m * -xcbcx * (s->imag);
|
||||
*(here->BJTcollCXBasePrimePtr) += m * -xcbcx * (s->real);
|
||||
*(here->BJTcollCXBasePrimePtr + 1) += m * -xcbcx * (s->imag);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -140,6 +140,19 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
if(!model->BJTemissionCoeffSGiven) {
|
||||
model->BJTemissionCoeffS = 1.0;
|
||||
}
|
||||
if((!model->BJTintCollResistGiven)
|
||||
||(model->BJTintCollResist<0.01)) {
|
||||
model->BJTintCollResist = 0.01;
|
||||
}
|
||||
if(!model->BJTepiSatVoltageGiven) {
|
||||
model->BJTepiSatVoltage = 10.0;
|
||||
}
|
||||
if(!model->BJTepiDopingGiven) {
|
||||
model->BJTepiDoping = 1.0e-11;
|
||||
}
|
||||
if(!model->BJTepiChargeGiven) {
|
||||
model->BJTepiCharge = 0.0;
|
||||
}
|
||||
if(!model->BJTtlevGiven) {
|
||||
model->BJTtlev = 0;
|
||||
}
|
||||
|
|
@ -322,6 +335,24 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
if(!model->BJTtisc2Given) {
|
||||
model->BJTtisc2 = 0.0;
|
||||
}
|
||||
if(!model->BJTquasimodGiven) {
|
||||
model->BJTquasimod = 0;
|
||||
}
|
||||
if(!model->BJTenergyGapQSGiven) {
|
||||
model->BJTenergyGapQS = 1.206;
|
||||
}
|
||||
if(!model->BJTtempExpRCIGiven) {
|
||||
if (model->BJTtype == NPN)
|
||||
model->BJTtempExpRCI = 2.42;
|
||||
else
|
||||
model->BJTtempExpRCI = 2.2;
|
||||
}
|
||||
if(!model->BJTtempExpVOGiven) {
|
||||
if (model->BJTtype == NPN)
|
||||
model->BJTtempExpVO = 0.87;
|
||||
else
|
||||
model->BJTtempExpVO = 0.52;
|
||||
}
|
||||
if(!model->BJTvbeMaxGiven) {
|
||||
model->BJTvbeMax = 1e99;
|
||||
}
|
||||
|
|
@ -370,7 +401,15 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
}
|
||||
|
||||
if(model->BJTcollectorResist == 0) {
|
||||
here->BJTcolPrimeNode = here->BJTcolNode;
|
||||
here->BJTcollCXNode = here->BJTcolNode;
|
||||
} else if(here->BJTcollCXNode == 0) {
|
||||
error = CKTmkVolt(ckt, &tmp, here->BJTname, "collCX");
|
||||
if(error) return(error);
|
||||
here->BJTcollCXNode = tmp->number;
|
||||
}
|
||||
|
||||
if(!model->BJTintCollResistGiven) {
|
||||
here->BJTcolPrimeNode = here->BJTcollCXNode;
|
||||
} else if(here->BJTcolPrimeNode == 0) {
|
||||
error = CKTmkVolt(ckt,&tmp,here->BJTname,"collector");
|
||||
if(error) return(error);
|
||||
|
|
@ -432,10 +471,11 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
||||
return(E_NOMEM);\
|
||||
} } while(0)
|
||||
TSTALLOC(BJTcolColPrimePtr,BJTcolNode,BJTcolPrimeNode);
|
||||
|
||||
TSTALLOC(BJTcollCollCXPtr,BJTcolNode,BJTcollCXNode);
|
||||
TSTALLOC(BJTbaseBasePrimePtr,BJTbaseNode,BJTbasePrimeNode);
|
||||
TSTALLOC(BJTemitEmitPrimePtr,BJTemitNode,BJTemitPrimeNode);
|
||||
TSTALLOC(BJTcolPrimeColPtr,BJTcolPrimeNode,BJTcolNode);
|
||||
TSTALLOC(BJTcollCXCollPtr,BJTcollCXNode,BJTcolNode);
|
||||
TSTALLOC(BJTcolPrimeBasePrimePtr,BJTcolPrimeNode,BJTbasePrimeNode);
|
||||
TSTALLOC(BJTcolPrimeEmitPrimePtr,BJTcolPrimeNode,BJTemitPrimeNode);
|
||||
TSTALLOC(BJTbasePrimeBasePtr,BJTbasePrimeNode,BJTbaseNode);
|
||||
|
|
@ -462,6 +502,15 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
|||
TSTALLOC(BJTsubstSubstConPtr,BJTsubstNode,BJTsubstConNode);
|
||||
TSTALLOC(BJTbaseColPrimePtr,BJTbaseNode,BJTcolPrimeNode);
|
||||
TSTALLOC(BJTcolPrimeBasePtr,BJTcolPrimeNode,BJTbaseNode);
|
||||
|
||||
TSTALLOC(BJTcollCXcollCXPtr,BJTcollCXNode,BJTcollCXNode);
|
||||
|
||||
if(model->BJTintCollResistGiven) {
|
||||
TSTALLOC(BJTcollCXBasePrimePtr,BJTcollCXNode,BJTbasePrimeNode);
|
||||
TSTALLOC(BJTbasePrimeCollCXPtr,BJTbasePrimeNode,BJTcollCXNode);
|
||||
TSTALLOC(BJTcolPrimeCollCXPtr,BJTcolPrimeNode,BJTcollCXNode);
|
||||
TSTALLOC(BJTcollCXColPrimePtr,BJTcollCXNode,BJTcolPrimeNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
@ -481,20 +530,25 @@ BJTunsetup(
|
|||
for (here = BJTinstances(model); here != NULL;
|
||||
here=BJTnextInstance(here))
|
||||
{
|
||||
if (here->BJTemitPrimeNode > 0
|
||||
&& here->BJTemitPrimeNode != here->BJTemitNode)
|
||||
CKTdltNNum(ckt, here->BJTemitPrimeNode);
|
||||
here->BJTemitPrimeNode = 0;
|
||||
if (here->BJTemitPrimeNode > 0
|
||||
&& here->BJTemitPrimeNode != here->BJTemitNode)
|
||||
CKTdltNNum(ckt, here->BJTemitPrimeNode);
|
||||
here->BJTemitPrimeNode = 0;
|
||||
|
||||
if (here->BJTbasePrimeNode > 0
|
||||
&& here->BJTbasePrimeNode != here->BJTbaseNode)
|
||||
CKTdltNNum(ckt, here->BJTbasePrimeNode);
|
||||
here->BJTbasePrimeNode = 0;
|
||||
if (here->BJTbasePrimeNode > 0
|
||||
&& here->BJTbasePrimeNode != here->BJTbaseNode)
|
||||
CKTdltNNum(ckt, here->BJTbasePrimeNode);
|
||||
here->BJTbasePrimeNode = 0;
|
||||
|
||||
if (here->BJTcolPrimeNode > 0
|
||||
&& here->BJTcolPrimeNode != here->BJTcolNode)
|
||||
if (here->BJTcollCXNode > 0
|
||||
&& here->BJTcollCXNode != here->BJTcolNode)
|
||||
CKTdltNNum(ckt, here->BJTcollCXNode);
|
||||
here->BJTcollCXNode = 0;
|
||||
|
||||
if (here->BJTcolPrimeNode > 0
|
||||
&& here->BJTcolPrimeNode != here->BJTcollCXNode)
|
||||
CKTdltNNum(ckt, here->BJTcolPrimeNode);
|
||||
here->BJTcolPrimeNode = 0;
|
||||
here->BJTcolPrimeNode = 0;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
|
|
|
|||
|
|
@ -177,6 +177,22 @@ BJTtemp(GENmodel *inModel, CKTcircuit *ckt)
|
|||
here->BJTtSatCur = pow(model->BJTsatCur,(1+model->BJTtis1*dt+model->BJTtis2*dt*dt));
|
||||
}
|
||||
|
||||
if (model->BJTintCollResistGiven) {
|
||||
if (model->BJTquasimod == 1) {
|
||||
double rT=here->BJTtemp/model->BJTtnom;
|
||||
here->BJTtintCollResist=model->BJTintCollResist*pow(rT,model->BJTtempExpRCI);
|
||||
here->BJTtepiSatVoltage=model->BJTepiSatVoltage*pow(rT,model->BJTtempExpVO);
|
||||
double xvar1=pow(rT,model->BJTtempExpIS);
|
||||
double xvar2=-model->BJTenergyGapQS*(1.0-rT)/vt;
|
||||
double xvar3=exp(xvar2);
|
||||
here->BJTtepiDoping=model->BJTepiDoping*xvar1*xvar3;
|
||||
} else {
|
||||
here->BJTtintCollResist=model->BJTintCollResist;
|
||||
here->BJTtepiSatVoltage=model->BJTepiSatVoltage;
|
||||
here->BJTtepiDoping=model->BJTepiDoping;
|
||||
}
|
||||
}
|
||||
|
||||
if (model->BJTtlev == 0) {
|
||||
bfactor = exp(ratlog*model->BJTbetaExp);
|
||||
} else if (model->BJTtlev == 1) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ BJTtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep)
|
|||
CKTterr(here->BJTqbe,ckt,timeStep);
|
||||
CKTterr(here->BJTqbc,ckt,timeStep);
|
||||
CKTterr(here->BJTqsub,ckt,timeStep);
|
||||
if (model->BJTintCollResistGiven) {
|
||||
CKTterr(here->BJTqbcx,ckt,timeStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -150,6 +150,36 @@ DEVfetlim(double vnew, double vold, double vto)
|
|||
return(vnew);
|
||||
}
|
||||
|
||||
/* DEVlimitlog(deltemp, deltemp_old, LIM_TOL, check)
|
||||
* Logarithmic damping the per-iteration change of deltemp beyond LIM_TOL.
|
||||
*/
|
||||
double
|
||||
DEVlimitlog(
|
||||
double deltemp,
|
||||
double deltemp_old,
|
||||
double LIM_TOL,
|
||||
int *check)
|
||||
{
|
||||
*check = 0;
|
||||
if (isnan (deltemp) || isnan (deltemp_old))
|
||||
{
|
||||
fprintf(stderr, "Alberto says: YOU TURKEY! The limiting function received NaN.\n");
|
||||
fprintf(stderr, "New prediction returns to 0.0!\n");
|
||||
deltemp = 0.0;
|
||||
*check = 1;
|
||||
}
|
||||
/* Logarithmic damping of deltemp beyond LIM_TOL */
|
||||
if (deltemp > deltemp_old + LIM_TOL) {
|
||||
deltemp = deltemp_old + LIM_TOL + log10((deltemp-deltemp_old)/LIM_TOL);
|
||||
*check = 1;
|
||||
}
|
||||
else if (deltemp < deltemp_old - LIM_TOL) {
|
||||
deltemp = deltemp_old - LIM_TOL - log10((deltemp_old-deltemp)/LIM_TOL);
|
||||
*check = 1;
|
||||
}
|
||||
return deltemp;
|
||||
}
|
||||
|
||||
int
|
||||
ACM_SourceDrainResistances(
|
||||
int ACM,
|
||||
|
|
|
|||
|
|
@ -97,14 +97,14 @@ c Stamp element: Itzf
|
|||
/*
|
||||
c Stamp element: Itzr
|
||||
*/
|
||||
*(here->VBICemitEIBaseBIPtr) += Itzr_Vbci;
|
||||
*(here->VBICemitEICollCIPtr) += -Itzr_Vbci;
|
||||
*(here->VBICemitEIBaseBIPtr) += Itzr_Vbei;
|
||||
*(here->VBICemitEIEmitEIPtr) += -Itzr_Vbei;
|
||||
*(here->VBICcollCIBaseBIPtr) += -Itzr_Vbci;
|
||||
*(here->VBICcollCICollCIPtr) += Itzr_Vbci;
|
||||
*(here->VBICemitEIBaseBIPtr) += Itzr_Vbci;
|
||||
*(here->VBICemitEICollCIPtr) += -Itzr_Vbci;
|
||||
*(here->VBICcollCIBaseBIPtr) += -Itzr_Vbei;
|
||||
*(here->VBICcollCIEmitEIPtr) += Itzr_Vbei;
|
||||
*(here->VBICcollCIBaseBIPtr) += -Itzr_Vbci;
|
||||
*(here->VBICcollCICollCIPtr) += Itzr_Vbci;
|
||||
/*
|
||||
c Stamp element: Ibc
|
||||
*/
|
||||
|
|
@ -124,12 +124,12 @@ c Stamp element: Ibep
|
|||
*(here->VBICbaseBPBaseBXPtr) += -Ibep_Vbep;
|
||||
*(here->VBICbaseBPBaseBPPtr) += Ibep_Vbep;
|
||||
/*
|
||||
c Stamp element: Ircx
|
||||
c Stamp element: Rcx
|
||||
*/
|
||||
*(here->VBICcollCollPtr) += Ircx_Vrcx;
|
||||
*(here->VBICcollCollPtr) += Ircx_Vrcx;
|
||||
*(here->VBICcollCXCollCXPtr) += Ircx_Vrcx;
|
||||
*(here->VBICcollCXCollPtr) += -Ircx_Vrcx;
|
||||
*(here->VBICcollCollCXPtr) += -Ircx_Vrcx;
|
||||
*(here->VBICcollCXCollPtr) += -Ircx_Vrcx;
|
||||
*(here->VBICcollCollCXPtr) += -Ircx_Vrcx;
|
||||
/*
|
||||
c Stamp element: Irci
|
||||
*/
|
||||
|
|
@ -146,12 +146,12 @@ c Stamp element: Irci
|
|||
*(here->VBICcollCIBaseBIPtr) += -Irci_Vbcx;
|
||||
*(here->VBICcollCICollCXPtr) += Irci_Vbcx;
|
||||
/*
|
||||
c Stamp element: Irbx
|
||||
c Stamp element: Rbx
|
||||
*/
|
||||
*(here->VBICbaseBasePtr) += Irbx_Vrbx;
|
||||
*(here->VBICbaseBasePtr) += Irbx_Vrbx;
|
||||
*(here->VBICbaseBXBaseBXPtr) += Irbx_Vrbx;
|
||||
*(here->VBICbaseBXBasePtr) += -Irbx_Vrbx;
|
||||
*(here->VBICbaseBaseBXPtr) += -Irbx_Vrbx;
|
||||
*(here->VBICbaseBXBasePtr) += -Irbx_Vrbx;
|
||||
*(here->VBICbaseBaseBXPtr) += -Irbx_Vrbx;
|
||||
/*
|
||||
c Stamp element: Irbi
|
||||
*/
|
||||
|
|
@ -168,12 +168,12 @@ c Stamp element: Irbi
|
|||
*(here->VBICbaseBIBaseBIPtr) += -Irbi_Vbci;
|
||||
*(here->VBICbaseBICollCIPtr) += Irbi_Vbci;
|
||||
/*
|
||||
c Stamp element: Ire
|
||||
c Stamp element: Re
|
||||
*/
|
||||
*(here->VBICemitEmitPtr) += Ire_Vre;
|
||||
*(here->VBICemitEmitPtr) += Ire_Vre;
|
||||
*(here->VBICemitEIEmitEIPtr) += Ire_Vre;
|
||||
*(here->VBICemitEIEmitPtr) += -Ire_Vre;
|
||||
*(here->VBICemitEmitEIPtr) += -Ire_Vre;
|
||||
*(here->VBICemitEIEmitPtr) += -Ire_Vre;
|
||||
*(here->VBICemitEmitEIPtr) += -Ire_Vre;
|
||||
/*
|
||||
c Stamp element: Irbp
|
||||
*/
|
||||
|
|
@ -212,12 +212,12 @@ c Stamp element: Iccp
|
|||
*(here->VBICsubsSISubsSIPtr) += -Iccp_Vbcp;
|
||||
*(here->VBICsubsSIBaseBPPtr) += Iccp_Vbcp;
|
||||
/*
|
||||
c Stamp element: Irs
|
||||
c Stamp element: Rs
|
||||
*/
|
||||
*(here->VBICsubsSubsPtr) += Irs_Vrs;
|
||||
*(here->VBICsubsSubsPtr) += Irs_Vrs;
|
||||
*(here->VBICsubsSISubsSIPtr) += Irs_Vrs;
|
||||
*(here->VBICsubsSISubsPtr) += -Irs_Vrs;
|
||||
*(here->VBICsubsSubsSIPtr) += -Irs_Vrs;
|
||||
*(here->VBICsubsSISubsPtr) += -Irs_Vrs;
|
||||
*(here->VBICsubsSubsSIPtr) += -Irs_Vrs;
|
||||
/*
|
||||
c The complex part
|
||||
*/
|
||||
|
|
@ -230,50 +230,50 @@ c The complex part
|
|||
XQbep_Vbci = *(ckt->CKTstate0 + here->VBICcqbepci) * ckt->CKTomega;
|
||||
XQbcp_Vbcp = *(ckt->CKTstate0 + here->VBICcqbcp) * ckt->CKTomega;
|
||||
/*
|
||||
c Stamp element: Qbe
|
||||
c Stamp element: Qbe
|
||||
*/
|
||||
*(here->VBICbaseBIBaseBIPtr + 1) += XQbe_Vbei;
|
||||
*(here->VBICbaseBIEmitEIPtr + 1) += -XQbe_Vbei;
|
||||
*(here->VBICbaseBIBaseBIPtr + 1) += XQbe_Vbci;
|
||||
*(here->VBICbaseBICollCIPtr + 1) += -XQbe_Vbci;
|
||||
*(here->VBICemitEIBaseBIPtr + 1) += -XQbe_Vbei;
|
||||
*(here->VBICemitEIEmitEIPtr + 1) += XQbe_Vbei;
|
||||
*(here->VBICemitEIBaseBIPtr + 1) += -XQbe_Vbci;
|
||||
*(here->VBICemitEICollCIPtr + 1) += XQbe_Vbci;
|
||||
*(here->VBICbaseBIBaseBIPtr + 1) += XQbe_Vbei;
|
||||
*(here->VBICbaseBIEmitEIPtr + 1) += -XQbe_Vbei;
|
||||
*(here->VBICbaseBIBaseBIPtr + 1) += XQbe_Vbci;
|
||||
*(here->VBICbaseBICollCIPtr + 1) += -XQbe_Vbci;
|
||||
*(here->VBICemitEIBaseBIPtr + 1) += -XQbe_Vbei;
|
||||
*(here->VBICemitEIEmitEIPtr + 1) += XQbe_Vbei;
|
||||
*(here->VBICemitEIBaseBIPtr + 1) += -XQbe_Vbci;
|
||||
*(here->VBICemitEICollCIPtr + 1) += XQbe_Vbci;
|
||||
/*
|
||||
c Stamp element: Qbex
|
||||
c Stamp element: Qbex
|
||||
*/
|
||||
*(here->VBICbaseBXBaseBXPtr + 1) += XQbex_Vbex;
|
||||
*(here->VBICbaseBXEmitEIPtr + 1) += -XQbex_Vbex;
|
||||
*(here->VBICemitEIBaseBXPtr + 1) += -XQbex_Vbex;
|
||||
*(here->VBICemitEIEmitEIPtr + 1) += XQbex_Vbex;
|
||||
*(here->VBICbaseBXBaseBXPtr + 1) += XQbex_Vbex;
|
||||
*(here->VBICbaseBXEmitEIPtr + 1) += -XQbex_Vbex;
|
||||
*(here->VBICemitEIBaseBXPtr + 1) += -XQbex_Vbex;
|
||||
*(here->VBICemitEIEmitEIPtr + 1) += XQbex_Vbex;
|
||||
/*
|
||||
c Stamp element: Qbc
|
||||
c Stamp element: Qbc
|
||||
*/
|
||||
*(here->VBICbaseBIBaseBIPtr + 1) += XQbc_Vbci;
|
||||
*(here->VBICbaseBICollCIPtr + 1) += -XQbc_Vbci;
|
||||
*(here->VBICcollCIBaseBIPtr + 1) += -XQbc_Vbci;
|
||||
*(here->VBICcollCICollCIPtr + 1) += XQbc_Vbci;
|
||||
*(here->VBICbaseBIBaseBIPtr + 1) += XQbc_Vbci;
|
||||
*(here->VBICbaseBICollCIPtr + 1) += -XQbc_Vbci;
|
||||
*(here->VBICcollCIBaseBIPtr + 1) += -XQbc_Vbci;
|
||||
*(here->VBICcollCICollCIPtr + 1) += XQbc_Vbci;
|
||||
/*
|
||||
c Stamp element: Qbcx
|
||||
c Stamp element: Qbcx
|
||||
*/
|
||||
*(here->VBICbaseBIBaseBIPtr + 1) += XQbcx_Vbcx;
|
||||
*(here->VBICbaseBICollCXPtr + 1) += -XQbcx_Vbcx;
|
||||
*(here->VBICcollCXBaseBIPtr + 1) += -XQbcx_Vbcx;
|
||||
*(here->VBICcollCXCollCXPtr + 1) += XQbcx_Vbcx;
|
||||
*(here->VBICbaseBIBaseBIPtr + 1) += XQbcx_Vbcx;
|
||||
*(here->VBICbaseBICollCXPtr + 1) += -XQbcx_Vbcx;
|
||||
*(here->VBICcollCXBaseBIPtr + 1) += -XQbcx_Vbcx;
|
||||
*(here->VBICcollCXCollCXPtr + 1) += XQbcx_Vbcx;
|
||||
/*
|
||||
c Stamp element: Qbep
|
||||
c Stamp element: Qbep
|
||||
*/
|
||||
*(here->VBICbaseBXBaseBXPtr + 1) += XQbep_Vbep;
|
||||
*(here->VBICbaseBXBaseBPPtr + 1) += -XQbep_Vbep;
|
||||
*(here->VBICbaseBXBaseBIPtr + 1) += XQbep_Vbci;
|
||||
*(here->VBICbaseBXCollCIPtr + 1) += -XQbep_Vbci;
|
||||
*(here->VBICbaseBPBaseBXPtr + 1) += -XQbep_Vbep;
|
||||
*(here->VBICbaseBPBaseBPPtr + 1) += XQbep_Vbep;
|
||||
*(here->VBICbaseBPBaseBIPtr + 1) += -XQbep_Vbci;
|
||||
*(here->VBICbaseBPCollCIPtr + 1) += XQbep_Vbci;
|
||||
*(here->VBICbaseBXBaseBXPtr + 1) += XQbep_Vbep;
|
||||
*(here->VBICbaseBXBaseBPPtr + 1) += -XQbep_Vbep;
|
||||
*(here->VBICbaseBXBaseBIPtr + 1) += XQbep_Vbci;
|
||||
*(here->VBICbaseBXCollCIPtr + 1) += -XQbep_Vbci;
|
||||
*(here->VBICbaseBPBaseBXPtr + 1) += -XQbep_Vbep;
|
||||
*(here->VBICbaseBPBaseBPPtr + 1) += XQbep_Vbep;
|
||||
*(here->VBICbaseBPBaseBIPtr + 1) += -XQbep_Vbci;
|
||||
*(here->VBICbaseBPCollCIPtr + 1) += XQbep_Vbci;
|
||||
/*
|
||||
c Stamp element: Qbcp
|
||||
c Stamp element: Qbcp
|
||||
*/
|
||||
*(here->VBICsubsSISubsSIPtr + 1) += XQbcp_Vbcp;
|
||||
*(here->VBICsubsSIBaseBPPtr + 1) += -XQbcp_Vbcp;
|
||||
|
|
|
|||
|
|
@ -220,13 +220,17 @@ typedef struct sVBICinstance {
|
|||
double *VBICbaseBPtempPtr;
|
||||
double *VBICemitEItempPtr;
|
||||
double *VBICsubsSItempPtr;
|
||||
double *VBICtempCollPtr;
|
||||
double *VBICtempCollCIPtr;
|
||||
double *VBICtempCollCXPtr;
|
||||
double *VBICtempBasePtr;
|
||||
double *VBICtempBaseBIPtr;
|
||||
double *VBICtempBaseBXPtr;
|
||||
double *VBICtempBaseBPPtr;
|
||||
double *VBICtempEmitPtr;
|
||||
double *VBICtempEmitEIPtr;
|
||||
double *VBICtempSubsPtr;
|
||||
double *VBICtempSubsSIPtr;
|
||||
double *VBICtempTempPtr;
|
||||
|
||||
unsigned VBICareaGiven :1; /* flag to indicate area was specified */
|
||||
|
|
|
|||
|
|
@ -38,36 +38,6 @@ int vbic_4T_et_cf_fj(double *,
|
|||
double *,double *,double *,double *,double *,double *, double *,
|
||||
double *,double *);
|
||||
|
||||
/* VBIClimitlog(deltemp, deltemp_old, LIM_TOL, check)
|
||||
* Logarithmic damping the per-iteration change of deltemp beyond LIM_TOL.
|
||||
*/
|
||||
static double
|
||||
VBIClimitlog(
|
||||
double deltemp,
|
||||
double deltemp_old,
|
||||
double LIM_TOL,
|
||||
int *check)
|
||||
{
|
||||
*check = 0;
|
||||
if (isnan (deltemp) || isnan (deltemp_old))
|
||||
{
|
||||
fprintf(stderr, "Alberto says: YOU TURKEY! The limiting function received NaN.\n");
|
||||
fprintf(stderr, "New prediction returns to 0.0!\n");
|
||||
deltemp = 0.0;
|
||||
*check = 1;
|
||||
}
|
||||
/* Logarithmic damping of deltemp beyond LIM_TOL */
|
||||
if (deltemp > deltemp_old + LIM_TOL) {
|
||||
deltemp = deltemp_old + LIM_TOL + log10((deltemp-deltemp_old)/LIM_TOL);
|
||||
*check = 1;
|
||||
}
|
||||
else if (deltemp < deltemp_old - LIM_TOL) {
|
||||
deltemp = deltemp_old - LIM_TOL - log10((deltemp_old-deltemp)/LIM_TOL);
|
||||
*check = 1;
|
||||
}
|
||||
return deltemp;
|
||||
}
|
||||
|
||||
int
|
||||
VBICload(GENmodel *inModel, CKTcircuit *ckt)
|
||||
/* actually load the current resistance value into the
|
||||
|
|
@ -720,7 +690,7 @@ VBICload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
here->VBICtVcrit,&ichk5);
|
||||
if (here->VBIC_selfheat) {
|
||||
ichk6 = 1;
|
||||
Vrth = VBIClimitlog(Vrth,
|
||||
Vrth = DEVlimitlog(Vrth,
|
||||
*(ckt->CKTstate0 + here->VBICvrth),100,&ichk6);
|
||||
}
|
||||
if ((ichk1 == 1) || (ichk2 == 1) || (ichk3 == 1) || (ichk4 == 1) || (ichk5 == 1) || (ichk6 == 1)) icheck=1;
|
||||
|
|
@ -1240,7 +1210,11 @@ c Stamp element: Ibep
|
|||
/*
|
||||
c Stamp element: Rcx
|
||||
*/
|
||||
*(here->VBICcollTempPtr) += Ircx_Vrth;
|
||||
rhs_current = -Ircx_Vrth * Vrth;
|
||||
*(ckt->CKTrhs + here->VBICcollNode) += -rhs_current;
|
||||
*(here->VBICcollTempPtr) += Ircx_Vrth;
|
||||
*(ckt->CKTrhs + here->VBICcollCXNode) += rhs_current;
|
||||
*(here->VBICcollCXtempPtr) += -Ircx_Vrth;
|
||||
/*
|
||||
c Stamp element: Irci
|
||||
*/
|
||||
|
|
@ -1252,7 +1226,11 @@ c Stamp element: Irci
|
|||
/*
|
||||
c Stamp element: Rbx
|
||||
*/
|
||||
*(here->VBICbaseTempPtr) += Irbx_Vrth;
|
||||
rhs_current = -Irbx_Vrth * Vrth;
|
||||
*(ckt->CKTrhs + here->VBICbaseNode) += -rhs_current;
|
||||
*(here->VBICbaseTempPtr) += Irbx_Vrth;
|
||||
*(ckt->CKTrhs + here->VBICbaseBXNode) += rhs_current;
|
||||
*(here->VBICbaseBXtempPtr) += -Irbx_Vrth;
|
||||
/*
|
||||
c Stamp element: Irbi
|
||||
*/
|
||||
|
|
@ -1264,7 +1242,11 @@ c Stamp element: Irbi
|
|||
/*
|
||||
c Stamp element: Re
|
||||
*/
|
||||
*(here->VBICemitTempPtr) += Ire_Vrth;
|
||||
rhs_current = -Ire_Vrth * Vrth;
|
||||
*(ckt->CKTrhs + here->VBICemitNode) += -rhs_current;
|
||||
*(here->VBICemitTempPtr) += Ire_Vrth;
|
||||
*(ckt->CKTrhs + here->VBICemitEINode) += rhs_current;
|
||||
*(here->VBICemitEItempPtr) += -Ire_Vrth;
|
||||
/*
|
||||
c Stamp element: Irbp
|
||||
*/
|
||||
|
|
@ -1292,7 +1274,11 @@ c Stamp element: Iccp
|
|||
/*
|
||||
c Stamp element: Rs
|
||||
*/
|
||||
*(here->VBICsubsTempPtr) += Irs_Vrth;
|
||||
rhs_current = -Irs_Vrth * Vrth;
|
||||
*(ckt->CKTrhs + here->VBICsubsNode) += -rhs_current;
|
||||
*(here->VBICsubsTempPtr) += Irs_Vrth;
|
||||
*(ckt->CKTrhs + here->VBICsubsSINode) += rhs_current;
|
||||
*(here->VBICsubsSItempPtr) += -Irs_Vrth;
|
||||
/*
|
||||
c Stamp element: Rth
|
||||
*/
|
||||
|
|
@ -1302,16 +1288,16 @@ c Stamp element: Cth
|
|||
*/
|
||||
*(here->VBICtempTempPtr) += Icth_Vrth;
|
||||
/*
|
||||
c Stamp element: Ith
|
||||
c Stamp element: Ith (all values are delivered with (-) sign)
|
||||
*/
|
||||
rhs_current = - Ith + Ith_Vrth*Vrth + Icth - Icth_Vrth*Vrth
|
||||
+ Ith_Vbei*Vbei + Ith_Vbci*Vbci + Ith_Vcei*Vcei
|
||||
+ Ith_Vbex*Vbex + Ith_Vbep*Vbep + Ith_Vbcp*Vbcp
|
||||
+ Ith_Vcep*Vcep + Ith_Vrci*Vrci + Ith_Vbcx*Vbcx
|
||||
+ Ith_Vrbi*Vrbi + Ith_Vrbp*Vrbp
|
||||
+ Ith_Vrcx*Vrcx + Ith_Vrbx*Vrbx + Ith_Vre*Vre + Ith_Vrs*Vrs;
|
||||
rhs_current = -Ith - Ith_Vrth*Vrth + Icth - Icth_Vrth*Vrth
|
||||
- Ith_Vbei*Vbei - Ith_Vbci*Vbci - Ith_Vcei*Vcei
|
||||
- Ith_Vbex*Vbex - Ith_Vbep*Vbep - Ith_Vbcp*Vbcp
|
||||
- Ith_Vcep*Vcep - Ith_Vrci*Vrci - Ith_Vbcx*Vbcx
|
||||
- Ith_Vrbi*Vrbi - Ith_Vrbp*Vrbp
|
||||
- Ith_Vrcx*Vrcx - Ith_Vrbx*Vrbx - Ith_Vre*Vre - Ith_Vrs*Vrs;
|
||||
|
||||
*(ckt->CKTrhs + here->VBICtempNode) -= rhs_current;
|
||||
*(ckt->CKTrhs + here->VBICtempNode) += rhs_current;
|
||||
|
||||
*(here->VBICtempTempPtr) += -Ith_Vrth;
|
||||
|
||||
|
|
@ -1337,11 +1323,14 @@ c Stamp element: Ith
|
|||
*(here->VBICtempBaseBIPtr) += +Ith_Vrbi;
|
||||
*(here->VBICtempBaseBPPtr) += -Ith_Vrbp;
|
||||
*(here->VBICtempCollCXPtr) += +Ith_Vrbp;
|
||||
|
||||
*(here->VBICtempCollPtr) += -Ith_Vrcx;
|
||||
*(here->VBICtempCollCXPtr) += +Ith_Vrcx;
|
||||
*(here->VBICtempBasePtr) += -Ith_Vrbx;
|
||||
*(here->VBICtempBaseBXPtr) += +Ith_Vrbx;
|
||||
*(here->VBICtempEmitPtr) += -Ith_Vre;
|
||||
*(here->VBICtempEmitEIPtr) += +Ith_Vre;
|
||||
*(here->VBICtempSubsPtr) += +Ith_Vrs;
|
||||
*(here->VBICtempSubsPtr) += -Ith_Vrs;
|
||||
*(here->VBICtempSubsSIPtr) += +Ith_Vrs;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -570,13 +570,17 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
|||
TSTALLOC(VBICbaseBPtempPtr,VBICbaseBPNode,VBICtempNode);
|
||||
TSTALLOC(VBICemitEItempPtr,VBICemitEINode,VBICtempNode);
|
||||
TSTALLOC(VBICsubsSItempPtr,VBICsubsSINode,VBICtempNode);
|
||||
TSTALLOC(VBICtempCollPtr,VBICtempNode,VBICcollNode);
|
||||
TSTALLOC(VBICtempCollCIPtr,VBICtempNode,VBICcollCINode);
|
||||
TSTALLOC(VBICtempCollCXPtr,VBICtempNode,VBICcollCXNode);
|
||||
TSTALLOC(VBICtempBaseBIPtr,VBICtempNode,VBICbaseBINode);
|
||||
TSTALLOC(VBICtempBasePtr,VBICtempNode,VBICbaseNode);
|
||||
TSTALLOC(VBICtempBaseBXPtr,VBICtempNode,VBICbaseBXNode);
|
||||
TSTALLOC(VBICtempBaseBPPtr,VBICtempNode,VBICbaseBPNode);
|
||||
TSTALLOC(VBICtempEmitPtr,VBICtempNode,VBICemitNode);
|
||||
TSTALLOC(VBICtempEmitEIPtr,VBICtempNode,VBICemitEINode);
|
||||
TSTALLOC(VBICtempSubsPtr,VBICtempNode,VBICsubsNode);
|
||||
TSTALLOC(VBICtempSubsSIPtr,VBICtempNode,VBICsubsSINode);
|
||||
TSTALLOC(VBICtempTempPtr,VBICtempNode,VBICtempNode);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,8 +94,8 @@ IFparm VDMOSmPTable[] = { /* model parameters */
|
|||
IOP( "trg2", VDMOS_MOD_TRG2, IF_REAL, "Gate resistance quadratic temperature coefficient"),
|
||||
IOP( "trs1", VDMOS_MOD_TRS1, IF_REAL, "Source resistance linear temperature coefficient"),
|
||||
IOP( "trs2", VDMOS_MOD_TRS2, IF_REAL, "Source resistance quadratic temperature coefficient"),
|
||||
IOP( "trb1", VDMOS_MOD_TRB1, IF_REAL, "Body resistance linear temperature coefficient"),
|
||||
IOP( "trb2", VDMOS_MOD_TRB2, IF_REAL, "Body resistance quadratic temperature coefficient"),
|
||||
IOP( "trb1", VDIO_MOD_TRB1, IF_REAL, "Body resistance linear temperature coefficient"),
|
||||
IOP( "trb2", VDIO_MOD_TRB2, IF_REAL, "Body resistance quadratic temperature coefficient"),
|
||||
|
||||
/* weak inversion */
|
||||
IOP("subshift", VDMOS_MOD_SUBSHIFT, IF_REAL, "Shift of weak inversion plot on the vgs axis"),
|
||||
|
|
@ -104,22 +104,22 @@ IFparm VDMOSmPTable[] = { /* model parameters */
|
|||
IOP("tksubthres2", VDMOS_MOD_TKSUBTHRES2, IF_REAL, "Quadratic temperature coefficient of ksubthres"),
|
||||
|
||||
/* body diode */
|
||||
IOP("bv", VDMOS_MOD_BV, IF_REAL, "Vds breakdown voltage"),
|
||||
IOP("ibv", VDMOS_MOD_IBV, IF_REAL, "Current at Vds=bv"),
|
||||
IOP("nbv", VDMOS_MOD_NBV, IF_REAL, "Vds breakdown emission coefficient"),
|
||||
IOP("bv", VDIO_MOD_BV, IF_REAL, "Vds breakdown voltage"),
|
||||
IOP("ibv", VDIO_MOD_IBV, IF_REAL, "Current at Vds=bv"),
|
||||
IOP("nbv", VDIO_MOD_NBV, IF_REAL, "Vds breakdown emission coefficient"),
|
||||
IOP("rds", VDMOS_MOD_RDS, IF_REAL, "Drain-source shunt resistance"),
|
||||
IOP("rb", VDMOS_MOD_RB, IF_REAL, "Body diode ohmic resistance"),
|
||||
IOP("n", VDMOS_MOD_N, IF_REAL, "Body diode emission coefficient"),
|
||||
IOP("tt", VDMOS_MOD_TT, IF_REAL, "Body diode transit time"),
|
||||
IOP("eg", VDMOS_MOD_EG, IF_REAL, "Body diode activation energy for temperature effect on Is"),
|
||||
IOP("xti", VDMOS_MOD_XTI, IF_REAL, "Body diode saturation current temperature exponent"),
|
||||
IOP("is", VDMOS_MOD_IS, IF_REAL, "Body diode saturation current"),
|
||||
IOP("vj", VDMOS_MOD_VJ, IF_REAL, "Body diode junction potential"),
|
||||
IOP("rb", VDIO_MOD_RB, IF_REAL, "Body diode ohmic resistance"),
|
||||
IOP("n", VDIO_MOD_N, IF_REAL, "Body diode emission coefficient"),
|
||||
IOP("tt", VDIO_MOD_TT, IF_REAL, "Body diode transit time"),
|
||||
IOP("eg", VDIO_MOD_EG, IF_REAL, "Body diode activation energy for temperature effect on Is"),
|
||||
IOP("xti", VDIO_MOD_XTI, IF_REAL, "Body diode saturation current temperature exponent"),
|
||||
IOP("is", VDIO_MOD_IS, IF_REAL, "Body diode saturation current"),
|
||||
IOP("vj", VDIO_MOD_VJ, IF_REAL, "Body diode junction potential"),
|
||||
|
||||
/* body diode capacitance (e.g. source-drain capacitance) */
|
||||
IOP("fc", VDMOS_MOD_FC, IF_REAL, "Body diode coefficient for forward-bias depletion capacitance formula"),
|
||||
IOPA("cjo", VDMOS_MOD_CJ, IF_REAL, "Zero-bias body diode junction capacitance"),
|
||||
IOP("m", VDMOS_MOD_MJ, IF_REAL, "Body diode grading coefficient"),
|
||||
IOP("fc", VDIO_MOD_FC, IF_REAL, "Body diode coefficient for forward-bias depletion capacitance formula"),
|
||||
IOPA("cjo", VDIO_MOD_CJ, IF_REAL, "Zero-bias body diode junction capacitance"),
|
||||
IOP("m", VDIO_MOD_MJ, IF_REAL, "Body diode grading coefficient"),
|
||||
|
||||
/* gate-source and gate-drain capacitances */
|
||||
IOPA("cgdmin", VDMOS_MOD_CGDMIN, IF_REAL, "Minimum non-linear G-D capacitance"),
|
||||
|
|
|
|||
|
|
@ -78,11 +78,13 @@ typedef struct sVDMOSinstance {
|
|||
double VDMOSgds;
|
||||
|
||||
double VDIOcap;
|
||||
double VDIOtSatCur; /* temperature corrected saturation Cur. density*/
|
||||
double VDIOtSatCur; /* temperature corrected saturation Cur. density */
|
||||
double VDIOtSatCur_dT;
|
||||
double VDIOinitCond;
|
||||
double VDIOtVcrit;
|
||||
double VDIOconductance;
|
||||
double VDIOtConductance;
|
||||
double VDIOtConductance_dT;
|
||||
double VDIOtBrkdwnV;
|
||||
double VDIOtJctCap;
|
||||
double VDIOtDepCap; /* temperature adjusted transition point in */
|
||||
|
|
@ -105,7 +107,6 @@ typedef struct sVDMOSinstance {
|
|||
double VDMOScdT;
|
||||
double VDMOScth; /* current alias power */
|
||||
|
||||
// double VDIOdIth_dVdio;
|
||||
/*
|
||||
* naming convention:
|
||||
* x = vgs
|
||||
|
|
@ -230,9 +231,11 @@ typedef struct sVDMOSinstance {
|
|||
double *VDMOSSPtempPtr;
|
||||
|
||||
double *VDIOTempposPrimePtr; /* Diode thermal contribution */
|
||||
double *VDIOTempnegPtr;
|
||||
double *VDMOSTempdPtr;
|
||||
double *VDIOPosPrimetempPtr;
|
||||
double *VDIONegtempPtr;
|
||||
double *VDMOSDtempPtr;
|
||||
double *VDMOStempSPtr;
|
||||
double *VDMOSSTempPtr;
|
||||
|
||||
double *VDMOSTcasetcasePtr; /* for Rthjc */
|
||||
double *VDMOSTcasetempPtr;
|
||||
|
|
@ -315,26 +318,28 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
double VDMOSsubshift;
|
||||
double VDMOSksubthres;
|
||||
double VDMOSmtr;
|
||||
double VDMOSrds;
|
||||
|
||||
/* body diode */
|
||||
double VDIOjunctionCap; /* input - use tCj */
|
||||
double VDIOjunctionPot; /* input - use tJctPot */
|
||||
double VDIOdepletionCapCoeff;
|
||||
double VDIOjctSatCur; /* input - use tSatCur */
|
||||
double VDMOSbv;
|
||||
double VDMOSibv;
|
||||
double VDIObv;
|
||||
double VDIOibv;
|
||||
double VDIObrkdEmissionCoeff;
|
||||
double VDIOresistance;
|
||||
double VDMOSrds;
|
||||
double VDMOSn;
|
||||
double VDIOn;
|
||||
double VDIOtransitTime;
|
||||
double VDIOtranTimeTemp1;
|
||||
double VDIOtranTimeTemp2;
|
||||
double VDMOSeg;
|
||||
double VDMOSxti;
|
||||
double VDIOeg;
|
||||
double VDIOxti;
|
||||
double VDIOgradCoeff;
|
||||
double VDIOgradCoeffTemp1;
|
||||
double VDIOgradCoeffTemp2;
|
||||
double VDIOtrb1;
|
||||
double VDIOtrb2;
|
||||
|
||||
double VDMOStcvth;
|
||||
double VDMOSrthjc;
|
||||
|
|
@ -349,8 +354,6 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
double VDMOStrg2;
|
||||
double VDMOStrs1;
|
||||
double VDMOStrs2;
|
||||
double VDMOStrb1;
|
||||
double VDMOStrb2;
|
||||
double VDMOStksubthres1;
|
||||
double VDMOStksubthres2;
|
||||
|
||||
|
|
@ -361,7 +364,6 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
double VDMOSvgdrMax;
|
||||
|
||||
unsigned VDMOStypeGiven :1;
|
||||
unsigned VDIOjctSatCurGiven :1;
|
||||
unsigned VDMOSdrainResistanceGiven :1;
|
||||
unsigned VDMOSsourceResistanceGiven :1;
|
||||
unsigned VDMOSgateResistanceGiven :1;
|
||||
|
|
@ -370,8 +372,6 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
unsigned VDMOSqsGiven :1;
|
||||
unsigned VDMOStransconductanceGiven :1;
|
||||
unsigned VDMOSvth0Given :1;
|
||||
unsigned VDIOgradCoeffGiven :1;
|
||||
unsigned VDIOdepletionCapCoeffGiven :1;
|
||||
unsigned VDMOSphiGiven :1;
|
||||
unsigned VDMOSlambdaGiven :1;
|
||||
unsigned VDMOSthetaGiven :1;
|
||||
|
|
@ -386,18 +386,23 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
unsigned VDMOSsubshiftGiven :1;
|
||||
unsigned VDMOSksubthresGiven :1;
|
||||
unsigned VDMOSmtrGiven :1;
|
||||
unsigned VDMOSrdsGiven :1;
|
||||
|
||||
unsigned VDMOSbvGiven :1;
|
||||
unsigned VDMOSibvGiven :1;
|
||||
unsigned VDIOjctSatCurGiven :1;
|
||||
unsigned VDIOgradCoeffGiven :1;
|
||||
unsigned VDIOdepletionCapCoeffGiven :1;
|
||||
unsigned VDIObvGiven :1;
|
||||
unsigned VDIOibvGiven :1;
|
||||
unsigned VDIOjunctionCapGiven :1;
|
||||
unsigned VDIOjunctionPotGiven :1;
|
||||
unsigned VDIObrkdEmissionCoeffGiven :1;
|
||||
unsigned VDIOresistanceGiven :1;
|
||||
unsigned VDMOSrdsGiven :1;
|
||||
unsigned VDMOSnGiven :1;
|
||||
unsigned VDIOnGiven :1;
|
||||
unsigned VDIOtransitTimeGiven :1;
|
||||
unsigned VDMOSegGiven :1;
|
||||
unsigned VDMOSxtiGiven :1;
|
||||
unsigned VDIOegGiven :1;
|
||||
unsigned VDIOxtiGiven :1;
|
||||
unsigned VDIOtrb1Given :1;
|
||||
unsigned VDIOtrb2Given :1;
|
||||
|
||||
unsigned VDMOStcvthGiven :1;
|
||||
unsigned VDMOSrthjcGiven :1;
|
||||
|
|
@ -412,8 +417,6 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
unsigned VDMOStrg2Given :1;
|
||||
unsigned VDMOStrs1Given :1;
|
||||
unsigned VDMOStrs2Given :1;
|
||||
unsigned VDMOStrb1Given :1;
|
||||
unsigned VDMOStrb2Given :1;
|
||||
unsigned VDMOStksubthres1Given :1;
|
||||
unsigned VDMOStksubthres2Given :1;
|
||||
|
||||
|
|
@ -456,11 +459,6 @@ enum {
|
|||
VDMOS_MOD_RG,
|
||||
VDMOS_MOD_RQ,
|
||||
VDMOS_MOD_VQ,
|
||||
VDMOS_MOD_IS,
|
||||
VDMOS_MOD_VJ,
|
||||
VDMOS_MOD_CJ,
|
||||
VDMOS_MOD_MJ,
|
||||
VDMOS_MOD_FC,
|
||||
VDMOS_MOD_NMOS,
|
||||
VDMOS_MOD_PMOS,
|
||||
VDMOS_MOD_TNOM,
|
||||
|
|
@ -472,18 +470,25 @@ enum {
|
|||
VDMOS_MOD_CGDMAX,
|
||||
VDMOS_MOD_A,
|
||||
VDMOS_MOD_CGS,
|
||||
VDMOS_MOD_RB,
|
||||
VDMOS_MOD_MTRIODE,
|
||||
VDMOS_MOD_SUBSHIFT,
|
||||
VDMOS_MOD_KSUBTHRES,
|
||||
VDMOS_MOD_BV,
|
||||
VDMOS_MOD_IBV,
|
||||
VDMOS_MOD_NBV,
|
||||
VDMOS_MOD_RDS,
|
||||
VDMOS_MOD_N,
|
||||
VDMOS_MOD_TT,
|
||||
VDMOS_MOD_EG,
|
||||
VDMOS_MOD_XTI,
|
||||
VDIO_MOD_IS,
|
||||
VDIO_MOD_VJ,
|
||||
VDIO_MOD_CJ,
|
||||
VDIO_MOD_MJ,
|
||||
VDIO_MOD_FC,
|
||||
VDIO_MOD_RB,
|
||||
VDIO_MOD_BV,
|
||||
VDIO_MOD_IBV,
|
||||
VDIO_MOD_NBV,
|
||||
VDIO_MOD_N,
|
||||
VDIO_MOD_TT,
|
||||
VDIO_MOD_EG,
|
||||
VDIO_MOD_XTI,
|
||||
VDIO_MOD_TRB1,
|
||||
VDIO_MOD_TRB2,
|
||||
VDMOS_MOD_TCVTH,
|
||||
VDMOS_MOD_RTHJC,
|
||||
VDMOS_MOD_RTHCA,
|
||||
|
|
@ -497,8 +502,6 @@ enum {
|
|||
VDMOS_MOD_TRG2,
|
||||
VDMOS_MOD_TRS1,
|
||||
VDMOS_MOD_TRS2,
|
||||
VDMOS_MOD_TRB1,
|
||||
VDMOS_MOD_TRB2,
|
||||
VDMOS_MOD_TKSUBTHRES1,
|
||||
VDMOS_MOD_TKSUBTHRES2,
|
||||
VDMOS_MOD_VGS_MAX,
|
||||
|
|
|
|||
|
|
@ -14,35 +14,7 @@ VDMOS: 2018 Holger Vogt, 2020 Dietmar Warning
|
|||
#include "ngspice/sperror.h"
|
||||
#include "ngspice/suffix.h"
|
||||
|
||||
/* VDMOSlimitlog(deltemp, deltemp_old, LIM_TOL, check)
|
||||
* Logarithmic damping the per-iteration change of deltemp beyond LIM_TOL.
|
||||
*/
|
||||
static double
|
||||
VDMOSlimitlog(
|
||||
double deltemp,
|
||||
double deltemp_old,
|
||||
double LIM_TOL,
|
||||
int *check)
|
||||
{
|
||||
*check = 0;
|
||||
if (isnan (deltemp) || isnan (deltemp_old))
|
||||
{
|
||||
fprintf(stderr, "Alberto says: YOU TURKEY! The limiting function received NaN.\n");
|
||||
fprintf(stderr, "New prediction returns to 0.0!\n");
|
||||
deltemp = 0.0;
|
||||
*check = 1;
|
||||
}
|
||||
/* Logarithmic damping of deltemp beyond LIM_TOL */
|
||||
if (deltemp > deltemp_old + LIM_TOL) {
|
||||
deltemp = deltemp_old + LIM_TOL + log10((deltemp-deltemp_old)/LIM_TOL);
|
||||
*check = 1;
|
||||
}
|
||||
else if (deltemp < deltemp_old - LIM_TOL) {
|
||||
deltemp = deltemp_old - LIM_TOL - log10((deltemp_old-deltemp)/LIM_TOL);
|
||||
*check = 1;
|
||||
}
|
||||
return deltemp;
|
||||
}
|
||||
void VDMOStempUpdate(VDMOSmodel *inModel, VDMOSinstance *here, double Temp, CKTcircuit *ckt);
|
||||
|
||||
int
|
||||
VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
|
||||
|
|
@ -88,6 +60,9 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
|
||||
register int selfheat;
|
||||
double rd0T, rd1T, dBeta_dT, dIds_dT;
|
||||
double Vrd=0.0, dIth_dVrd=0.0, dIrd_dT=0.0;
|
||||
double drd0T_dT, drd1T_dT, drd_dT, dgdrain_dT=0.0;
|
||||
double dIrd_dVrd, dIrd_dgdrain;
|
||||
double deldelTemp=0.0, delTemp, delTemp1, Temp, Vds, Vgs;
|
||||
double ceqqth=0.0;
|
||||
double GmT, gTtg, gTtdp, gTtt, gTtsp, gcTt=0.0;
|
||||
|
|
@ -298,15 +273,20 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
vgs = vgd + vds;
|
||||
}
|
||||
if (selfheat)
|
||||
delTemp = VDMOSlimitlog(delTemp,
|
||||
*(ckt->CKTstate0 + here->VDMOSdelTemp),100,&Check_th);
|
||||
delTemp = DEVlimitlog(delTemp,
|
||||
*(ckt->CKTstate0 + here->VDMOSdelTemp),30,&Check_th);
|
||||
else
|
||||
delTemp = 0.0;
|
||||
#endif /*NODELIMITING*/
|
||||
|
||||
}
|
||||
|
||||
Temp = here->VDMOStemp + delTemp;
|
||||
if (selfheat) {
|
||||
Temp = here->VDMOStemp + delTemp;
|
||||
VDMOStempUpdate(model, here, Temp, ckt);
|
||||
} else {
|
||||
Temp = here->VDMOStemp;
|
||||
}
|
||||
here->VDMOSTempSH = Temp; /* added for portability of SH Temp for noise analysis */
|
||||
|
||||
/* Calculate temperature dependent values for self-heating effect */
|
||||
|
|
@ -315,17 +295,23 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
Beta = here->VDMOStTransconductance * pow(TempRatio,model->VDMOSmu);
|
||||
dBeta_dT = Beta * model->VDMOSmu / Temp;
|
||||
rd0T = here->VDMOSdrainResistance * pow(TempRatio, model->VDMOStexp0);
|
||||
drd0T_dT = rd0T * model->VDMOStexp0 / Temp;
|
||||
rd1T = 0.0;
|
||||
drd1T_dT = 0.0;
|
||||
if (model->VDMOSqsGiven) {
|
||||
rd1T = here->VDMOSqsResistance * pow(TempRatio, model->VDMOStexp1);
|
||||
drd1T_dT = rd1T * model->VDMOStexp1 / Temp;
|
||||
}
|
||||
} else {
|
||||
Beta = here->VDMOStTransconductance;
|
||||
dBeta_dT = 0.0;
|
||||
rd0T = here->VDMOSdrainResistance;
|
||||
drd0T_dT = 0.0;
|
||||
rd1T = 0.0;
|
||||
drd1T_dT = 0.0;
|
||||
if (model->VDMOSqsGiven)
|
||||
rd1T = here->VDMOSqsResistance;
|
||||
drd1T_dT = 0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -428,13 +414,19 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
*(ckt->CKTrhsOld + here->VDMOSdNode) -
|
||||
*(ckt->CKTrhsOld + here->VDMOSsNode));
|
||||
double rd = rd0T + rd1T * (vdsn / (vdsn + fabs(model->VDMOSqsVoltage)));
|
||||
if (rd > 0)
|
||||
drd_dT = drd0T_dT + drd1T_dT * (vdsn / (vdsn + fabs(model->VDMOSqsVoltage)));
|
||||
if (rd > 0) {
|
||||
here->VDMOSdrainConductance = 1 / rd + ckt->CKTgmin;
|
||||
else
|
||||
dgdrain_dT = -drd_dT / (rd*rd);
|
||||
} else {
|
||||
here->VDMOSdrainConductance = 1 / rd0T;
|
||||
dgdrain_dT = -drd0T_dT / (rd0T*rd0T);
|
||||
}
|
||||
} else {
|
||||
if (rd0T > 0)
|
||||
if (rd0T > 0) {
|
||||
here->VDMOSdrainConductance = 1 / rd0T;
|
||||
dgdrain_dT = -drd0T_dT / (rd0T*rd0T);
|
||||
}
|
||||
}
|
||||
|
||||
if (selfheat) {
|
||||
|
|
@ -446,15 +438,20 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
}
|
||||
|
||||
if (selfheat) {
|
||||
/* note that sign is switched because power flows out
|
||||
of device into the temperature node. */
|
||||
here->VDMOSgtempg = -model->VDMOStype*here->VDMOSgm * Vds;
|
||||
here->VDMOSgtempT = -GmT * Vds;
|
||||
here->VDMOSgtempd = -model->VDMOStype* (here->VDMOSgds * Vds + cdrain);
|
||||
here->VDMOScth = - cdrain * Vds
|
||||
- 1/here->VDMOSdrainConductance * cdrain*cdrain
|
||||
/* power flows from ground into the temperature node. */
|
||||
here->VDMOSgtempg = model->VDMOStype*here->VDMOSgm * Vds;
|
||||
here->VDMOSgtempT = GmT * Vds;
|
||||
here->VDMOSgtempd = model->VDMOStype* (here->VDMOSgds * Vds + cdrain);
|
||||
here->VDMOScth = cdrain * Vds
|
||||
- model->VDMOStype * (here->VDMOSgtempg * Vgs + here->VDMOSgtempd * Vds)
|
||||
- here->VDMOSgtempT * delTemp;
|
||||
|
||||
Vrd = *(ckt->CKTrhsOld + here->VDMOSdNode) - *(ckt->CKTrhsOld + here->VDMOSdNodePrime);
|
||||
dIth_dVrd = here->VDMOSdrainConductance * Vrd;
|
||||
dIrd_dVrd = here->VDMOSdrainConductance;
|
||||
dIrd_dgdrain = Vrd;
|
||||
dIrd_dT = dIrd_dgdrain * dgdrain_dT;
|
||||
here->VDMOScth += here->VDMOSdrainConductance * Vrd*Vrd - dIth_dVrd*Vrd - dIrd_dT*Vrd*delTemp;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -605,9 +602,10 @@ bypass:
|
|||
*(ckt->CKTrhs + here->VDMOSdNodePrime) += (-cdreq + model->VDMOStype * ceqgd);
|
||||
*(ckt->CKTrhs + here->VDMOSsNodePrime) += cdreq + model->VDMOStype * ceqgs;
|
||||
if (selfheat) {
|
||||
*(ckt->CKTrhs + here->VDMOSdNodePrime) += GmT * delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOSdNode) += dIrd_dT * delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOSdNodePrime) += GmT * delTemp - dIrd_dT * delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOSsNodePrime) += -GmT * delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOStempNode) -= here->VDMOScth + ceqqth; /* MOS dissipated power + Cthj current */
|
||||
*(ckt->CKTrhs + here->VDMOStempNode) += here->VDMOScth - ceqqth;
|
||||
double vCktTemp = (ckt->CKTtemp-CONSTCtoK); /* ckt temperature */
|
||||
if (ckt->CKTmode & MODETRANOP)
|
||||
vCktTemp *= ckt->CKTsrcFact;
|
||||
|
|
@ -648,13 +646,16 @@ bypass:
|
|||
|
||||
if (selfheat)
|
||||
{
|
||||
(*(here->VDMOSDPtempPtr) += GmT);
|
||||
|
||||
(*(here->VDMOSDtempPtr) += dIrd_dT);
|
||||
(*(here->VDMOSDPtempPtr) += GmT - dIrd_dT);
|
||||
(*(here->VDMOSSPtempPtr) += -GmT);
|
||||
(*(here->VDMOSGPtempPtr) += 0.0);
|
||||
(*(here->VDMOSTemptempPtr) += gTtt + 1/model->VDMOSrthjc + gcTt);
|
||||
(*(here->VDMOSTempgpPtr) += gTtg);
|
||||
(*(here->VDMOSTempdpPtr) += gTtdp);
|
||||
(*(here->VDMOSTempspPtr) += gTtsp);
|
||||
(*(here->VDMOSTemptempPtr) += -gTtt - dIrd_dT*Vrd + 1/model->VDMOSrthjc + gcTt);
|
||||
(*(here->VDMOSTempgpPtr) += -gTtg);
|
||||
(*(here->VDMOSTempdPtr) += -dIth_dVrd);
|
||||
(*(here->VDMOSTempdpPtr) += -gTtdp + dIth_dVrd);
|
||||
(*(here->VDMOSTempspPtr) += -gTtsp);
|
||||
(*(here->VDMOSTemptcasePtr) += -1/model->VDMOSrthjc);
|
||||
(*(here->VDMOSTcasetempPtr) += -1/model->VDMOSrthjc);
|
||||
(*(here->VDMOSTcasetcasePtr) += 1/model->VDMOSrthjc + 1/model->VDMOSrthca);
|
||||
|
|
@ -672,14 +673,15 @@ bypass:
|
|||
double vd, cd;
|
||||
double vte;
|
||||
double vtebrk, vbrknp;
|
||||
double cdb, csat, cdeq;
|
||||
double cdb, cdeq;
|
||||
double capd;
|
||||
double gd, gdb, gspr;
|
||||
double delvd; /* change in diode voltage temporary */
|
||||
double evrev;
|
||||
double Ith=0.0, dIth_dT=0.0;
|
||||
double dIdio_dT=0.0, dIth_dVdio=0.0;
|
||||
double arg1, darg1_dT, arg2, darg2_dT, csat_dT;
|
||||
double vrs=0.0, dIrs_dT=0.0, dIth_dVrs=0.0;
|
||||
|
||||
#ifndef NOBYPASS
|
||||
double tol; /* temporary for tolerance calculations */
|
||||
#endif
|
||||
|
|
@ -691,7 +693,7 @@ bypass:
|
|||
gspr = here->VDIOtConductance;
|
||||
|
||||
vt = CONSTKoverQ * Temp;
|
||||
vte = model->VDMOSn * vt;
|
||||
vte = model->VDIOn * vt;
|
||||
vtebrk = model->VDIObrkdEmissionCoeff * vt;
|
||||
vbrknp = here->VDIOtBrkdwnV;
|
||||
|
||||
|
|
@ -758,7 +760,7 @@ bypass:
|
|||
/*
|
||||
* limit new junction voltage
|
||||
*/
|
||||
if ((model->VDMOSbvGiven) &&
|
||||
if ((model->VDIObvGiven) &&
|
||||
(vd < MIN(0, -vbrknp + 10 * vtebrk))) {
|
||||
double vdtemp;
|
||||
vdtemp = -(vd + vbrknp);
|
||||
|
|
@ -773,19 +775,6 @@ bypass:
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* temperature dependent diode saturation current and derivative
|
||||
*/
|
||||
arg1 = ((Temp / model->VDMOStnom) - 1) * model->VDMOSeg / (model->VDMOSn*vt);
|
||||
darg1_dT = model->VDMOSeg / (vte*model->VDMOStnom)
|
||||
- model->VDMOSeg*(Temp/model->VDMOStnom -1)/(vte*Temp);
|
||||
|
||||
arg2 = model->VDMOSxti / model->VDMOSn * log(Temp / model->VDMOStnom);
|
||||
darg2_dT = model->VDMOSxti / model->VDMOSn / Temp;
|
||||
|
||||
csat = here->VDMOSm * model->VDIOjctSatCur * exp(arg1 + arg2);
|
||||
csat_dT = here->VDMOSm * model->VDIOjctSatCur * exp(arg1 + arg2) * (darg1_dT + darg2_dT);
|
||||
|
||||
/*
|
||||
* compute dc current and derivatives
|
||||
*/
|
||||
|
|
@ -793,27 +782,27 @@ bypass:
|
|||
double evd;
|
||||
|
||||
evd = exp(vd / vte);
|
||||
cdb = csat*(evd - 1);
|
||||
dIdio_dT = csat_dT * (evd - 1) - csat * vd * evd / (vte * Temp);
|
||||
gdb = csat*evd / vte;
|
||||
cdb = here->VDIOtSatCur*(evd - 1);
|
||||
dIdio_dT = here->VDIOtSatCur_dT * (evd - 1) - here->VDIOtSatCur * vd * evd / (vte * Temp);
|
||||
gdb = here->VDIOtSatCur*evd / vte;
|
||||
|
||||
} else if ((!(model->VDMOSbvGiven)) ||
|
||||
} else if ((!(model->VDIObvGiven)) ||
|
||||
vd >= -vbrknp) { /* reverse */
|
||||
double arg3, darg3_dT;
|
||||
|
||||
arg = 3 * vte / (vd*CONSTe);
|
||||
arg3 = arg * arg * arg;
|
||||
darg3_dT = 3 * arg3 / Temp;
|
||||
cdb = -csat*(1 + arg3);
|
||||
dIdio_dT = -csat_dT * (arg3 + 1) - csat * darg3_dT;
|
||||
gdb = csat * 3 * arg / vd;
|
||||
cdb = -here->VDIOtSatCur*(1 + arg3);
|
||||
dIdio_dT = -here->VDIOtSatCur_dT * (arg3 + 1) - here->VDIOtSatCur * darg3_dT;
|
||||
gdb = here->VDIOtSatCur * 3 * arg / vd;
|
||||
|
||||
} else { /* breakdown */
|
||||
|
||||
evrev = exp(-(vbrknp + vd) / vtebrk);
|
||||
cdb = -csat*evrev;
|
||||
dIdio_dT = csat * (-vbrknp-vd) * evrev / vtebrk / Temp - csat_dT * evrev;
|
||||
gdb = csat*evrev / vtebrk;
|
||||
cdb = -here->VDIOtSatCur*evrev;
|
||||
dIdio_dT = here->VDIOtSatCur * (-vbrknp-vd) * evrev / vtebrk / Temp - here->VDIOtSatCur_dT * evrev;
|
||||
gdb = here->VDIOtSatCur*evrev / vtebrk;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -855,7 +844,7 @@ bypass:
|
|||
if (ckt->CKTmode & MODEINITSMSIG) {
|
||||
*(ckt->CKTstate0 + here->VDIOcapCurrent) = capd;
|
||||
|
||||
goto load;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -893,9 +882,18 @@ bypass:
|
|||
|
||||
load:
|
||||
if (selfheat) {
|
||||
Ith = vd*cd;
|
||||
double dIrs_dgspr, dIth_dIrs;
|
||||
vrs = *(ckt->CKTrhsOld + here->VDMOSsNode) - *(ckt->CKTrhsOld + here->VDIOposPrimeNode);
|
||||
|
||||
Ith = vd*cd + vrs*vrs*gspr;
|
||||
|
||||
dIth_dVdio = cd + vd*gd;
|
||||
dIth_dT = dIdio_dT*vd;
|
||||
dIth_dVrs = vrs*gspr;
|
||||
|
||||
dIrs_dgspr = vrs;
|
||||
dIrs_dT = dIrs_dgspr * here->VDIOtConductance_dT;
|
||||
dIth_dIrs = vrs;
|
||||
dIth_dT = dIth_dIrs*dIrs_dT + dIdio_dT*vd;
|
||||
}
|
||||
/*
|
||||
* load current vector
|
||||
|
|
@ -909,9 +907,10 @@ load:
|
|||
*(ckt->CKTrhs + here->VDIOposPrimeNode) += cdeq;
|
||||
}
|
||||
if (selfheat) {
|
||||
*(ckt->CKTrhs + here->VDMOSdNode) += dIdio_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->VDIOposPrimeNode) -= dIdio_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOStempNode) += Ith - model->VDMOStype*dIth_dVdio*vd + dIth_dT*delTemp; /* Diode dissipated power */
|
||||
*(ckt->CKTrhs + here->VDIOposPrimeNode) += dIdio_dT*delTemp - dIrs_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOSdNode) += -dIdio_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOSsNode) += dIrs_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOStempNode) += Ith - model->VDMOStype*dIth_dVdio*vd - dIth_dVrs*vrs - dIth_dT*delTemp;
|
||||
}
|
||||
/*
|
||||
* load matrix
|
||||
|
|
@ -924,11 +923,13 @@ load:
|
|||
*(here->VDIORPsPtr) -= gspr;
|
||||
*(here->VDIORPdPtr) -= gd;
|
||||
if (selfheat) {
|
||||
(*(here->VDMOSTemptempPtr) += dIth_dT);
|
||||
(*(here->VDIOTempposPrimePtr) += -dIth_dVdio);
|
||||
(*(here->VDIOTempnegPtr) += dIth_dVdio);
|
||||
(*(here->VDIOPosPrimetempPtr) += -dIdio_dT);
|
||||
(*(here->VDIONegtempPtr) += dIdio_dT);
|
||||
(*(here->VDMOStempSPtr) += -dIth_dVrs);
|
||||
(*(here->VDIOTempposPrimePtr) += -dIth_dVdio + dIth_dVrs);
|
||||
(*(here->VDMOSTempdPtr) += dIth_dVdio);
|
||||
(*(here->VDMOSTemptempPtr) += -dIth_dT);
|
||||
(*(here->VDIOPosPrimetempPtr) += dIdio_dT - dIrs_dT);
|
||||
(*(here->VDMOSSTempPtr) += dIrs_dT);
|
||||
(*(here->VDMOSDtempPtr) += -dIdio_dT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,47 +83,47 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
|
|||
return(OK);
|
||||
|
||||
/* body diode */
|
||||
case VDMOS_MOD_RB:
|
||||
case VDIO_MOD_RB:
|
||||
value->rValue = model->VDIOresistance;
|
||||
return(OK);
|
||||
case VDMOS_MOD_IS:
|
||||
case VDIO_MOD_IS:
|
||||
value->rValue = model->VDIOjctSatCur;
|
||||
return(OK);
|
||||
case VDMOS_MOD_N:
|
||||
value->rValue = model->VDMOSn;
|
||||
case VDIO_MOD_N:
|
||||
value->rValue = model->VDIOn;
|
||||
return(OK);
|
||||
case VDMOS_MOD_VJ:
|
||||
case VDIO_MOD_VJ:
|
||||
value->rValue = model->VDIOjunctionPot;
|
||||
return(OK);
|
||||
case VDMOS_MOD_CJ:
|
||||
case VDIO_MOD_CJ:
|
||||
value->rValue = model->VDIOjunctionCap;
|
||||
return(OK);
|
||||
case VDMOS_MOD_MJ:
|
||||
case VDIO_MOD_MJ:
|
||||
value->rValue = model->VDIOgradCoeff;
|
||||
return(OK);
|
||||
case VDMOS_MOD_BV:
|
||||
value->rValue = model->VDMOSbv;
|
||||
case VDIO_MOD_BV:
|
||||
value->rValue = model->VDIObv;
|
||||
return(OK);
|
||||
case VDMOS_MOD_IBV:
|
||||
value->rValue = model->VDMOSibv;
|
||||
case VDIO_MOD_IBV:
|
||||
value->rValue = model->VDIOibv;
|
||||
return(OK);
|
||||
case VDMOS_MOD_NBV:
|
||||
case VDIO_MOD_NBV:
|
||||
value->rValue = model->VDIObrkdEmissionCoeff;
|
||||
return(OK);
|
||||
case VDMOS_MOD_RDS:
|
||||
value->rValue = model->VDMOSrds;
|
||||
return(OK);
|
||||
case VDMOS_MOD_FC:
|
||||
case VDIO_MOD_FC:
|
||||
value->rValue = model->VDIOdepletionCapCoeff;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TT:
|
||||
case VDIO_MOD_TT:
|
||||
value->rValue = model->VDIOtransitTime;
|
||||
return(OK);
|
||||
case VDMOS_MOD_EG:
|
||||
value->rValue = model->VDMOSeg;
|
||||
case VDIO_MOD_EG:
|
||||
value->rValue = model->VDIOeg;
|
||||
return(OK);
|
||||
case VDMOS_MOD_XTI:
|
||||
value->rValue = model->VDMOSxti;
|
||||
case VDIO_MOD_XTI:
|
||||
value->rValue = model->VDIOxti;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TCVTH:
|
||||
value->rValue = model->VDMOStcvth;
|
||||
|
|
@ -164,11 +164,11 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
|
|||
case VDMOS_MOD_TRS2:
|
||||
value->rValue = model->VDMOStrs2;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TRB1:
|
||||
value->rValue = model->VDMOStrb1;
|
||||
case VDIO_MOD_TRB1:
|
||||
value->rValue = model->VDIOtrb1;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TRB2:
|
||||
value->rValue = model->VDMOStrb2;
|
||||
case VDIO_MOD_TRB2:
|
||||
value->rValue = model->VDIOtrb2;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TKSUBTHRES1:
|
||||
value->rValue = model->VDMOStksubthres1;
|
||||
|
|
|
|||
|
|
@ -60,29 +60,29 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->VDMOSqsVoltage = value->rValue;
|
||||
model->VDMOSqsVoltageGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_RB:
|
||||
case VDIO_MOD_RB:
|
||||
model->VDIOresistance = value->rValue;
|
||||
model->VDIOresistanceGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_IS:
|
||||
case VDIO_MOD_IS:
|
||||
model->VDIOjctSatCur = value->rValue;
|
||||
model->VDIOjctSatCurGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_VJ:
|
||||
case VDIO_MOD_VJ:
|
||||
model->VDIOjunctionPot = value->rValue;
|
||||
model->VDIOjunctionPotGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_CJ:
|
||||
case VDIO_MOD_CJ:
|
||||
model->VDIOjunctionCap = value->rValue;
|
||||
model->VDIOjunctionCapGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_MJ:
|
||||
case VDIO_MOD_MJ:
|
||||
model->VDIOgradCoeff = value->rValue;
|
||||
model->VDIOgradCoeffGiven = TRUE;
|
||||
model->VDIOgradCoeffTemp1 = 0;
|
||||
model->VDIOgradCoeffTemp2 = 0;
|
||||
break;
|
||||
case VDMOS_MOD_FC:
|
||||
case VDIO_MOD_FC:
|
||||
model->VDIOdepletionCapCoeff = value->rValue;
|
||||
model->VDIOdepletionCapCoeffGiven = TRUE;
|
||||
break;
|
||||
|
|
@ -140,15 +140,15 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->VDMOSksubthres = value->rValue;
|
||||
model->VDMOSksubthresGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_BV:
|
||||
model->VDMOSbv = value->rValue;
|
||||
model->VDMOSbvGiven = TRUE;
|
||||
case VDIO_MOD_BV:
|
||||
model->VDIObv = value->rValue;
|
||||
model->VDIObvGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_IBV:
|
||||
model->VDMOSibv = value->rValue;
|
||||
model->VDMOSibvGiven = TRUE;
|
||||
case VDIO_MOD_IBV:
|
||||
model->VDIOibv = value->rValue;
|
||||
model->VDIOibvGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_NBV:
|
||||
case VDIO_MOD_NBV:
|
||||
model->VDIObrkdEmissionCoeff = value->rValue;
|
||||
model->VDIObrkdEmissionCoeffGiven = TRUE;
|
||||
break;
|
||||
|
|
@ -156,23 +156,23 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->VDMOSrds = value->rValue;
|
||||
model->VDMOSrdsGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_N:
|
||||
model->VDMOSn = value->rValue;
|
||||
model->VDMOSnGiven = TRUE;
|
||||
case VDIO_MOD_N:
|
||||
model->VDIOn = value->rValue;
|
||||
model->VDIOnGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_TT:
|
||||
case VDIO_MOD_TT:
|
||||
model->VDIOtransitTime = value->rValue;
|
||||
model->VDIOtransitTimeGiven = TRUE;
|
||||
model->VDIOtranTimeTemp1 = 0;
|
||||
model->VDIOtranTimeTemp2 = 0;
|
||||
break;
|
||||
case VDMOS_MOD_EG:
|
||||
model->VDMOSeg = value->rValue;
|
||||
model->VDMOSegGiven = TRUE;
|
||||
case VDIO_MOD_EG:
|
||||
model->VDIOeg = value->rValue;
|
||||
model->VDIOegGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_XTI:
|
||||
model->VDMOSxti = value->rValue;
|
||||
model->VDMOSxtiGiven = TRUE;
|
||||
case VDIO_MOD_XTI:
|
||||
model->VDIOxti = value->rValue;
|
||||
model->VDIOxtiGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_TCVTH:
|
||||
model->VDMOStcvth = value->rValue;
|
||||
|
|
@ -226,13 +226,13 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->VDMOStrs2 = value->rValue;
|
||||
model->VDMOStrs2Given = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_TRB1:
|
||||
model->VDMOStrb1 = value->rValue;
|
||||
model->VDMOStrb1Given = TRUE;
|
||||
case VDIO_MOD_TRB1:
|
||||
model->VDIOtrb1 = value->rValue;
|
||||
model->VDIOtrb1Given = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_TRB2:
|
||||
model->VDMOStrb2 = value->rValue;
|
||||
model->VDMOStrb2Given = TRUE;
|
||||
case VDIO_MOD_TRB2:
|
||||
model->VDIOtrb2 = value->rValue;
|
||||
model->VDIOtrb2Given = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_TKSUBTHRES1:
|
||||
model->VDMOStksubthres1 = value->rValue;
|
||||
|
|
|
|||
|
|
@ -85,11 +85,11 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
if (!model->VDMOSmtrGiven)
|
||||
model->VDMOSmtr = 1.;
|
||||
|
||||
if (!model->VDMOSbvGiven)
|
||||
model->VDMOSbv = 1.0e30;
|
||||
if (!model->VDIObvGiven)
|
||||
model->VDIObv = 1.0e30;
|
||||
|
||||
if (!model->VDMOSibvGiven)
|
||||
model->VDMOSibv = 1.0e-10;
|
||||
if (!model->VDIOibvGiven)
|
||||
model->VDIOibv = 1.0e-10;
|
||||
|
||||
if (!model->VDIObrkdEmissionCoeffGiven)
|
||||
model->VDIObrkdEmissionCoeff = 1.;
|
||||
|
|
@ -109,14 +109,14 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
if (!model->VDIOresistanceGiven)
|
||||
model->VDIOresistance = 10e-03;
|
||||
|
||||
if (!model->VDMOSnGiven)
|
||||
model->VDMOSn = 1.;
|
||||
if (!model->VDIOnGiven)
|
||||
model->VDIOn = 1.;
|
||||
|
||||
if (!model->VDIOtransitTimeGiven)
|
||||
model->VDIOtransitTime = 0.;
|
||||
|
||||
if (!model->VDMOSegGiven)
|
||||
model->VDMOSeg = 1.11;
|
||||
if (!model->VDIOegGiven)
|
||||
model->VDIOeg = 1.11;
|
||||
|
||||
if (!model->VDMOSrthjcGiven)
|
||||
model->VDMOSrthjc = 1.0e-03;
|
||||
|
|
@ -157,11 +157,11 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
if (!model->VDMOStrs2Given)
|
||||
model->VDMOStrs2 = 0.0;
|
||||
|
||||
if (!model->VDMOStrb1Given)
|
||||
model->VDMOStrb1 = 0.0;
|
||||
if (!model->VDIOtrb1Given)
|
||||
model->VDIOtrb1 = 0.0;
|
||||
|
||||
if (!model->VDMOStrb2Given)
|
||||
model->VDMOStrb2 = 0.0;
|
||||
if (!model->VDIOtrb2Given)
|
||||
model->VDIOtrb2 = 0.0;
|
||||
|
||||
if (!model->VDMOStksubthres1Given)
|
||||
model->VDMOStksubthres1 = 0.0;
|
||||
|
|
@ -189,6 +189,38 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
else
|
||||
model->VDMOSqsGiven = 0;
|
||||
|
||||
if(!model->VDMOStnomGiven) {
|
||||
model->VDMOStnom = ckt->CKTnomTemp;
|
||||
}
|
||||
|
||||
/* now model parameter preprocessing */
|
||||
if (model->VDMOSphi <= 0.0) {
|
||||
SPfrontEnd->IFerrorf(ERR_FATAL,
|
||||
"%s: Phi is not positive.", model->VDMOSmodName);
|
||||
return(E_BADPARM);
|
||||
}
|
||||
|
||||
model->VDMOSoxideCapFactor = 3.9 * 8.854214871e-12 / 1e-07; /* use default Tox of 100nm */
|
||||
|
||||
/* body diode model */
|
||||
/* limit activation energy to min of .1 */
|
||||
if (model->VDIOeg<.1) {
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: body diode activation energy too small, limited to 0.1",
|
||||
model->VDMOSmodName);
|
||||
model->VDIOeg = .1;
|
||||
}
|
||||
/* limit depletion cap coeff to max of .95 */
|
||||
if (model->VDIOdepletionCapCoeff>.95) {
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: coefficient Fc too large, limited to 0.95",
|
||||
model->VDMOSmodName);
|
||||
model->VDIOdepletionCapCoeff = .95;
|
||||
}
|
||||
/* set lower limit of saturation current */
|
||||
if (model->VDIOjctSatCur < ckt->CKTepsmin)
|
||||
model->VDIOjctSatCur = ckt->CKTepsmin;
|
||||
|
||||
/* loop through all the instances of the model */
|
||||
for (here = VDMOSinstances(model); here != NULL;
|
||||
here = VDMOSnextInstance(here)) {
|
||||
|
|
@ -368,58 +400,61 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
|||
return(E_NOMEM);\
|
||||
} } while(0)
|
||||
|
||||
if ((here->VDMOSthermalGiven) && (model->VDMOSrthjcGiven)) {
|
||||
TSTALLOC(VDMOSTemptempPtr, VDMOStempNode, VDMOStempNode); /* Transistor thermal contribution */
|
||||
TSTALLOC(VDMOSTempdpPtr, VDMOStempNode, VDMOSdNodePrime);
|
||||
TSTALLOC(VDMOSTempspPtr, VDMOStempNode, VDMOSsNodePrime);
|
||||
TSTALLOC(VDMOSTempgpPtr, VDMOStempNode, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSGPtempPtr, VDMOSgNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSDPtempPtr, VDMOSdNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSSPtempPtr, VDMOSsNodePrime, VDMOStempNode);
|
||||
|
||||
TSTALLOC(VDIOTempposPrimePtr, VDMOStempNode, VDIOposPrimeNode);/* Diode thermal contribution */
|
||||
TSTALLOC(VDIOTempnegPtr, VDMOStempNode, VDMOSdNode);
|
||||
TSTALLOC(VDIOPosPrimetempPtr, VDIOposPrimeNode, VDMOStempNode);
|
||||
TSTALLOC(VDIONegtempPtr, VDMOSdNode, VDMOStempNode);
|
||||
|
||||
TSTALLOC(VDMOSTcasetcasePtr, VDMOStcaseNode, VDMOStcaseNode); /* Rthjc between tj and tcase*/
|
||||
TSTALLOC(VDMOSTcasetempPtr, VDMOStcaseNode, VDMOStempNode);
|
||||
TSTALLOC(VDMOSTemptcasePtr, VDMOStempNode, VDMOStcaseNode);
|
||||
TSTALLOC(VDMOSTptpPtr, VDMOStNodePrime, VDMOStNodePrime); /* Rthca between tcase and Vsrc */
|
||||
TSTALLOC(VDMOSTptcasePtr, VDMOStNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSTcasetpPtr, VDMOStempNode, VDMOStNodePrime);
|
||||
TSTALLOC(VDMOSCktTcktTPtr, VDMOSvcktTbranch, VDMOSvcktTbranch); /* Vsrc=cktTemp to gnd */
|
||||
TSTALLOC(VDMOSCktTtpPtr, VDMOSvcktTbranch, VDMOStNodePrime);
|
||||
TSTALLOC(VDMOSTpcktTPtr, VDMOStNodePrime, VDMOSvcktTbranch);
|
||||
}
|
||||
TSTALLOC(VDMOSDdPtr, VDMOSdNode, VDMOSdNode);
|
||||
TSTALLOC(VDMOSGgPtr, VDMOSgNode, VDMOSgNode);
|
||||
TSTALLOC(VDMOSSsPtr, VDMOSsNode, VDMOSsNode);
|
||||
TSTALLOC(VDMOSDdPtr, VDMOSdNode, VDMOSdNode);
|
||||
TSTALLOC(VDMOSGgPtr, VDMOSgNode, VDMOSgNode);
|
||||
TSTALLOC(VDMOSSsPtr, VDMOSsNode, VDMOSsNode);
|
||||
TSTALLOC(VDMOSDPdpPtr, VDMOSdNodePrime, VDMOSdNodePrime);
|
||||
TSTALLOC(VDMOSSPspPtr, VDMOSsNodePrime, VDMOSsNodePrime);
|
||||
TSTALLOC(VDMOSGPgpPtr, VDMOSgNodePrime, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSDdpPtr, VDMOSdNode, VDMOSdNodePrime);
|
||||
TSTALLOC(VDMOSDdpPtr, VDMOSdNode, VDMOSdNodePrime);
|
||||
TSTALLOC(VDMOSGPdpPtr, VDMOSgNodePrime, VDMOSdNodePrime);
|
||||
TSTALLOC(VDMOSGPspPtr, VDMOSgNodePrime, VDMOSsNodePrime);
|
||||
TSTALLOC(VDMOSSspPtr, VDMOSsNode, VDMOSsNodePrime);
|
||||
TSTALLOC(VDMOSSspPtr, VDMOSsNode, VDMOSsNodePrime);
|
||||
TSTALLOC(VDMOSDPspPtr, VDMOSdNodePrime, VDMOSsNodePrime);
|
||||
TSTALLOC(VDMOSDPdPtr, VDMOSdNodePrime, VDMOSdNode);
|
||||
TSTALLOC(VDMOSDPdPtr, VDMOSdNodePrime, VDMOSdNode);
|
||||
TSTALLOC(VDMOSDPgpPtr, VDMOSdNodePrime, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSSPgpPtr, VDMOSsNodePrime, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSSPsPtr, VDMOSsNodePrime, VDMOSsNode);
|
||||
TSTALLOC(VDMOSSPsPtr, VDMOSsNodePrime, VDMOSsNode);
|
||||
TSTALLOC(VDMOSSPdpPtr, VDMOSsNodePrime, VDMOSdNodePrime);
|
||||
|
||||
TSTALLOC(VDMOSGgpPtr, VDMOSgNode, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSGgpPtr, VDMOSgNode, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSGPgPtr, VDMOSgNodePrime, VDMOSgNode);
|
||||
|
||||
TSTALLOC(VDMOSDsPtr, VDMOSdNode, VDMOSsNode);
|
||||
TSTALLOC(VDMOSSdPtr, VDMOSsNode, VDMOSdNode);
|
||||
|
||||
TSTALLOC(VDIORPdPtr, VDIOposPrimeNode, VDMOSdNode);
|
||||
TSTALLOC(VDIODrpPtr, VDMOSdNode, VDIOposPrimeNode);
|
||||
TSTALLOC(VDIOSrpPtr, VDMOSsNode, VDIOposPrimeNode);
|
||||
TSTALLOC(VDIORPsPtr, VDIOposPrimeNode, VDMOSsNode);
|
||||
TSTALLOC(VDIORPdPtr, VDIOposPrimeNode, VDMOSdNode);
|
||||
TSTALLOC(VDIODrpPtr, VDMOSdNode, VDIOposPrimeNode);
|
||||
TSTALLOC(VDIOSrpPtr, VDMOSsNode, VDIOposPrimeNode);
|
||||
TSTALLOC(VDIORPsPtr, VDIOposPrimeNode, VDMOSsNode);
|
||||
TSTALLOC(VDIORPrpPtr, VDIOposPrimeNode, VDIOposPrimeNode);
|
||||
|
||||
if ((here->VDMOSthermalGiven) && (model->VDMOSrthjcGiven)) {
|
||||
TSTALLOC(VDMOSTemptempPtr, VDMOStempNode, VDMOStempNode); /* Transistor thermal contribution */
|
||||
TSTALLOC(VDMOSTempdpPtr, VDMOStempNode, VDMOSdNodePrime);
|
||||
TSTALLOC(VDMOSTempspPtr, VDMOStempNode, VDMOSsNodePrime);
|
||||
TSTALLOC(VDMOSTempgpPtr, VDMOStempNode, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSGPtempPtr, VDMOSgNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSDPtempPtr, VDMOSdNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSSPtempPtr, VDMOSsNodePrime, VDMOStempNode);
|
||||
|
||||
TSTALLOC(VDIOTempposPrimePtr, VDMOStempNode, VDIOposPrimeNode);/* Diode thermal contribution */
|
||||
TSTALLOC(VDMOSTempdPtr, VDMOStempNode, VDMOSdNode);
|
||||
TSTALLOC(VDIOPosPrimetempPtr, VDIOposPrimeNode, VDMOStempNode);
|
||||
TSTALLOC(VDMOSDtempPtr, VDMOSdNode, VDMOStempNode);
|
||||
TSTALLOC(VDMOStempSPtr, VDMOStempNode, VDMOSsNode);
|
||||
TSTALLOC(VDMOSSTempPtr, VDMOSsNode, VDMOStempNode);
|
||||
|
||||
TSTALLOC(VDMOSTcasetcasePtr, VDMOStcaseNode, VDMOStcaseNode); /* Rthjc between tj and tcase*/
|
||||
TSTALLOC(VDMOSTcasetempPtr, VDMOStcaseNode, VDMOStempNode);
|
||||
TSTALLOC(VDMOSTemptcasePtr, VDMOStempNode, VDMOStcaseNode);
|
||||
TSTALLOC(VDMOSTptpPtr, VDMOStNodePrime, VDMOStNodePrime); /* Rthca between tcase and Vsrc */
|
||||
TSTALLOC(VDMOSTptcasePtr, VDMOStNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSTcasetpPtr, VDMOStempNode, VDMOStNodePrime);
|
||||
TSTALLOC(VDMOSCktTcktTPtr, VDMOSvcktTbranch, VDMOSvcktTbranch); /* Vsrc=cktTemp to gnd */
|
||||
TSTALLOC(VDMOSCktTtpPtr, VDMOSvcktTbranch, VDMOStNodePrime);
|
||||
TSTALLOC(VDMOSTpcktTPtr, VDMOStNodePrime, VDMOSvcktTbranch);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ Modified: 2000 AlansFixes
|
|||
VDMOS: 2018 Holger Vogt, 2020 Dietmar Warning
|
||||
**********/
|
||||
|
||||
/* perform the temperature update to the vdmos */
|
||||
|
||||
#include "ngspice/ngspice.h"
|
||||
#include "ngspice/cktdefs.h"
|
||||
#include "vdmosdefs.h"
|
||||
|
|
@ -12,11 +14,9 @@ VDMOS: 2018 Holger Vogt, 2020 Dietmar Warning
|
|||
#include "ngspice/sperror.h"
|
||||
#include "ngspice/suffix.h"
|
||||
|
||||
int
|
||||
VDMOStemp(GENmodel *inModel, CKTcircuit *ckt)
|
||||
{
|
||||
VDMOSmodel *model = (VDMOSmodel *)inModel;
|
||||
VDMOSinstance *here;
|
||||
void VDMOStempUpdate(VDMOSmodel *inModel, VDMOSinstance *here, double Temp, CKTcircuit *ckt) {
|
||||
|
||||
VDMOSmodel *model = (VDMOSmodel*)inModel;
|
||||
|
||||
double egfet,egfet1;
|
||||
double fact1,fact2;
|
||||
|
|
@ -28,199 +28,179 @@ VDMOStemp(GENmodel *inModel, CKTcircuit *ckt)
|
|||
double vt,vtnom;
|
||||
double xfc;
|
||||
|
||||
/* loop through all the resistor models */
|
||||
for( ; model != NULL; model = VDMOSnextModel(model)) {
|
||||
|
||||
fact1 = model->VDMOStnom/REFTEMP;
|
||||
vtnom = model->VDMOStnom*CONSTKoverQ;
|
||||
kt1 = CONSTboltz * model->VDMOStnom;
|
||||
egfet1 = 1.16-(7.02e-4*model->VDMOStnom*model->VDMOStnom)/
|
||||
(model->VDMOStnom+1108);
|
||||
arg1 = -egfet1/(kt1+kt1)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
||||
pbfact1 = -2*vtnom *(1.5*log(fact1)+CHARGE*arg1);
|
||||
|
||||
/* perform model defaulting */
|
||||
if(!model->VDMOStnomGiven) {
|
||||
model->VDMOStnom = ckt->CKTnomTemp;
|
||||
}
|
||||
xfc = log(1 - model->VDIOdepletionCapCoeff);
|
||||
|
||||
fact1 = model->VDMOStnom/REFTEMP;
|
||||
vtnom = model->VDMOStnom*CONSTKoverQ;
|
||||
kt1 = CONSTboltz * model->VDMOStnom;
|
||||
egfet1 = 1.16-(7.02e-4*model->VDMOStnom*model->VDMOStnom)/
|
||||
(model->VDMOStnom+1108);
|
||||
arg1 = -egfet1/(kt1+kt1)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
||||
pbfact1 = -2*vtnom *(1.5*log(fact1)+CHARGE*arg1);
|
||||
double arg; /* 1 - fc */
|
||||
|
||||
/* now model parameter preprocessing */
|
||||
if (model->VDMOSphi <= 0.0) {
|
||||
SPfrontEnd->IFerrorf(ERR_FATAL,
|
||||
"%s: Phi is not positive.", model->VDMOSmodName);
|
||||
return(E_BADPARM);
|
||||
}
|
||||
double dt = Temp - model->VDMOStnom;
|
||||
|
||||
model->VDMOSoxideCapFactor = 3.9 * 8.854214871e-12 / 1e-07; /* use default Tox of 100nm */
|
||||
/* vdmos temperature model */
|
||||
ratio = Temp/model->VDMOStnom;
|
||||
here->VDMOStTransconductance = model->VDMOStransconductance
|
||||
* here->VDMOSm * pow(ratio, model->VDMOSmu);
|
||||
|
||||
/* body diode model */
|
||||
/* limit activation energy to min of .1 */
|
||||
if (model->VDMOSeg<.1) {
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: body diode activation energy too small, limited to 0.1",
|
||||
model->VDMOSmodName);
|
||||
model->VDMOSeg = .1;
|
||||
}
|
||||
/* limit depletion cap coeff to max of .95 */
|
||||
if (model->VDIOdepletionCapCoeff>.95) {
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: coefficient Fc too large, limited to 0.95",
|
||||
model->VDMOSmodName);
|
||||
model->VDIOdepletionCapCoeff = .95;
|
||||
}
|
||||
/* set lower limit of saturation current */
|
||||
if (model->VDIOjctSatCur < ckt->CKTepsmin)
|
||||
model->VDIOjctSatCur = ckt->CKTepsmin;
|
||||
here->VDMOStVth = model->VDMOSvth0 - model->VDMOStype * model->VDMOStcvth * dt;
|
||||
|
||||
xfc = log(1 - model->VDIOdepletionCapCoeff);
|
||||
here->VDMOStksubthres = model->VDMOSksubthres * (1.0 + (model->VDMOStksubthres1 * dt) + (model->VDMOStksubthres2 * dt * dt));
|
||||
|
||||
/* loop through all instances of the model */
|
||||
for(here = VDMOSinstances(model); here!= NULL;
|
||||
here = VDMOSnextInstance(here)) {
|
||||
double arg; /* 1 - fc */
|
||||
if (model->VDMOStexp0Given)
|
||||
here->VDMOSdrainResistance = model->VDMOSdrainResistance / here->VDMOSm * pow(ratio, model->VDMOStexp0);
|
||||
else
|
||||
here->VDMOSdrainResistance = model->VDMOSdrainResistance / here->VDMOSm * (1.0 + (model->VDMOStrd1 * dt) + (model->VDMOStrd2 * dt * dt));
|
||||
|
||||
/* perform the parameter defaulting */
|
||||
if(!here->VDMOSdtempGiven) {
|
||||
here->VDMOSdtemp = 0.0;
|
||||
}
|
||||
if(!here->VDMOStempGiven) {
|
||||
here->VDMOStemp = ckt->CKTtemp + here->VDMOSdtemp;
|
||||
}
|
||||
here->VDMOSgateConductance = here->VDMOSgateConductance / (1.0 + (model->VDMOStrg1 * dt) + (model->VDMOStrg2 * dt * dt));
|
||||
|
||||
double dt = here->VDMOStemp - model->VDMOStnom;
|
||||
here->VDMOSsourceConductance = here->VDMOSsourceConductance / (1.0 + (model->VDMOStrs1 * dt) + (model->VDMOStrs2 * dt * dt));
|
||||
|
||||
/* vdmos temperature model */
|
||||
ratio = here->VDMOStemp/model->VDMOStnom;
|
||||
here->VDMOStTransconductance = model->VDMOStransconductance
|
||||
* here->VDMOSm * pow(ratio, model->VDMOSmu);
|
||||
if (model->VDMOSqsGiven)
|
||||
here->VDMOSqsResistance = model->VDMOSqsResistance / here->VDMOSm * pow(ratio, model->VDMOStexp1);
|
||||
|
||||
here->VDMOStVth = model->VDMOSvth0 - model->VDMOStype * model->VDMOStcvth * dt;
|
||||
vt = Temp * CONSTKoverQ;
|
||||
fact2 = Temp/REFTEMP;
|
||||
kt = Temp * CONSTboltz;
|
||||
egfet = 1.16-(7.02e-4*Temp*Temp)/
|
||||
(Temp+1108);
|
||||
arg = -egfet/(kt+kt)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
||||
pbfact = -2*vt *(1.5*log(fact2)+CHARGE*arg);
|
||||
|
||||
here->VDMOStksubthres = model->VDMOSksubthres * (1.0 + (model->VDMOStksubthres1 * dt) + (model->VDMOStksubthres2 * dt * dt));
|
||||
phio = (model->VDMOSphi - pbfact1) / fact1;
|
||||
here->VDMOStPhi = fact2 * phio + pbfact; /* needed for distortion analysis */
|
||||
|
||||
if (model->VDMOStexp0Given)
|
||||
here->VDMOSdrainResistance = model->VDMOSdrainResistance / here->VDMOSm * pow(ratio, model->VDMOStexp0);
|
||||
else
|
||||
here->VDMOSdrainResistance = model->VDMOSdrainResistance / here->VDMOSm * (1.0 + (model->VDMOStrd1 * dt) + (model->VDMOStrd2 * dt * dt));
|
||||
/* body diode temperature model */
|
||||
double pbo, gmaold;
|
||||
double gmanew, factor;
|
||||
double tBreakdownVoltage, vte, cbv;
|
||||
double xbv, xcbv, tol, iter;
|
||||
double arg1_dT, arg2, arg2_dT;
|
||||
|
||||
here->VDMOSgateConductance = here->VDMOSgateConductance / (1.0 + (model->VDMOStrg1 * dt) + (model->VDMOStrg2 * dt * dt));
|
||||
/* Junction grading temperature adjust */
|
||||
factor = 1.0 + (model->VDIOgradCoeffTemp1 * dt)
|
||||
+ (model->VDIOgradCoeffTemp2 * dt * dt);
|
||||
here->VDIOtGradingCoeff = model->VDIOgradCoeff * factor;
|
||||
|
||||
here->VDMOSsourceConductance = here->VDMOSsourceConductance / (1.0 + (model->VDMOStrs1 * dt) + (model->VDMOStrs2 * dt * dt));
|
||||
pbo = (model->VDIOjunctionPot - pbfact1) / fact1;
|
||||
gmaold = (model->VDIOjunctionPot - pbo) / pbo;
|
||||
here->VDIOtJctCap = here->VDMOSm * model->VDIOjunctionCap /
|
||||
(1 + here->VDIOtGradingCoeff*
|
||||
(400e-6*(model->VDMOStnom - REFTEMP) - gmaold));
|
||||
here->VDIOtJctPot = pbfact + fact2*pbo;
|
||||
gmanew = (here->VDIOtJctPot - pbo) / pbo;
|
||||
here->VDIOtJctCap *= 1 + here->VDIOtGradingCoeff*
|
||||
(400e-6*(Temp - REFTEMP) - gmanew);
|
||||
|
||||
if (model->VDMOSqsGiven)
|
||||
here->VDMOSqsResistance = model->VDMOSqsResistance / here->VDMOSm * pow(ratio, model->VDMOStexp1);
|
||||
vte = model->VDIOn*vt;
|
||||
|
||||
vt = here->VDMOStemp * CONSTKoverQ;
|
||||
fact2 = here->VDMOStemp/REFTEMP;
|
||||
kt = here->VDMOStemp * CONSTboltz;
|
||||
egfet = 1.16-(7.02e-4*here->VDMOStemp*here->VDMOStemp)/
|
||||
(here->VDMOStemp+1108);
|
||||
arg = -egfet/(kt+kt)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
||||
pbfact = -2*vt *(1.5*log(fact2)+CHARGE*arg);
|
||||
arg1 = ((Temp / model->VDMOStnom) - 1) * model->VDIOeg / vte;
|
||||
arg1_dT = model->VDIOeg / (vte*model->VDMOStnom)
|
||||
- model->VDIOeg*(Temp/model->VDMOStnom -1)/(vte*Temp);
|
||||
arg2 = model->VDIOxti / model->VDIOn * log(Temp / model->VDMOStnom);
|
||||
arg2_dT = model->VDIOxti / model->VDIOn / Temp;
|
||||
here->VDIOtSatCur = here->VDMOSm * model->VDIOjctSatCur * exp(arg1 + arg2);
|
||||
here->VDIOtSatCur_dT = here->VDMOSm * model->VDIOjctSatCur * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
||||
|
||||
phio = (model->VDMOSphi - pbfact1) / fact1;
|
||||
here->VDMOStPhi = fact2 * phio + pbfact; /* needed for distortion analysis */
|
||||
/* the defintion of f1, just recompute after temperature adjusting
|
||||
* all the variables used in it */
|
||||
here->VDIOtF1 = here->VDIOtJctPot*
|
||||
(1 - exp((1 - here->VDIOtGradingCoeff)*xfc)) /
|
||||
(1 - here->VDIOtGradingCoeff);
|
||||
/* same for Depletion Capacitance */
|
||||
here->VDIOtDepCap = model->VDIOdepletionCapCoeff *
|
||||
here->VDIOtJctPot;
|
||||
|
||||
/* body diode temperature model */
|
||||
double pbo, gmaold;
|
||||
double gmanew, factor;
|
||||
double tBreakdownVoltage, vte, cbv;
|
||||
double xbv, xcbv, tol, iter;
|
||||
/* and Vcrit */
|
||||
here->VDIOtVcrit = vte * log(vte / (CONSTroot2*here->VDIOtSatCur));
|
||||
|
||||
/* Junction grading temperature adjust */
|
||||
factor = 1.0 + (model->VDIOgradCoeffTemp1 * dt)
|
||||
+ (model->VDIOgradCoeffTemp2 * dt * dt);
|
||||
here->VDIOtGradingCoeff = model->VDIOgradCoeff * factor;
|
||||
|
||||
pbo = (model->VDIOjunctionPot - pbfact1) / fact1;
|
||||
gmaold = (model->VDIOjunctionPot - pbo) / pbo;
|
||||
here->VDIOtJctCap = here->VDMOSm * model->VDIOjunctionCap /
|
||||
(1 + here->VDIOtGradingCoeff*
|
||||
(400e-6*(model->VDMOStnom - REFTEMP) - gmaold));
|
||||
here->VDIOtJctPot = pbfact + fact2*pbo;
|
||||
gmanew = (here->VDIOtJctPot - pbo) / pbo;
|
||||
here->VDIOtJctCap *= 1 + here->VDIOtGradingCoeff*
|
||||
(400e-6*(here->VDMOStemp - REFTEMP) - gmanew);
|
||||
|
||||
here->VDIOtSatCur = here->VDMOSm * model->VDIOjctSatCur * exp(
|
||||
((here->VDMOStemp / model->VDMOStnom) - 1) *
|
||||
model->VDMOSeg / (model->VDMOSn*vt) +
|
||||
model->VDMOSxti / model->VDMOSn *
|
||||
log(here->VDMOStemp / model->VDMOStnom));
|
||||
|
||||
/* the defintion of f1, just recompute after temperature adjusting
|
||||
* all the variables used in it */
|
||||
here->VDIOtF1 = here->VDIOtJctPot*
|
||||
(1 - exp((1 - here->VDIOtGradingCoeff)*xfc)) /
|
||||
(1 - here->VDIOtGradingCoeff);
|
||||
/* same for Depletion Capacitance */
|
||||
here->VDIOtDepCap = model->VDIOdepletionCapCoeff *
|
||||
here->VDIOtJctPot;
|
||||
|
||||
/* and Vcrit */
|
||||
vte = model->VDMOSn*vt;
|
||||
|
||||
here->VDIOtVcrit = vte * log(vte / (CONSTroot2*here->VDIOtSatCur));
|
||||
|
||||
/* limit junction potential to max of 1/FC */
|
||||
if (here->VDIOtDepCap > 2.5) {
|
||||
here->VDIOtJctPot = 2.5 / model->VDMOSn;
|
||||
here->VDIOtDepCap = model->VDMOSn*here->VDIOtJctPot;
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: junction potential VJ too large, limited to %f",
|
||||
model->VDMOSmodName, here->VDIOtJctPot);
|
||||
}
|
||||
|
||||
/* and now to compute the breakdown voltage, again, using
|
||||
* temperature adjusted basic parameters */
|
||||
if (model->VDMOSbvGiven) {
|
||||
/* tlev == 0 */
|
||||
tBreakdownVoltage = fabs(model->VDMOSbv);
|
||||
|
||||
cbv = model->VDMOSibv;
|
||||
|
||||
if (cbv < here->VDIOtSatCur * tBreakdownVoltage / vt) {
|
||||
cbv = here->VDIOtSatCur * tBreakdownVoltage / vt;
|
||||
#ifdef TRACE
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING, "%s: breakdown current increased to %g to resolve", here->VDMOSname, cbv);
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"incompatibility with specified saturation current");
|
||||
#endif
|
||||
xbv = tBreakdownVoltage;
|
||||
}
|
||||
else {
|
||||
tol = ckt->CKTreltol*cbv;
|
||||
xbv = tBreakdownVoltage - model->VDIObrkdEmissionCoeff*vt*log(1 + cbv /
|
||||
(here->VDIOtSatCur));
|
||||
iter = 0;
|
||||
for (iter = 0; iter < 25; iter++) {
|
||||
xbv = tBreakdownVoltage - model->VDIObrkdEmissionCoeff*vt*log(cbv /
|
||||
(here->VDIOtSatCur) + 1 - xbv / vt);
|
||||
xcbv = here->VDIOtSatCur *
|
||||
(exp((tBreakdownVoltage - xbv) / (model->VDIObrkdEmissionCoeff*vt)) - 1 + xbv / vt);
|
||||
if (fabs(xcbv - cbv) <= tol) goto matched;
|
||||
}
|
||||
#ifdef TRACE
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING, "%s: unable to match forward and reverse diode regions: bv = %g, ibv = %g", here->VDMOSname, xbv, xcbv);
|
||||
#endif
|
||||
}
|
||||
matched:
|
||||
here->VDIOtBrkdwnV = xbv;
|
||||
}
|
||||
|
||||
/* transit time temperature adjust */
|
||||
factor = 1.0 + (model->VDIOtranTimeTemp1 * dt)
|
||||
+ (model->VDIOtranTimeTemp2 * dt * dt);
|
||||
here->VDIOtTransitTime = model->VDIOtransitTime * factor;
|
||||
|
||||
/* Series resistance temperature adjust */
|
||||
here->VDIOtConductance = here->VDIOconductance / (1.0 + (model->VDMOStrb1 * dt) + (model->VDMOStrb2 * dt * dt));
|
||||
|
||||
here->VDIOtF2 = exp((1 + here->VDIOtGradingCoeff)*xfc);
|
||||
here->VDIOtF3 = 1 - model->VDIOdepletionCapCoeff*
|
||||
(1 + here->VDIOtGradingCoeff);
|
||||
}
|
||||
/* limit junction potential to max of 1/FC */
|
||||
if (here->VDIOtDepCap > 2.5) {
|
||||
here->VDIOtJctPot = 2.5 / model->VDIOn;
|
||||
here->VDIOtDepCap = model->VDIOn*here->VDIOtJctPot;
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: junction potential VJ too large, limited to %f",
|
||||
model->VDMOSmodName, here->VDIOtJctPot);
|
||||
}
|
||||
|
||||
/* and now to compute the breakdown voltage, again, using
|
||||
* temperature adjusted basic parameters */
|
||||
if (model->VDIObvGiven) {
|
||||
/* tlev == 0 */
|
||||
tBreakdownVoltage = fabs(model->VDIObv);
|
||||
|
||||
cbv = model->VDIOibv;
|
||||
|
||||
if (cbv < here->VDIOtSatCur * tBreakdownVoltage / vt) {
|
||||
cbv = here->VDIOtSatCur * tBreakdownVoltage / vt;
|
||||
#ifdef TRACE
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING, "%s: breakdown current increased to %g to resolve", here->VDMOSname, cbv);
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"incompatibility with specified saturation current");
|
||||
#endif
|
||||
xbv = tBreakdownVoltage;
|
||||
}
|
||||
else {
|
||||
tol = ckt->CKTreltol*cbv;
|
||||
xbv = tBreakdownVoltage - model->VDIObrkdEmissionCoeff*vt*log(1 + cbv /
|
||||
(here->VDIOtSatCur));
|
||||
iter = 0;
|
||||
for (iter = 0; iter < 25; iter++) {
|
||||
xbv = tBreakdownVoltage - model->VDIObrkdEmissionCoeff*vt*log(cbv /
|
||||
(here->VDIOtSatCur) + 1 - xbv / vt);
|
||||
xcbv = here->VDIOtSatCur *
|
||||
(exp((tBreakdownVoltage - xbv) / (model->VDIObrkdEmissionCoeff*vt)) - 1 + xbv / vt);
|
||||
if (fabs(xcbv - cbv) <= tol) goto matched;
|
||||
}
|
||||
#ifdef TRACE
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING, "%s: unable to match forward and reverse diode regions: bv = %g, ibv = %g", here->VDMOSname, xbv, xcbv);
|
||||
#endif
|
||||
}
|
||||
matched:
|
||||
here->VDIOtBrkdwnV = xbv;
|
||||
}
|
||||
|
||||
/* transit time temperature adjust */
|
||||
factor = 1.0 + (model->VDIOtranTimeTemp1 * dt)
|
||||
+ (model->VDIOtranTimeTemp2 * dt * dt);
|
||||
here->VDIOtTransitTime = model->VDIOtransitTime * factor;
|
||||
|
||||
/* Series resistance temperature adjust */
|
||||
factor = 1.0 + (model->VDIOtrb1) * dt
|
||||
+ (model->VDIOtrb2 * dt * dt);
|
||||
here->VDIOtConductance = here->VDIOconductance / factor;
|
||||
here->VDIOtConductance_dT = -here->VDIOconductance * (model->VDIOtrb1 + model->VDIOtrb2 * dt) / (factor*factor);
|
||||
|
||||
here->VDIOtF2 = exp((1 + here->VDIOtGradingCoeff)*xfc);
|
||||
here->VDIOtF3 = 1 - model->VDIOdepletionCapCoeff*
|
||||
(1 + here->VDIOtGradingCoeff);
|
||||
}
|
||||
|
||||
int
|
||||
VDMOStemp(GENmodel *inModel, CKTcircuit *ckt)
|
||||
{
|
||||
VDMOSmodel *model = (VDMOSmodel*)inModel;
|
||||
VDMOSinstance *here;
|
||||
|
||||
/* loop through all the vdmos models */
|
||||
for( ; model != NULL; model = VDMOSnextModel(model)) {
|
||||
|
||||
/* loop through all the instances */
|
||||
for(here=VDMOSinstances(model);here;here=VDMOSnextInstance(here)) {
|
||||
|
||||
if(!here->VDMOSdtempGiven) here->VDMOSdtemp = 0.0;
|
||||
|
||||
if(!here->VDMOStempGiven)
|
||||
here->VDMOStemp = ckt->CKTtemp + here->VDMOSdtemp;
|
||||
|
||||
VDMOStempUpdate(model, here, here->VDMOStemp, ckt);
|
||||
|
||||
} /* instance */
|
||||
|
||||
} /* model */
|
||||
return(OK);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ VDMOStrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep)
|
|||
|
||||
CKTterr(here->VDMOSqgs,ckt,timeStep);
|
||||
CKTterr(here->VDMOSqgd,ckt,timeStep);
|
||||
CKTterr(here->VDIOcapCharge,ckt,timeStep);
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
Loading…
Reference in New Issue