formatting mos1...3 noise code
This commit is contained in:
parent
1c9f8b6345
commit
2a6db71726
|
|
@ -20,16 +20,14 @@ 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;
|
||||
|
|
@ -39,151 +37,161 @@ MOS1noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt,
|
|||
|
||||
/* 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));
|
||||
NevalSrc( & noizDens[MOS1IDNOIZ], & lnNdens[MOS1IDNOIZ],
|
||||
ckt, THERMNOISE, inst -> MOS1dNodePrime, inst -> MOS1sNodePrime,
|
||||
(2.0 / 3.0 * fabs(inst -> MOS1gm)));
|
||||
|
||||
noizDens[MOS1TOTNOIZ] = noizDens[MOS1RDNOIZ] +
|
||||
noizDens[MOS1RSNOIZ] +
|
||||
noizDens[MOS1IDNOIZ] +
|
||||
noizDens[MOS1FLNOIZ];
|
||||
lnNdens[MOS1TOTNOIZ] =
|
||||
log(MAX(noizDens[MOS1TOTNOIZ], N_MINLOG));
|
||||
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));
|
||||
|
||||
*OnDens += noizDens[MOS1TOTNOIZ];
|
||||
noizDens[MOS1TOTNOIZ] = noizDens[MOS1RDNOIZ] +
|
||||
noizDens[MOS1RSNOIZ] +
|
||||
noizDens[MOS1IDNOIZ] +
|
||||
noizDens[MOS1FLNOIZ];
|
||||
lnNdens[MOS1TOTNOIZ] =
|
||||
log(MAX(noizDens[MOS1TOTNOIZ], N_MINLOG));
|
||||
|
||||
if (data->delFreq == 0.0) {
|
||||
* OnDens += noizDens[MOS1TOTNOIZ];
|
||||
|
||||
/* if we haven't done any previous integration, we need to */
|
||||
/* initialize our "history" variables */
|
||||
if (data -> delFreq == 0.0) {
|
||||
|
||||
for (i=0; i < MOS1NSRCS; i++) {
|
||||
inst->MOS1nVar[LNLSTDENS][i] = lnNdens[i];
|
||||
}
|
||||
/* if we haven't done any previous integration, we need to */
|
||||
/* initialize our "history" variables */
|
||||
|
||||
/* clear out our integration variables if it's the first pass */
|
||||
for (i = 0; i < MOS1NSRCS; i++) {
|
||||
inst -> MOS1nVar[LNLSTDENS][i] = lnNdens[i];
|
||||
}
|
||||
|
||||
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;
|
||||
/* 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,16 +20,14 @@ 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];
|
||||
|
|
@ -38,142 +36,151 @@ MOS2noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt,
|
|||
|
||||
/* 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)));
|
||||
NevalSrc( & noizDens[MOS2IDNOIZ], & lnNdens[MOS2IDNOIZ],
|
||||
ckt, THERMNOISE, inst -> MOS2dNodePrime, inst -> MOS2sNodePrime,
|
||||
(2.0 / 3.0 * fabs(inst -> MOS2gm)));
|
||||
|
||||
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));
|
||||
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));
|
||||
|
||||
noizDens[MOS2TOTNOIZ] = noizDens[MOS2RDNOIZ] +
|
||||
noizDens[MOS2RSNOIZ] +
|
||||
noizDens[MOS2IDNOIZ] +
|
||||
noizDens[MOS2FLNOIZ];
|
||||
lnNdens[MOS2TOTNOIZ] =
|
||||
log(MAX(noizDens[MOS2TOTNOIZ], N_MINLOG));
|
||||
noizDens[MOS2TOTNOIZ] = noizDens[MOS2RDNOIZ] +
|
||||
noizDens[MOS2RSNOIZ] +
|
||||
noizDens[MOS2IDNOIZ] +
|
||||
noizDens[MOS2FLNOIZ];
|
||||
lnNdens[MOS2TOTNOIZ] =
|
||||
log(MAX(noizDens[MOS2TOTNOIZ], N_MINLOG));
|
||||
|
||||
*OnDens += noizDens[MOS2TOTNOIZ];
|
||||
* OnDens += noizDens[MOS2TOTNOIZ];
|
||||
|
||||
if (data->delFreq == 0.0) {
|
||||
if (data -> delFreq == 0.0) {
|
||||
|
||||
/* if we haven't done any previous integration, we need to */
|
||||
/* initialize our "history" variables */
|
||||
/* 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];
|
||||
}
|
||||
for (i = 0; i < MOS2NSRCS; i++) {
|
||||
inst -> MOS2nVar[LNLSTDENS][i] = lnNdens[i];
|
||||
}
|
||||
|
||||
/* clear out our integration variables if it's the first pass */
|
||||
/* 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 -> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,16 +20,14 @@ 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];
|
||||
|
|
@ -38,143 +36,151 @@ MOS3noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt,
|
|||
|
||||
/* 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));
|
||||
NevalSrc( & noizDens[MOS3IDNOIZ], & lnNdens[MOS3IDNOIZ],
|
||||
ckt, THERMNOISE, inst -> MOS3dNodePrime, inst -> MOS3sNodePrime,
|
||||
(2.0 / 3.0 * fabs(inst -> MOS3gm)));
|
||||
|
||||
noizDens[MOS3TOTNOIZ] = noizDens[MOS3RDNOIZ] +
|
||||
noizDens[MOS3RSNOIZ] +
|
||||
noizDens[MOS3IDNOIZ] +
|
||||
noizDens[MOS3FLNOIZ];
|
||||
lnNdens[MOS3TOTNOIZ] =
|
||||
log(MAX(noizDens[MOS3TOTNOIZ], N_MINLOG));
|
||||
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));
|
||||
|
||||
*OnDens += noizDens[MOS3TOTNOIZ];
|
||||
noizDens[MOS3TOTNOIZ] = noizDens[MOS3RDNOIZ] +
|
||||
noizDens[MOS3RSNOIZ] +
|
||||
noizDens[MOS3IDNOIZ] +
|
||||
noizDens[MOS3FLNOIZ];
|
||||
lnNdens[MOS3TOTNOIZ] =
|
||||
log(MAX(noizDens[MOS3TOTNOIZ], N_MINLOG));
|
||||
|
||||
if (data->delFreq == 0.0) {
|
||||
* OnDens += noizDens[MOS3TOTNOIZ];
|
||||
|
||||
/* if we haven't done any previous integration, we need to */
|
||||
/* initialize our "history" variables */
|
||||
if (data -> delFreq == 0.0) {
|
||||
|
||||
for (i=0; i < MOS3NSRCS; i++) {
|
||||
inst->MOS3nVar[LNLSTDENS][i] = lnNdens[i];
|
||||
}
|
||||
/* if we haven't done any previous integration, we need to */
|
||||
/* initialize our "history" variables */
|
||||
|
||||
/* clear out our integration variables if it's the first pass */
|
||||
for (i = 0; i < MOS3NSRCS; i++) {
|
||||
inst -> MOS3nVar[LNLSTDENS][i] = lnNdens[i];
|
||||
}
|
||||
|
||||
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;
|
||||
/* 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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue