diff --git a/configure.ac b/configure.ac index 48b776c4c..a19e417e8 100644 --- a/configure.ac +++ b/configure.ac @@ -118,7 +118,7 @@ LT_INIT([shared static]) LT_NGSPICE_CURRENT=0 LT_NGSPICE_REVISION=9 -LT_NGSPICE_AGE=2 +LT_NGSPICE_AGE=0 LIBNGSPICE_SO_VERSION=$LT_NGSPICE_CURRENT.$LT_NGSPICE_REVISION.$LT_NGSPICE_AGE # Announce the libtool version diff --git a/examples/various/transformers1.cir b/examples/various/transformers1.cir index 552be7550..cf26601b4 100644 --- a/examples/various/transformers1.cir +++ b/examples/various/transformers1.cir @@ -6,6 +6,8 @@ V1 1 0 dc 0 ac 1 sin (0 1 1k) Xtr1 1 0 2 0 tr1 +Xtr1a 1 0 32 0 tr1a psr=1m ssr=1m lp=1m ls=4m kt=0.98 + Xtr2 1 0 12 0 tr2 Xtr3 1 0 22 0 tr3 @@ -22,6 +24,16 @@ Xtr3 1 0 22 0 tr3 K1 L1 L2 0.98 ; coupling constant .ends +* transformer 1a +* ngspice manual 3.3.10, with parameters replacing fixed values +.subckt tr1a p1 p2 s1 s2 psr=1m ssr=1m lp=100u ls=100u kt=1 + Rp1 p1 pint1 {psr} ; primary series resistance + Rs1 s1 sint1 {ssr} ; secondary series resistance + L1 pint1 p2 {lp} ; primary inductance + L2 sint1 s2 {ls} ; secondary inductance + K1 L1 L2 {kt} ; coupling constant +.ends + * transformer 2 * ngspice manual 12.2.20 and 12.2.21 * px primary nodes, sx secondary nodes of electric circuit @@ -53,7 +65,7 @@ Xtr3 1 0 22 0 tr3 .control run set xbrushwidth=2 -plot V(1) v(2) V(1)+5 V(12)+5 V(1)+10 V(22)+10 +plot V(1) v(2) V(1)+5 V(12)+5 V(1)+10 V(22)+10 V(1)+15 V(32)+15 .endc .end diff --git a/src/Makefile.am b/src/Makefile.am index 62a3536a2..aa2a49183 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -649,7 +649,7 @@ endif ## if !SHWIN ## if !SHCYG -libngspice_la_LDFLAGS += -version-info $(LT_NGSPICE_CURRENT):$(LT_NGSPICE_REVISION):$(LT_LIBNGSPICE_AGE) +libngspice_la_LDFLAGS += -version-info $(LT_NGSPICE_CURRENT):$(LT_NGSPICE_REVISION):$(LT_NGSPICE_AGE) ## endif ## endif diff --git a/src/frontend/plotting/x11.c b/src/frontend/plotting/x11.c index fed83762c..ca468cd24 100644 --- a/src/frontend/plotting/x11.c +++ b/src/frontend/plotting/x11.c @@ -1085,14 +1085,23 @@ zoomin(GRAPH *graph) if ((t = strchr(buf2, ':')) != NULL) *t = '\0'; + /* Set the foreground and background colors to the + * "calling" window's colors using undocumented keyword, "sgraphid". + */ + if (!eq(plot_cur->pl_typename, buf2)) { + /* Switch plot before and after "plot" command. */ (void) sprintf(buf, - "setplot %s; %s xlimit %.20e %.20e ylimit %.20e %.20e sgraphid %d; setplot $curplot\n", - buf2, graph->commandline, fx0, fx1, fy0, fy1, graph->graphid); + "setplot %s; %s xlimit %.20e %.20e ylimit %.20e %.20e " + "sgraphid %d; setplot $curplot\n", + buf2, graph->commandline, fx0, fx1, fy0, fy1, + graph->graphid); } else { - /* set the foreground and background colors to the "calling" window's colors */ - (void) sprintf(buf, "%s xlimit %e %e ylimit %e %e sgraphid %d\n", - graph->commandline, fx0, fx1, fy0, fy1, graph->graphid); + (void) sprintf(buf, + "%s xlimit %.20e %.20e ylimit %.20e %.20e " + "sgraphid %d\n", + graph->commandline, fx0, fx1, fy0, fy1, + graph->graphid); } /* don't use the following if using GNU Readline or BSD EditLine */ diff --git a/src/frontend/spec.c b/src/frontend/spec.c index 8e5d2c108..40625996d 100644 --- a/src/frontend/spec.c +++ b/src/frontend/spec.c @@ -126,11 +126,6 @@ com_spec(wordlist *wl) } } else if (eq(window, "blackman")) { - int order; - if (!cp_getvar("specwindoworder", CP_NUM, &order, 0)) - order = 2; - if (order < 2) /* only order 2 supported here */ - order = 2; for (i = 0; i < tlen; i++) { if (maxt-time[i] > span) { win[i] = 0; diff --git a/src/frontend/wdisp/windisp.c b/src/frontend/wdisp/windisp.c index 33a238fcd..ed8bc5a3c 100644 --- a/src/frontend/wdisp/windisp.c +++ b/src/frontend/wdisp/windisp.c @@ -630,11 +630,13 @@ LRESULT CALLBACK PlotWindowProc(HWND hwnd, UINT uMsg, if (!eq(plot_cur->pl_typename, buf2)) { (void) sprintf(buf, -// "setplot %s; %s xlimit %e %e ylimit %e %e; setplot $curplot\n", - "setplot %s; %s xlimit %e %e ylimit %e %e sgraphid %d\n", - buf2, gr->commandline, fx0, fxe, fy0, fye, gr->graphid); + "setplot %s; %s xlimit %.20e %.20e ylimit %.20e " + "%.20e sgraphid %d ; setplot $curplot\n", + buf2, gr->commandline, fx0, fxe, fy0, fye, + gr->graphid); } else { - (void) sprintf(buf, "%s xlimit %e %e ylimit %e %e sgraphid %d\n", + (void) sprintf(buf, "%s xlimit %.20e %.20e ylimit %.20e %.20e " + "sgraphid %d\n", gr->commandline, fx0, fxe, fy0, fye, gr->graphid); } diff --git a/src/maths/fft/fftext.c b/src/maths/fft/fftext.c index 6dc6400e8..fd0be8863 100644 --- a/src/maths/fft/fftext.c +++ b/src/maths/fft/fftext.c @@ -114,8 +114,10 @@ fft_windows(char *window, double *win, double *time, int length, double maxt, do for (i = 0; i < length; i++) { if (maxt-time[i] > span) win[i] = 0.0; + else if (maxt-time[i] < span/2) + win[i] = 4.0 * (maxt-time[i]) / span; else - win[i] = 2.0 - fabs(2+4*(time[i]-maxt)/span); + win[i] = 4.0 - 4.0 * (maxt-time[i]) / span; } else if (eq(window, "hann") || eq(window, "hanning") || eq(window, "cosine")) for (i = 0; i < length; i++) { @@ -141,6 +143,17 @@ fft_windows(char *window, double *win, double *time, int length, double maxt, do win[i] += 0.08/0.42*cos(4*M_PI*(time[i]-maxt)/span); } } + else if (eq(window, "blackmanharris")) + for (i = 0; i < length; i++) { + if (maxt-time[i] > span) { + win[i] = 0; + } else { + win[i] = 1.0; + win[i] -= 0.48829/0.35875*cos(2*M_PI*(time[i]-maxt)/span); + win[i] += 0.14128/0.35875*cos(4*M_PI*(time[i]-maxt)/span); + win[i] -= 0.01168/0.35875*cos(6*M_PI*(time[i]-maxt)/span); + } + } else if (eq(window, "flattop")) for (i = 0; i < length; i++) { if (maxt-time[i] > span) { diff --git a/src/spicelib/analysis/span.c b/src/spicelib/analysis/span.c index 86e59daa0..f4bdcbefa 100644 --- a/src/spicelib/analysis/span.c +++ b/src/spicelib/analysis/span.c @@ -126,7 +126,7 @@ CKTspnoise(CKTcircuit* ckt, int mode, int operation, Ndata* data, NOISEAN* noise cplx Ycor = csubco(ckt->CKTYmat->d[0][0], cmultco( cdivco(tempCy->d[0][1], tempCy->d[1][1]), - tempCy->d[1][0] + ckt->CKTYmat->d[1][0] )); double Y11_Ycor = cmodsqr(csubco(ckt->CKTYmat->d[0][0], Ycor)); @@ -138,7 +138,7 @@ CKTspnoise(CKTcircuit* ckt, int mode, int operation, Ndata* data, NOISEAN* noise caddco(Y0, Ysopt)); Fmin = 1.0 + 2.0 * Rn * (Ycor.re + Ysopt.re); double Ysoptmod = cmodu(csubco(Y0, Ysopt)); - NF = Fmin + (Rn / Ysopt.re) * SQR(Ysoptmod); + NF = Fmin + (Rn / Y0.re) * SQR(Ysoptmod); Fmin = 10.0 * log10(Fmin); NF = 10.0 * log10(NF); } diff --git a/src/spicelib/devices/mos1/mos1.c b/src/spicelib/devices/mos1/mos1.c index 54bee5f79..beaa11bc0 100644 --- a/src/spicelib/devices/mos1/mos1.c +++ b/src/spicelib/devices/mos1/mos1.c @@ -148,7 +148,9 @@ IFparm MOS1mPTable[] = { /* model parameters */ IOP("nss", MOS1_MOD_NSS, IF_REAL ,"Surface state density"), IOP("tnom", MOS1_MOD_TNOM, IF_REAL ,"Parameter measurement temperature"), IOP("kf", MOS1_MOD_KF, IF_REAL ,"Flicker noise coefficient"), - IOP("af", MOS1_MOD_AF, IF_REAL ,"Flicker noise exponent") + IOP("af", MOS1_MOD_AF, IF_REAL ,"Flicker noise exponent"), + IOP("nlev", MOS1_MOD_NLEV, IF_INTEGER ,"Noise model selection"), + IOP("gdsnoi", MOS1_MOD_GDSNOI, IF_REAL ,"Channel shot noise coefficient") }; char *MOS1names[] = { diff --git a/src/spicelib/devices/mos1/mos1defs.h b/src/spicelib/devices/mos1/mos1defs.h index b6fc299b3..6103b23ba 100644 --- a/src/spicelib/devices/mos1/mos1defs.h +++ b/src/spicelib/devices/mos1/mos1defs.h @@ -383,6 +383,8 @@ typedef struct sMOS1model { /* model structure for a resistor */ double MOS1surfaceMobility; /* input - use tSurfMob */ double MOS1fNcoef; double MOS1fNexp; + int MOS1nlev; + double MOS1gdsnoi; unsigned MOS1typeGiven :1; unsigned MOS1latDiffGiven :1; @@ -415,6 +417,8 @@ typedef struct sMOS1model { /* model structure for a resistor */ unsigned MOS1tnomGiven :1; unsigned MOS1fNcoefGiven :1; unsigned MOS1fNexpGiven :1; + unsigned MOS1nlevGiven :1; + unsigned MOS1gdsnoiGiven :1; } MOS1model; @@ -483,6 +487,8 @@ enum { MOS1_MOD_TNOM, MOS1_MOD_KF, MOS1_MOD_AF, + MOS1_MOD_NLEV, + MOS1_MOD_GDSNOI, MOS1_MOD_TYPE, }; diff --git a/src/spicelib/devices/mos1/mos1mask.c b/src/spicelib/devices/mos1/mos1mask.c index 494392609..e0c610c56 100644 --- a/src/spicelib/devices/mos1/mos1mask.c +++ b/src/spicelib/devices/mos1/mos1mask.c @@ -105,11 +105,17 @@ MOS1mAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) case MOS1_MOD_NSS: value->rValue = model->MOS1surfaceStateDensity; return(OK); + case MOS1_MOD_NLEV: + value->iValue = model->MOS1nlev; + return(OK); + case MOS1_MOD_GDSNOI: + value->rValue = model->MOS1gdsnoi; + return(OK); case MOS1_MOD_TYPE: - if (model->MOS1type > 0) - value->sValue = "nmos"; - else - value->sValue = "pmos"; + if (model->MOS1type > 0) + value->sValue = "nmos"; + else + value->sValue = "pmos"; return(OK); default: return(E_BADPARM); diff --git a/src/spicelib/devices/mos1/mos1mpar.c b/src/spicelib/devices/mos1/mos1mpar.c index 1986e1750..d849626ff 100644 --- a/src/spicelib/devices/mos1/mos1mpar.c +++ b/src/spicelib/devices/mos1/mos1mpar.c @@ -139,14 +139,22 @@ MOS1mParam(int param, IFvalue *value, GENmodel *inModel) model->MOS1typeGiven = TRUE; } break; - case MOS1_MOD_KF: - model->MOS1fNcoef = value->rValue; - model->MOS1fNcoefGiven = TRUE; - break; - case MOS1_MOD_AF: - model->MOS1fNexp = value->rValue; - model->MOS1fNexpGiven = TRUE; - break; + case MOS1_MOD_KF: + model->MOS1fNcoef = value->rValue; + model->MOS1fNcoefGiven = TRUE; + break; + case MOS1_MOD_AF: + model->MOS1fNexp = value->rValue; + model->MOS1fNexpGiven = TRUE; + break; + case MOS1_MOD_NLEV: + model->MOS1nlev = value->iValue; + model->MOS1nlevGiven = TRUE; + break; + case MOS1_MOD_GDSNOI: + model->MOS1gdsnoi = value->rValue; + model->MOS1gdsnoiGiven = TRUE; + break; default: return(E_BADPARM); } diff --git a/src/spicelib/devices/mos1/mos1noi.c b/src/spicelib/devices/mos1/mos1noi.c index 79d91442e..2c853c9a9 100644 --- a/src/spicelib/devices/mos1/mos1noi.c +++ b/src/spicelib/devices/mos1/mos1noi.c @@ -10,6 +10,7 @@ Modified: 2000 AlansFixes #include "ngspice/iferrmsg.h" #include "ngspice/noisedef.h" #include "ngspice/suffix.h" +#include "ngspice/compatmode.h" /* * MOS1noise (mode, operation, firstModel, ckt, data, OnDens) @@ -20,170 +21,234 @@ Modified: 2000 AlansFixes * all of the MOSFET's is summed with the variable "OnDens". */ - int -MOS1noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, - Ndata *data, double *OnDens) -{ - NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; +MOS1noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt, + Ndata * data, double * OnDens) { + NOISEAN * job = (NOISEAN * ) ckt->CKTcurJob; - MOS1model *firstModel = (MOS1model *) genmodel; - MOS1model *model; - MOS1instance *inst; + MOS1model * firstModel = (MOS1model * ) genmodel; + MOS1model * model; + MOS1instance * inst; double coxSquared; double tempOnoise; double tempInoise; double noizDens[MOS1NSRCS]; double lnNdens[MOS1NSRCS]; int i; + double vgs, vds, vgd, vgst, alpha, beta, Sid; /* define the names of the noise sources */ - static char *MOS1nNames[MOS1NSRCS] = { /* Note that we have to keep the order */ - "_rd", /* noise due to rd */ /* consistent with thestrchr definitions */ - "_rs", /* noise due to rs */ /* in MOS1defs.h */ - "_id", /* noise due to id */ - "_1overf", /* flicker (1/f) noise */ - "" /* total transistor noise */ + static char * MOS1nNames[MOS1NSRCS] = { + /* Note that we have to keep the order */ + "_rd", + /* noise due to rd */ /* consistent with thestrchr definitions */ + "_rs", + /* noise due to rs */ /* in MOS1defs.h */ + "_id", + /* noise due to id */ + "_1overf", + /* flicker (1/f) noise */ + "" /* total transistor noise */ }; - for (model=firstModel; model != NULL; model=MOS1nextModel(model)) { + for (model = firstModel; model != NULL; model = MOS1nextModel(model)) { - /* Oxide capacitance can be zero in MOS level 1. Since this will give us problems in our 1/f */ - /* noise model, we ASSUME an actual "tox" of 1e-7 */ + /* Oxide capacitance can be zero in MOS level 1. Since this will give us problems in our 1/f */ + /* noise model, we ASSUME an actual "tox" of 1e-7 */ - if (model->MOS1oxideCapFactor == 0.0) { - coxSquared = 3.9 * 8.854214871e-12 / 1e-7; + if (model->MOS1oxideCapFactor == 0.0) { + coxSquared = 3.9 * 8.854214871e-12 / 1e-7; } else { - coxSquared = model->MOS1oxideCapFactor; + coxSquared = model->MOS1oxideCapFactor; } - coxSquared *= coxSquared; - for (inst=MOS1instances(model); inst != NULL; inst=MOS1nextInstance(inst)) { - - switch (operation) { + coxSquared *= coxSquared; + for (inst = MOS1instances(model); inst != NULL; inst = MOS1nextInstance(inst)) { - case N_OPEN: + switch (operation) { - /* see if we have to to produce a summary report */ - /* if so, name all the noise generators */ + case N_OPEN: - if (job->NStpsSm != 0) { - switch (mode) { + /* see if we have to to produce a summary report */ + /* if so, name all the noise generators */ - case N_DENS: - for (i=0; i < MOS1NSRCS; i++) { - NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->MOS1name, MOS1nNames[i]); - } - break; + if (job->NStpsSm != 0) { + switch (mode) { - case INT_NOIZ: - for (i=0; i < MOS1NSRCS; i++) { - NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->MOS1name, MOS1nNames[i]); - NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->MOS1name, MOS1nNames[i]); - } - break; - } - } - break; + case N_DENS: + for (i = 0; i < MOS1NSRCS; i++) { + NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->MOS1name, MOS1nNames[i]); + } + break; - case N_CALC: - switch (mode) { + case INT_NOIZ: + for (i = 0; i < MOS1NSRCS; i++) { + NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->MOS1name, MOS1nNames[i]); + NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->MOS1name, MOS1nNames[i]); + } + break; + } + } + break; - case N_DENS: - NevalSrc(&noizDens[MOS1RDNOIZ],&lnNdens[MOS1RDNOIZ], - ckt,THERMNOISE,inst->MOS1dNodePrime,inst->MOS1dNode, - inst->MOS1drainConductance); + case N_CALC: + switch (mode) { - NevalSrc(&noizDens[MOS1RSNOIZ],&lnNdens[MOS1RSNOIZ], - ckt,THERMNOISE,inst->MOS1sNodePrime,inst->MOS1sNode, - inst->MOS1sourceConductance); + case N_DENS: + NevalSrc( & noizDens[MOS1RDNOIZ], & lnNdens[MOS1RDNOIZ], + ckt, THERMNOISE, inst->MOS1dNodePrime, inst->MOS1dNode, + inst->MOS1drainConductance); - NevalSrc(&noizDens[MOS1IDNOIZ],&lnNdens[MOS1IDNOIZ], - ckt,THERMNOISE,inst->MOS1dNodePrime,inst->MOS1sNodePrime, - (2.0/3.0 * fabs(inst->MOS1gm))); + NevalSrc( & noizDens[MOS1RSNOIZ], & lnNdens[MOS1RSNOIZ], + ckt, THERMNOISE, inst->MOS1sNodePrime, inst->MOS1sNode, + inst->MOS1sourceConductance); - NevalSrc(&noizDens[MOS1FLNOIZ], NULL, ckt, - N_GAIN,inst->MOS1dNodePrime, inst->MOS1sNodePrime, - (double)0.0); - noizDens[MOS1FLNOIZ] *= model->MOS1fNcoef * - exp(model->MOS1fNexp * - log(MAX(fabs(inst->MOS1cd),N_MINLOG))) / - (data->freq * inst->MOS1w * - (inst->MOS1l - 2*model->MOS1latDiff) * coxSquared); - lnNdens[MOS1FLNOIZ] = - log(MAX(noizDens[MOS1FLNOIZ],N_MINLOG)); + if (model->MOS1nlev < 3) { - noizDens[MOS1TOTNOIZ] = noizDens[MOS1RDNOIZ] + - noizDens[MOS1RSNOIZ] + - noizDens[MOS1IDNOIZ] + - noizDens[MOS1FLNOIZ]; - lnNdens[MOS1TOTNOIZ] = - log(MAX(noizDens[MOS1TOTNOIZ], N_MINLOG)); + Sid = 2.0 / 3.0 * fabs(inst->MOS1gm); - *OnDens += noizDens[MOS1TOTNOIZ]; + } else { + vds = *(ckt->CKTstate0 + inst->MOS1vds); + vgs = *(ckt->CKTstate0 + inst->MOS1vgs); + vgd = vgs - vds; - if (data->delFreq == 0.0) { + vgst=(inst->MOS1mode==1?vgs:vgd) - model->MOS1type*inst->MOS1von; + if (vgst > 0) { + if (vgst <= (vds*inst->MOS1mode)) { + /* saturation region */ + alpha = 0.0; + } else { + /* linear region */ + alpha = 1.0 - (vds*inst->MOS1mode/(model->MOS1type*inst->MOS1vdsat)); + } + } + beta = inst->MOS1tTransconductance * inst->MOS1m * + inst->MOS1w/(inst->MOS1l - 2 * model->MOS1latDiff); + Sid = 2.0 / 3.0 * beta * vgst * (1.0+alpha+alpha*alpha) / (1.0+alpha) * model->MOS1gdsnoi; + } - /* if we haven't done any previous integration, we need to */ - /* initialize our "history" variables */ + NevalSrc( & noizDens[MOS1IDNOIZ], & lnNdens[MOS1IDNOIZ], + ckt, THERMNOISE, inst->MOS1dNodePrime, inst->MOS1sNodePrime, + Sid); - for (i=0; i < MOS1NSRCS; i++) { - inst->MOS1nVar[LNLSTDENS][i] = lnNdens[i]; - } + NevalSrc( & noizDens[MOS1FLNOIZ], NULL, ckt, + N_GAIN, inst->MOS1dNodePrime, inst->MOS1sNodePrime, + (double) 0.0); + if (newcompat.s3) { + noizDens[MOS1FLNOIZ] *= model->MOS1fNcoef * + exp(model->MOS1fNexp * + log(MAX(fabs(inst->MOS1cd), N_MINLOG))) / + (data->freq * + inst->MOS1w * + (inst->MOS1l - 2 * model->MOS1latDiff) * + coxSquared); + } else { + switch (model->MOS1nlev) { + case 0: + noizDens[MOS1FLNOIZ] *= model->MOS1fNcoef * + exp(model->MOS1fNexp * + log(MAX(fabs(inst->MOS1cd), N_MINLOG))) / + (data->freq * + (inst->MOS1l - 2 * model->MOS1latDiff) * + (inst->MOS1l - 2 * model->MOS1latDiff) * + sqrt(coxSquared)); + break; + case 1: + noizDens[MOS1FLNOIZ] *= model->MOS1fNcoef * + exp(model->MOS1fNexp * + log(MAX(fabs(inst->MOS1cd), N_MINLOG))) / + (data->freq * + inst->MOS1w * + (inst->MOS1l - 2 * model->MOS1latDiff) * + sqrt(coxSquared)); + break; + case 2: case 3: + noizDens[MOS1FLNOIZ] *= model->MOS1fNcoef * + inst->MOS1gm * inst->MOS1gm / + (pow(data->freq, model->MOS1fNexp) * + inst->MOS1w * + (inst->MOS1l - 2 * model->MOS1latDiff) * + sqrt(coxSquared)); + break; + } + } + lnNdens[MOS1FLNOIZ] = + log(MAX(noizDens[MOS1FLNOIZ], N_MINLOG)); - /* clear out our integration variables if it's the first pass */ + noizDens[MOS1TOTNOIZ] = noizDens[MOS1RDNOIZ] + + noizDens[MOS1RSNOIZ] + + noizDens[MOS1IDNOIZ] + + noizDens[MOS1FLNOIZ]; + lnNdens[MOS1TOTNOIZ] = + log(MAX(noizDens[MOS1TOTNOIZ], N_MINLOG)); - if (data->freq == job->NstartFreq) { - for (i=0; i < MOS1NSRCS; i++) { - inst->MOS1nVar[OUTNOIZ][i] = 0.0; - inst->MOS1nVar[INNOIZ][i] = 0.0; - } - } - } else { /* data->delFreq != 0.0 (we have to integrate) */ - for (i=0; i < MOS1NSRCS; i++) { - if (i != MOS1TOTNOIZ) { - tempOnoise = Nintegrate(noizDens[i], lnNdens[i], - inst->MOS1nVar[LNLSTDENS][i], data); - tempInoise = Nintegrate(noizDens[i] * data->GainSqInv , - lnNdens[i] + data->lnGainInv, - inst->MOS1nVar[LNLSTDENS][i] + data->lnGainInv, - data); - inst->MOS1nVar[LNLSTDENS][i] = lnNdens[i]; - data->outNoiz += tempOnoise; - data->inNoise += tempInoise; - if (job->NStpsSm != 0) { - inst->MOS1nVar[OUTNOIZ][i] += tempOnoise; - inst->MOS1nVar[OUTNOIZ][MOS1TOTNOIZ] += tempOnoise; - inst->MOS1nVar[INNOIZ][i] += tempInoise; - inst->MOS1nVar[INNOIZ][MOS1TOTNOIZ] += tempInoise; + * OnDens += noizDens[MOS1TOTNOIZ]; + + if (data->delFreq == 0.0) { + + /* if we haven't done any previous integration, we need to */ + /* initialize our "history" variables */ + + for (i = 0; i < MOS1NSRCS; i++) { + inst->MOS1nVar[LNLSTDENS][i] = lnNdens[i]; + } + + /* clear out our integration variables if it's the first pass */ + + if (data->freq == job->NstartFreq) { + for (i = 0; i < MOS1NSRCS; i++) { + inst->MOS1nVar[OUTNOIZ][i] = 0.0; + inst->MOS1nVar[INNOIZ][i] = 0.0; + } + } + } else { + /* data->delFreq != 0.0 (we have to integrate) */ + for (i = 0; i < MOS1NSRCS; i++) { + if (i != MOS1TOTNOIZ) { + tempOnoise = Nintegrate(noizDens[i], lnNdens[i], + inst->MOS1nVar[LNLSTDENS][i], data); + tempInoise = Nintegrate(noizDens[i] * data->GainSqInv, + lnNdens[i] + data->lnGainInv, + inst->MOS1nVar[LNLSTDENS][i] + data->lnGainInv, + data); + inst->MOS1nVar[LNLSTDENS][i] = lnNdens[i]; + data->outNoiz += tempOnoise; + data->inNoise += tempInoise; + if (job->NStpsSm != 0) { + inst->MOS1nVar[OUTNOIZ][i] += tempOnoise; + inst->MOS1nVar[OUTNOIZ][MOS1TOTNOIZ] += tempOnoise; + inst->MOS1nVar[INNOIZ][i] += tempInoise; + inst->MOS1nVar[INNOIZ][MOS1TOTNOIZ] += tempInoise; } - } - } - } - if (data->prtSummary) { - for (i=0; i < MOS1NSRCS; i++) { /* print a summary report */ - data->outpVector[data->outNumber++] = noizDens[i]; - } - } - break; + } + } + } + if (data->prtSummary) { + for (i = 0; i < MOS1NSRCS; i++) { + /* print a summary report */ + data->outpVector[data->outNumber++] = noizDens[i]; + } + } + break; - case INT_NOIZ: /* already calculated, just output */ - if (job->NStpsSm != 0) { - for (i=0; i < MOS1NSRCS; i++) { - data->outpVector[data->outNumber++] = inst->MOS1nVar[OUTNOIZ][i]; - data->outpVector[data->outNumber++] = inst->MOS1nVar[INNOIZ][i]; - } - } /* if */ - break; - } /* switch (mode) */ - break; + case INT_NOIZ: + /* already calculated, just output */ + if (job->NStpsSm != 0) { + for (i = 0; i < MOS1NSRCS; i++) { + data->outpVector[data->outNumber++] = inst->MOS1nVar[OUTNOIZ][i]; + data->outpVector[data->outNumber++] = inst->MOS1nVar[INNOIZ][i]; + } + } /* if */ + break; + } /* switch (mode) */ + break; - case N_CLOSE: - return (OK); /* do nothing, the main calling routine will close */ - break; /* the plots */ - } /* switch (operation) */ - } /* for inst */ - } /* for model */ + case N_CLOSE: + return (OK); /* do nothing, the main calling routine will close */ + break; /* the plots */ + } /* switch (operation) */ + } /* for inst */ + } /* for model */ -return(OK); + return (OK); } diff --git a/src/spicelib/devices/mos1/mos1set.c b/src/spicelib/devices/mos1/mos1set.c index 6912cbe71..912e029a9 100644 --- a/src/spicelib/devices/mos1/mos1set.c +++ b/src/spicelib/devices/mos1/mos1set.c @@ -4,8 +4,8 @@ Author: 1985 Thomas L. Quarles Modified: 2000 AlansFixes **********/ - /* load the MOS1 device structure with those pointers needed later - * for fast matrix loading + /* load the MOS1 device structure with those pointers needed later + * for fast matrix loading */ #include "ngspice/ngspice.h" @@ -81,12 +81,18 @@ MOS1setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, if(!model->MOS1gammaGiven) { model->MOS1gamma = 0; } - if(!model->MOS1fNcoefGiven) { - model->MOS1fNcoef = 0; - } - if(!model->MOS1fNexpGiven) { - model->MOS1fNexp = 1; - } + if(!model->MOS1fNcoefGiven) { + model->MOS1fNcoef = 0; + } + if(!model->MOS1fNexpGiven) { + model->MOS1fNexp = 1; + } + if(!model->MOS1nlevGiven) { + model->MOS1nlev = 2; + } + if(!model->MOS1gdsnoiGiven) { + model->MOS1gdsnoi = 1; + } /* loop through all the instances of the model */ for (here = MOS1instances(model); here != NULL ; @@ -121,34 +127,34 @@ MOS1setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, if(!here->MOS1vonGiven) { here->MOS1von = 0; } - if(!here->MOS1drainSquaresGiven) { - here->MOS1drainSquares=1; - } - if(!here->MOS1sourceSquaresGiven) { - here->MOS1sourceSquares=1; - } + if(!here->MOS1drainSquaresGiven) { + here->MOS1drainSquares=1; + } + if(!here->MOS1sourceSquaresGiven) { + here->MOS1sourceSquares=1; + } if ((model->MOS1drainResistance != 0 - || (model->MOS1sheetResistance != 0 + || (model->MOS1sheetResistance != 0 && here->MOS1drainSquares != 0) )) { if (here->MOS1dNodePrime == 0) { error = CKTmkVolt(ckt,&tmp,here->MOS1name,"drain"); if(error) return(error); here->MOS1dNodePrime = tmp->number; - + if (ckt->CKTcopyNodesets) { - CKTnode *tmpNode; - IFuid tmpName; + CKTnode *tmpNode; + IFuid tmpName; if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { - tmp->nodeset=tmpNode->nodeset; - tmp->nsGiven=tmpNode->nsGiven; + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; } } } } - + } else { here->MOS1dNodePrime = here->MOS1dNode; } @@ -160,19 +166,19 @@ MOS1setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, error = CKTmkVolt(ckt,&tmp,here->MOS1name,"source"); if(error) return(error); here->MOS1sNodePrime = tmp->number; - + if (ckt->CKTcopyNodesets) { - CKTnode *tmpNode; - IFuid tmpName; + CKTnode *tmpNode; + IFuid tmpName; if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { - tmp->nodeset=tmpNode->nodeset; - tmp->nsGiven=tmpNode->nsGiven; + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; } } } - + } } else { here->MOS1sNodePrime = here->MOS1sNode; @@ -218,21 +224,21 @@ MOS1unsetup(GENmodel *inModel, CKTcircuit *ckt) MOS1instance *here; for (model = (MOS1model *)inModel; model != NULL; - model = MOS1nextModel(model)) + model = MOS1nextModel(model)) { for (here = MOS1instances(model); here != NULL; here=MOS1nextInstance(here)) - { - if (here->MOS1sNodePrime > 0 - && here->MOS1sNodePrime != here->MOS1sNode) - CKTdltNNum(ckt, here->MOS1sNodePrime); - here->MOS1sNodePrime= 0; + { + if (here->MOS1sNodePrime > 0 + && here->MOS1sNodePrime != here->MOS1sNode) + CKTdltNNum(ckt, here->MOS1sNodePrime); + here->MOS1sNodePrime= 0; - if (here->MOS1dNodePrime > 0 - && here->MOS1dNodePrime != here->MOS1dNode) - CKTdltNNum(ckt, here->MOS1dNodePrime); - here->MOS1dNodePrime= 0; - } + if (here->MOS1dNodePrime > 0 + && here->MOS1dNodePrime != here->MOS1dNode) + CKTdltNNum(ckt, here->MOS1dNodePrime); + here->MOS1dNodePrime= 0; + } } return OK; } diff --git a/src/spicelib/devices/mos2/mos2.c b/src/spicelib/devices/mos2/mos2.c index d36a08147..bc577da61 100644 --- a/src/spicelib/devices/mos2/mos2.c +++ b/src/spicelib/devices/mos2/mos2.c @@ -156,7 +156,9 @@ IFparm MOS2mPTable[] = { /* model parameters */ IOP("nfs", MOS2_MOD_NFS, IF_REAL ,"Fast surface state density"), IOPU("tnom", MOS2_MOD_TNOM, IF_REAL ,"Parameter measurement temperature"), IOP("kf", MOS2_MOD_KF, IF_REAL ,"Flicker noise coefficient"), - IOP("af", MOS2_MOD_AF, IF_REAL ,"Flicker noise exponent") + IOP("af", MOS2_MOD_AF, IF_REAL ,"Flicker noise exponent"), + IOP("nlev", MOS2_MOD_NLEV, IF_INTEGER ,"Noise model selection"), + IOP("gdsnoi", MOS2_MOD_GDSNOI, IF_REAL ,"Channel shot noise coefficient") }; char *MOS2names[] = { diff --git a/src/spicelib/devices/mos2/mos2defs.h b/src/spicelib/devices/mos2/mos2defs.h index bf59484d2..8a1fc8ce1 100644 --- a/src/spicelib/devices/mos2/mos2defs.h +++ b/src/spicelib/devices/mos2/mos2defs.h @@ -390,6 +390,8 @@ typedef struct sMOS2model { /* model structure for a resistor */ double MOS2surfaceMobility; double MOS2fNcoef; double MOS2fNexp; + int MOS2nlev; + double MOS2gdsnoi; double MOS2narrowFactor; /* delta */ double MOS2critFieldExp; /* uexp */ @@ -437,6 +439,8 @@ typedef struct sMOS2model { /* model structure for a resistor */ unsigned MOS2channelChargeGiven :1; /* neff */ unsigned MOS2fNcoefGiven :1; unsigned MOS2fNexpGiven :1; + unsigned MOS2nlevGiven :1; + unsigned MOS2gdsnoiGiven :1; } MOS2model; @@ -574,6 +578,8 @@ enum { enum { MOS2_MOD_KF = 139, MOS2_MOD_AF, + MOS2_MOD_NLEV, + MOS2_MOD_GDSNOI, MOS2_MOD_TYPE, }; diff --git a/src/spicelib/devices/mos2/mos2mask.c b/src/spicelib/devices/mos2/mos2mask.c index b3cfda751..ff125669e 100644 --- a/src/spicelib/devices/mos2/mos2mask.c +++ b/src/spicelib/devices/mos2/mos2mask.c @@ -124,18 +124,24 @@ MOS2mAsk(CKTcircuit *ckt, GENmodel *inModel, int param, case MOS2_MOD_UCRIT: value->rValue = model->MOS2critField; break; - case MOS2_MOD_KF: - value->rValue = model->MOS2fNcoef; - break; - case MOS2_MOD_AF: - value->rValue = model->MOS2fNexp; - break; - case MOS2_MOD_TYPE: - if (model->MOS2type > 0) - value->sValue = "nmos"; - else - value->sValue = "pmos"; - break; + case MOS2_MOD_KF: + value->rValue = model->MOS2fNcoef; + break; + case MOS2_MOD_AF: + value->rValue = model->MOS2fNexp; + break; + case MOS2_MOD_NLEV: + value->iValue = model->MOS2nlev; + break; + case MOS2_MOD_GDSNOI: + value->rValue = model->MOS2gdsnoi; + return(OK); + case MOS2_MOD_TYPE: + if (model->MOS2type > 0) + value->sValue = "nmos"; + else + value->sValue = "pmos"; + break; default: return(E_BADPARM); } diff --git a/src/spicelib/devices/mos2/mos2mpar.c b/src/spicelib/devices/mos2/mos2mpar.c index 49967db0a..7c8f3dc15 100644 --- a/src/spicelib/devices/mos2/mos2mpar.c +++ b/src/spicelib/devices/mos2/mos2mpar.c @@ -170,14 +170,22 @@ MOS2mParam(int param, IFvalue *value, GENmodel *inModel) model->MOS2typeGiven = TRUE; } break; - case MOS2_MOD_KF: - model->MOS2fNcoef = value->rValue; - model->MOS2fNcoefGiven = TRUE; - break; - case MOS2_MOD_AF: - model->MOS2fNexp = value->rValue; - model->MOS2fNexpGiven = TRUE; - break; + case MOS2_MOD_KF: + model->MOS2fNcoef = value->rValue; + model->MOS2fNcoefGiven = TRUE; + break; + case MOS2_MOD_AF: + model->MOS2fNexp = value->rValue; + model->MOS2fNexpGiven = TRUE; + break; + case MOS2_MOD_NLEV: + model->MOS2nlev = value->iValue; + model->MOS2nlevGiven = TRUE; + break; + case MOS2_MOD_GDSNOI: + model->MOS2gdsnoi = value->rValue; + model->MOS2gdsnoiGiven = TRUE; + break; default: return(E_BADPARM); } diff --git a/src/spicelib/devices/mos2/mos2noi.c b/src/spicelib/devices/mos2/mos2noi.c index f20c5f01c..c3e942adf 100644 --- a/src/spicelib/devices/mos2/mos2noi.c +++ b/src/spicelib/devices/mos2/mos2noi.c @@ -10,6 +10,7 @@ Modified: 2000 AlansFixes #include "ngspice/iferrmsg.h" #include "ngspice/noisedef.h" #include "ngspice/suffix.h" +#include "ngspice/compatmode.h" /* * MOS2noise (mode, operation, firstModel, ckt, data, OnDens) @@ -20,160 +21,223 @@ Modified: 2000 AlansFixes * all of the MOSFET's is summed with the variable "OnDens". */ - int -MOS2noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, - Ndata *data, double *OnDens) -{ - NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; +MOS2noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt, + Ndata * data, double * OnDens) { + NOISEAN * job = (NOISEAN * ) ckt->CKTcurJob; - MOS2model *firstModel = (MOS2model *) genmodel; - MOS2model *model; - MOS2instance *inst; + MOS2model * firstModel = (MOS2model * ) genmodel; + MOS2model * model; + MOS2instance * inst; double tempOnoise; double tempInoise; double noizDens[MOS2NSRCS]; double lnNdens[MOS2NSRCS]; int i; + double vgs, vds, vgd, vgst, alpha, beta, Sid; /* define the names of the noise sources */ - static char *MOS2nNames[MOS2NSRCS] = { /* Note that we have to keep the order */ - "_rd", /* noise due to rd */ /* consistent with thestrchr definitions */ - "_rs", /* noise due to rs */ /* in MOS2defs.h */ - "_id", /* noise due to id */ - "_1overf", /* flicker (1/f) noise */ - "" /* total transistor noise */ + static char * MOS2nNames[MOS2NSRCS] = { + /* Note that we have to keep the order */ + "_rd", + /* noise due to rd */ /* consistent with thestrchr definitions */ + "_rs", + /* noise due to rs */ /* in MOS2defs.h */ + "_id", + /* noise due to id */ + "_1overf", + /* flicker (1/f) noise */ + "" /* total transistor noise */ }; - for (model=firstModel; model != NULL; model=MOS2nextModel(model)) { - for (inst=MOS2instances(model); inst != NULL; inst=MOS2nextInstance(inst)) { + for (model = firstModel; model != NULL; model = MOS2nextModel(model)) { + for (inst = MOS2instances(model); inst != NULL; inst = MOS2nextInstance(inst)) { - switch (operation) { + switch (operation) { - case N_OPEN: + case N_OPEN: - /* see if we have to to produce a summary report */ - /* if so, name all the noise generators */ + /* see if we have to to produce a summary report */ + /* if so, name all the noise generators */ - if (job->NStpsSm != 0) { - switch (mode) { + if (job->NStpsSm != 0) { + switch (mode) { - case N_DENS: - for (i=0; i < MOS2NSRCS; i++) { - NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->MOS2name, MOS2nNames[i]); - } - break; + case N_DENS: + for (i = 0; i < MOS2NSRCS; i++) { + NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->MOS2name, MOS2nNames[i]); + } + break; - case INT_NOIZ: - for (i=0; i < MOS2NSRCS; i++) { - NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->MOS2name, MOS2nNames[i]); - NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->MOS2name, MOS2nNames[i]); - } - break; - } - } - break; + case INT_NOIZ: + for (i = 0; i < MOS2NSRCS; i++) { + NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->MOS2name, MOS2nNames[i]); + NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->MOS2name, MOS2nNames[i]); + } + break; + } + } + break; - case N_CALC: - switch (mode) { + case N_CALC: + switch (mode) { - case N_DENS: - NevalSrc(&noizDens[MOS2RDNOIZ],&lnNdens[MOS2RDNOIZ], - ckt,THERMNOISE,inst->MOS2dNodePrime,inst->MOS2dNode, - inst->MOS2drainConductance); + case N_DENS: + NevalSrc( & noizDens[MOS2RDNOIZ], & lnNdens[MOS2RDNOIZ], + ckt, THERMNOISE, inst->MOS2dNodePrime, inst->MOS2dNode, + inst->MOS2drainConductance); - NevalSrc(&noizDens[MOS2RSNOIZ],&lnNdens[MOS2RSNOIZ], - ckt,THERMNOISE,inst->MOS2sNodePrime,inst->MOS2sNode, - inst->MOS2sourceConductance); + NevalSrc( & noizDens[MOS2RSNOIZ], & lnNdens[MOS2RSNOIZ], + ckt, THERMNOISE, inst->MOS2sNodePrime, inst->MOS2sNode, + inst->MOS2sourceConductance); - NevalSrc(&noizDens[MOS2IDNOIZ],&lnNdens[MOS2IDNOIZ], - ckt,THERMNOISE,inst->MOS2dNodePrime,inst->MOS2sNodePrime, - (2.0/3.0 * fabs(inst->MOS2gm))); + if (model->MOS2nlev < 3) { - NevalSrc(&noizDens[MOS2FLNOIZ], NULL, ckt, - N_GAIN,inst->MOS2dNodePrime, inst->MOS2sNodePrime, - (double)0.0); - noizDens[MOS2FLNOIZ] *= model->MOS2fNcoef * - exp(model->MOS2fNexp * - log(MAX(fabs(inst->MOS2cd),N_MINLOG))) / - (data->freq * inst->MOS2w * - (inst->MOS2l - 2*model->MOS2latDiff) * - model->MOS2oxideCapFactor * model->MOS2oxideCapFactor); - lnNdens[MOS2FLNOIZ] = - log(MAX(noizDens[MOS2FLNOIZ],N_MINLOG)); + Sid = 2.0 / 3.0 * fabs(inst->MOS2gm); - noizDens[MOS2TOTNOIZ] = noizDens[MOS2RDNOIZ] + - noizDens[MOS2RSNOIZ] + - noizDens[MOS2IDNOIZ] + - noizDens[MOS2FLNOIZ]; - lnNdens[MOS2TOTNOIZ] = - log(MAX(noizDens[MOS2TOTNOIZ], N_MINLOG)); + } else { + vds = *(ckt->CKTstate0 + inst->MOS2vds); + vgs = *(ckt->CKTstate0 + inst->MOS2vgs); + vgd = vgs - vds; - *OnDens += noizDens[MOS2TOTNOIZ]; + vgst=(inst->MOS2mode==1?vgs:vgd) - model->MOS2type*inst->MOS2von; + if (vgst > 0) { + if (vgst <= (vds*inst->MOS2mode)) { + /* saturation region */ + alpha = 0.0; + } else { + /* linear region */ + alpha = 1.0 - (vds*inst->MOS2mode/(model->MOS2type*inst->MOS2vdsat)); + } + } + beta = inst->MOS2tTransconductance * inst->MOS2m * + inst->MOS2w/(inst->MOS2l - 2 * model->MOS2latDiff); + Sid = 2.0 / 3.0 * beta * vgst * (1.0+alpha+alpha*alpha) / (1.0+alpha) * model->MOS2gdsnoi; + } - if (data->delFreq == 0.0) { + NevalSrc( & noizDens[MOS2IDNOIZ], & lnNdens[MOS2IDNOIZ], + ckt, THERMNOISE, inst->MOS2dNodePrime, inst->MOS2sNodePrime, + Sid); - /* if we haven't done any previous integration, we need to */ - /* initialize our "history" variables */ + NevalSrc( & noizDens[MOS2FLNOIZ], NULL, ckt, + N_GAIN, inst->MOS2dNodePrime, inst->MOS2sNodePrime, + (double) 0.0); + if (newcompat.s3) { + noizDens[MOS2FLNOIZ] *= model->MOS2fNcoef * + exp(model->MOS2fNexp * + log(MAX(fabs(inst->MOS2cd), N_MINLOG))) / + (data->freq * + inst->MOS2w * + (inst->MOS2l - 2 * model->MOS2latDiff) * + model->MOS2oxideCapFactor * model->MOS2oxideCapFactor); + } else { + switch (model->MOS2nlev) { + case 0: + noizDens[MOS2FLNOIZ] *= model->MOS2fNcoef * + exp(model->MOS2fNexp * + log(MAX(fabs(inst->MOS2cd), N_MINLOG))) / + (data->freq * + (inst->MOS2l - 2 * model->MOS2latDiff) * + (inst->MOS2l - 2 * model->MOS2latDiff) * + model->MOS2oxideCapFactor); + break; + case 1: + noizDens[MOS2FLNOIZ] *= model->MOS2fNcoef * + exp(model->MOS2fNexp * + log(MAX(fabs(inst->MOS2cd), N_MINLOG))) / + (data->freq * + inst->MOS2w * + (inst->MOS2l - 2 * model->MOS2latDiff) * + model->MOS2oxideCapFactor); + break; + case 2: case 3: + noizDens[MOS2FLNOIZ] *= model->MOS2fNcoef * + inst->MOS2gm * inst->MOS2gm / + (pow(data->freq, model->MOS2fNexp) * + inst->MOS2w * + (inst->MOS2l - 2 * model->MOS2latDiff) * + model->MOS2oxideCapFactor); + break; + } + } + lnNdens[MOS2FLNOIZ] = + log(MAX(noizDens[MOS2FLNOIZ], N_MINLOG)); - for (i=0; i < MOS2NSRCS; i++) { - inst->MOS2nVar[LNLSTDENS][i] = lnNdens[i]; - } + noizDens[MOS2TOTNOIZ] = noizDens[MOS2RDNOIZ] + + noizDens[MOS2RSNOIZ] + + noizDens[MOS2IDNOIZ] + + noizDens[MOS2FLNOIZ]; + lnNdens[MOS2TOTNOIZ] = + log(MAX(noizDens[MOS2TOTNOIZ], N_MINLOG)); - /* clear out our integration variables if it's the first pass */ + * OnDens += noizDens[MOS2TOTNOIZ]; - if (data->freq == job->NstartFreq) { - for (i=0; i < MOS2NSRCS; i++) { - inst->MOS2nVar[OUTNOIZ][i] = 0.0; - inst->MOS2nVar[INNOIZ][i] = 0.0; - } - } - } else { /* data->delFreq != 0.0 (we have to integrate) */ - for (i=0; i < MOS2NSRCS; i++) { - if (i != MOS2TOTNOIZ) { - tempOnoise = Nintegrate(noizDens[i], lnNdens[i], - inst->MOS2nVar[LNLSTDENS][i], data); - tempInoise = Nintegrate(noizDens[i] * data->GainSqInv , - lnNdens[i] + data->lnGainInv, - inst->MOS2nVar[LNLSTDENS][i] + data->lnGainInv, - data); - inst->MOS2nVar[LNLSTDENS][i] = lnNdens[i]; - data->outNoiz += tempOnoise; - data->inNoise += tempInoise; - if (job->NStpsSm != 0) { - inst->MOS2nVar[OUTNOIZ][i] += tempOnoise; - inst->MOS2nVar[OUTNOIZ][MOS2TOTNOIZ] += tempOnoise; - inst->MOS2nVar[INNOIZ][i] += tempInoise; - inst->MOS2nVar[INNOIZ][MOS2TOTNOIZ] += tempInoise; + if (data->delFreq == 0.0) { + + /* if we haven't done any previous integration, we need to */ + /* initialize our "history" variables */ + + for (i = 0; i < MOS2NSRCS; i++) { + inst->MOS2nVar[LNLSTDENS][i] = lnNdens[i]; + } + + /* clear out our integration variables if it's the first pass */ + + if (data->freq == job->NstartFreq) { + for (i = 0; i < MOS2NSRCS; i++) { + inst->MOS2nVar[OUTNOIZ][i] = 0.0; + inst->MOS2nVar[INNOIZ][i] = 0.0; + } + } + } else { + /* data->delFreq != 0.0 (we have to integrate) */ + for (i = 0; i < MOS2NSRCS; i++) { + if (i != MOS2TOTNOIZ) { + tempOnoise = Nintegrate(noizDens[i], lnNdens[i], + inst->MOS2nVar[LNLSTDENS][i], data); + tempInoise = Nintegrate(noizDens[i] * data->GainSqInv, + lnNdens[i] + data->lnGainInv, + inst->MOS2nVar[LNLSTDENS][i] + data->lnGainInv, + data); + inst->MOS2nVar[LNLSTDENS][i] = lnNdens[i]; + data->outNoiz += tempOnoise; + data->inNoise += tempInoise; + if (job->NStpsSm != 0) { + inst->MOS2nVar[OUTNOIZ][i] += tempOnoise; + inst->MOS2nVar[OUTNOIZ][MOS2TOTNOIZ] += tempOnoise; + inst->MOS2nVar[INNOIZ][i] += tempInoise; + inst->MOS2nVar[INNOIZ][MOS2TOTNOIZ] += tempInoise; } - } - } - } - if (data->prtSummary) { - for (i=0; i < MOS2NSRCS; i++) { /* print a summary report */ - data->outpVector[data->outNumber++] = noizDens[i]; - } - } - break; + } + } + } + if (data->prtSummary) { + for (i = 0; i < MOS2NSRCS; i++) { + /* print a summary report */ + data->outpVector[data->outNumber++] = noizDens[i]; + } + } + break; - case INT_NOIZ: /* already calculated, just output */ - if (job->NStpsSm != 0) { - for (i=0; i < MOS2NSRCS; i++) { - data->outpVector[data->outNumber++] = inst->MOS2nVar[OUTNOIZ][i]; - data->outpVector[data->outNumber++] = inst->MOS2nVar[INNOIZ][i]; - } - } /* if */ - break; - } /* switch (mode) */ - break; + case INT_NOIZ: + /* already calculated, just output */ + if (job->NStpsSm != 0) { + for (i = 0; i < MOS2NSRCS; i++) { + data->outpVector[data->outNumber++] = inst->MOS2nVar[OUTNOIZ][i]; + data->outpVector[data->outNumber++] = inst->MOS2nVar[INNOIZ][i]; + } + } /* if */ + break; + } /* switch (mode) */ + break; - case N_CLOSE: - return (OK); /* do nothing, the main calling routine will close */ - break; /* the plots */ - } /* switch (operation) */ - } /* for inst */ - } /* for model */ + case N_CLOSE: + return (OK); /* do nothing, the main calling routine will close */ + break; /* the plots */ + } /* switch (operation) */ + } /* for inst */ + } /* for model */ -return(OK); + return (OK); } diff --git a/src/spicelib/devices/mos2/mos2set.c b/src/spicelib/devices/mos2/mos2set.c index 3c3acfd4d..34e58bef5 100644 --- a/src/spicelib/devices/mos2/mos2set.c +++ b/src/spicelib/devices/mos2/mos2set.c @@ -14,8 +14,8 @@ Modified: 2000 AlansFixes int MOS2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) - /* load the MOS2 device structure with those pointers needed later - * for fast matrix loading + /* load the MOS2 device structure with those pointers needed later + * for fast matrix loading */ { MOS2model *model = (MOS2model *)inModel; @@ -110,20 +110,26 @@ MOS2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->MOS2fastSurfaceStateDensityGiven) { model->MOS2fastSurfaceStateDensity = 0; } - if(!model->MOS2fNcoefGiven) { - model->MOS2fNcoef = 0; - } - if(!model->MOS2fNexpGiven) { - model->MOS2fNexp = 1; - } + if(!model->MOS2fNcoefGiven) { + model->MOS2fNcoef = 0; + } + if(!model->MOS2fNexpGiven) { + model->MOS2fNexp = 1; + } + if(!model->MOS2nlevGiven) { + model->MOS2nlev = 2; + } + if(!model->MOS2gdsnoiGiven) { + model->MOS2gdsnoi = 1; + } /* loop through all the instances of the model */ for (here = MOS2instances(model); here != NULL ; here=MOS2nextInstance(here)) { - - CKTnode *tmpNode; - IFuid tmpName; - + + CKTnode *tmpNode; + IFuid tmpName; + /* allocate a chunk of the state vector */ here->MOS2states = *states; *states += MOS2numStates; @@ -150,52 +156,52 @@ MOS2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!here->MOS2vdsatGiven) { here->MOS2vdsat = 0; } - if (!here->MOS2drainSquaresGiven) { - here->MOS2drainSquares=1; - } - if (!here->MOS2sourceSquaresGiven) { - here->MOS2sourceSquares=1; - } + if (!here->MOS2drainSquaresGiven) { + here->MOS2drainSquares=1; + } + if (!here->MOS2sourceSquaresGiven) { + here->MOS2sourceSquares=1; + } if ((model->MOS2drainResistance != 0 || (here->MOS2drainSquares != 0 - && model->MOS2sheetResistance != 0))) { + && model->MOS2sheetResistance != 0))) { if (here->MOS2dNodePrime == 0) { error = CKTmkVolt(ckt,&tmp,here->MOS2name,"internal#drain"); if(error) return(error); here->MOS2dNodePrime = tmp->number; - + if (ckt->CKTcopyNodesets) { if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { - tmp->nodeset=tmpNode->nodeset; - tmp->nsGiven=tmpNode->nsGiven; + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; } } } } - + } else { here->MOS2dNodePrime = here->MOS2dNode; } - if( ( (model->MOS2sourceResistance != 0) || + if( ( (model->MOS2sourceResistance != 0) || ((here->MOS2sourceSquares != 0) && (model->MOS2sheetResistance != 0)) )) { if (here->MOS2sNodePrime == 0) { error = CKTmkVolt(ckt,&tmp,here->MOS2name,"internal#source"); if(error) return(error); here->MOS2sNodePrime = tmp->number; - + if (ckt->CKTcopyNodesets) { if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { - tmp->nodeset=tmpNode->nodeset; - tmp->nsGiven=tmpNode->nsGiven; + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; } } } } - + } else { here->MOS2sNodePrime = here->MOS2sNode; } @@ -241,21 +247,21 @@ MOS2unsetup(GENmodel *inModel, CKTcircuit *ckt) MOS2instance *here; for (model = (MOS2model *)inModel; model != NULL; - model = MOS2nextModel(model)) + model = MOS2nextModel(model)) { for (here = MOS2instances(model); here != NULL; here=MOS2nextInstance(here)) - { - if (here->MOS2sNodePrime > 0 - && here->MOS2sNodePrime != here->MOS2sNode) - CKTdltNNum(ckt, here->MOS2sNodePrime); - here->MOS2sNodePrime = 0; + { + if (here->MOS2sNodePrime > 0 + && here->MOS2sNodePrime != here->MOS2sNode) + CKTdltNNum(ckt, here->MOS2sNodePrime); + here->MOS2sNodePrime = 0; - if (here->MOS2dNodePrime > 0 - && here->MOS2dNodePrime != here->MOS2dNode) - CKTdltNNum(ckt, here->MOS2dNodePrime); - here->MOS2dNodePrime = 0; - } + if (here->MOS2dNodePrime > 0 + && here->MOS2dNodePrime != here->MOS2dNode) + CKTdltNNum(ckt, here->MOS2dNodePrime); + here->MOS2dNodePrime = 0; + } } return OK; } diff --git a/src/spicelib/devices/mos3/mos3.c b/src/spicelib/devices/mos3/mos3.c index 553840366..a7f2cdf81 100644 --- a/src/spicelib/devices/mos3/mos3.c +++ b/src/spicelib/devices/mos3/mos3.c @@ -156,7 +156,9 @@ IFparm MOS3mPTable[] = { /* model parameters */ IOP("kappa", MOS3_MOD_KAPPA, IF_REAL ,"Kappa"), IOPU("tnom", MOS3_MOD_TNOM, IF_REAL ,"Parameter measurement temperature"), IOP("kf", MOS3_MOD_KF, IF_REAL ,"Flicker noise coefficient"), - IOP("af", MOS3_MOD_AF, IF_REAL ,"Flicker noise exponent") + IOP("af", MOS3_MOD_AF, IF_REAL ,"Flicker noise exponent"), + IOP("nlev", MOS3_MOD_NLEV, IF_INTEGER ,"Noise model selection"), + IOP("gdsnoi", MOS3_MOD_GDSNOI, IF_REAL ,"Channel shot noise coefficient") }; char *MOS3names[] = { diff --git a/src/spicelib/devices/mos3/mos3defs.h b/src/spicelib/devices/mos3/mos3defs.h index 7e4c9aba4..42b79faa4 100644 --- a/src/spicelib/devices/mos3/mos3defs.h +++ b/src/spicelib/devices/mos3/mos3defs.h @@ -400,6 +400,8 @@ typedef struct sMOS3model { /* model structure for a resistor */ double MOS3kappa; /* kappa */ double MOS3fNcoef; double MOS3fNexp; + int MOS3nlev; + double MOS3gdsnoi; unsigned MOS3typeGiven :1; unsigned MOS3latDiffGiven :1; @@ -442,6 +444,8 @@ typedef struct sMOS3model { /* model structure for a resistor */ unsigned MOS3tnomGiven :1; /* Tnom was given? */ unsigned MOS3fNcoefGiven :1; unsigned MOS3fNexpGiven :1; + unsigned MOS3nlevGiven :1; + unsigned MOS3gdsnoiGiven :1; } MOS3model; @@ -580,6 +584,8 @@ enum { MOS3_MOD_TNOM, MOS3_MOD_KF, MOS3_MOD_AF, + MOS3_MOD_NLEV, + MOS3_MOD_GDSNOI, MOS3_MOD_TYPE, MOS3_MOD_XL, MOS3_MOD_WD, diff --git a/src/spicelib/devices/mos3/mos3mask.c b/src/spicelib/devices/mos3/mos3mask.c index d66c89029..355362111 100644 --- a/src/spicelib/devices/mos3/mos3mask.c +++ b/src/spicelib/devices/mos3/mos3mask.c @@ -18,148 +18,154 @@ Modified: 2000 AlansFixes /*ARGSUSED*/ int -MOS3mAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) +MOS3mAsk(CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) { - MOS3model *here = (MOS3model *)inst; + MOS3model *model = (MOS3model *)inModel; NG_IGNORE(ckt); switch(which) { case MOS3_MOD_TNOM: - value->rValue = here->MOS3tnom-CONSTCtoK; + value->rValue = model->MOS3tnom-CONSTCtoK; return(OK); case MOS3_MOD_VTO: - value->rValue = here->MOS3vt0; + value->rValue = model->MOS3vt0; return(OK); case MOS3_MOD_KP: - value->rValue = here->MOS3transconductance; + value->rValue = model->MOS3transconductance; return(OK); case MOS3_MOD_GAMMA: - value->rValue = here->MOS3gamma; + value->rValue = model->MOS3gamma; return(OK); case MOS3_MOD_PHI: - value->rValue = here->MOS3phi; + value->rValue = model->MOS3phi; return(OK); case MOS3_MOD_RD: - value->rValue = here->MOS3drainResistance; + value->rValue = model->MOS3drainResistance; return(OK); case MOS3_MOD_RS: - value->rValue = here->MOS3sourceResistance; + value->rValue = model->MOS3sourceResistance; return(OK); case MOS3_MOD_CBD: - value->rValue = here->MOS3capBD; + value->rValue = model->MOS3capBD; return(OK); case MOS3_MOD_CBS: - value->rValue = here->MOS3capBS; + value->rValue = model->MOS3capBS; return(OK); case MOS3_MOD_IS: - value->rValue = here->MOS3jctSatCur; + value->rValue = model->MOS3jctSatCur; return(OK); case MOS3_MOD_PB: - value->rValue = here->MOS3bulkJctPotential; + value->rValue = model->MOS3bulkJctPotential; return(OK); case MOS3_MOD_CGSO: - value->rValue = here->MOS3gateSourceOverlapCapFactor; + value->rValue = model->MOS3gateSourceOverlapCapFactor; return(OK); case MOS3_MOD_CGDO: - value->rValue = here->MOS3gateDrainOverlapCapFactor; + value->rValue = model->MOS3gateDrainOverlapCapFactor; return(OK); case MOS3_MOD_CGBO: - value->rValue = here->MOS3gateBulkOverlapCapFactor; + value->rValue = model->MOS3gateBulkOverlapCapFactor; return(OK); case MOS3_MOD_CJ: - value->rValue = here->MOS3bulkCapFactor; + value->rValue = model->MOS3bulkCapFactor; return(OK); case MOS3_MOD_MJ: - value->rValue = here->MOS3bulkJctBotGradingCoeff; + value->rValue = model->MOS3bulkJctBotGradingCoeff; return(OK); case MOS3_MOD_CJSW: - value->rValue = here->MOS3sideWallCapFactor; + value->rValue = model->MOS3sideWallCapFactor; return(OK); case MOS3_MOD_MJSW: - value->rValue = here->MOS3bulkJctSideGradingCoeff; + value->rValue = model->MOS3bulkJctSideGradingCoeff; return(OK); case MOS3_MOD_JS: - value->rValue = here->MOS3jctSatCurDensity; + value->rValue = model->MOS3jctSatCurDensity; return(OK); case MOS3_MOD_TOX: - value->rValue = here->MOS3oxideThickness; + value->rValue = model->MOS3oxideThickness; return(OK); case MOS3_MOD_LD: - value->rValue = here->MOS3latDiff; + value->rValue = model->MOS3latDiff; return(OK); case MOS3_MOD_XL: - value->rValue = here->MOS3lengthAdjust; + value->rValue = model->MOS3lengthAdjust; return(OK); case MOS3_MOD_WD: - value->rValue = here->MOS3widthNarrow; + value->rValue = model->MOS3widthNarrow; return(OK); case MOS3_MOD_XW: - value->rValue = here->MOS3widthAdjust; + value->rValue = model->MOS3widthAdjust; return(OK); case MOS3_MOD_DELVTO: - value->rValue = here->MOS3delvt0; - return(OK); + value->rValue = model->MOS3delvt0; + return(OK); case MOS3_MOD_RSH: - value->rValue = here->MOS3sheetResistance; + value->rValue = model->MOS3sheetResistance; return(OK); case MOS3_MOD_U0: - value->rValue = here->MOS3surfaceMobility; + value->rValue = model->MOS3surfaceMobility; return(OK); case MOS3_MOD_FC: - value->rValue = here->MOS3fwdCapDepCoeff; + value->rValue = model->MOS3fwdCapDepCoeff; return(OK); case MOS3_MOD_NSUB: - value->rValue = here->MOS3substrateDoping; + value->rValue = model->MOS3substrateDoping; return(OK); case MOS3_MOD_TPG: - value->iValue = here->MOS3gateType; + value->iValue = model->MOS3gateType; return(OK); case MOS3_MOD_NSS: - value->rValue = here->MOS3surfaceStateDensity; + value->rValue = model->MOS3surfaceStateDensity; return(OK); case MOS3_MOD_NFS: - value->rValue = here->MOS3fastSurfaceStateDensity; + value->rValue = model->MOS3fastSurfaceStateDensity; return(OK); case MOS3_MOD_DELTA: - value->rValue = here->MOS3narrowFactor; + value->rValue = model->MOS3narrowFactor; return(OK); case MOS3_MOD_VMAX: - value->rValue = here->MOS3maxDriftVel; + value->rValue = model->MOS3maxDriftVel; return(OK); case MOS3_MOD_XJ: - value->rValue = here->MOS3junctionDepth; + value->rValue = model->MOS3junctionDepth; return(OK); case MOS3_MOD_ETA: - value->rValue = here->MOS3eta; + value->rValue = model->MOS3eta; return(OK); case MOS3_MOD_XD: - value->rValue = here->MOS3coeffDepLayWidth; + value->rValue = model->MOS3coeffDepLayWidth; return(OK); case MOS3_DELTA: - value->rValue = here->MOS3delta; + value->rValue = model->MOS3delta; return(OK); case MOS3_MOD_THETA: - value->rValue = here->MOS3theta; + value->rValue = model->MOS3theta; return(OK); case MOS3_MOD_ALPHA: - value->rValue = here->MOS3alpha; + value->rValue = model->MOS3alpha; return(OK); case MOS3_MOD_KAPPA: - value->rValue = here->MOS3kappa; - return(OK); + value->rValue = model->MOS3kappa; + return(OK); case MOS3_MOD_KF: - value->rValue = here->MOS3fNcoef; + value->rValue = model->MOS3fNcoef; return(OK); case MOS3_MOD_AF: - value->rValue = here->MOS3fNexp; - return(OK); - case MOS3_MOD_TYPE: - if (here->MOS3type > 0) - value->sValue = "nmos"; - else - value->sValue = "pmos"; - return(OK); + value->rValue = model->MOS3fNexp; + return(OK); + case MOS3_MOD_NLEV: + value->iValue = model->MOS3nlev; + return(OK); + case MOS3_MOD_GDSNOI: + value->rValue = model->MOS3gdsnoi; + return(OK); + case MOS3_MOD_TYPE: + if (model->MOS3type > 0) + value->sValue = "nmos"; + else + value->sValue = "pmos"; + return(OK); default: return(E_BADPARM); } diff --git a/src/spicelib/devices/mos3/mos3mpar.c b/src/spicelib/devices/mos3/mos3mpar.c index 8b4a57e87..aa6f678c3 100644 --- a/src/spicelib/devices/mos3/mos3mpar.c +++ b/src/spicelib/devices/mos3/mos3mpar.c @@ -118,7 +118,7 @@ MOS3mParam(int param, IFvalue *value, GENmodel *inModel) case MOS3_MOD_DELVTO: model->MOS3delvt0 = value->rValue; model->MOS3delvt0Given = TRUE; - break; + break; case MOS3_MOD_U0: model->MOS3surfaceMobility = value->rValue; model->MOS3surfaceMobilityGiven = TRUE; @@ -183,14 +183,22 @@ MOS3mParam(int param, IFvalue *value, GENmodel *inModel) model->MOS3tnom = value->rValue+CONSTCtoK; model->MOS3tnomGiven = TRUE; break; - case MOS3_MOD_KF: - model->MOS3fNcoef = value->rValue; - model->MOS3fNcoefGiven = TRUE; - break; - case MOS3_MOD_AF: - model->MOS3fNexp = value->rValue; - model->MOS3fNexpGiven = TRUE; - break; + case MOS3_MOD_KF: + model->MOS3fNcoef = value->rValue; + model->MOS3fNcoefGiven = TRUE; + break; + case MOS3_MOD_AF: + model->MOS3fNexp = value->rValue; + model->MOS3fNexpGiven = TRUE; + break; + case MOS3_MOD_NLEV: + model->MOS3nlev = value->iValue; + model->MOS3nlevGiven = TRUE; + break; + case MOS3_MOD_GDSNOI: + model->MOS3gdsnoi = value->rValue; + model->MOS3gdsnoiGiven = TRUE; + break; default: return(E_BADPARM); } diff --git a/src/spicelib/devices/mos3/mos3noi.c b/src/spicelib/devices/mos3/mos3noi.c index 82008d9b5..3d7551184 100644 --- a/src/spicelib/devices/mos3/mos3noi.c +++ b/src/spicelib/devices/mos3/mos3noi.c @@ -10,6 +10,7 @@ Modified: 2000 AlansFixes #include "ngspice/iferrmsg.h" #include "ngspice/noisedef.h" #include "ngspice/suffix.h" +#include "ngspice/compatmode.h" /* * MOS3noise (mode, operation, firstModel, ckt, data, OnDens) @@ -20,161 +21,223 @@ Modified: 2000 AlansFixes * all of the MOSFET's is summed with the variable "OnDens". */ - int -MOS3noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, - Ndata *data, double *OnDens) -{ - NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; +MOS3noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt, + Ndata * data, double * OnDens) { + NOISEAN * job = (NOISEAN * ) ckt->CKTcurJob; - MOS3model *firstModel = (MOS3model *) genmodel; - MOS3model *model; - MOS3instance *inst; + MOS3model * firstModel = (MOS3model * ) genmodel; + MOS3model * model; + MOS3instance * inst; double tempOnoise; double tempInoise; double noizDens[MOS3NSRCS]; double lnNdens[MOS3NSRCS]; int i; + double vgs, vds, vgd, vgst, alpha, beta, Sid; /* define the names of the noise sources */ - static char *MOS3nNames[MOS3NSRCS] = { /* Note that we have to keep the order */ - "_rd", /* noise due to rd */ /* consistent with thestrchr definitions */ - "_rs", /* noise due to rs */ /* in MOS3defs.h */ - "_id", /* noise due to id */ - "_1overf", /* flicker (1/f) noise */ - "" /* total transistor noise */ + static char * MOS3nNames[MOS3NSRCS] = { + /* Note that we have to keep the order */ + "_rd", + /* noise due to rd */ /* consistent with thestrchr definitions */ + "_rs", + /* noise due to rs */ /* in MOS3defs.h */ + "_id", + /* noise due to id */ + "_1overf", + /* flicker (1/f) noise */ + "" /* total transistor noise */ }; - for (model=firstModel; model != NULL; model=MOS3nextModel(model)) { - for (inst=MOS3instances(model); inst != NULL; inst=MOS3nextInstance(inst)) { - - switch (operation) { + for (model = firstModel; model != NULL; model = MOS3nextModel(model)) { + for (inst = MOS3instances(model); inst != NULL; inst = MOS3nextInstance(inst)) { - case N_OPEN: + switch (operation) { - /* see if we have to to produce a summary report */ - /* if so, name all the noise generators */ + case N_OPEN: - if (job->NStpsSm != 0) { - switch (mode) { + /* see if we have to to produce a summary report */ + /* if so, name all the noise generators */ - case N_DENS: - for (i=0; i < MOS3NSRCS; i++) { - NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->MOS3name, MOS3nNames[i]); - } - break; + if (job->NStpsSm != 0) { + switch (mode) { - case INT_NOIZ: - for (i=0; i < MOS3NSRCS; i++) { - NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->MOS3name, MOS3nNames[i]); - NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->MOS3name, MOS3nNames[i]); - } - break; - } - } - break; + case N_DENS: + for (i = 0; i < MOS3NSRCS; i++) { + NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->MOS3name, MOS3nNames[i]); + } + break; - case N_CALC: - switch (mode) { + case INT_NOIZ: + for (i = 0; i < MOS3NSRCS; i++) { + NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->MOS3name, MOS3nNames[i]); + NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->MOS3name, MOS3nNames[i]); + } + break; + } + } + break; - case N_DENS: - NevalSrc(&noizDens[MOS3RDNOIZ],&lnNdens[MOS3RDNOIZ], - ckt,THERMNOISE,inst->MOS3dNodePrime,inst->MOS3dNode, - inst->MOS3drainConductance); + case N_CALC: + switch (mode) { - NevalSrc(&noizDens[MOS3RSNOIZ],&lnNdens[MOS3RSNOIZ], - ckt,THERMNOISE,inst->MOS3sNodePrime,inst->MOS3sNode, - inst->MOS3sourceConductance); + case N_DENS: + NevalSrc( & noizDens[MOS3RDNOIZ], & lnNdens[MOS3RDNOIZ], + ckt, THERMNOISE, inst->MOS3dNodePrime, inst->MOS3dNode, + inst->MOS3drainConductance); - NevalSrc(&noizDens[MOS3IDNOIZ],&lnNdens[MOS3IDNOIZ], - ckt,THERMNOISE,inst->MOS3dNodePrime,inst->MOS3sNodePrime, - (2.0/3.0 * fabs(inst->MOS3gm))); + NevalSrc( & noizDens[MOS3RSNOIZ], & lnNdens[MOS3RSNOIZ], + ckt, THERMNOISE, inst->MOS3sNodePrime, inst->MOS3sNode, + inst->MOS3sourceConductance); - NevalSrc(&noizDens[MOS3FLNOIZ], NULL, ckt, - N_GAIN,inst->MOS3dNodePrime, inst->MOS3sNodePrime, - (double)0.0); - noizDens[MOS3FLNOIZ] *= model->MOS3fNcoef * - exp(model->MOS3fNexp * - log(MAX(fabs(inst->MOS3cd),N_MINLOG))) / - (data->freq * - (inst->MOS3w - 2*model->MOS3widthNarrow) * - (inst->MOS3l - 2*model->MOS3latDiff) * - model->MOS3oxideCapFactor * model->MOS3oxideCapFactor); - lnNdens[MOS3FLNOIZ] = - log(MAX(noizDens[MOS3FLNOIZ],N_MINLOG)); + if (model->MOS3nlev < 3) { - noizDens[MOS3TOTNOIZ] = noizDens[MOS3RDNOIZ] + - noizDens[MOS3RSNOIZ] + - noizDens[MOS3IDNOIZ] + - noizDens[MOS3FLNOIZ]; - lnNdens[MOS3TOTNOIZ] = - log(MAX(noizDens[MOS3TOTNOIZ], N_MINLOG)); + Sid = 2.0 / 3.0 * fabs(inst->MOS3gm); - *OnDens += noizDens[MOS3TOTNOIZ]; + } else { + vds = *(ckt->CKTstate0 + inst->MOS3vds); + vgs = *(ckt->CKTstate0 + inst->MOS3vgs); + vgd = vgs - vds; - if (data->delFreq == 0.0) { + vgst=(inst->MOS3mode==1?vgs:vgd) - model->MOS3type*inst->MOS3von; + if (vgst > 0) { + if (vgst <= (vds*inst->MOS3mode)) { + /* saturation region */ + alpha = 0.0; + } else { + /* linear region */ + alpha = 1.0 - (vds*inst->MOS3mode/(model->MOS3type*inst->MOS3vdsat)); + } + } + beta = inst->MOS3tTransconductance * inst->MOS3m * + inst->MOS3w/(inst->MOS3l - 2 * model->MOS3latDiff); + Sid = 2.0 / 3.0 * beta * vgst * (1.0+alpha+alpha*alpha) / (1.0+alpha) * model->MOS3gdsnoi; + } - /* if we haven't done any previous integration, we need to */ - /* initialize our "history" variables */ + NevalSrc( & noizDens[MOS3IDNOIZ], & lnNdens[MOS3IDNOIZ], + ckt, THERMNOISE, inst->MOS3dNodePrime, inst->MOS3sNodePrime, + Sid); - for (i=0; i < MOS3NSRCS; i++) { - inst->MOS3nVar[LNLSTDENS][i] = lnNdens[i]; - } + NevalSrc( & noizDens[MOS3FLNOIZ], NULL, ckt, + N_GAIN, inst->MOS3dNodePrime, inst->MOS3sNodePrime, + (double) 0.0); + if (newcompat.s3) { + noizDens[MOS3FLNOIZ] *= model->MOS3fNcoef * + exp(model->MOS3fNexp * + log(MAX(fabs(inst->MOS3cd), N_MINLOG))) / + (data->freq * + (inst->MOS3w - 2 * model->MOS3widthNarrow) * + (inst->MOS3l - 2 * model->MOS3latDiff) * + model->MOS3oxideCapFactor * model->MOS3oxideCapFactor); + } else { + switch (model->MOS3nlev) { + case 0: + noizDens[MOS3FLNOIZ] *= model->MOS3fNcoef * + exp(model->MOS3fNexp * + log(MAX(fabs(inst->MOS3cd), N_MINLOG))) / + (data->freq * + (inst->MOS3l - 2 * model->MOS3latDiff) * + (inst->MOS3l - 2 * model->MOS3latDiff) * + model->MOS3oxideCapFactor); + break; + case 1: + noizDens[MOS3FLNOIZ] *= model->MOS3fNcoef * + exp(model->MOS3fNexp * + log(MAX(fabs(inst->MOS3cd), N_MINLOG))) / + (data->freq * + (inst->MOS3w - 2 * model->MOS3widthNarrow) * + (inst->MOS3l - 2 * model->MOS3latDiff) * + model->MOS3oxideCapFactor); + break; + case 2: case 3: + noizDens[MOS3FLNOIZ] *= model->MOS3fNcoef * + inst->MOS3gm * inst->MOS3gm / + (pow(data->freq, model->MOS3fNexp) * + (inst->MOS3w - 2 * model->MOS3widthNarrow) * + (inst->MOS3l - 2 * model->MOS3latDiff) * + model->MOS3oxideCapFactor); + break; + } + } + lnNdens[MOS3FLNOIZ] = + log(MAX(noizDens[MOS3FLNOIZ], N_MINLOG)); - /* clear out our integration variables if it's the first pass */ + noizDens[MOS3TOTNOIZ] = noizDens[MOS3RDNOIZ] + + noizDens[MOS3RSNOIZ] + + noizDens[MOS3IDNOIZ] + + noizDens[MOS3FLNOIZ]; + lnNdens[MOS3TOTNOIZ] = + log(MAX(noizDens[MOS3TOTNOIZ], N_MINLOG)); - if (data->freq == job->NstartFreq) { - for (i=0; i < MOS3NSRCS; i++) { - inst->MOS3nVar[OUTNOIZ][i] = 0.0; - inst->MOS3nVar[INNOIZ][i] = 0.0; - } - } - } else { /* data->delFreq != 0.0 (we have to integrate) */ - for (i=0; i < MOS3NSRCS; i++) { - if (i != MOS3TOTNOIZ) { - tempOnoise = Nintegrate(noizDens[i], lnNdens[i], - inst->MOS3nVar[LNLSTDENS][i], data); - tempInoise = Nintegrate(noizDens[i] * data->GainSqInv , - lnNdens[i] + data->lnGainInv, - inst->MOS3nVar[LNLSTDENS][i] + data->lnGainInv, - data); - inst->MOS3nVar[LNLSTDENS][i] = lnNdens[i]; - data->outNoiz += tempOnoise; - data->inNoise += tempInoise; - if (job->NStpsSm != 0) { - inst->MOS3nVar[OUTNOIZ][i] += tempOnoise; - inst->MOS3nVar[OUTNOIZ][MOS3TOTNOIZ] += tempOnoise; - inst->MOS3nVar[INNOIZ][i] += tempInoise; - inst->MOS3nVar[INNOIZ][MOS3TOTNOIZ] += tempInoise; + * OnDens += noizDens[MOS3TOTNOIZ]; + + if (data->delFreq == 0.0) { + + /* if we haven't done any previous integration, we need to */ + /* initialize our "history" variables */ + + for (i = 0; i < MOS3NSRCS; i++) { + inst->MOS3nVar[LNLSTDENS][i] = lnNdens[i]; + } + + /* clear out our integration variables if it's the first pass */ + + if (data->freq == job->NstartFreq) { + for (i = 0; i < MOS3NSRCS; i++) { + inst->MOS3nVar[OUTNOIZ][i] = 0.0; + inst->MOS3nVar[INNOIZ][i] = 0.0; + } + } + } else { + /* data->delFreq != 0.0 (we have to integrate) */ + for (i = 0; i < MOS3NSRCS; i++) { + if (i != MOS3TOTNOIZ) { + tempOnoise = Nintegrate(noizDens[i], lnNdens[i], + inst->MOS3nVar[LNLSTDENS][i], data); + tempInoise = Nintegrate(noizDens[i] * data->GainSqInv, + lnNdens[i] + data->lnGainInv, + inst->MOS3nVar[LNLSTDENS][i] + data->lnGainInv, + data); + inst->MOS3nVar[LNLSTDENS][i] = lnNdens[i]; + data->outNoiz += tempOnoise; + data->inNoise += tempInoise; + if (job->NStpsSm != 0) { + inst->MOS3nVar[OUTNOIZ][i] += tempOnoise; + inst->MOS3nVar[OUTNOIZ][MOS3TOTNOIZ] += tempOnoise; + inst->MOS3nVar[INNOIZ][i] += tempInoise; + inst->MOS3nVar[INNOIZ][MOS3TOTNOIZ] += tempInoise; } - } - } - } - if (data->prtSummary) { - for (i=0; i < MOS3NSRCS; i++) { /* print a summary report */ - data->outpVector[data->outNumber++] = noizDens[i]; - } - } - break; + } + } + } + if (data->prtSummary) { + for (i = 0; i < MOS3NSRCS; i++) { + /* print a summary report */ + data->outpVector[data->outNumber++] = noizDens[i]; + } + } + break; - case INT_NOIZ: /* already calculated, just output */ - if (job->NStpsSm != 0) { - for (i=0; i < MOS3NSRCS; i++) { - data->outpVector[data->outNumber++] = inst->MOS3nVar[OUTNOIZ][i]; - data->outpVector[data->outNumber++] = inst->MOS3nVar[INNOIZ][i]; - } - } /* if */ - break; - } /* switch (mode) */ - break; + case INT_NOIZ: + /* already calculated, just output */ + if (job->NStpsSm != 0) { + for (i = 0; i < MOS3NSRCS; i++) { + data->outpVector[data->outNumber++] = inst->MOS3nVar[OUTNOIZ][i]; + data->outpVector[data->outNumber++] = inst->MOS3nVar[INNOIZ][i]; + } + } /* if */ + break; + } /* switch (mode) */ + break; - case N_CLOSE: - return (OK); /* do nothing, the main calling routine will close */ - break; /* the plots */ - } /* switch (operation) */ - } /* for inst */ - } /* for model */ + case N_CLOSE: + return (OK); /* do nothing, the main calling routine will close */ + break; /* the plots */ + } /* switch (operation) */ + } /* for inst */ + } /* for model */ -return(OK); + return (OK); } diff --git a/src/spicelib/devices/mos3/mos3set.c b/src/spicelib/devices/mos3/mos3set.c index 4432ba461..5a947de33 100644 --- a/src/spicelib/devices/mos3/mos3set.c +++ b/src/spicelib/devices/mos3/mos3set.c @@ -17,8 +17,8 @@ Modified: 2000 AlansFixes int MOS3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) - /* load the MOS3 device structure with those pointers needed later - * for fast matrix loading + /* load the MOS3 device structure with those pointers needed later + * for fast matrix loading */ { @@ -48,7 +48,7 @@ MOS3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) } if(!model->MOS3delvt0Given) { model->MOS3delvt0 = 0; - } + } if(!model->MOS3jctSatCurDensityGiven) { model->MOS3jctSatCurDensity = 0; } @@ -132,21 +132,27 @@ MOS3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) } if(!model->MOS3oxideThicknessGiven) { model->MOS3oxideThickness = 1e-7; - } - if(!model->MOS3fNcoefGiven) { - model->MOS3fNcoef = 0; - } - if(!model->MOS3fNexpGiven) { - model->MOS3fNexp = 1; - } + } + if(!model->MOS3fNcoefGiven) { + model->MOS3fNcoef = 0; + } + if(!model->MOS3fNexpGiven) { + model->MOS3fNexp = 1; + } + if(!model->MOS3nlevGiven) { + model->MOS3nlev = 2; + } + if(!model->MOS3gdsnoiGiven) { + model->MOS3gdsnoi = 1; + } /* loop through all the instances of the model */ for (here = MOS3instances(model); here != NULL ; here=MOS3nextInstance(here)) { - CKTnode *tmpNode; - IFuid tmpName; - + CKTnode *tmpNode; + IFuid tmpName; + /* allocate a chunk of the state vector */ here->MOS3states = *states; *states += MOS3NUMSTATES; @@ -195,8 +201,8 @@ MOS3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if (ckt->CKTcopyNodesets) { if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { - tmp->nodeset=tmpNode->nodeset; - tmp->nsGiven=tmpNode->nsGiven; + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; } } } @@ -206,7 +212,7 @@ MOS3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) } if((model->MOS3sourceResistance != 0 || - (model->MOS3sheetResistance != 0 && + (model->MOS3sheetResistance != 0 && here->MOS3sourceSquares != 0 ) )) { if (here->MOS3sNodePrime == 0) { error = CKTmkVolt(ckt,&tmp,here->MOS3name,"internal#source"); @@ -215,8 +221,8 @@ MOS3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if (ckt->CKTcopyNodesets) { if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { - tmp->nodeset=tmpNode->nodeset; - tmp->nsGiven=tmpNode->nsGiven; + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; } } } @@ -266,21 +272,21 @@ MOS3unsetup(GENmodel *inModel, CKTcircuit *ckt) MOS3instance *here; for (model = (MOS3model *)inModel; model != NULL; - model = MOS3nextModel(model)) + model = MOS3nextModel(model)) { for (here = MOS3instances(model); here != NULL; here=MOS3nextInstance(here)) - { - if (here->MOS3sNodePrime > 0 - && here->MOS3sNodePrime != here->MOS3sNode) - CKTdltNNum(ckt, here->MOS3sNodePrime); - here->MOS3sNodePrime= 0; + { + if (here->MOS3sNodePrime > 0 + && here->MOS3sNodePrime != here->MOS3sNode) + CKTdltNNum(ckt, here->MOS3sNodePrime); + here->MOS3sNodePrime= 0; - if (here->MOS3dNodePrime > 0 - && here->MOS3dNodePrime != here->MOS3dNode) - CKTdltNNum(ckt, here->MOS3dNodePrime); - here->MOS3dNodePrime= 0; - } + if (here->MOS3dNodePrime > 0 + && here->MOS3dNodePrime != here->MOS3dNode) + CKTdltNNum(ckt, here->MOS3dNodePrime); + here->MOS3dNodePrime= 0; + } } return OK; } diff --git a/src/spicelib/parser/inpgval.c b/src/spicelib/parser/inpgval.c index f9f84ad14..626681570 100644 --- a/src/spicelib/parser/inpgval.c +++ b/src/spicelib/parser/inpgval.c @@ -89,7 +89,7 @@ INPgetValue(CKTcircuit *ckt, char **line, int type, INPtables *tab) INPgetNetTok(line, &word, 1); INPtermInsert(ckt, &word, tab, &(temp.nValue)); } else if (type == IF_INSTANCE) { - INPgetTok(line, &word, 1); + INPgetNetTok(line, &word, 1); INPinsert(&word, tab); temp.uValue = word; } else if (type == IF_STRING) { diff --git a/src/tclspice.c b/src/tclspice.c index 367eb334e..7e8e47b92 100644 --- a/src/tclspice.c +++ b/src/tclspice.c @@ -2433,7 +2433,7 @@ tmeasure TCL_CMDPROCARGS(clientData, interp, argc, argv) return TCL_ERROR; } - wl = wl_build((char **)argv); + wl = wl_build((const char * const *)argv); get_measure2(wl, &mvalue, NULL, FALSE);