23 changed files with 457 additions and 235 deletions
-
1src/spicelib/devices/bsim2/Makefile.am
-
4src/spicelib/devices/bsim2/b2.c
-
74src/spicelib/devices/bsim2/b2acld.c
-
62src/spicelib/devices/bsim2/b2ask.c
-
6src/spicelib/devices/bsim2/b2cvtest.c
-
7src/spicelib/devices/bsim2/b2del.c
-
5src/spicelib/devices/bsim2/b2dest.c
-
15src/spicelib/devices/bsim2/b2eval.c
-
6src/spicelib/devices/bsim2/b2getic.c
-
66src/spicelib/devices/bsim2/b2ld.c
-
13src/spicelib/devices/bsim2/b2mask.c
-
7src/spicelib/devices/bsim2/b2mdel.c
-
1src/spicelib/devices/bsim2/b2moscap.c
-
14src/spicelib/devices/bsim2/b2mpar.c
-
212src/spicelib/devices/bsim2/b2noi.c
-
11src/spicelib/devices/bsim2/b2par.c
-
108src/spicelib/devices/bsim2/b2pzld.c
-
12src/spicelib/devices/bsim2/b2set.c
-
5src/spicelib/devices/bsim2/b2temp.c
-
7src/spicelib/devices/bsim2/b2trunc.c
-
32src/spicelib/devices/bsim2/bsim2def.h
-
22src/spicelib/devices/bsim2/bsim2ext.h
-
2src/spicelib/devices/bsim2/bsim2init.c
@ -0,0 +1,212 @@ |
|||||
|
/********** |
||||
|
Copyright 2003 ??. All rights reserved. |
||||
|
Author: 2003 Paolo Nenzi |
||||
|
**********/ |
||||
|
|
||||
|
#include "ngspice.h" |
||||
|
#include "bsim2def.h" |
||||
|
#include "cktdefs.h" |
||||
|
#include "iferrmsg.h" |
||||
|
#include "noisedef.h" |
||||
|
#include "suffix.h" |
||||
|
|
||||
|
/* |
||||
|
* B2noise (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 |
||||
|
B2noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, |
||||
|
Ndata *data, double *OnDens) |
||||
|
{ |
||||
|
B2model *firstModel = (B2model *) genmodel; |
||||
|
B2model *model; |
||||
|
B2instance *inst; |
||||
|
char name[N_MXVLNTH]; |
||||
|
double tempOnoise; |
||||
|
double tempInoise; |
||||
|
double noizDens[B2NSRCS]; |
||||
|
double lnNdens[B2NSRCS]; |
||||
|
int i; |
||||
|
|
||||
|
/* define the names of the noise sources */ |
||||
|
|
||||
|
static char *B2nNames[B2NSRCS] = { /* 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->B2nextModel) { |
||||
|
for (inst=model->B2instances; inst != NULL; inst=inst->B2nextInstance) { |
||||
|
if (inst->B2owner != 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 < B2NSRCS; i++) { |
||||
|
(void)sprintf(name,"onoise_%s%s",inst->B2name,B2nNames[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 < B2NSRCS; i++) { |
||||
|
(void)sprintf(name,"onoise_total_%s%s",inst->B2name,B2nNames[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->B2name,B2nNames[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[B2RDNOIZ],&lnNdens[B2RDNOIZ], |
||||
|
ckt,THERMNOISE,inst->B2dNodePrime,inst->B2dNode, |
||||
|
inst->B2drainConductance * inst->B2m); |
||||
|
|
||||
|
NevalSrc(&noizDens[B2RSNOIZ],&lnNdens[B2RSNOIZ], |
||||
|
ckt,THERMNOISE,inst->B2sNodePrime,inst->B2sNode, |
||||
|
inst->B2sourceConductance * inst->B2m); |
||||
|
|
||||
|
NevalSrc(&noizDens[B2IDNOIZ],&lnNdens[B2IDNOIZ], |
||||
|
ckt,THERMNOISE,inst->B2dNodePrime,inst->B2sNodePrime, |
||||
|
(2.0/3.0 * fabs(inst->B2gm * inst->B2m))); |
||||
|
|
||||
|
NevalSrc(&noizDens[B2FLNOIZ],(double*)NULL,ckt, |
||||
|
N_GAIN,inst->B2dNodePrime, inst->B2sNodePrime, |
||||
|
(double)0.0); |
||||
|
noizDens[B2FLNOIZ] *= model->B2fNcoef * inst->B2m * |
||||
|
exp(model->B2fNexp * |
||||
|
log(MAX(fabs(inst->B2cd),N_MINLOG))) / |
||||
|
(data->freq * |
||||
|
(inst->B2w - model->B2deltaW * 1e-6) * |
||||
|
(inst->B2l - model->B2deltaL * 1e-6) * |
||||
|
model->B2Cox * model->B2Cox); |
||||
|
lnNdens[B2FLNOIZ] = |
||||
|
log(MAX(noizDens[B2FLNOIZ],N_MINLOG)); |
||||
|
|
||||
|
noizDens[B2TOTNOIZ] = noizDens[B2RDNOIZ] + |
||||
|
noizDens[B2RSNOIZ] + |
||||
|
noizDens[B2IDNOIZ] + |
||||
|
noizDens[B2FLNOIZ]; |
||||
|
lnNdens[B2TOTNOIZ] = |
||||
|
log(MAX(noizDens[B2TOTNOIZ], N_MINLOG)); |
||||
|
|
||||
|
*OnDens += noizDens[B2TOTNOIZ]; |
||||
|
|
||||
|
if (data->delFreq == 0.0) { |
||||
|
|
||||
|
/* if we haven't done any previous integration, we need to */ |
||||
|
/* initialize our "history" variables */ |
||||
|
|
||||
|
for (i=0; i < B2NSRCS; i++) { |
||||
|
inst->B2nVar[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 < B2NSRCS; i++) { |
||||
|
inst->B2nVar[OUTNOIZ][i] = 0.0; |
||||
|
inst->B2nVar[INNOIZ][i] = 0.0; |
||||
|
} |
||||
|
} |
||||
|
} else { /* data->delFreq != 0.0 (we have to integrate) */ |
||||
|
for (i=0; i < B2NSRCS; i++) { |
||||
|
if (i != B2TOTNOIZ) { |
||||
|
tempOnoise = Nintegrate(noizDens[i], lnNdens[i], |
||||
|
inst->B2nVar[LNLSTDENS][i], data); |
||||
|
tempInoise = Nintegrate(noizDens[i] * data->GainSqInv , |
||||
|
lnNdens[i] + data->lnGainInv, |
||||
|
inst->B2nVar[LNLSTDENS][i] + data->lnGainInv, |
||||
|
data); |
||||
|
inst->B2nVar[LNLSTDENS][i] = lnNdens[i]; |
||||
|
data->outNoiz += tempOnoise; |
||||
|
data->inNoise += tempInoise; |
||||
|
if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) { |
||||
|
inst->B2nVar[OUTNOIZ][i] += tempOnoise; |
||||
|
inst->B2nVar[OUTNOIZ][B2TOTNOIZ] += tempOnoise; |
||||
|
inst->B2nVar[INNOIZ][i] += tempInoise; |
||||
|
inst->B2nVar[INNOIZ][B2TOTNOIZ] += tempInoise; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if (data->prtSummary) { |
||||
|
for (i=0; i < B2NSRCS; 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 < B2NSRCS; i++) { |
||||
|
data->outpVector[data->outNumber++] = inst->B2nVar[OUTNOIZ][i]; |
||||
|
data->outpVector[data->outNumber++] = inst->B2nVar[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