Merge branch 'pre-master-43' into bt_dev
This commit is contained in:
commit
b5f96d68de
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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[] = {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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[] = {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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[] = {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue