|
|
@ -1,5 +1,5 @@ |
|
|
/**** BSIM4.4.0 Released by Xuemei (Jane) Xi 03/04/2004 ****/ |
|
|
/**** BSIM4.4.0 Released by Xuemei (Jane) Xi 03/04/2004 ****/ |
|
|
|
|
|
|
|
|
|
|
|
/* ngspice multirevision code extension covering 4.2.1 & 4.3.0 & 4.4.0 */ |
|
|
/********** |
|
|
/********** |
|
|
* Copyright 2004 Regents of the University of California. All rights reserved. |
|
|
* Copyright 2004 Regents of the University of California. All rights reserved. |
|
|
* File: b4noi.c of BSIM4.4.0. |
|
|
* File: b4noi.c of BSIM4.4.0. |
|
|
@ -18,7 +18,6 @@ |
|
|
#include "cktdefs.h" |
|
|
#include "cktdefs.h" |
|
|
#include "iferrmsg.h" |
|
|
#include "iferrmsg.h" |
|
|
#include "noisedef.h" |
|
|
#include "noisedef.h" |
|
|
#include "suffix.h" |
|
|
|
|
|
#include "const.h" |
|
|
#include "const.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -36,23 +35,47 @@ BSIM4v4instance *here, |
|
|
double freq, double temp) |
|
|
double freq, double temp) |
|
|
{ |
|
|
{ |
|
|
struct bsim4SizeDependParam *pParam; |
|
|
struct bsim4SizeDependParam *pParam; |
|
|
double cd, esat, DelClm, EffFreq, N0, Nl, Leff, Leffsq; |
|
|
|
|
|
double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Ssi; |
|
|
|
|
|
|
|
|
double cd, esat=0.0, DelClm, EffFreq, N0, Nl, Leff, Leffsq=0.0; |
|
|
|
|
|
double T0, T1, T2=0.0, T3, T4, T5, T6, T7=0.0, T8, T9, Ssi; |
|
|
|
|
|
|
|
|
pParam = here->pParam; |
|
|
pParam = here->pParam; |
|
|
cd = fabs(here->BSIM4v4cd); |
|
|
cd = fabs(here->BSIM4v4cd); |
|
|
Leff = pParam->BSIM4v4leff - 2.0 * model->BSIM4v4lintnoi; |
|
|
|
|
|
Leffsq = Leff * Leff; |
|
|
|
|
|
esat = 2.0 * here->BSIM4v4vsattemp / here->BSIM4v4ueff; |
|
|
|
|
|
|
|
|
switch (model->BSIM4v4intVersion) { |
|
|
|
|
|
case BSIM4vOLD: case BSIM4v21: case BSIM4v30: |
|
|
|
|
|
break; |
|
|
|
|
|
case BSIM4v40: |
|
|
|
|
|
Leff = pParam->BSIM4v4leff - 2.0 * model->BSIM4v4lintnoi; |
|
|
|
|
|
Leffsq = Leff * Leff; |
|
|
|
|
|
break; |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
switch (model->BSIM4v4intVersion) { |
|
|
|
|
|
case BSIM4vOLD: case BSIM4v21: |
|
|
|
|
|
esat = 2.0 * pParam->BSIM4v4vsattemp / here->BSIM4v4ueff; |
|
|
|
|
|
break; |
|
|
|
|
|
case BSIM4v30: case BSIM4v40: |
|
|
|
|
|
esat = 2.0 * here->BSIM4v4vsattemp / here->BSIM4v4ueff; |
|
|
|
|
|
break; |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
if(model->BSIM4v4em<=0.0) DelClm = 0.0; /* flicker noise modified -JX */ |
|
|
if(model->BSIM4v4em<=0.0) DelClm = 0.0; /* flicker noise modified -JX */ |
|
|
else { |
|
|
else { |
|
|
T0 = ((((Vds - here->BSIM4v4Vdseff) / pParam->BSIM4v4litl) |
|
|
|
|
|
+ model->BSIM4v4em) / esat); |
|
|
|
|
|
DelClm = pParam->BSIM4v4litl * log (MAX(T0, N_MINLOG)); |
|
|
|
|
|
|
|
|
T0 = ((((Vds - here->BSIM4v4Vdseff) / pParam->BSIM4v4litl) |
|
|
|
|
|
+ model->BSIM4v4em) / esat); |
|
|
|
|
|
DelClm = pParam->BSIM4v4litl * log (MAX(T0, N_MINLOG)); |
|
|
} |
|
|
} |
|
|
EffFreq = pow(freq, model->BSIM4v4ef); |
|
|
EffFreq = pow(freq, model->BSIM4v4ef); |
|
|
T1 = CHARGE * CHARGE * CONSTboltz * cd * temp * here->BSIM4v4ueff; |
|
|
T1 = CHARGE * CHARGE * CONSTboltz * cd * temp * here->BSIM4v4ueff; |
|
|
T2 = 1.0e10 * EffFreq * here->BSIM4v4Abulk * model->BSIM4v4coxe * Leffsq; |
|
|
|
|
|
|
|
|
switch (model->BSIM4v4intVersion) { |
|
|
|
|
|
case BSIM4vOLD: case BSIM4v21: case BSIM4v30: |
|
|
|
|
|
T2 = 1.0e10 * EffFreq * here->BSIM4v4Abulk * model->BSIM4v4coxe |
|
|
|
|
|
* pParam->BSIM4v4leff * pParam->BSIM4v4leff; |
|
|
|
|
|
break; |
|
|
|
|
|
case BSIM4v40: |
|
|
|
|
|
T2 = 1.0e10 * EffFreq * here->BSIM4v4Abulk * model->BSIM4v4coxe * Leffsq; |
|
|
|
|
|
break; |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
N0 = model->BSIM4v4coxe * here->BSIM4v4Vgsteff / CHARGE; |
|
|
N0 = model->BSIM4v4coxe * here->BSIM4v4Vgsteff / CHARGE; |
|
|
Nl = model->BSIM4v4coxe * here->BSIM4v4Vgsteff |
|
|
Nl = model->BSIM4v4coxe * here->BSIM4v4Vgsteff |
|
|
* (1.0 - here->BSIM4v4AbovVgst2Vtm * here->BSIM4v4Vdseff) / CHARGE; |
|
|
* (1.0 - here->BSIM4v4AbovVgst2Vtm * here->BSIM4v4Vdseff) / CHARGE; |
|
|
@ -63,7 +86,16 @@ double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Ssi; |
|
|
T5 = model->BSIM4v4oxideTrapDensityC * 0.5 * (N0 * N0 - Nl * Nl); |
|
|
T5 = model->BSIM4v4oxideTrapDensityC * 0.5 * (N0 * N0 - Nl * Nl); |
|
|
|
|
|
|
|
|
T6 = CONSTboltz * temp * cd * cd; |
|
|
T6 = CONSTboltz * temp * cd * cd; |
|
|
T7 = 1.0e10 * EffFreq * Leffsq * pParam->BSIM4v4weff; |
|
|
|
|
|
|
|
|
switch (model->BSIM4v4intVersion) { |
|
|
|
|
|
case BSIM4vOLD: case BSIM4v21: case BSIM4v30: |
|
|
|
|
|
T7 = 1.0e10 * EffFreq * pParam->BSIM4v4leff |
|
|
|
|
|
* pParam->BSIM4v4leff * pParam->BSIM4v4weff; |
|
|
|
|
|
break; |
|
|
|
|
|
case BSIM4v40: |
|
|
|
|
|
T7 = 1.0e10 * EffFreq * Leffsq * pParam->BSIM4v4weff; |
|
|
|
|
|
break; |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
T8 = model->BSIM4v4oxideTrapDensityA + model->BSIM4v4oxideTrapDensityB * Nl |
|
|
T8 = model->BSIM4v4oxideTrapDensityA + model->BSIM4v4oxideTrapDensityB * Nl |
|
|
+ model->BSIM4v4oxideTrapDensityC * Nl * Nl; |
|
|
+ model->BSIM4v4oxideTrapDensityC * Nl * Nl; |
|
|
T9 = (Nl + here->BSIM4v4nstar) * (Nl + here->BSIM4v4nstar); |
|
|
T9 = (Nl + here->BSIM4v4nstar) * (Nl + here->BSIM4v4nstar); |
|
|
@ -89,6 +121,7 @@ double tempInoise; |
|
|
double noizDens[BSIM4v4NSRCS]; |
|
|
double noizDens[BSIM4v4NSRCS]; |
|
|
double lnNdens[BSIM4v4NSRCS]; |
|
|
double lnNdens[BSIM4v4NSRCS]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double T0, T1, T2, T5, T10, T11; |
|
|
double T0, T1, T2, T5, T10, T11; |
|
|
double Vds, Ssi, Swi; |
|
|
double Vds, Ssi, Swi; |
|
|
double tmp=0.0, gdpr, gspr, npart_theta=0.0, npart_beta=0.0, igsquare; |
|
|
double tmp=0.0, gdpr, gspr, npart_theta=0.0, npart_beta=0.0, igsquare; |
|
|
@ -100,106 +133,117 @@ int i; |
|
|
/* define the names of the noise sources */ |
|
|
/* define the names of the noise sources */ |
|
|
static char *BSIM4v4nNames[BSIM4v4NSRCS] = |
|
|
static char *BSIM4v4nNames[BSIM4v4NSRCS] = |
|
|
{ /* Note that we have to keep the order */ |
|
|
{ /* Note that we have to keep the order */ |
|
|
".rd", /* noise due to rd */ |
|
|
|
|
|
".rs", /* noise due to rs */ |
|
|
|
|
|
|
|
|
".rd", /* noise due to rd */ |
|
|
|
|
|
".rs", /* noise due to rs */ |
|
|
".rg", /* noise due to rgeltd */ |
|
|
".rg", /* noise due to rgeltd */ |
|
|
".rbps", /* noise due to rbps */ |
|
|
".rbps", /* noise due to rbps */ |
|
|
".rbpd", /* noise due to rbpd */ |
|
|
".rbpd", /* noise due to rbpd */ |
|
|
".rbpb", /* noise due to rbpb */ |
|
|
".rbpb", /* noise due to rbpb */ |
|
|
".rbsb", /* noise due to rbsb */ |
|
|
".rbsb", /* noise due to rbsb */ |
|
|
".rbdb", /* noise due to rbdb */ |
|
|
".rbdb", /* noise due to rbdb */ |
|
|
".id", /* noise due to id */ |
|
|
|
|
|
".1overf", /* flicker (1/f) noise */ |
|
|
|
|
|
|
|
|
".id", /* noise due to id */ |
|
|
|
|
|
".1overf", /* flicker (1/f) noise */ |
|
|
".igs", /* shot noise due to IGS */ |
|
|
".igs", /* shot noise due to IGS */ |
|
|
".igd", /* shot noise due to IGD */ |
|
|
".igd", /* shot noise due to IGD */ |
|
|
".igb", /* shot noise due to IGB */ |
|
|
".igb", /* shot noise due to IGB */ |
|
|
"" /* total transistor noise */ |
|
|
|
|
|
|
|
|
"" /* total transistor noise */ |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
for (; model != NULL; model = model->BSIM4v4nextModel) |
|
|
for (; model != NULL; model = model->BSIM4v4nextModel) |
|
|
{ for (here = model->BSIM4v4instances; here != NULL; |
|
|
{ for (here = model->BSIM4v4instances; here != NULL; |
|
|
here = here->BSIM4v4nextInstance) |
|
|
|
|
|
{ pParam = here->pParam; |
|
|
|
|
|
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 < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ (void) sprintf(name, "onoise.%s%s", |
|
|
|
|
|
here->BSIM4v4name, |
|
|
|
|
|
BSIM4v4nNames[i]); |
|
|
|
|
|
|
|
|
here = here->BSIM4v4nextInstance) |
|
|
|
|
|
{ pParam = here->pParam; |
|
|
|
|
|
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 < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ (void) sprintf(name, "onoise.%s%s", |
|
|
|
|
|
here->BSIM4v4name, |
|
|
|
|
|
BSIM4v4nNames[i]); |
|
|
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); |
|
|
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); |
|
|
if (!data->namelist) |
|
|
if (!data->namelist) |
|
|
return(E_NOMEM); |
|
|
|
|
|
SPfrontEnd->IFnewUid (ckt, |
|
|
|
|
|
&(data->namelist[data->numPlots++]), |
|
|
|
|
|
NULL, name, UID_OTHER, |
|
|
|
|
|
NULL); |
|
|
|
|
|
/* we've added one more plot */ |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case INT_NOIZ: |
|
|
|
|
|
for (i = 0; i < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ (void) sprintf(name, "onoise_total.%s%s", |
|
|
|
|
|
here->BSIM4v4name, |
|
|
|
|
|
BSIM4v4nNames[i]); |
|
|
|
|
|
|
|
|
return(E_NOMEM); |
|
|
|
|
|
SPfrontEnd->IFnewUid (ckt, |
|
|
|
|
|
&(data->namelist[data->numPlots++]), |
|
|
|
|
|
NULL, name, UID_OTHER, |
|
|
|
|
|
NULL); |
|
|
|
|
|
/* we've added one more plot */ |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case INT_NOIZ: |
|
|
|
|
|
for (i = 0; i < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ (void) sprintf(name, "onoise_total.%s%s", |
|
|
|
|
|
here->BSIM4v4name, |
|
|
|
|
|
BSIM4v4nNames[i]); |
|
|
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); |
|
|
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); |
|
|
if (!data->namelist) |
|
|
if (!data->namelist) |
|
|
return(E_NOMEM); |
|
|
|
|
|
SPfrontEnd->IFnewUid (ckt, |
|
|
|
|
|
&(data->namelist[data->numPlots++]), |
|
|
|
|
|
NULL, name, UID_OTHER, |
|
|
|
|
|
NULL); |
|
|
|
|
|
/* we've added one more plot */ |
|
|
|
|
|
|
|
|
|
|
|
(void) sprintf(name, "inoise_total.%s%s", |
|
|
|
|
|
here->BSIM4v4name, |
|
|
|
|
|
BSIM4v4nNames[i]); |
|
|
|
|
|
|
|
|
return(E_NOMEM); |
|
|
|
|
|
SPfrontEnd->IFnewUid (ckt, |
|
|
|
|
|
&(data->namelist[data->numPlots++]), |
|
|
|
|
|
NULL, name, UID_OTHER, |
|
|
|
|
|
NULL); |
|
|
|
|
|
/* we've added one more plot */ |
|
|
|
|
|
|
|
|
|
|
|
(void) sprintf(name, "inoise_total.%s%s", |
|
|
|
|
|
here->BSIM4v4name, |
|
|
|
|
|
BSIM4v4nNames[i]); |
|
|
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); |
|
|
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); |
|
|
if (!data->namelist) |
|
|
if (!data->namelist) |
|
|
return(E_NOMEM); |
|
|
|
|
|
SPfrontEnd->IFnewUid (ckt, |
|
|
|
|
|
&(data->namelist[data->numPlots++]), |
|
|
|
|
|
NULL, name, UID_OTHER, |
|
|
|
|
|
NULL); |
|
|
|
|
|
/* we've added one more plot */ |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case N_CALC: |
|
|
|
|
|
m = here->BSIM4v4m; |
|
|
|
|
|
switch (mode) |
|
|
|
|
|
{ case N_DENS: |
|
|
|
|
|
if (model->BSIM4v4tnoiMod == 0) |
|
|
|
|
|
{ if (model->BSIM4v4rdsMod == 0) |
|
|
|
|
|
{ gspr = here->BSIM4v4sourceConductance; |
|
|
|
|
|
|
|
|
return(E_NOMEM); |
|
|
|
|
|
SPfrontEnd->IFnewUid (ckt, |
|
|
|
|
|
&(data->namelist[data->numPlots++]), |
|
|
|
|
|
NULL, name, UID_OTHER, |
|
|
|
|
|
NULL); |
|
|
|
|
|
/* we've added one more plot */ |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case N_CALC: |
|
|
|
|
|
m = here->BSIM4v4m; |
|
|
|
|
|
switch (mode) |
|
|
|
|
|
{ case N_DENS: |
|
|
|
|
|
if (model->BSIM4v4tnoiMod == 0) |
|
|
|
|
|
{ if (model->BSIM4v4rdsMod == 0) |
|
|
|
|
|
{ gspr = here->BSIM4v4sourceConductance; |
|
|
gdpr = here->BSIM4v4drainConductance; |
|
|
gdpr = here->BSIM4v4drainConductance; |
|
|
if (here->BSIM4v4grdsw > 0.0) |
|
|
|
|
|
tmp = 1.0 / here->BSIM4v4grdsw; /* tmp used below */ |
|
|
|
|
|
else |
|
|
|
|
|
tmp = 0.0; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ gspr = here->BSIM4v4gstot; |
|
|
|
|
|
|
|
|
if (here->BSIM4v4grdsw > 0.0) |
|
|
|
|
|
tmp = 1.0 / here->BSIM4v4grdsw; /* tmp used below */ |
|
|
|
|
|
else |
|
|
|
|
|
tmp = 0.0; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ gspr = here->BSIM4v4gstot; |
|
|
gdpr = here->BSIM4v4gdtot; |
|
|
gdpr = here->BSIM4v4gdtot; |
|
|
tmp = 0.0; |
|
|
tmp = 0.0; |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ T5 = here->BSIM4v4Vgsteff / here->BSIM4v4EsatL; |
|
|
|
|
|
T5 *= T5; |
|
|
|
|
|
npart_beta = model->BSIM4v4rnoia * (1.0 + T5 |
|
|
|
|
|
* model->BSIM4v4tnoia * pParam->BSIM4v4leff); |
|
|
|
|
|
npart_theta = model->BSIM4v4rnoib * (1.0 + T5 |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ T5 = here->BSIM4v4Vgsteff / here->BSIM4v4EsatL; |
|
|
|
|
|
T5 *= T5; |
|
|
|
|
|
switch (model->BSIM4v4intVersion) { |
|
|
|
|
|
case BSIM4vOLD: case BSIM4v21: |
|
|
|
|
|
npart_beta = 0.577 * (1.0 + T5 |
|
|
|
|
|
* model->BSIM4v4tnoia * pParam->BSIM4v4leff); |
|
|
|
|
|
npart_theta = 0.37 * (1.0 + T5 |
|
|
* model->BSIM4v4tnoib * pParam->BSIM4v4leff); |
|
|
* model->BSIM4v4tnoib * pParam->BSIM4v4leff); |
|
|
|
|
|
break; |
|
|
|
|
|
case BSIM4v30: case BSIM4v40: |
|
|
|
|
|
npart_beta = model->BSIM4v4rnoia * (1.0 + T5 |
|
|
|
|
|
* model->BSIM4v4tnoia * pParam->BSIM4v4leff); |
|
|
|
|
|
npart_theta = model->BSIM4v4rnoib * (1.0 + T5 |
|
|
|
|
|
* model->BSIM4v4tnoib * pParam->BSIM4v4leff); |
|
|
|
|
|
break; |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (model->BSIM4v4rdsMod == 0) |
|
|
|
|
|
|
|
|
if (model->BSIM4v4rdsMod == 0) |
|
|
{ gspr = here->BSIM4v4sourceConductance; |
|
|
{ gspr = here->BSIM4v4sourceConductance; |
|
|
gdpr = here->BSIM4v4drainConductance; |
|
|
gdpr = here->BSIM4v4drainConductance; |
|
|
} |
|
|
} |
|
|
@ -208,42 +252,55 @@ int i; |
|
|
gdpr = here->BSIM4v4gdtot; |
|
|
gdpr = here->BSIM4v4gdtot; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ((*(ckt->CKTstates[0] + here->BSIM4v4vds)) >= 0.0) |
|
|
|
|
|
gspr = gspr / (1.0 + npart_theta * npart_theta * gspr |
|
|
|
|
|
/ here->BSIM4v4IdovVds); /* bugfix */ |
|
|
|
|
|
else |
|
|
|
|
|
gdpr = gdpr / (1.0 + npart_theta * npart_theta * gdpr |
|
|
|
|
|
/ here->BSIM4v4IdovVds); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
switch (model->BSIM4v4intVersion) { |
|
|
|
|
|
case BSIM4vOLD: case BSIM4v21: |
|
|
|
|
|
if ((*(ckt->CKTstates[0] + here->BSIM4v4vds)) >= 0.0) |
|
|
|
|
|
gspr = gspr * (1.0 + npart_theta * npart_theta * gspr |
|
|
|
|
|
/ here->BSIM4v4IdovVds); |
|
|
|
|
|
else |
|
|
|
|
|
gdpr = gdpr * (1.0 + npart_theta * npart_theta * gdpr |
|
|
|
|
|
/ here->BSIM4v4IdovVds); |
|
|
|
|
|
break; |
|
|
|
|
|
case BSIM4v30: case BSIM4v40: |
|
|
|
|
|
if ((*(ckt->CKTstates[0] + here->BSIM4v4vds)) >= 0.0) |
|
|
|
|
|
gspr = gspr / (1.0 + npart_theta * npart_theta * gspr |
|
|
|
|
|
/ here->BSIM4v4IdovVds); /* bugfix */ |
|
|
|
|
|
else |
|
|
|
|
|
gdpr = gdpr / (1.0 + npart_theta * npart_theta * gdpr |
|
|
|
|
|
/ here->BSIM4v4IdovVds); |
|
|
|
|
|
break; |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4RDNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4RDNOIZ], ckt, THERMNOISE, |
|
|
|
|
|
here->BSIM4v4dNodePrime, here->BSIM4v4dNode, |
|
|
|
|
|
gdpr * m); |
|
|
|
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4RDNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4RDNOIZ], ckt, THERMNOISE, |
|
|
|
|
|
here->BSIM4v4dNodePrime, here->BSIM4v4dNode, |
|
|
|
|
|
gdpr * m); |
|
|
|
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4RSNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4RSNOIZ], ckt, THERMNOISE, |
|
|
|
|
|
here->BSIM4v4sNodePrime, here->BSIM4v4sNode, |
|
|
|
|
|
gspr * m); |
|
|
|
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4RSNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4RSNOIZ], ckt, THERMNOISE, |
|
|
|
|
|
here->BSIM4v4sNodePrime, here->BSIM4v4sNode, |
|
|
|
|
|
gspr * m); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((here->BSIM4v4rgateMod == 1) || (here->BSIM4v4rgateMod == 2)) |
|
|
|
|
|
{ NevalSrc(&noizDens[BSIM4v4RGNOIZ], |
|
|
|
|
|
|
|
|
if ((here->BSIM4v4rgateMod == 1) || (here->BSIM4v4rgateMod == 2)) |
|
|
|
|
|
{ NevalSrc(&noizDens[BSIM4v4RGNOIZ], |
|
|
&lnNdens[BSIM4v4RGNOIZ], ckt, THERMNOISE, |
|
|
&lnNdens[BSIM4v4RGNOIZ], ckt, THERMNOISE, |
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4gNodeExt, |
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4gNodeExt, |
|
|
here->BSIM4v4grgeltd * m); |
|
|
here->BSIM4v4grgeltd * m); |
|
|
} |
|
|
|
|
|
else if (here->BSIM4v4rgateMod == 3) |
|
|
|
|
|
{ NevalSrc(&noizDens[BSIM4v4RGNOIZ], |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
else if (here->BSIM4v4rgateMod == 3) |
|
|
|
|
|
{ NevalSrc(&noizDens[BSIM4v4RGNOIZ], |
|
|
&lnNdens[BSIM4v4RGNOIZ], ckt, THERMNOISE, |
|
|
&lnNdens[BSIM4v4RGNOIZ], ckt, THERMNOISE, |
|
|
here->BSIM4v4gNodeMid, here->BSIM4v4gNodeExt, |
|
|
here->BSIM4v4gNodeMid, here->BSIM4v4gNodeExt, |
|
|
here->BSIM4v4grgeltd * m); |
|
|
here->BSIM4v4grgeltd * m); |
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ noizDens[BSIM4v4RGNOIZ] = 0.0; |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ noizDens[BSIM4v4RGNOIZ] = 0.0; |
|
|
lnNdens[BSIM4v4RGNOIZ] = |
|
|
lnNdens[BSIM4v4RGNOIZ] = |
|
|
log(MAX(noizDens[BSIM4v4RGNOIZ], N_MINLOG)); |
|
|
log(MAX(noizDens[BSIM4v4RGNOIZ], N_MINLOG)); |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (here->BSIM4v4rbodyMod) |
|
|
if (here->BSIM4v4rbodyMod) |
|
|
@ -286,49 +343,49 @@ int i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(model->BSIM4v4tnoiMod) |
|
|
switch(model->BSIM4v4tnoiMod) |
|
|
{ case 0: |
|
|
|
|
|
T0 = m * here->BSIM4v4ueff * fabs(here->BSIM4v4qinv); |
|
|
|
|
|
T1 = T0 * tmp + pParam->BSIM4v4leff |
|
|
|
|
|
|
|
|
{ case 0: |
|
|
|
|
|
T0 = m * here->BSIM4v4ueff * fabs(here->BSIM4v4qinv); |
|
|
|
|
|
T1 = T0 * tmp + pParam->BSIM4v4leff |
|
|
* pParam->BSIM4v4leff; |
|
|
* pParam->BSIM4v4leff; |
|
|
NevalSrc(&noizDens[BSIM4v4IDNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IDNOIZ], ckt, |
|
|
|
|
|
THERMNOISE, here->BSIM4v4dNodePrime, |
|
|
|
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IDNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IDNOIZ], ckt, |
|
|
|
|
|
THERMNOISE, here->BSIM4v4dNodePrime, |
|
|
here->BSIM4v4sNodePrime, |
|
|
here->BSIM4v4sNodePrime, |
|
|
(T0 / T1) * model->BSIM4v4ntnoi); |
|
|
|
|
|
break; |
|
|
|
|
|
case 1: |
|
|
|
|
|
T0 = m * (here->BSIM4v4gm + here->BSIM4v4gmbs + here->BSIM4v4gds); |
|
|
|
|
|
T0 *= T0; |
|
|
|
|
|
igsquare = npart_theta * npart_theta * T0 / here->BSIM4v4IdovVds; |
|
|
|
|
|
T1 = npart_beta * (here->BSIM4v4gm |
|
|
|
|
|
+ here->BSIM4v4gmbs) + here->BSIM4v4gds; |
|
|
|
|
|
T2 = T1 * T1 / here->BSIM4v4IdovVds; |
|
|
|
|
|
|
|
|
(T0 / T1) * model->BSIM4v4ntnoi); |
|
|
|
|
|
break; |
|
|
|
|
|
case 1: |
|
|
|
|
|
T0 = m * (here->BSIM4v4gm + here->BSIM4v4gmbs + here->BSIM4v4gds); |
|
|
|
|
|
T0 *= T0; |
|
|
|
|
|
igsquare = npart_theta * npart_theta * T0 / here->BSIM4v4IdovVds; |
|
|
|
|
|
T1 = npart_beta * (here->BSIM4v4gm |
|
|
|
|
|
+ here->BSIM4v4gmbs) + here->BSIM4v4gds; |
|
|
|
|
|
T2 = T1 * T1 / here->BSIM4v4IdovVds; |
|
|
NevalSrc(&noizDens[BSIM4v4IDNOIZ], |
|
|
NevalSrc(&noizDens[BSIM4v4IDNOIZ], |
|
|
&lnNdens[BSIM4v4IDNOIZ], ckt, |
|
|
&lnNdens[BSIM4v4IDNOIZ], ckt, |
|
|
THERMNOISE, here->BSIM4v4dNodePrime, |
|
|
THERMNOISE, here->BSIM4v4dNodePrime, |
|
|
here->BSIM4v4sNodePrime, (T2 - igsquare)); |
|
|
here->BSIM4v4sNodePrime, (T2 - igsquare)); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4FLNOIZ], NULL, |
|
|
|
|
|
ckt, N_GAIN, here->BSIM4v4dNodePrime, |
|
|
|
|
|
here->BSIM4v4sNodePrime, (double) 0.0); |
|
|
|
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4FLNOIZ], NULL, |
|
|
|
|
|
ckt, N_GAIN, here->BSIM4v4dNodePrime, |
|
|
|
|
|
here->BSIM4v4sNodePrime, (double) 0.0); |
|
|
|
|
|
|
|
|
switch(model->BSIM4v4fnoiMod) |
|
|
switch(model->BSIM4v4fnoiMod) |
|
|
{ case 0: |
|
|
|
|
|
noizDens[BSIM4v4FLNOIZ] *= m * model->BSIM4v4kf |
|
|
|
|
|
* exp(model->BSIM4v4af |
|
|
|
|
|
* log(MAX(fabs(here->BSIM4v4cd), |
|
|
|
|
|
N_MINLOG))) |
|
|
|
|
|
/ (pow(data->freq, model->BSIM4v4ef) |
|
|
|
|
|
* pParam->BSIM4v4leff |
|
|
|
|
|
* pParam->BSIM4v4leff |
|
|
|
|
|
* model->BSIM4v4coxe); |
|
|
|
|
|
break; |
|
|
|
|
|
case 1: |
|
|
|
|
|
Vds = *(ckt->CKTstates[0] + here->BSIM4v4vds); |
|
|
|
|
|
if (Vds < 0.0) |
|
|
|
|
|
Vds = -Vds; |
|
|
|
|
|
|
|
|
{ case 0: |
|
|
|
|
|
noizDens[BSIM4v4FLNOIZ] *= m * model->BSIM4v4kf |
|
|
|
|
|
* exp(model->BSIM4v4af |
|
|
|
|
|
* log(MAX(fabs(here->BSIM4v4cd), |
|
|
|
|
|
N_MINLOG))) |
|
|
|
|
|
/ (pow(data->freq, model->BSIM4v4ef) |
|
|
|
|
|
* pParam->BSIM4v4leff |
|
|
|
|
|
* pParam->BSIM4v4leff |
|
|
|
|
|
* model->BSIM4v4coxe); |
|
|
|
|
|
break; |
|
|
|
|
|
case 1: |
|
|
|
|
|
Vds = *(ckt->CKTstates[0] + here->BSIM4v4vds); |
|
|
|
|
|
if (Vds < 0.0) |
|
|
|
|
|
Vds = -Vds; |
|
|
|
|
|
|
|
|
Ssi = BSIM4v4Eval1ovFNoise(Vds, model, here, |
|
|
Ssi = BSIM4v4Eval1ovFNoise(Vds, model, here, |
|
|
data->freq, ckt->CKTtemp); |
|
|
data->freq, ckt->CKTtemp); |
|
|
@ -336,7 +393,7 @@ int i; |
|
|
* CONSTboltz * ckt->CKTtemp; |
|
|
* CONSTboltz * ckt->CKTtemp; |
|
|
T11 = pParam->BSIM4v4weff * pParam->BSIM4v4leff |
|
|
T11 = pParam->BSIM4v4weff * pParam->BSIM4v4leff |
|
|
* pow(data->freq, model->BSIM4v4ef) * 1.0e10 |
|
|
* pow(data->freq, model->BSIM4v4ef) * 1.0e10 |
|
|
* here->BSIM4v4nstar * here->BSIM4v4nstar; |
|
|
|
|
|
|
|
|
* here->BSIM4v4nstar * here->BSIM4v4nstar; |
|
|
Swi = T10 / T11 * here->BSIM4v4cd |
|
|
Swi = T10 / T11 * here->BSIM4v4cd |
|
|
* here->BSIM4v4cd; |
|
|
* here->BSIM4v4cd; |
|
|
T1 = Swi + Ssi; |
|
|
T1 = Swi + Ssi; |
|
|
@ -344,133 +401,148 @@ int i; |
|
|
noizDens[BSIM4v4FLNOIZ] *= m * (Ssi * Swi) / T1; |
|
|
noizDens[BSIM4v4FLNOIZ] *= m * (Ssi * Swi) / T1; |
|
|
else |
|
|
else |
|
|
noizDens[BSIM4v4FLNOIZ] *= 0.0; |
|
|
noizDens[BSIM4v4FLNOIZ] *= 0.0; |
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
lnNdens[BSIM4v4FLNOIZ] = |
|
|
|
|
|
log(MAX(noizDens[BSIM4v4FLNOIZ], N_MINLOG)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(here->BSIM4v4mode >= 0) { /* bugfix */ |
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IGSNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IGSNOIZ], ckt, SHOTNOISE, |
|
|
|
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4sNodePrime, |
|
|
|
|
|
m * (here->BSIM4v4Igs + here->BSIM4v4Igcs)); |
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IGDNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IGDNOIZ], ckt, SHOTNOISE, |
|
|
|
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4dNodePrime, |
|
|
|
|
|
m * (here->BSIM4v4Igd + here->BSIM4v4Igcd)); |
|
|
|
|
|
} else { |
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IGSNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IGSNOIZ], ckt, SHOTNOISE, |
|
|
|
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4sNodePrime, |
|
|
|
|
|
m * (here->BSIM4v4Igs + here->BSIM4v4Igcd)); |
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IGDNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IGDNOIZ], ckt, SHOTNOISE, |
|
|
|
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4dNodePrime, |
|
|
|
|
|
m * (here->BSIM4v4Igd + here->BSIM4v4Igcs)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
lnNdens[BSIM4v4FLNOIZ] = |
|
|
|
|
|
log(MAX(noizDens[BSIM4v4FLNOIZ], N_MINLOG)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (model->BSIM4v4intVersion) { |
|
|
|
|
|
case BSIM4vOLD: case BSIM4v21: |
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IGSNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IGSNOIZ], ckt, SHOTNOISE, |
|
|
|
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4sNodePrime, |
|
|
|
|
|
m * (here->BSIM4v4Igs + here->BSIM4v4Igcs)); |
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IGDNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IGDNOIZ], ckt, SHOTNOISE, |
|
|
|
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4dNodePrime, |
|
|
|
|
|
m * (here->BSIM4v4Igd + here->BSIM4v4Igcd)); |
|
|
|
|
|
break; |
|
|
|
|
|
case BSIM4v30: case BSIM4v40: |
|
|
|
|
|
if(here->BSIM4v4mode >= 0) { /* bugfix */ |
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IGSNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IGSNOIZ], ckt, SHOTNOISE, |
|
|
|
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4sNodePrime, |
|
|
|
|
|
m * (here->BSIM4v4Igs + here->BSIM4v4Igcs)); |
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IGDNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IGDNOIZ], ckt, SHOTNOISE, |
|
|
|
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4dNodePrime, |
|
|
|
|
|
m * (here->BSIM4v4Igd + here->BSIM4v4Igcd)); |
|
|
|
|
|
} else { |
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IGSNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IGSNOIZ], ckt, SHOTNOISE, |
|
|
|
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4sNodePrime, |
|
|
|
|
|
m * (here->BSIM4v4Igs + here->BSIM4v4Igcd)); |
|
|
|
|
|
NevalSrc(&noizDens[BSIM4v4IGDNOIZ], |
|
|
|
|
|
&lnNdens[BSIM4v4IGDNOIZ], ckt, SHOTNOISE, |
|
|
|
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4dNodePrime, |
|
|
|
|
|
m * (here->BSIM4v4Igd + here->BSIM4v4Igcs)); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
NevalSrc(&noizDens[BSIM4v4IGBNOIZ], |
|
|
NevalSrc(&noizDens[BSIM4v4IGBNOIZ], |
|
|
&lnNdens[BSIM4v4IGBNOIZ], ckt, SHOTNOISE, |
|
|
&lnNdens[BSIM4v4IGBNOIZ], ckt, SHOTNOISE, |
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4bNodePrime, |
|
|
here->BSIM4v4gNodePrime, here->BSIM4v4bNodePrime, |
|
|
m * here->BSIM4v4Igb); |
|
|
m * here->BSIM4v4Igb); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
noizDens[BSIM4v4TOTNOIZ] = noizDens[BSIM4v4RDNOIZ] |
|
|
|
|
|
+ noizDens[BSIM4v4RSNOIZ] + noizDens[BSIM4v4RGNOIZ] |
|
|
|
|
|
+ noizDens[BSIM4v4RBPSNOIZ] + noizDens[BSIM4v4RBPDNOIZ] |
|
|
|
|
|
+ noizDens[BSIM4v4RBPBNOIZ] |
|
|
|
|
|
+ noizDens[BSIM4v4RBSBNOIZ] + noizDens[BSIM4v4RBDBNOIZ] |
|
|
|
|
|
+ noizDens[BSIM4v4IDNOIZ] + noizDens[BSIM4v4FLNOIZ] |
|
|
|
|
|
|
|
|
noizDens[BSIM4v4TOTNOIZ] = noizDens[BSIM4v4RDNOIZ] |
|
|
|
|
|
+ noizDens[BSIM4v4RSNOIZ] + noizDens[BSIM4v4RGNOIZ] |
|
|
|
|
|
+ noizDens[BSIM4v4RBPSNOIZ] + noizDens[BSIM4v4RBPDNOIZ] |
|
|
|
|
|
+ noizDens[BSIM4v4RBPBNOIZ] |
|
|
|
|
|
+ noizDens[BSIM4v4RBSBNOIZ] + noizDens[BSIM4v4RBDBNOIZ] |
|
|
|
|
|
+ noizDens[BSIM4v4IDNOIZ] + noizDens[BSIM4v4FLNOIZ] |
|
|
+ noizDens[BSIM4v4IGSNOIZ] + noizDens[BSIM4v4IGDNOIZ] |
|
|
+ noizDens[BSIM4v4IGSNOIZ] + noizDens[BSIM4v4IGDNOIZ] |
|
|
+ noizDens[BSIM4v4IGBNOIZ]; |
|
|
+ noizDens[BSIM4v4IGBNOIZ]; |
|
|
lnNdens[BSIM4v4TOTNOIZ] = |
|
|
|
|
|
log(MAX(noizDens[BSIM4v4TOTNOIZ], N_MINLOG)); |
|
|
|
|
|
|
|
|
|
|
|
*OnDens += noizDens[BSIM4v4TOTNOIZ]; |
|
|
|
|
|
|
|
|
|
|
|
if (data->delFreq == 0.0) |
|
|
|
|
|
{ /* if we haven't done any previous |
|
|
|
|
|
integration, we need to initialize our |
|
|
|
|
|
"history" variables. |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ here->BSIM4v4nVar[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 < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ here->BSIM4v4nVar[OUTNOIZ][i] = 0.0; |
|
|
|
|
|
here->BSIM4v4nVar[INNOIZ][i] = 0.0; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ /* data->delFreq != 0.0, |
|
|
|
|
|
we have to integrate. |
|
|
|
|
|
*/ |
|
|
|
|
|
for (i = 0; i < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ if (i != BSIM4v4TOTNOIZ) |
|
|
|
|
|
{ tempOnoise = Nintegrate(noizDens[i], |
|
|
|
|
|
lnNdens[i], |
|
|
|
|
|
here->BSIM4v4nVar[LNLSTDENS][i], |
|
|
|
|
|
data); |
|
|
|
|
|
tempInoise = Nintegrate(noizDens[i] |
|
|
|
|
|
* data->GainSqInv, lnNdens[i] |
|
|
|
|
|
+ data->lnGainInv, |
|
|
|
|
|
here->BSIM4v4nVar[LNLSTDENS][i] |
|
|
|
|
|
+ data->lnGainInv, data); |
|
|
|
|
|
here->BSIM4v4nVar[LNLSTDENS][i] = |
|
|
|
|
|
lnNdens[i]; |
|
|
|
|
|
data->outNoiz += tempOnoise; |
|
|
|
|
|
data->inNoise += tempInoise; |
|
|
|
|
|
if (((NOISEAN*) |
|
|
|
|
|
ckt->CKTcurJob)->NStpsSm != 0) |
|
|
|
|
|
{ here->BSIM4v4nVar[OUTNOIZ][i] |
|
|
|
|
|
+= tempOnoise; |
|
|
|
|
|
here->BSIM4v4nVar[OUTNOIZ][BSIM4v4TOTNOIZ] |
|
|
|
|
|
+= tempOnoise; |
|
|
|
|
|
here->BSIM4v4nVar[INNOIZ][i] |
|
|
|
|
|
+= tempInoise; |
|
|
|
|
|
here->BSIM4v4nVar[INNOIZ][BSIM4v4TOTNOIZ] |
|
|
|
|
|
+= tempInoise; |
|
|
|
|
|
|
|
|
lnNdens[BSIM4v4TOTNOIZ] = |
|
|
|
|
|
log(MAX(noizDens[BSIM4v4TOTNOIZ], N_MINLOG)); |
|
|
|
|
|
|
|
|
|
|
|
*OnDens += noizDens[BSIM4v4TOTNOIZ]; |
|
|
|
|
|
|
|
|
|
|
|
if (data->delFreq == 0.0) |
|
|
|
|
|
{ /* if we haven't done any previous |
|
|
|
|
|
integration, we need to initialize our |
|
|
|
|
|
"history" variables. |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ here->BSIM4v4nVar[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 < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ here->BSIM4v4nVar[OUTNOIZ][i] = 0.0; |
|
|
|
|
|
here->BSIM4v4nVar[INNOIZ][i] = 0.0; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ /* data->delFreq != 0.0, |
|
|
|
|
|
we have to integrate. |
|
|
|
|
|
*/ |
|
|
|
|
|
for (i = 0; i < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ if (i != BSIM4v4TOTNOIZ) |
|
|
|
|
|
{ tempOnoise = Nintegrate(noizDens[i], |
|
|
|
|
|
lnNdens[i], |
|
|
|
|
|
here->BSIM4v4nVar[LNLSTDENS][i], |
|
|
|
|
|
data); |
|
|
|
|
|
tempInoise = Nintegrate(noizDens[i] |
|
|
|
|
|
* data->GainSqInv, lnNdens[i] |
|
|
|
|
|
+ data->lnGainInv, |
|
|
|
|
|
here->BSIM4v4nVar[LNLSTDENS][i] |
|
|
|
|
|
+ data->lnGainInv, data); |
|
|
|
|
|
here->BSIM4v4nVar[LNLSTDENS][i] = |
|
|
|
|
|
lnNdens[i]; |
|
|
|
|
|
data->outNoiz += tempOnoise; |
|
|
|
|
|
data->inNoise += tempInoise; |
|
|
|
|
|
if (((NOISEAN*) |
|
|
|
|
|
ckt->CKTcurJob)->NStpsSm != 0) |
|
|
|
|
|
{ here->BSIM4v4nVar[OUTNOIZ][i] |
|
|
|
|
|
+= tempOnoise; |
|
|
|
|
|
here->BSIM4v4nVar[OUTNOIZ][BSIM4v4TOTNOIZ] |
|
|
|
|
|
+= tempOnoise; |
|
|
|
|
|
here->BSIM4v4nVar[INNOIZ][i] |
|
|
|
|
|
+= tempInoise; |
|
|
|
|
|
here->BSIM4v4nVar[INNOIZ][BSIM4v4TOTNOIZ] |
|
|
|
|
|
+= tempInoise; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (data->prtSummary) |
|
|
|
|
|
{ for (i = 0; i < BSIM4v4NSRCS; 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 < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ data->outpVector[data->outNumber++] |
|
|
|
|
|
= here->BSIM4v4nVar[OUTNOIZ][i]; |
|
|
|
|
|
data->outpVector[data->outNumber++] |
|
|
|
|
|
= here->BSIM4v4nVar[INNOIZ][i]; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case N_CLOSE: |
|
|
|
|
|
/* do nothing, the main calling routine will close */ |
|
|
|
|
|
return (OK); |
|
|
|
|
|
break; /* the plots */ |
|
|
|
|
|
} /* switch (operation) */ |
|
|
|
|
|
} /* for here */ |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (data->prtSummary) |
|
|
|
|
|
{ for (i = 0; i < BSIM4v4NSRCS; 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 < BSIM4v4NSRCS; i++) |
|
|
|
|
|
{ data->outpVector[data->outNumber++] |
|
|
|
|
|
= here->BSIM4v4nVar[OUTNOIZ][i]; |
|
|
|
|
|
data->outpVector[data->outNumber++] |
|
|
|
|
|
= here->BSIM4v4nVar[INNOIZ][i]; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case N_CLOSE: |
|
|
|
|
|
/* do nothing, the main calling routine will close */ |
|
|
|
|
|
return (OK); |
|
|
|
|
|
break; /* the plots */ |
|
|
|
|
|
} /* switch (operation) */ |
|
|
|
|
|
} /* for here */ |
|
|
} /* for model */ |
|
|
} /* for model */ |
|
|
|
|
|
|
|
|
return(OK); |
|
|
return(OK); |
|
|
|