You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

724 lines
28 KiB

/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Hong J. Park, Thomas L. Quarles
**********/
#include "ngspice.h"
#include "cktdefs.h"
#include "bsim2def.h"
#include "trandefs.h"
#include "const.h"
#include "sperror.h"
#include "devdefs.h"
#include "suffix.h"
int
B2load(GENmodel *inModel, CKTcircuit *ckt)
/* actually load the current value into the
* sparse matrix previously provided
*/
{
B2model *model = (B2model*)inModel;
B2instance *here;
double DrainSatCurrent;
double EffectiveLength;
double GateBulkOverlapCap;
double GateDrainOverlapCap;
double GateSourceOverlapCap;
double SourceSatCurrent;
double DrainArea;
double SourceArea;
double DrainPerimeter;
double SourcePerimeter;
double arg;
double capbd = 0.0;
double capbs = 0.0;
double cbd;
double cbhat;
double cbs;
double cd;
double cdrain;
double cdhat;
double cdreq;
double ceq;
double ceqbd;
double ceqbs;
double ceqqb;
double ceqqd;
double ceqqg;
double czbd;
double czbdsw;
double czbs;
double czbssw;
double delvbd;
double delvbs;
double delvds;
double delvgd;
double delvgs;
double evbd;
double evbs;
double gbd;
double gbs;
double gcbdb;
double gcbgb;
double gcbsb;
double gcddb;
double gcdgb;
double gcdsb;
double gcgdb;
double gcggb;
double gcgsb;
double gcsdb;
double gcsgb;
double gcssb;
double gds;
double geq;
double gm;
double gmbs;
double sarg;
double sargsw;
double vbd;
double vbs;
double vcrit;
double vds;
double vdsat;
double vgb;
double vgd;
double vgdo;
double vgs;
double von;
#ifndef PREDICTOR
double xfact;
#endif
double xnrm;
double xrev;
int Check;
double cgdb;
double cgsb;
double cbdb;
double cdgb;
double cddb;
double cdsb;
double cggb;
double cbgb;
double cbsb;
double csgb;
double cssb;
double csdb;
double PhiB;
double PhiBSW;
double MJ;
double MJSW;
double argsw;
double qgate;
double qbulk;
double qdrn;
double qsrc;
double cqgate;
double cqbulk;
double cqdrn;
double vt0;
double args[8];
int ByPass;
#ifndef NOBYPASS
double tempv;
#endif /*NOBYPASS*/
int error;
double m;
/* loop through all the B2 device models */
for( ; model != NULL; model = model->B2nextModel ) {
/* loop through all the instances of the model */
for (here = model->B2instances; here != NULL ;
here=here->B2nextInstance) {
if (here->B2owner != ARCHme) continue;
EffectiveLength=here->B2l - model->B2deltaL * 1.e-6;/* m */
DrainArea = here->B2drainArea;
SourceArea = here->B2sourceArea;
DrainPerimeter = here->B2drainPerimeter;
SourcePerimeter = here->B2sourcePerimeter;
if( (DrainSatCurrent=DrainArea*model->B2jctSatCurDensity)
< 1e-15){
DrainSatCurrent = 1.0e-15;
}
if( (SourceSatCurrent=SourceArea*model->B2jctSatCurDensity)
<1.0e-15){
SourceSatCurrent = 1.0e-15;
}
GateSourceOverlapCap = model->B2gateSourceOverlapCap *here->B2w;
GateDrainOverlapCap = model->B2gateDrainOverlapCap * here->B2w;
GateBulkOverlapCap = model->B2gateBulkOverlapCap *EffectiveLength;
von = model->B2type * here->B2von;
vdsat = model->B2type * here->B2vdsat;
vt0 = model->B2type * here->pParam->B2vt0;
Check=1;
ByPass = 0;
if((ckt->CKTmode & MODEINITSMSIG)) {
vbs= *(ckt->CKTstate0 + here->B2vbs);
vgs= *(ckt->CKTstate0 + here->B2vgs);
vds= *(ckt->CKTstate0 + here->B2vds);
} else if ((ckt->CKTmode & MODEINITTRAN)) {
vbs= *(ckt->CKTstate1 + here->B2vbs);
vgs= *(ckt->CKTstate1 + here->B2vgs);
vds= *(ckt->CKTstate1 + here->B2vds);
} else if((ckt->CKTmode & MODEINITJCT) && !here->B2off) {
vds= model->B2type * here->B2icVDS;
vgs= model->B2type * here->B2icVGS;
vbs= model->B2type * here->B2icVBS;
if((vds==0) && (vgs==0) && (vbs==0) &&
((ckt->CKTmode &
(MODETRAN|MODEAC|MODEDCOP|MODEDCTRANCURVE)) ||
(!(ckt->CKTmode & MODEUIC)))) {
vbs = -1;
vgs = vt0;
vds = 0;
}
} else if((ckt->CKTmode & (MODEINITJCT | MODEINITFIX) ) &&
(here->B2off)) {
vbs=vgs=vds=0;
} else {
#ifndef PREDICTOR
if((ckt->CKTmode & MODEINITPRED)) {
xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1];
*(ckt->CKTstate0 + here->B2vbs) =
*(ckt->CKTstate1 + here->B2vbs);
vbs = (1+xfact)* (*(ckt->CKTstate1 + here->B2vbs))
-(xfact * (*(ckt->CKTstate2 + here->B2vbs)));
*(ckt->CKTstate0 + here->B2vgs) =
*(ckt->CKTstate1 + here->B2vgs);
vgs = (1+xfact)* (*(ckt->CKTstate1 + here->B2vgs))
-(xfact * (*(ckt->CKTstate2 + here->B2vgs)));
*(ckt->CKTstate0 + here->B2vds) =
*(ckt->CKTstate1 + here->B2vds);
vds = (1+xfact)* (*(ckt->CKTstate1 + here->B2vds))
-(xfact * (*(ckt->CKTstate2 + here->B2vds)));
*(ckt->CKTstate0 + here->B2vbd) =
*(ckt->CKTstate0 + here->B2vbs)-
*(ckt->CKTstate0 + here->B2vds);
*(ckt->CKTstate0 + here->B2cd) =
*(ckt->CKTstate1 + here->B2cd);
*(ckt->CKTstate0 + here->B2cbs) =
*(ckt->CKTstate1 + here->B2cbs);
*(ckt->CKTstate0 + here->B2cbd) =
*(ckt->CKTstate1 + here->B2cbd);
*(ckt->CKTstate0 + here->B2gm) =
*(ckt->CKTstate1 + here->B2gm);
*(ckt->CKTstate0 + here->B2gds) =
*(ckt->CKTstate1 + here->B2gds);
*(ckt->CKTstate0 + here->B2gmbs) =
*(ckt->CKTstate1 + here->B2gmbs);
*(ckt->CKTstate0 + here->B2gbd) =
*(ckt->CKTstate1 + here->B2gbd);
*(ckt->CKTstate0 + here->B2gbs) =
*(ckt->CKTstate1 + here->B2gbs);
*(ckt->CKTstate0 + here->B2cggb) =
*(ckt->CKTstate1 + here->B2cggb);
*(ckt->CKTstate0 + here->B2cbgb) =
*(ckt->CKTstate1 + here->B2cbgb);
*(ckt->CKTstate0 + here->B2cbsb) =
*(ckt->CKTstate1 + here->B2cbsb);
*(ckt->CKTstate0 + here->B2cgdb) =
*(ckt->CKTstate1 + here->B2cgdb);
*(ckt->CKTstate0 + here->B2cgsb) =
*(ckt->CKTstate1 + here->B2cgsb);
*(ckt->CKTstate0 + here->B2cbdb) =
*(ckt->CKTstate1 + here->B2cbdb);
*(ckt->CKTstate0 + here->B2cdgb) =
*(ckt->CKTstate1 + here->B2cdgb);
*(ckt->CKTstate0 + here->B2cddb) =
*(ckt->CKTstate1 + here->B2cddb);
*(ckt->CKTstate0 + here->B2cdsb) =
*(ckt->CKTstate1 + here->B2cdsb);
} else {
#endif /* PREDICTOR */
vbs = model->B2type * (
*(ckt->CKTrhsOld+here->B2bNode) -
*(ckt->CKTrhsOld+here->B2sNodePrime));
vgs = model->B2type * (
*(ckt->CKTrhsOld+here->B2gNode) -
*(ckt->CKTrhsOld+here->B2sNodePrime));
vds = model->B2type * (
*(ckt->CKTrhsOld+here->B2dNodePrime) -
*(ckt->CKTrhsOld+here->B2sNodePrime));
#ifndef PREDICTOR
}
#endif /* PREDICTOR */
vbd=vbs-vds;
vgd=vgs-vds;
vgdo = *(ckt->CKTstate0 + here->B2vgs) -
*(ckt->CKTstate0 + here->B2vds);
delvbs = vbs - *(ckt->CKTstate0 + here->B2vbs);
delvbd = vbd - *(ckt->CKTstate0 + here->B2vbd);
delvgs = vgs - *(ckt->CKTstate0 + here->B2vgs);
delvds = vds - *(ckt->CKTstate0 + here->B2vds);
delvgd = vgd-vgdo;
if (here->B2mode >= 0) {
cdhat=
*(ckt->CKTstate0 + here->B2cd) -
*(ckt->CKTstate0 + here->B2gbd) * delvbd +
*(ckt->CKTstate0 + here->B2gmbs) * delvbs +
*(ckt->CKTstate0 + here->B2gm) * delvgs +
*(ckt->CKTstate0 + here->B2gds) * delvds ;
} else {
cdhat=
*(ckt->CKTstate0 + here->B2cd) -
( *(ckt->CKTstate0 + here->B2gbd) -
*(ckt->CKTstate0 + here->B2gmbs)) * delvbd -
*(ckt->CKTstate0 + here->B2gm) * delvgd +
*(ckt->CKTstate0 + here->B2gds) * delvds;
}
cbhat=
*(ckt->CKTstate0 + here->B2cbs) +
*(ckt->CKTstate0 + here->B2cbd) +
*(ckt->CKTstate0 + here->B2gbd) * delvbd +
*(ckt->CKTstate0 + here->B2gbs) * delvbs ;
#ifndef NOBYPASS
/* now lets see if we can bypass (ugh) */
/* following should be one big if connected by && all over
* the place, but some C compilers can't handle that, so
* we split it up here to let them digest it in stages
*/
tempv = MAX(fabs(cbhat),fabs(*(ckt->CKTstate0 + here->B2cbs)
+ *(ckt->CKTstate0 + here->B2cbd)))+ckt->CKTabstol;
if((!(ckt->CKTmode & MODEINITPRED)) && (ckt->CKTbypass) )
if( (fabs(delvbs) < (ckt->CKTreltol * MAX(fabs(vbs),
fabs(*(ckt->CKTstate0+here->B2vbs)))+
ckt->CKTvoltTol)) )
if ( (fabs(delvbd) < (ckt->CKTreltol * MAX(fabs(vbd),
fabs(*(ckt->CKTstate0+here->B2vbd)))+
ckt->CKTvoltTol)) )
if( (fabs(delvgs) < (ckt->CKTreltol * MAX(fabs(vgs),
fabs(*(ckt->CKTstate0+here->B2vgs)))+
ckt->CKTvoltTol)))
if ( (fabs(delvds) < (ckt->CKTreltol * MAX(fabs(vds),
fabs(*(ckt->CKTstate0+here->B2vds)))+
ckt->CKTvoltTol)) )
if( (fabs(cdhat- *(ckt->CKTstate0 + here->B2cd)) <
ckt->CKTreltol * MAX(fabs(cdhat),fabs(*(ckt->CKTstate0 +
here->B2cd))) + ckt->CKTabstol) )
if ( (fabs(cbhat-(*(ckt->CKTstate0 + here->B2cbs) +
*(ckt->CKTstate0 + here->B2cbd))) < ckt->CKTreltol *
tempv)) {
/* bypass code */
vbs = *(ckt->CKTstate0 + here->B2vbs);
vbd = *(ckt->CKTstate0 + here->B2vbd);
vgs = *(ckt->CKTstate0 + here->B2vgs);
vds = *(ckt->CKTstate0 + here->B2vds);
vgd = vgs - vds;
vgb = vgs - vbs;
cd = *(ckt->CKTstate0 + here->B2cd);
cbs = *(ckt->CKTstate0 + here->B2cbs);
cbd = *(ckt->CKTstate0 + here->B2cbd);
cdrain = here->B2mode * (cd + cbd);
gm = *(ckt->CKTstate0 + here->B2gm);
gds = *(ckt->CKTstate0 + here->B2gds);
gmbs = *(ckt->CKTstate0 + here->B2gmbs);
gbd = *(ckt->CKTstate0 + here->B2gbd);
gbs = *(ckt->CKTstate0 + here->B2gbs);
if((ckt->CKTmode & (MODETRAN | MODEAC)) ||
((ckt->CKTmode & MODETRANOP) &&
(ckt->CKTmode & MODEUIC))) {
cggb = *(ckt->CKTstate0 + here->B2cggb);
cgdb = *(ckt->CKTstate0 + here->B2cgdb);
cgsb = *(ckt->CKTstate0 + here->B2cgsb);
cbgb = *(ckt->CKTstate0 + here->B2cbgb);
cbdb = *(ckt->CKTstate0 + here->B2cbdb);
cbsb = *(ckt->CKTstate0 + here->B2cbsb);
cdgb = *(ckt->CKTstate0 + here->B2cdgb);
cddb = *(ckt->CKTstate0 + here->B2cddb);
cdsb = *(ckt->CKTstate0 + here->B2cdsb);
capbs = *(ckt->CKTstate0 + here->B2capbs);
capbd = *(ckt->CKTstate0 + here->B2capbd);
ByPass = 1;
goto line755;
} else {
goto line850;
}
}
#endif /*NOBYPASS*/
von = model->B2type * here->B2von;
if(*(ckt->CKTstate0 + here->B2vds) >=0) {
vgs = DEVfetlim(vgs,*(ckt->CKTstate0 + here->B2vgs)
,von);
vds = vgs - vgd;
vds = DEVlimvds(vds,*(ckt->CKTstate0 + here->B2vds));
vgd = vgs - vds;
} else {
vgd = DEVfetlim(vgd,vgdo,von);
vds = vgs - vgd;
vds = -DEVlimvds(-vds,-(*(ckt->CKTstate0 +
here->B2vds)));
vgs = vgd + vds;
}
if(vds >= 0) {
vcrit = CONSTvt0 *log(CONSTvt0/(CONSTroot2*SourceSatCurrent));
vbs = DEVpnjlim(vbs,*(ckt->CKTstate0 + here->B2vbs),
CONSTvt0,vcrit,&Check); /* B2 test */
vbd = vbs-vds;
} else {
vcrit = CONSTvt0 * log(CONSTvt0/(CONSTroot2*DrainSatCurrent));
vbd = DEVpnjlim(vbd,*(ckt->CKTstate0 + here->B2vbd),
CONSTvt0,vcrit,&Check); /* B2 test*/
vbs = vbd + vds;
}
}
/* determine DC current and derivatives */
vbd = vbs - vds;
vgd = vgs - vds;
vgb = vgs - vbs;
if(vbs <= 0.0 ) {
gbs = SourceSatCurrent / CONSTvt0 + ckt->CKTgmin;
cbs = gbs * vbs ;
} else {
evbs = exp(vbs/CONSTvt0);
gbs = SourceSatCurrent*evbs/CONSTvt0 + ckt->CKTgmin;
cbs = SourceSatCurrent * (evbs-1) + ckt->CKTgmin * vbs ;
}
if(vbd <= 0.0) {
gbd = DrainSatCurrent / CONSTvt0 + ckt->CKTgmin;
cbd = gbd * vbd ;
} else {
evbd = exp(vbd/CONSTvt0);
gbd = DrainSatCurrent*evbd/CONSTvt0 +ckt->CKTgmin;
cbd = DrainSatCurrent *(evbd-1)+ckt->CKTgmin*vbd;
}
/* line 400 */
if(vds >= 0) {
/* normal mode */
here->B2mode = 1;
} else {
/* inverse mode */
here->B2mode = -1;
}
/* call B2evaluate to calculate drain current and its
* derivatives and charge and capacitances related to gate
* drain, and bulk
*/
if( vds >= 0 ) {
B2evaluate(vds,vbs,vgs,here,model,&gm,&gds,&gmbs,&qgate,
&qbulk,&qdrn,&cggb,&cgdb,&cgsb,&cbgb,&cbdb,&cbsb,&cdgb,
&cddb,&cdsb,&cdrain,&von,&vdsat,ckt);
} else {
B2evaluate(-vds,vbd,vgd,here,model,&gm,&gds,&gmbs,&qgate,
&qbulk,&qsrc,&cggb,&cgsb,&cgdb,&cbgb,&cbsb,&cbdb,&csgb,
&cssb,&csdb,&cdrain,&von,&vdsat,ckt);
}
here->B2von = model->B2type * von;
here->B2vdsat = model->B2type * vdsat;
/*
* COMPUTE EQUIVALENT DRAIN CURRENT SOURCE
*/
cd=here->B2mode * cdrain - cbd;
if ((ckt->CKTmode & (MODETRAN | MODEAC | MODEINITSMSIG)) ||
((ckt->CKTmode & MODETRANOP ) &&
(ckt->CKTmode & MODEUIC))) {
/*
* charge storage elements
*
* bulk-drain and bulk-source depletion capacitances
* czbd : zero bias drain junction capacitance
* czbs : zero bias source junction capacitance
* czbdsw:zero bias drain junction sidewall capacitance
* czbssw:zero bias source junction sidewall capacitance
*/
czbd = model->B2unitAreaJctCap * DrainArea;
czbs = model->B2unitAreaJctCap * SourceArea;
czbdsw= model->B2unitLengthSidewallJctCap * DrainPerimeter;
czbssw= model->B2unitLengthSidewallJctCap * SourcePerimeter;
PhiB = model->B2bulkJctPotential;
PhiBSW = model->B2sidewallJctPotential;
MJ = model->B2bulkJctBotGradingCoeff;
MJSW = model->B2bulkJctSideGradingCoeff;
/* Source Bulk Junction */
if( vbs < 0 ) {
arg = 1 - vbs / PhiB;
argsw = 1 - vbs / PhiBSW;
sarg = exp(-MJ*log(arg));
sargsw = exp(-MJSW*log(argsw));
*(ckt->CKTstate0 + here->B2qbs) =
PhiB * czbs * (1-arg*sarg)/(1-MJ) + PhiBSW *
czbssw * (1-argsw*sargsw)/(1-MJSW);
capbs = czbs * sarg + czbssw * sargsw ;
} else {
*(ckt->CKTstate0+here->B2qbs) =
vbs*(czbs+czbssw)+ vbs*vbs*(czbs*MJ*0.5/PhiB
+ czbssw * MJSW * 0.5/PhiBSW);
capbs = czbs + czbssw + vbs *(czbs*MJ/PhiB+
czbssw * MJSW / PhiBSW );
}
/* Drain Bulk Junction */
if( vbd < 0 ) {
arg = 1 - vbd / PhiB;
argsw = 1 - vbd / PhiBSW;
sarg = exp(-MJ*log(arg));
sargsw = exp(-MJSW*log(argsw));
*(ckt->CKTstate0 + here->B2qbd) =
PhiB * czbd * (1-arg*sarg)/(1-MJ) + PhiBSW *
czbdsw * (1-argsw*sargsw)/(1-MJSW);
capbd = czbd * sarg + czbdsw * sargsw ;
} else {
*(ckt->CKTstate0+here->B2qbd) =
vbd*(czbd+czbdsw)+ vbd*vbd*(czbd*MJ*0.5/PhiB
+ czbdsw * MJSW * 0.5/PhiBSW);
capbd = czbd + czbdsw + vbd *(czbd*MJ/PhiB+
czbdsw * MJSW / PhiBSW );
}
}
/*
* check convergence
*/
if ( (here->B2off == 0) || (!(ckt->CKTmode & MODEINITFIX)) ){
if (Check == 1) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *) here;
}
}
*(ckt->CKTstate0 + here->B2vbs) = vbs;
*(ckt->CKTstate0 + here->B2vbd) = vbd;
*(ckt->CKTstate0 + here->B2vgs) = vgs;
*(ckt->CKTstate0 + here->B2vds) = vds;
*(ckt->CKTstate0 + here->B2cd) = cd;
*(ckt->CKTstate0 + here->B2cbs) = cbs;
*(ckt->CKTstate0 + here->B2cbd) = cbd;
*(ckt->CKTstate0 + here->B2gm) = gm;
*(ckt->CKTstate0 + here->B2gds) = gds;
*(ckt->CKTstate0 + here->B2gmbs) = gmbs;
*(ckt->CKTstate0 + here->B2gbd) = gbd;
*(ckt->CKTstate0 + here->B2gbs) = gbs;
*(ckt->CKTstate0 + here->B2cggb) = cggb;
*(ckt->CKTstate0 + here->B2cgdb) = cgdb;
*(ckt->CKTstate0 + here->B2cgsb) = cgsb;
*(ckt->CKTstate0 + here->B2cbgb) = cbgb;
*(ckt->CKTstate0 + here->B2cbdb) = cbdb;
*(ckt->CKTstate0 + here->B2cbsb) = cbsb;
*(ckt->CKTstate0 + here->B2cdgb) = cdgb;
*(ckt->CKTstate0 + here->B2cddb) = cddb;
*(ckt->CKTstate0 + here->B2cdsb) = cdsb;
*(ckt->CKTstate0 + here->B2capbs) = capbs;
*(ckt->CKTstate0 + here->B2capbd) = capbd;
/* bulk and channel charge plus overlaps */
if((!(ckt->CKTmode & (MODETRAN | MODEAC))) &&
((!(ckt->CKTmode & MODETRANOP)) ||
(!(ckt->CKTmode & MODEUIC))) && (!(ckt->CKTmode
& MODEINITSMSIG))) goto line850;
#ifndef NOBYPASS
line755:
#endif
if( here->B2mode > 0 ) {
args[0] = GateDrainOverlapCap;
args[1] = GateSourceOverlapCap;
args[2] = GateBulkOverlapCap;
args[3] = capbd;
args[4] = capbs;
args[5] = cggb;
args[6] = cgdb;
args[7] = cgsb;
B2mosCap(ckt,vgd,vgs,vgb,
args,
/*
GateDrainOverlapCap,
GateSourceOverlapCap,GateBulkOverlapCap,
capbd,capbs,cggb,cgdb,cgsb,
*/
cbgb,cbdb,cbsb,cdgb,cddb,cdsb
,&gcggb,&gcgdb,&gcgsb,&gcbgb,&gcbdb,&gcbsb,&gcdgb
,&gcddb,&gcdsb,&gcsgb,&gcsdb,&gcssb,&qgate,&qbulk
,&qdrn,&qsrc);
} else {
args[0] = GateSourceOverlapCap;
args[1] = GateDrainOverlapCap;
args[2] = GateBulkOverlapCap;
args[3] = capbs;
args[4] = capbd;
args[5] = cggb;
args[6] = cgsb;
args[7] = cgdb;
B2mosCap(ckt,vgs,vgd,vgb,args,
/*
GateSourceOverlapCap,
GateDrainOverlapCap,GateBulkOverlapCap,
capbs,capbd,cggb,cgsb,cgdb,
*/
cbgb,cbsb,cbdb,csgb,cssb,csdb
,&gcggb,&gcgsb,&gcgdb,&gcbgb,&gcbsb,&gcbdb,&gcsgb
,&gcssb,&gcsdb,&gcdgb,&gcdsb,&gcddb,&qgate,&qbulk
,&qsrc,&qdrn);
}
if(ByPass) goto line860;
*(ckt->CKTstate0 + here->B2qg) = qgate;
*(ckt->CKTstate0 + here->B2qd) = qdrn -
*(ckt->CKTstate0 + here->B2qbd);
*(ckt->CKTstate0 + here->B2qb) = qbulk +
*(ckt->CKTstate0 + here->B2qbd) +
*(ckt->CKTstate0 + here->B2qbs);
/* store small signal parameters */
if((!(ckt->CKTmode & (MODEAC | MODETRAN))) &&
(ckt->CKTmode & MODETRANOP ) && (ckt->CKTmode &
MODEUIC )) goto line850;
if(ckt->CKTmode & MODEINITSMSIG ) {
*(ckt->CKTstate0+here->B2cggb) = cggb;
*(ckt->CKTstate0+here->B2cgdb) = cgdb;
*(ckt->CKTstate0+here->B2cgsb) = cgsb;
*(ckt->CKTstate0+here->B2cbgb) = cbgb;
*(ckt->CKTstate0+here->B2cbdb) = cbdb;
*(ckt->CKTstate0+here->B2cbsb) = cbsb;
*(ckt->CKTstate0+here->B2cdgb) = cdgb;
*(ckt->CKTstate0+here->B2cddb) = cddb;
*(ckt->CKTstate0+here->B2cdsb) = cdsb;
*(ckt->CKTstate0+here->B2capbd) = capbd;
*(ckt->CKTstate0+here->B2capbs) = capbs;
goto line1000;
}
if(ckt->CKTmode & MODEINITTRAN ) {
*(ckt->CKTstate1+here->B2qb) =
*(ckt->CKTstate0+here->B2qb) ;
*(ckt->CKTstate1+here->B2qg) =
*(ckt->CKTstate0+here->B2qg) ;
*(ckt->CKTstate1+here->B2qd) =
*(ckt->CKTstate0+here->B2qd) ;
}
error = NIintegrate(ckt,&geq,&ceq,0.0,here->B2qb);
if(error) return(error);
error = NIintegrate(ckt,&geq,&ceq,0.0,here->B2qg);
if(error) return(error);
error = NIintegrate(ckt,&geq,&ceq,0.0,here->B2qd);
if(error) return(error);
goto line860;
line850:
/* initialize to zero charge conductance and current */
ceqqg = ceqqb = ceqqd = 0.0;
gcdgb = gcddb = gcdsb = 0.0;
gcsgb = gcsdb = gcssb = 0.0;
gcggb = gcgdb = gcgsb = 0.0;
gcbgb = gcbdb = gcbsb = 0.0;
goto line900;
line860:
/* evaluate equivalent charge current */
cqgate = *(ckt->CKTstate0 + here->B2iqg);
cqbulk = *(ckt->CKTstate0 + here->B2iqb);
cqdrn = *(ckt->CKTstate0 + here->B2iqd);
ceqqg = cqgate - gcggb * vgb + gcgdb * vbd + gcgsb * vbs;
ceqqb = cqbulk - gcbgb * vgb + gcbdb * vbd + gcbsb * vbs;
ceqqd = cqdrn - gcdgb * vgb + gcddb * vbd + gcdsb * vbs;
if(ckt->CKTmode & MODEINITTRAN ) {
*(ckt->CKTstate1 + here->B2iqb) =
*(ckt->CKTstate0 + here->B2iqb);
*(ckt->CKTstate1 + here->B2iqg) =
*(ckt->CKTstate0 + here->B2iqg);
*(ckt->CKTstate1 + here->B2iqd) =
*(ckt->CKTstate0 + here->B2iqd);
}
/*
* load current vector
*/
line900:
m = here->B2m;
ceqbs = model->B2type * (cbs-(gbs-ckt->CKTgmin)*vbs);
ceqbd = model->B2type * (cbd-(gbd-ckt->CKTgmin)*vbd);
ceqqg = model->B2type * ceqqg;
ceqqb = model->B2type * ceqqb;
ceqqd = model->B2type * ceqqd;
if (here->B2mode >= 0) {
xnrm=1;
xrev=0;
cdreq=model->B2type*(cdrain-gds*vds-gm*vgs-gmbs*vbs);
} else {
xnrm=0;
xrev=1;
cdreq = -(model->B2type)*(cdrain+gds*vds-gm*vgd-gmbs*vbd);
}
*(ckt->CKTrhs + here->B2gNode) -= m * (ceqqg);
*(ckt->CKTrhs + here->B2bNode) -= m * (ceqbs+ceqbd+ceqqb);
*(ckt->CKTrhs + here->B2dNodePrime) +=
m * (ceqbd-cdreq-ceqqd);
*(ckt->CKTrhs + here->B2sNodePrime) +=
m * (cdreq+ceqbs+ceqqg+ceqqb+ceqqd);
/*
* load y matrix
*/
*(here->B2DdPtr) += m * (here->B2drainConductance);
*(here->B2GgPtr) += m * (gcggb);
*(here->B2SsPtr) += m * (here->B2sourceConductance);
*(here->B2BbPtr) += m * (gbd+gbs-gcbgb-gcbdb-gcbsb);
*(here->B2DPdpPtr) +=
m * (here->B2drainConductance+gds+gbd+xrev*(gm+gmbs)+gcddb);
*(here->B2SPspPtr) +=
m * (here->B2sourceConductance+gds+gbs+xnrm*(gm+gmbs)+gcssb);
*(here->B2DdpPtr) += m * (-here->B2drainConductance);
*(here->B2GbPtr) += m * (-gcggb-gcgdb-gcgsb);
*(here->B2GdpPtr) += m * (gcgdb);
*(here->B2GspPtr) += m * (gcgsb);
*(here->B2SspPtr) += m * (-here->B2sourceConductance);
*(here->B2BgPtr) += m * (gcbgb);
*(here->B2BdpPtr) += m * (-gbd+gcbdb);
*(here->B2BspPtr) += m * (-gbs+gcbsb);
*(here->B2DPdPtr) += m * (-here->B2drainConductance);
*(here->B2DPgPtr) += m * ((xnrm-xrev)*gm+gcdgb);
*(here->B2DPbPtr) += m * (-gbd+(xnrm-xrev)*gmbs-gcdgb-gcddb-gcdsb);
*(here->B2DPspPtr) += m * (-gds-xnrm*(gm+gmbs)+gcdsb);
*(here->B2SPgPtr) += m * (-(xnrm-xrev)*gm+gcsgb);
*(here->B2SPsPtr) += m * (-here->B2sourceConductance);
*(here->B2SPbPtr) += m * (-gbs-(xnrm-xrev)*gmbs-gcsgb-gcsdb-gcssb);
*(here->B2SPdpPtr) += m * (-gds-xrev*(gm+gmbs)+gcsdb);
line1000: ;
} /* End of Mosfet Instance */
} /* End of Model Instance */
return(OK);
}