Merge branch 'pre-master-43' into bt_dev

This commit is contained in:
Brian Taylor 2024-02-13 09:02:29 -08:00
commit b5f96d68de
28 changed files with 907 additions and 600 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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[] = {

View File

@ -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,
};

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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[] = {

View File

@ -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,
};

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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[] = {

View File

@ -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,

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);