Browse Source
Added noise analysis to bsim1, and parallel multiplier. (Do not rely on distortion analysis).
pre-master-46
Added noise analysis to bsim1, and parallel multiplier. (Do not rely on distortion analysis).
pre-master-46
25 changed files with 482 additions and 282 deletions
-
1src/spicelib/devices/bsim1/Makefile.am
-
4src/spicelib/devices/bsim1/b1.c
-
73src/spicelib/devices/bsim1/b1acld.c
-
64src/spicelib/devices/bsim1/b1ask.c
-
6src/spicelib/devices/bsim1/b1cvtest.c
-
6src/spicelib/devices/bsim1/b1del.c
-
5src/spicelib/devices/bsim1/b1dest.c
-
7src/spicelib/devices/bsim1/b1disto.c
-
26src/spicelib/devices/bsim1/b1dset.c
-
39src/spicelib/devices/bsim1/b1eval.c
-
6src/spicelib/devices/bsim1/b1getic.c
-
62src/spicelib/devices/bsim1/b1ld.c
-
13src/spicelib/devices/bsim1/b1mask.c
-
7src/spicelib/devices/bsim1/b1mdel.c
-
1src/spicelib/devices/bsim1/b1moscap.c
-
14src/spicelib/devices/bsim1/b1mpar.c
-
212src/spicelib/devices/bsim1/b1noi.c
-
12src/spicelib/devices/bsim1/b1par.c
-
107src/spicelib/devices/bsim1/b1pzld.c
-
23src/spicelib/devices/bsim1/b1set.c
-
7src/spicelib/devices/bsim1/b1temp.c
-
6src/spicelib/devices/bsim1/b1trunc.c
-
37src/spicelib/devices/bsim1/bsim1def.h
-
24src/spicelib/devices/bsim1/bsim1ext.h
-
2src/spicelib/devices/bsim1/bsim1init.c
@ -0,0 +1,212 @@ |
|||
/********** |
|||
Copyright 2003 ??. All rights reserved. |
|||
Author: 2003 Paolo Nenzi |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "bsim1def.h" |
|||
#include "cktdefs.h" |
|||
#include "iferrmsg.h" |
|||
#include "noisedef.h" |
|||
#include "suffix.h" |
|||
|
|||
/* |
|||
* B1noise (mode, operation, firstModel, ckt, data, OnDens) |
|||
* This routine names and evaluates all of the noise sources |
|||
* associated with MOSFET's. It starts with the model *firstModel and |
|||
* traverses all of its insts. It then proceeds to any other models |
|||
* on the linked list. The total output noise density generated by |
|||
* all of the MOSFET's is summed with the variable "OnDens". |
|||
*/ |
|||
|
|||
extern void NevalSrc(); |
|||
extern double Nintegrate(); |
|||
|
|||
int |
|||
B1noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, |
|||
Ndata *data, double *OnDens) |
|||
{ |
|||
B1model *firstModel = (B1model *) genmodel; |
|||
B1model *model; |
|||
B1instance *inst; |
|||
char name[N_MXVLNTH]; |
|||
double tempOnoise; |
|||
double tempInoise; |
|||
double noizDens[B1NSRCS]; |
|||
double lnNdens[B1NSRCS]; |
|||
int i; |
|||
|
|||
/* define the names of the noise sources */ |
|||
|
|||
static char *B1nNames[B1NSRCS] = { /* Note that we have to keep the order */ |
|||
"_rd", /* noise due to rd */ /* consistent with thestrchr definitions */ |
|||
"_rs", /* noise due to rs */ /* in bsim1defs.h */ |
|||
"_id", /* noise due to id */ |
|||
"_1overf", /* flicker (1/f) noise */ |
|||
"" /* total transistor noise */ |
|||
}; |
|||
|
|||
for (model=firstModel; model != NULL; model=model->B1nextModel) { |
|||
for (inst=model->B1instances; inst != NULL; inst=inst->B1nextInstance) { |
|||
if (inst->B1owner != ARCHme) continue; |
|||
|
|||
switch (operation) { |
|||
|
|||
case N_OPEN: |
|||
|
|||
/* see if we have to to produce a summary report */ |
|||
/* if so, name all the noise generators */ |
|||
|
|||
if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) { |
|||
switch (mode) { |
|||
|
|||
case N_DENS: |
|||
for (i=0; i < B1NSRCS; i++) { |
|||
(void)sprintf(name,"onoise_%s%s",inst->B1name,B1nNames[i]); |
|||
|
|||
|
|||
data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); |
|||
if (!data->namelist) return(E_NOMEM); |
|||
(*(SPfrontEnd->IFnewUid))(ckt, |
|||
&(data->namelist[data->numPlots++]), |
|||
(IFuid)NULL,name,UID_OTHER,(void **)NULL); |
|||
/* we've added one more plot */ |
|||
|
|||
|
|||
} |
|||
break; |
|||
|
|||
case INT_NOIZ: |
|||
for (i=0; i < B1NSRCS; i++) { |
|||
(void)sprintf(name,"onoise_total_%s%s",inst->B1name,B1nNames[i]); |
|||
|
|||
|
|||
data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); |
|||
if (!data->namelist) return(E_NOMEM); |
|||
(*(SPfrontEnd->IFnewUid))(ckt, |
|||
&(data->namelist[data->numPlots++]), |
|||
(IFuid)NULL,name,UID_OTHER,(void **)NULL); |
|||
/* we've added one more plot */ |
|||
|
|||
|
|||
(void)sprintf(name,"inoise_total_%s%s",inst->B1name,B1nNames[i]); |
|||
|
|||
|
|||
data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); |
|||
if (!data->namelist) return(E_NOMEM); |
|||
(*(SPfrontEnd->IFnewUid))(ckt, |
|||
&(data->namelist[data->numPlots++]), |
|||
(IFuid)NULL,name,UID_OTHER,(void **)NULL); |
|||
/* we've added one more plot */ |
|||
|
|||
|
|||
|
|||
} |
|||
break; |
|||
} |
|||
} |
|||
break; |
|||
|
|||
case N_CALC: |
|||
switch (mode) { |
|||
|
|||
case N_DENS: |
|||
NevalSrc(&noizDens[B1RDNOIZ],&lnNdens[B1RDNOIZ], |
|||
ckt,THERMNOISE,inst->B1dNodePrime,inst->B1dNode, |
|||
inst->B1drainConductance * inst->B1m); |
|||
|
|||
NevalSrc(&noizDens[B1RSNOIZ],&lnNdens[B1RSNOIZ], |
|||
ckt,THERMNOISE,inst->B1sNodePrime,inst->B1sNode, |
|||
inst->B1sourceConductance * inst->B1m); |
|||
|
|||
NevalSrc(&noizDens[B1IDNOIZ],&lnNdens[B1IDNOIZ], |
|||
ckt,THERMNOISE,inst->B1dNodePrime,inst->B1sNodePrime, |
|||
(2.0/3.0 * fabs(inst->B1gm * inst->B1m))); |
|||
|
|||
NevalSrc(&noizDens[B1FLNOIZ],(double*)NULL,ckt, |
|||
N_GAIN,inst->B1dNodePrime, inst->B1sNodePrime, |
|||
(double)0.0); |
|||
noizDens[B1FLNOIZ] *= model->B1fNcoef * inst->B1m * |
|||
exp(model->B1fNexp * |
|||
log(MAX(fabs(inst->B1cd),N_MINLOG))) / |
|||
(data->freq * |
|||
(inst->B1w - model->B1deltaW * 1e-6) * |
|||
(inst->B1l - model->B1deltaL * 1e-6) * |
|||
model->B1Cox * model->B1Cox); |
|||
lnNdens[B1FLNOIZ] = |
|||
log(MAX(noizDens[B1FLNOIZ],N_MINLOG)); |
|||
|
|||
noizDens[B1TOTNOIZ] = noizDens[B1RDNOIZ] + |
|||
noizDens[B1RSNOIZ] + |
|||
noizDens[B1IDNOIZ] + |
|||
noizDens[B1FLNOIZ]; |
|||
lnNdens[B1TOTNOIZ] = |
|||
log(MAX(noizDens[B1TOTNOIZ], N_MINLOG)); |
|||
|
|||
*OnDens += noizDens[B1TOTNOIZ]; |
|||
|
|||
if (data->delFreq == 0.0) { |
|||
|
|||
/* if we haven't done any previous integration, we need to */ |
|||
/* initialize our "history" variables */ |
|||
|
|||
for (i=0; i < B1NSRCS; i++) { |
|||
inst->B1nVar[LNLSTDENS][i] = lnNdens[i]; |
|||
} |
|||
|
|||
/* clear out our integration variables if it's the first pass */ |
|||
|
|||
if (data->freq == ((NOISEAN*)ckt->CKTcurJob)->NstartFreq) { |
|||
for (i=0; i < B1NSRCS; i++) { |
|||
inst->B1nVar[OUTNOIZ][i] = 0.0; |
|||
inst->B1nVar[INNOIZ][i] = 0.0; |
|||
} |
|||
} |
|||
} else { /* data->delFreq != 0.0 (we have to integrate) */ |
|||
for (i=0; i < B1NSRCS; i++) { |
|||
if (i != B1TOTNOIZ) { |
|||
tempOnoise = Nintegrate(noizDens[i], lnNdens[i], |
|||
inst->B1nVar[LNLSTDENS][i], data); |
|||
tempInoise = Nintegrate(noizDens[i] * data->GainSqInv , |
|||
lnNdens[i] + data->lnGainInv, |
|||
inst->B1nVar[LNLSTDENS][i] + data->lnGainInv, |
|||
data); |
|||
inst->B1nVar[LNLSTDENS][i] = lnNdens[i]; |
|||
data->outNoiz += tempOnoise; |
|||
data->inNoise += tempInoise; |
|||
if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) { |
|||
inst->B1nVar[OUTNOIZ][i] += tempOnoise; |
|||
inst->B1nVar[OUTNOIZ][B1TOTNOIZ] += tempOnoise; |
|||
inst->B1nVar[INNOIZ][i] += tempInoise; |
|||
inst->B1nVar[INNOIZ][B1TOTNOIZ] += tempInoise; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (data->prtSummary) { |
|||
for (i=0; i < B1NSRCS; i++) { /* print a summary report */ |
|||
data->outpVector[data->outNumber++] = noizDens[i]; |
|||
} |
|||
} |
|||
break; |
|||
|
|||
case INT_NOIZ: /* already calculated, just output */ |
|||
if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) { |
|||
for (i=0; i < B1NSRCS; i++) { |
|||
data->outpVector[data->outNumber++] = inst->B1nVar[OUTNOIZ][i]; |
|||
data->outpVector[data->outNumber++] = inst->B1nVar[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 */ |
|||
|
|||
return(OK); |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue