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.
 
 
 
 
 
 

991 lines
34 KiB

/**********
Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved.
Author: Trond Ytterdal
**********/
#include "ngspice.h"
#include "devdefs.h"
#include "cktdefs.h"
#include "mesadefs.h"
#include "const.h"
#include "trandefs.h"
#include "sperror.h"
#include "suffix.h"
/*
#define true 1
#define false 0
*/
#define EPSILONGAAS (12.244*8.85418e-12)
#define W (here->MESAwidth)
#define L (here->MESAlength)
static void mesa1(MESAmodel*, MESAinstance*, double, double, double,
double*, double*, double*, double*,double*);
static void mesa2(MESAmodel*, MESAinstance*, double, double, double,
double*, double*, double*, double*,double*);
static void mesa3(MESAmodel*, MESAinstance*, double, double, double,
double*, double*, double*, double*,double*);
void Pause(void);
int
MESAload(GENmodel *inModel, CKTcircuit *ckt)
{
MESAmodel *model = (MESAmodel*)inModel;
MESAinstance *here;
double capgd = 0.0;
double capgs = 0.0;
double cd;
double cdhat = 0.0;
double cdrain = 0.0;
double cdreq;
double ceq;
double ceqgd;
double ceqgs;
double cg;
double cgd;
double cgs;
double cghat = 0.0;
double arg;
double earg;
double delvds;
double delvgd;
double delvgs;
double delvgspp = 0.0;
double delvgdpp = 0.0;
double evgd;
double evgs;
double gds = 0.0;
double geq;
double ggd;
double ggs;
double gm = 0.0;
double ggspp = 0.0;
double cgspp = 0.0;
double ggdpp = 0.0;
double cgdpp = 0.0;
double vcrits;
double vcritd;
double vds = 0.0;
double vgd = 0.0;
double vgs = 0.0;
double vgspp = 0.0;
double vgdpp = 0.0;
double vgs1 = 0.0;
double vgd1 = 0.0;
#ifndef PREDICTOR
double xfact;
#endif
double temp;
double vted;
double vtes;
double vtd;
double vts;
double von;
double ccorr;
int inverse = FALSE;
int icheck;
int ichk1;
int error;
double m;
/* loop through all the models */
for( ; model != NULL; model = model->MESAnextModel ) {
/* loop through all the instances of the model */
for (here = model->MESAinstances; here != NULL ;
here=here->MESAnextInstance) {
if (here->MESAowner != ARCHme) continue;
/*
* dc model parameters
*/
vcrits = here->MESAvcrits;
vcritd = here->MESAvcritd;
vtd = CONSTKoverQ * here->MESAtd;
vts = CONSTKoverQ * here->MESAts;
vted = model->MESAn*vtd;
vtes = model->MESAn*vts;
/*
* initialization
*/
icheck = 1;
if( ckt->CKTmode & MODEINITSMSIG) {
vgs = *(ckt->CKTstate0 + here->MESAvgs);
vgd = *(ckt->CKTstate0 + here->MESAvgd);
vgspp = *(ckt->CKTstate0 + here->MESAvgspp);
vgdpp = *(ckt->CKTstate0 + here->MESAvgdpp);
} else if (ckt->CKTmode & MODEINITTRAN) {
vgs = *(ckt->CKTstate1 + here->MESAvgs);
vgd = *(ckt->CKTstate1 + here->MESAvgd);
vgspp = *(ckt->CKTstate1 + here->MESAvgspp);
vgdpp = *(ckt->CKTstate1 + here->MESAvgdpp);
} else if ( (ckt->CKTmode & MODEINITJCT) &&
(ckt->CKTmode & MODETRANOP) &&
(ckt->CKTmode & MODEUIC) ) {
vds = here->MESAicVDS;
vgs = here->MESAicVGS;
vgd = vgs-vds;
vgspp = vgs;
vgdpp = vgd;
} else if ( (ckt->CKTmode & MODEINITJCT) &&
(here->MESAoff == 0) ) {
vgs = -1;
vgd = -1;
vgspp = 0;
vgdpp = 0;
} else if( (ckt->CKTmode & MODEINITJCT) ||
((ckt->CKTmode & MODEINITFIX) && (here->MESAoff))) {
vgs = 0;
vgd = 0;
vgspp = 0;
vgdpp = 0;
} else {
#ifndef PREDICTOR
if(ckt->CKTmode & MODEINITPRED) {
xfact = ckt->CKTdelta/ckt->CKTdeltaOld[2];
*(ckt->CKTstate0 + here->MESAvgs) =
*(ckt->CKTstate1 + here->MESAvgs);
vgs = (1+xfact) * *(ckt->CKTstate1 + here->MESAvgs) -
xfact * *(ckt->CKTstate2 + here->MESAvgs);
*(ckt->CKTstate0 + here->MESAvgspp) =
*(ckt->CKTstate1 + here->MESAvgspp);
vgspp = (1+xfact) * *(ckt->CKTstate1 + here->MESAvgspp) -
xfact * *(ckt->CKTstate2 + here->MESAvgspp);
*(ckt->CKTstate0 + here->MESAvgd) =
*(ckt->CKTstate1 + here->MESAvgd);
vgd = (1+xfact)* *(ckt->CKTstate1 + here->MESAvgd) -
xfact * *(ckt->CKTstate2 + here->MESAvgd);
*(ckt->CKTstate0 + here->MESAvgdpp) =
*(ckt->CKTstate1 + here->MESAvgdpp);
vgdpp = (1+xfact) * *(ckt->CKTstate1 + here->MESAvgdpp) -
xfact * *(ckt->CKTstate2 + here->MESAvgdpp);
*(ckt->CKTstate0 + here->MESAcg) =
*(ckt->CKTstate1 + here->MESAcg);
*(ckt->CKTstate0 + here->MESAcd) =
*(ckt->CKTstate1 + here->MESAcd);
*(ckt->CKTstate0 + here->MESAcgd) =
*(ckt->CKTstate1 + here->MESAcgd);
*(ckt->CKTstate0 + here->MESAcgs) =
*(ckt->CKTstate1 + here->MESAcgs);
*(ckt->CKTstate0 + here->MESAgm) =
*(ckt->CKTstate1 + here->MESAgm);
*(ckt->CKTstate0 + here->MESAgds) =
*(ckt->CKTstate1 + here->MESAgds);
*(ckt->CKTstate0 + here->MESAggs) =
*(ckt->CKTstate1 + here->MESAggs);
*(ckt->CKTstate0 + here->MESAggd) =
*(ckt->CKTstate1 + here->MESAggd);
*(ckt->CKTstate0 + here->MESAggspp) =
*(ckt->CKTstate1 + here->MESAggspp);
*(ckt->CKTstate0 + here->MESAcgspp) =
*(ckt->CKTstate1 + here->MESAcgspp);
*(ckt->CKTstate0 + here->MESAggdpp) =
*(ckt->CKTstate1 + here->MESAggdpp);
*(ckt->CKTstate0 + here->MESAcgdpp) =
*(ckt->CKTstate1 + here->MESAcgdpp);
} else {
#endif /* PREDICTOR */
/*
* compute new nonlinear branch voltages
*/
vgs = (*(ckt->CKTrhsOld+ here->MESAgatePrimeNode)-
*(ckt->CKTrhsOld+here->MESAsourcePrimeNode));
vgd = (*(ckt->CKTrhsOld+here->MESAgatePrimeNode)-
*(ckt->CKTrhsOld+here->MESAdrainPrimeNode));
vgspp = (*(ckt->CKTrhsOld+here->MESAgatePrimeNode)-
*(ckt->CKTrhsOld+here->MESAsourcePrmPrmNode));
vgdpp = (*(ckt->CKTrhsOld+here->MESAgatePrimeNode)-
*(ckt->CKTrhsOld+here->MESAdrainPrmPrmNode));
#ifndef PREDICTOR
}
#endif /* PREDICTOR */
delvgs=vgs - *(ckt->CKTstate0 + here->MESAvgs);
delvgd=vgd - *(ckt->CKTstate0 + here->MESAvgd);
delvds=delvgs - delvgd;
delvgspp = vgspp - *(ckt->CKTstate0 + here->MESAvgspp);
delvgdpp = vgdpp - *(ckt->CKTstate0 + here->MESAvgdpp);
cghat= *(ckt->CKTstate0 + here->MESAcg) +
*(ckt->CKTstate0 + here->MESAggd)*delvgd +
*(ckt->CKTstate0 + here->MESAggs)*delvgs +
*(ckt->CKTstate0 + here->MESAggspp)*delvgspp+
*(ckt->CKTstate0 + here->MESAggdpp)*delvgdpp;
cdhat= *(ckt->CKTstate0 + here->MESAcd) +
*(ckt->CKTstate0 + here->MESAgm)*delvgs +
*(ckt->CKTstate0 + here->MESAgds)*delvds -
*(ckt->CKTstate0 + here->MESAggd)*delvgd;
/*
* bypass if solution has not changed
*/
if((ckt->CKTbypass) &&
(!(ckt->CKTmode & MODEINITPRED)) &&
(fabs(delvgs) < ckt->CKTreltol*MAX(fabs(vgs),
fabs(*(ckt->CKTstate0 + here->MESAvgs)))+
ckt->CKTvoltTol) )
if((fabs(delvgd) < ckt->CKTreltol*MAX(fabs(vgd),
fabs(*(ckt->CKTstate0 + here->MESAvgd)))+
ckt->CKTvoltTol))
if((fabs(delvgspp) < ckt->CKTreltol*MAX(fabs(vgspp),
fabs(*(ckt->CKTstate0 + here->MESAvgspp)))+
ckt->CKTvoltTol))
if((fabs(delvgdpp) < ckt->CKTreltol*MAX(fabs(vgdpp),
fabs(*(ckt->CKTstate0 + here->MESAvgdpp)))+
ckt->CKTvoltTol))
if((fabs(cghat-*(ckt->CKTstate0 + here->MESAcg))
< ckt->CKTreltol*MAX(fabs(cghat),
fabs(*(ckt->CKTstate0 + here->MESAcg)))+
ckt->CKTabstol))
if((fabs(cdhat-*(ckt->CKTstate0 + here->MESAcd))
< ckt->CKTreltol*MAX(fabs(cdhat),
fabs(*(ckt->CKTstate0 + here->MESAcd)))+
ckt->CKTabstol)) {
/* we can do a bypass */
vgs= *(ckt->CKTstate0 + here->MESAvgs);
vgd= *(ckt->CKTstate0 + here->MESAvgd);
vds= vgs-vgd;
vgspp = *(ckt->CKTstate0 + here->MESAvgspp);
vgdpp = *(ckt->CKTstate0 + here->MESAvgdpp);
cg= *(ckt->CKTstate0 + here->MESAcg);
cd= *(ckt->CKTstate0 + here->MESAcd);
cgs= *(ckt->CKTstate0 + here->MESAcgs);
cgd= *(ckt->CKTstate0 + here->MESAcgd);
gm= *(ckt->CKTstate0 + here->MESAgm);
gds= *(ckt->CKTstate0 + here->MESAgds);
ggs= *(ckt->CKTstate0 + here->MESAggs);
ggd= *(ckt->CKTstate0 + here->MESAggd);
ggspp = *(ckt->CKTstate0 + here->MESAggspp);
cgspp = *(ckt->CKTstate0 + here->MESAcgspp);
ggdpp = *(ckt->CKTstate0 + here->MESAggdpp);
cgdpp = *(ckt->CKTstate0 + here->MESAcgdpp);
goto load;
}
/*
* limit nonlinear branch voltages
*/
ichk1=1;
vgs = DEVpnjlim(vgs,*(ckt->CKTstate0 + here->MESAvgs),vtes,
vcrits, &icheck);
vgd = DEVpnjlim(vgd,*(ckt->CKTstate0 + here->MESAvgd),vted,
vcritd,&ichk1);
if (ichk1 == 1) {
icheck=1;
}
vgs = DEVfetlim(vgs,*(ckt->CKTstate0 + here->MESAvgs),
here->MESAtVto);
vgd = DEVfetlim(vgd,*(ckt->CKTstate0 + here->MESAvgd),
here->MESAtVto);
if(here->MESAsourcePrmPrmNode == here->MESAsourcePrimeNode)
vgspp = vgs;
if(here->MESAdrainPrmPrmNode == here->MESAdrainPrimeNode)
vgdpp = vgd;
}
/*
* determine dc current and derivatives
*/
vds = vgs-vgd;
arg = -vgs*model->MESAdel/vts;
earg = exp(arg);
evgs = exp(vgs/vtes);
ggs = here->MESAcsatfs*evgs/vtes+here->MESAggrwl*earg*(1-arg)+ckt->CKTgmin;
cgs = here->MESAcsatfs*(evgs-1)+here->MESAggrwl*vgs*earg+
ckt->CKTgmin*vgs;
cg = cgs;
arg = -vgd*model->MESAdel/vtd;
earg = exp(arg);
evgd = exp(vgd/vted);
ggd = here->MESAcsatfd*evgd/vted+here->MESAggrwl*earg*(1-arg)+ckt->CKTgmin;
cgd = here->MESAcsatfd*(evgd-1)+here->MESAggrwl*vgd*earg+
ckt->CKTgmin*vgd;
cg = cg+cgd;
if(vds < 0) {
vds = -vds;
inverse = TRUE;
}
von = here->MESAtVto+model->MESAks*(*(ckt->CKTrhsOld+here->MESAsourcePrimeNode)-model->MESAvsg);
if(model->MESAlevel == 2)
mesa1(model,here,inverse?vgd:vgs,vds,von,&cdrain,&gm,&gds,&capgs,&capgd);
else if(model->MESAlevel == 3)
mesa2(model,here,inverse?vgd:vgs,vds,von,&cdrain,&gm,&gds,&capgs,&capgd);
else if(model->MESAlevel == 4)
mesa3(model,here,inverse?vgd:vgs,vds,von,&cdrain,&gm,&gds,&capgs,&capgd);
if(inverse) {
cdrain = -cdrain;
vds = -vds;
temp = capgs;
capgs = capgd;
capgd = temp;
}
/*
* compute equivalent drain current source
*/
cd = cdrain - cgd;
if ( (ckt->CKTmode & (MODETRAN|MODEINITSMSIG)) ||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) ){
/*
* charge storage elements
*/
vgs1 = *(ckt->CKTstate1 + here->MESAvgspp);
vgd1 = *(ckt->CKTstate1 + here->MESAvgdpp);
if(ckt->CKTmode & MODEINITTRAN) {
*(ckt->CKTstate1 + here->MESAqgs) = capgs*vgspp;
*(ckt->CKTstate1 + here->MESAqgd) = capgd*vgdpp;
}
*(ckt->CKTstate0+here->MESAqgs) = *(ckt->CKTstate1 + here->MESAqgs) +
capgs*(vgspp-vgs1);
*(ckt->CKTstate0+here->MESAqgd) = *(ckt->CKTstate1 + here->MESAqgd) +
capgd*(vgdpp-vgd1);
/*
* store small-signal parameters
*/
if( (!(ckt->CKTmode & MODETRANOP)) ||
(!(ckt->CKTmode & MODEUIC)) ) {
if(ckt->CKTmode & MODEINITSMSIG) {
*(ckt->CKTstate0 + here->MESAqgs) = capgs;
*(ckt->CKTstate0 + here->MESAqgd) = capgd;
continue; /*go to 1000*/
}
/*
* transient analysis
*/
if(ckt->CKTmode & MODEINITTRAN) {
*(ckt->CKTstate1 + here->MESAqgs) =
*(ckt->CKTstate0 + here->MESAqgs);
*(ckt->CKTstate1 + here->MESAqgd) =
*(ckt->CKTstate0 + here->MESAqgd);
}
error = NIintegrate(ckt,&geq,&ceq,capgs,here->MESAqgs);
if(error) return(error);
ggspp = geq;
cgspp = *(ckt->CKTstate0 + here->MESAcqgs);
cg = cg + cgspp;
error = NIintegrate(ckt,&geq,&ceq,capgd,here->MESAqgd);
if(error) return(error);
ggdpp = geq;
cgdpp = *(ckt->CKTstate0 + here->MESAcqgd);
cg = cg + cgdpp;
cd = cd - cgdpp;
if (ckt->CKTmode & MODEINITTRAN) {
*(ckt->CKTstate1 + here->MESAcqgs) =
*(ckt->CKTstate0 + here->MESAcqgs);
*(ckt->CKTstate1 + here->MESAcqgd) =
*(ckt->CKTstate0 + here->MESAcqgd);
}
}
}
/*
* check convergence
*/
if( (!(ckt->CKTmode & MODEINITFIX)) | (!(ckt->CKTmode & MODEUIC))) {
if( (icheck == 1)
|| (fabs(cghat-cg) >= ckt->CKTreltol*
MAX(fabs(cghat),fabs(cg))+ckt->CKTabstol) ||
(fabs(cdhat-cd) > ckt->CKTreltol*
MAX(fabs(cdhat),fabs(cd))+ckt->CKTabstol)
) {
ckt->CKTnoncon++;
}
}
*(ckt->CKTstate0 + here->MESAvgs) = vgs;
*(ckt->CKTstate0 + here->MESAvgspp) = vgspp;
*(ckt->CKTstate0 + here->MESAvgd) = vgd;
*(ckt->CKTstate0 + here->MESAvgdpp) = vgdpp;
*(ckt->CKTstate0 + here->MESAcg) = cg;
*(ckt->CKTstate0 + here->MESAcd) = cd;
*(ckt->CKTstate0 + here->MESAcgd) = cgd;
*(ckt->CKTstate0 + here->MESAcgs) = cgs;
*(ckt->CKTstate0 + here->MESAgm) = gm;
*(ckt->CKTstate0 + here->MESAgds) = gds;
*(ckt->CKTstate0 + here->MESAggs) = ggs;
*(ckt->CKTstate0 + here->MESAggd) = ggd;
*(ckt->CKTstate0 + here->MESAggspp) = ggspp;
*(ckt->CKTstate0 + here->MESAcgspp) = cgspp;
*(ckt->CKTstate0 + here->MESAggdpp) = ggdpp;
*(ckt->CKTstate0 + here->MESAcgdpp) = cgdpp;
/*
* load current vector
*/
load:
m = here->MESAm;
ccorr = model->MESAag*(cgs-cgd);
ceqgd = cgd + cgdpp - ggd*vgd - ggdpp*vgdpp;
ceqgs = cgs + cgspp - ggs*vgs - ggspp*vgspp;
cdreq=((cd+cgd+cgdpp)-gds*vds-gm*vgs);
*(ckt->CKTrhs + here->MESAgatePrimeNode) += m * (-ceqgs-ceqgd);
ceqgd = (cgd-ggd*vgd);
*(ckt->CKTrhs + here->MESAdrainPrimeNode) += m * (-cdreq+ceqgd+ccorr);
ceqgd = (cgdpp-ggdpp*vgdpp);
*(ckt->CKTrhs + here->MESAdrainPrmPrmNode) += ceqgd;
ceqgs = (cgs-ggs*vgs);
*(ckt->CKTrhs + here->MESAsourcePrimeNode) += m * (cdreq+ceqgs-ccorr);
ceqgs = (cgspp-ggspp*vgspp);
*(ckt->CKTrhs + here->MESAsourcePrmPrmNode) += ceqgs;
/*
* load y matrix
*/
*(here->MESAdrainDrainPtr) += m * (here->MESAdrainConduct);
*(here->MESAsourceSourcePtr) += m * (here->MESAsourceConduct);
*(here->MESAgateGatePtr) += m * (here->MESAgateConduct);
*(here->MESAsourcePrmPrmSourcePrmPrmPtr) += m * (here->MESAtGi+ggspp);
*(here->MESAdrainPrmPrmDrainPrmPrmPtr) += m * (here->MESAtGf+ggdpp);
*(here->MESAgatePrimeGatePrimePtr) += m * (ggd+ggs+here->MESAgateConduct+ggspp+ggdpp);
*(here->MESAdrainPrimeDrainPrimePtr) += m * (gds+ggd+here->MESAdrainConduct+here->MESAtGf);
*(here->MESAsourcePrimeSourcePrimePtr) += m * (gds+gm+ggs+here->MESAsourceConduct+here->MESAtGi);
*(here->MESAdrainDrainPrimePtr) -= m * (here->MESAdrainConduct);
*(here->MESAdrainPrimeDrainPtr) -= m * (here->MESAdrainConduct);
*(here->MESAsourceSourcePrimePtr) -= m * (here->MESAsourceConduct);
*(here->MESAsourcePrimeSourcePtr) -= m * (here->MESAsourceConduct);
*(here->MESAgateGatePrimePtr) -= m * (here->MESAgateConduct);
*(here->MESAgatePrimeGatePtr) -= m * (here->MESAgateConduct);
*(here->MESAgatePrimeDrainPrimePtr) -= m * (ggd);
*(here->MESAgatePrimeSourcePrimePtr) -= m * (ggs);
*(here->MESAdrainPrimeGatePrimePtr) += m * (gm-ggd);
*(here->MESAdrainPrimeSourcePrimePtr) += m * (-gds-gm);
*(here->MESAsourcePrimeGatePrimePtr) += m * (-ggs-gm);
*(here->MESAsourcePrimeDrainPrimePtr) -= m * (gds);
*(here->MESAsourcePrimeSourcePrmPrmPtr) -= m * (here->MESAtGi);
*(here->MESAsourcePrmPrmSourcePrimePtr) -= m * (here->MESAtGi);
*(here->MESAgatePrimeSourcePrmPrmPtr) -= m * (ggspp);
*(here->MESAsourcePrmPrmGatePrimePtr) -= m * (ggspp);
*(here->MESAdrainPrimeDrainPrmPrmPtr) -= m * (here->MESAtGf);
*(here->MESAdrainPrmPrmDrainPrimePtr) -= m * (here->MESAtGf);
*(here->MESAgatePrimeDrainPrmPrmPtr) -= m * (ggdpp);
*(here->MESAdrainPrmPrmGatePrimePtr) -= m * (ggdpp);
}
}
return(OK);
}
#define ETA (here->MESAtEta)
#define MU0 (here->MESAtMu)
#define RS (here->MESAtRsi)
#define RD (here->MESAtRdi)
#define SIGMA0 (model->MESAsigma0)
#define VSIGMAT (model->MESAvsigmat)
#define VSIGMA (model->MESAvsigma)
#define THETA (model->MESAtheta)
#define VS (model->MESAvs)
#define ND (model->MESAnd)
#define D (model->MESAd)
#define TC (model->MESAtc)
#define MC (model->MESAmc)
#define M0 (model->MESAm)
#define ALPHA (model->MESAalpha)
#define LAMBDA (here->MESAtLambda)
#define NDELTA (model->MESAndelta)
#define TH (model->MESAth)
#define NDU (model->MESAndu)
#define DU (model->MESAdu)
#define NMAX (model->MESAnmax)
#define GAMMA (model->MESAgamma)
static void mesa1(MESAmodel *model, MESAinstance *here, double vgs,
double vds, double von, double *cdrain,
double *gm, double *gds, double *capgs, double *capgd)
{
double vt;
double etavth;
double vl;
double rt;
double mu;
double beta;
double vgt;
double vgt0;
double sigma;
double vgte;
double isat;
double isata;
double isatb;
double ns;
double a;
double b;
double c;
double d;
double e;
double f;
double g;
double h;
double m;
double p;
double q;
double r;
double s;
double t;
double u;
double v;
double w;
double temp;
double gch;
double gchi;
double vsate;
double vdse;
double cgc;
double sqrt1;
double delidgch;
double delgchgchi;
double delgchins;
double delnsvgt;
double delnsvgte;
double delvgtevgt;
double delidvsate;
double delvsateisat;
double delisatisata;
double delisatavgte;
double delisatabeta;
double delisatisatb;
double delvsategch;
double delidvds;
double ddevgte;
double dvgtvgs;
double dgchivgt;
double dvgtevds;
double dgchivds;
double disatavgt;
double disatavds;
double disatbvgt;
double dvsatevgt;
double dvsatevds;
double gmmadd;
double gdsmadd;
vt = CONSTKoverQ * here->MESAts;
etavth = ETA*vt;
rt = RS+RD;
vgt0 = vgs - von;
s = exp((vgt0-VSIGMAT)/VSIGMA);
sigma = SIGMA0/(1+s);
vgt = vgt0+sigma*vds;
mu = MU0+THETA*vgt;
vl = VS/mu*here->MESAlength;
beta = here->MESAbeta/(model->MESAvpo+3*vl);
u = vgt/vt-1;
t = sqrt(model->MESAdeltaSqr+u*u);
vgte = 0.5*vt*(2+u+t);
a = 2*beta*vgte;
b = exp(-vgt/etavth);
if(vgte > model->MESAvpo)
sqrt1 = 0;
else
sqrt1 = sqrt(1-vgte/model->MESAvpo);
ns = 1.0/(1.0/ND/D/(1-sqrt1) + 1.0/here->MESAn0*b);
if(ns < 1.0e-38) {
*cdrain = 0;
*gm = 0.0;
*gds = 0.0;
*capgs = here->MESAcf;
*capgd = here->MESAcf;
return;
}
gchi = here->MESAgchi0*mu*ns;
gch = gchi/(1+gchi*rt);
f = sqrt(1+2*a*RS);
d = 1+a*RS + f;
e = 1+TC*vgte;
isata = a*vgte/(d*e);
isatb = here->MESAisatb0*mu*exp(vgt/etavth);
isat = isata*isatb/(isata+isatb);
vsate = isat/gch;
vdse = vds*pow(1+pow(vds/vsate,MC),-1.0/MC);
m = M0+ALPHA*vgte;
g = pow(vds/vsate,m);
h = pow(1+g,1.0/m);
here->MESAdelidgch0 = vds/h;
delidgch = here->MESAdelidgch0*(1+LAMBDA*vds);
*cdrain = gch*delidgch;
if(vgt > model->MESAvpo)
temp = 0;
else
temp = sqrt(1-vgt/model->MESAvpo);
cgc = W*L*EPSILONGAAS/(temp+b)/D;
c = (vsate-vdse)/(2*vsate-vdse);
c = c*c;
*capgs = here->MESAcf+2.0/3.0*cgc*(1-c);
c = vsate/(2*vsate-vdse);
c = c*c;
*capgd = here->MESAcf+2.0/3.0*cgc*(1-c);
temp = 1+gchi*rt;
delgchgchi = 1.0/(temp*temp);
delgchins = here->MESAgchi0*mu;
delnsvgt = ns*ns*1.0/here->MESAn0/etavth*b;
q = 1 - sqrt1;
if(sqrt1 == 0)
delnsvgte = 0;
else
delnsvgte = 0.5*ns*ns/(model->MESAvpo*ND*D*sqrt1*q*q);
delvgtevgt = 0.5*(1+u/t);
here->MESAdelidvds0 = gch/h;
if(vds != 0.0)
here->MESAdelidvds1 = (*cdrain)*pow(vds/vsate,m-1)/(vsate*(1+g));
else
here->MESAdelidvds1 = 0.0;
delidvds = here->MESAdelidvds0*(1+2*LAMBDA*vds) - here->MESAdelidvds1;
delidvsate = (*cdrain)*g/(vsate*(1+g));
delvsateisat = 1.0/gch;
r = isata+isatb;
r = r*r;
delisatisata = isatb*isatb/r;
v = 1.0+1.0/f;
ddevgte = 2*beta*RS*v*e+d*TC;
temp = d*d*e*e;
delisatavgte = (2*a*d*e - a*vgte*ddevgte)/temp;
delisatabeta = 2*vgte*vgte*(d*e-a*e*RS*v)/temp;
delisatisatb = isata*isata/r;
delvsategch = -vsate/gch;
dvgtvgs = 1 - SIGMA0*vds*s/VSIGMA/((1+s)*(1+s));
temp = here->MESAgchi0*ns*THETA;
dgchivgt = delgchins*(delnsvgte*delvgtevgt+delnsvgt)+temp;
dvgtevds = delvgtevgt*sigma;
dgchivds = delgchins*(delnsvgte*dvgtevds+delnsvgt*sigma)+temp*sigma;
temp = delisatabeta*3*beta*vl*THETA/(mu*(model->MESAvpo+3*vl));
disatavgt = delisatavgte*delvgtevgt+temp;
disatavds = delisatavgte*dvgtevds+temp*sigma;
disatbvgt = isatb/etavth+isatb/mu*THETA;
p = delgchgchi*dgchivgt;
w = delgchgchi*dgchivds;
dvsatevgt = delvsateisat*(delisatisata*disatavgt+delisatisatb*disatbvgt)+delvsategch*p;
dvsatevds = delvsateisat*(delisatisata*disatavds+delisatisatb*disatbvgt*sigma)+delvsategch*w;
if(ALPHA != 0) {
if(vds == 0)
gmmadd = 0;
else
gmmadd = (*cdrain)*(log(1+g)/(m*m)-g*log(vds/vsate)/(m*(1+g)))*
ALPHA*delvgtevgt;
gdsmadd = gmmadd*sigma;
} else {
gmmadd = 0;
gdsmadd = 0;
}
here->MESAgm0 = p;
here->MESAgm1 = delidvsate*dvsatevgt;
here->MESAgm2 = dvgtvgs;
g = delidgch*p+here->MESAgm1;
*gm = (g+gmmadd)*dvgtvgs;
here->MESAgds0 = delidvsate*dvsatevds+delidgch*w+gdsmadd;
*gds = delidvds+here->MESAgds0;
}
static void mesa2(MESAmodel *model, MESAinstance *here, double vgs,
double vds, double von, double *cdrain, double *gm,
double *gds, double *capgs, double *capgd)
{
double vt;
double rt;
double vgt;
double etavth;
double vgt0;
double sigma;
double vgte;
double isat;
double isata;
double isatb;
double nsa;
double nsb;
double ns;
double a;
double b;
double c;
double d;
double e;
double f;
double g;
double h;
double p;
double q;
double r;
double s;
double t;
double gch;
double gchi;
double vsate;
double vdse;
double ca;
double cb;
double cgc;
double delidgch;
double delgchgchi;
double delgchins;
double delnsvgt;
double delnsbvgt;
double delnsavgte;
double delvgtevgt;
double delidvsate;
double delvsateisat;
double delisatisata;
double delisatavgte;
double delisatisatb;
double delvsategch;
double delisatbvgt;
double delvsatevgt;
double delidvds;
double ddevgte;
double delvgtvgs;
vt = CONSTKoverQ * here->MESAts;
etavth = ETA*vt;
rt = RS+RD;
vgt0 = vgs - von;
s = exp((vgt0-VSIGMAT)/VSIGMA);
sigma = SIGMA0/(1+s);
vgt = vgt0+sigma*vds;
t = vgt/vt-1;
q = sqrt(model->MESAdeltaSqr+t*t);
vgte = 0.5*vt*(2+t+q);
a = 2*model->MESAbeta*vgte;
if(vgt > model->MESAvpod) {
if(vgte > model->MESAvpo) {
nsa = NDELTA*TH + NDU*DU;
ca = EPSILONGAAS/DU;
delnsavgte = 0;
} else {
r = sqrt((model->MESAvpo-vgte)/model->MESAvpou);
nsa = NDELTA*TH + NDU*DU*(1-r);
ca = EPSILONGAAS/DU/r;
delnsavgte = NDU*DU/model->MESAvpou/2.0/r;
}
} else {
if(model->MESAvpod - vgte < 0) {
nsa = NDELTA*TH*(1-DU/TH);
ca = EPSILONGAAS/DU;
delnsavgte = 0;
} else {
r = sqrt(1+NDU/NDELTA*(model->MESAvpod - vgte)/model->MESAvpou);
nsa = NDELTA*TH*(1-DU/TH*(r-1));
ca = EPSILONGAAS/DU/r;
delnsavgte = DU*NDU/2.0/model->MESAvpou/r;
}
}
b = exp(vgt/etavth);
cb = EPSILONGAAS/(DU+TH)*b;
nsb = here->MESAnsb0*b;
delnsbvgt = nsb/etavth;
ns = nsa*nsb/(nsa+nsb);
if(ns < 1.0e-38) {
*cdrain = 0;
*gm = 0.0;
*gds = 0.0;
*capgs = here->MESAcf;
*capgd = here->MESAcf;
return;
}
gchi = here->MESAgchi0*ns;
gch = gchi/(1+gchi*rt);
f = sqrt(1+2*a*RS);
d = 1+a*RS + f;
e = 1+TC*vgte;
isata = a*vgte/d/e;
isatb = here->MESAisatb0*b;
isat = isata*isatb/(isata+isatb);
vsate = isat/gch;
vdse = vds*pow(1+pow(vds/vsate,MC),-1.0/MC);
g = pow(vds/vsate,M0);
h = pow(1+g,1.0/M0);
here->MESAdelidgch0 = vds/h;
delidgch = here->MESAdelidgch0*(1+LAMBDA*vds);
*cdrain = gch*delidgch;
cgc = W*L*ca*cb/(ca+cb);
c = (vsate-vdse)/(2*vsate-vdse);
c = c*c;
*capgs = here->MESAcf+2.0/3.0*cgc*(1-c);
c = vsate/(2*vsate-vdse);
c = c*c;
*capgd = here->MESAcf+2.0/3.0*cgc*(1-c);
c = vgt/vt-1;
delvgtevgt = 0.5*(1+t/q);
here->MESAdelidvds0 = gch/h;
if(vds != 0.0)
here->MESAdelidvds1 = (*cdrain)*pow(vds/vsate,M0-1)/vsate/(1+g);
else
here->MESAdelidvds1 = 0.0;
delidvds = here->MESAdelidvds0*(1+2*LAMBDA*vds) -
here->MESAdelidvds1;
delgchgchi = 1.0/(1+gchi*rt)/(1+gchi*rt);
delgchins = here->MESAgchi0;
r = nsa+nsb;
r = r*r;
delnsvgt = (nsb*nsb*delvgtevgt*delnsavgte + nsa*nsa*delnsbvgt)/r;
delidvsate = (*cdrain)*g/vsate/(1+g);
delvsateisat = 1.0/gch;
r = isata+isatb;
r = r*r;
delisatisata = isatb*isatb/r;
ddevgte = 2*model->MESAbeta*RS*(1+1.0/f)*e+d*TC;
delisatavgte = (2*a*d*e - a*vgte*ddevgte)/d/d/e/e;
delisatisatb = isata*isata/r;
delisatbvgt = isatb/etavth;
delvsategch = -vsate/gch;
delvgtvgs = 1-SIGMA0*vds*s/VSIGMA/(1+s)/(1+s);
p = delgchgchi*delgchins*delnsvgt;
delvsatevgt = delvsateisat*(delisatisata*delisatavgte*delvgtevgt +
delisatisatb*delisatbvgt) + delvsategch*p;
here->MESAgm0 = p;
here->MESAgm1 = delidvsate*delvsatevgt;
here->MESAgm2 = delvgtvgs;
g = delidgch*p + here->MESAgm1;
*gm = g*delvgtvgs;
here->MESAgds0 = g*sigma;
*gds = delidvds+here->MESAgds0;
}
static void mesa3(MESAmodel *model, MESAinstance *here, double vgs,
double vds, double von, double *cdrain, double *gm,
double *gds, double *capgs, double *capgd)
{
double vt;
double vgt;
double vgt0;
double sigma;
double vgte;
double isat;
double isatm;
double ns;
double nsm;
double a;
double b;
double c;
double d;
double e;
double g;
double h;
double p;
double q;
double s;
double t;
double u;
double temp;
double etavth;
double gch;
double gchi;
double gchim;
double vsate;
double vdse;
double cgc;
double cgcm;
double rt;
double vl;
double delidgch;
double delgchgchi;
double delgchins;
double delnsnsm;
double delnsmvgt;
double delvgtevgt;
double delidvsate;
double delvsateisat;
double delisatisatm;
double delisatmvgte;
double delisatmgchim;
double delvsategch;
double delidvds;
double delvgtvgs;
double delvsatevgt;
vt = CONSTKoverQ * here->MESAts;
etavth = ETA*vt;
vl = VS/MU0*L;
rt = RS+RD;
vgt0 = vgs - von;
s = exp((vgt0-VSIGMAT)/VSIGMA);
sigma = SIGMA0/(1+s);
vgt = vgt0+sigma*vds;
u = 0.5*vgt/vt-1;
t = sqrt(model->MESAdeltaSqr+u*u);
vgte = vt*(2+u+t);
b = exp(vgt/etavth);
nsm = 2*here->MESAn0*log(1+0.5*b);
if(nsm < 1.0e-38) {
*cdrain = 0;
*gm = 0.0;
*gds = 0.0;
*capgs = here->MESAcf;
*capgd = here->MESAcf;
return;
}
c = pow(nsm/NMAX,GAMMA);
q = pow(1+c,1.0/GAMMA);
ns = nsm/q;
gchi = here->MESAgchi0*ns;
gch = gchi/(1+gchi*rt);
gchim = here->MESAgchi0*nsm;
h = sqrt(1+2*gchim*model->MESArsi + vgte*vgte/(vl*vl));
p = 1+gchim*RS+h;
isatm = gchim*vgte/p;
g = pow(isatm/here->MESAimax,GAMMA);
isat = isatm/pow(1+g,1/GAMMA);
vsate = isat/gch;
vdse = vds*pow(1+pow(vds/vsate,MC),-1.0/MC);
d = pow(vds/vsate,M0);
e = pow(1+d,1.0/M0);
delidgch = vds*(1+LAMBDA*vds)/e;
*cdrain = gch*delidgch;
cgcm = 1.0/(1/model->MESAcas*D/model->MESAepsi +
1/model->MESAcbs*etavth/CHARGE/here->MESAn0*exp(-vgt/etavth));
cgc = W*L*cgcm/pow(1+c,1+1.0/GAMMA);
/*
{
char buf[256];
void far pascal OutputDebugString(char*);
sprintf(buf,"\n%f\t%e",vgs,cgc);
OutputDebugString(buf);
}
*/
a = (vsate-vdse)/(2*vsate-vdse);
a = a*a;
temp = 2.0/3.0;
*capgs = here->MESAcf+temp*cgc*(1-a);
a = vsate/(2*vsate-vdse);
a = a*a;
*capgd = here->MESAcf+temp*cgc*(1-a);
delidvsate = (*cdrain)*d/vsate/(1+d);
delidvds = gch*(1+2*LAMBDA*vds)/e-(*cdrain)*
pow(vds/vsate,M0-1)/(vsate*(1+d));
a = 1+gchi*rt;
delgchgchi = 1.0/(a*a);
delgchins = here->MESAgchi0;
delnsnsm = ns/nsm*(1-c/(1+c));
delnsmvgt = here->MESAn0/etavth/(1.0/b + 0.5);
delvgtevgt = 0.5*(1+u/t);
delvsateisat = 1.0/gch;
delisatisatm = isat/isatm*(1-g/(1+g));
delisatmvgte = gchim*(p - vgte*vgte/(vl*vl*h))/(p*p);
delvsategch = -vsate/gch;
delisatmgchim = vgte*(p - gchim*RS*(1+1.0/h))/(p*p);
delvgtvgs = 1-vds*SIGMA0/VSIGMA*s/((1+s)*(1+s));
p = delgchgchi*delgchins*delnsnsm*delnsmvgt;
delvsatevgt = (delvsateisat*delisatisatm*(delisatmvgte*delvgtevgt +
delisatmgchim*here->MESAgchi0*delnsmvgt)+delvsategch*p);
g = delidgch*p + delidvsate*delvsatevgt;
*gm = g*delvgtvgs;
*gds = delidvds + g*sigma;
}