예제 #1
0
파일: b4v7noi.c 프로젝트: Anastien/ngspice
int
BSIM4v7noise (
int mode, int operation,
GENmodel *inModel,
CKTcircuit *ckt,
Ndata *data,
double *OnDens)
{
NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

BSIM4v7model *model = (BSIM4v7model *)inModel;
BSIM4v7instance *here;
struct bsim4SizeDependParam *pParam;
char name[N_MXVLNTH];
double tempOnoise;
double tempInoise;
double noizDens[BSIM4v7NSRCS];
double lnNdens[BSIM4v7NSRCS];

double T0, T1, T2, T3, T4, T5, T6, T7, T8, T10, T11;
double Vds, Ssi, Swi;
double tmp=0.0, gdpr, gspr, npart_theta=0.0, npart_beta=0.0, igsquare, bodymode;

/* tnoiMod=2 (v4.7) */
double eta, Leff, Lvsat, gamma, delta, epsilon, GammaGd0=0.0;
double npart_c, sigrat=0.0, C0, omega, ctnoi=0.0;

int i;

double m;

    /* define the names of the noise sources */
    static char *BSIM4v7nNames[BSIM4v7NSRCS] =
    {   /* Note that we have to keep the order */
        ".rd",              /* noise due to rd */
        ".rs",              /* noise due to rs */
        ".rg",              /* noise due to rgeltd */
        ".rbps",            /* noise due to rbps */
        ".rbpd",            /* noise due to rbpd */
        ".rbpb",            /* noise due to rbpb */
        ".rbsb",            /* noise due to rbsb */
        ".rbdb",            /* noise due to rbdb */
        ".id",              /* noise due to id (for tnoiMod2: uncorrelated portion only) */
        ".1overf",          /* flicker (1/f) noise */
        ".igs",             /* shot noise due to IGS */
        ".igd",             /* shot noise due to IGD */
        ".igb",             /* shot noise due to IGB */
        ".corl",            /* contribution of correlated drain and induced gate noise */
        ""                  /* total transistor noise */
    };

    for (; model != NULL; model = model->BSIM4v7nextModel)
    {
         if(model->BSIM4v7tnoiMod != 2) {
             noizDens[BSIM4v7CORLNOIZ] = 0.0;
             lnNdens[BSIM4v7CORLNOIZ] = N_MINLOG;
         }
         for (here = model->BSIM4v7instances; here != NULL;
              here = here->BSIM4v7nextInstance)
         {    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 (job->NStpsSm != 0)
                      {   switch (mode)
                          {  case N_DENS:
                                  for (i = 0; i < BSIM4v7NSRCS; i++)
                                  {    (void) sprintf(name, "onoise.%s%s",
                                                      here->BSIM4v7name,
                                                      BSIM4v7nNames[i]);
                                       data->namelist = TREALLOC(IFuid,
                                             data->namelist,
                                             data->numPlots + 1);
                                       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 < BSIM4v7NSRCS; i++)
                                  {    (void) sprintf(name, "onoise_total.%s%s",
                                                      here->BSIM4v7name,
                                                      BSIM4v7nNames[i]);
                                       data->namelist = TREALLOC(IFuid,
                                             data->namelist,
                                             data->numPlots + 1);
                                       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->BSIM4v7name,
                                                      BSIM4v7nNames[i]);
                                       data->namelist = TREALLOC(IFuid,
                                             data->namelist,
                                             data->numPlots + 1);
                                       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->BSIM4v7m;
                      switch (mode)
                      {  case N_DENS:
                              if (model->BSIM4v7tnoiMod == 0)
                              {   if (model->BSIM4v7rdsMod == 0)
                                  {   gspr = here->BSIM4v7sourceConductance;
                                      gdpr = here->BSIM4v7drainConductance;
                                      if (here->BSIM4v7grdsw > 0.0)
                                          tmp = 1.0 / here->BSIM4v7grdsw; /* tmp used below */
                                      else
                                          tmp = 0.0;
                                  }
                                  else
                                  {   gspr = here->BSIM4v7gstot;
                                      gdpr = here->BSIM4v7gdtot;
                                      tmp = 0.0;
                                  }
                              }
                              else if(model->BSIM4v7tnoiMod == 1)
                              {   T5 = here->BSIM4v7Vgsteff / here->BSIM4v7EsatL;
                                  T5 *= T5;
                                  npart_beta = model->BSIM4v7rnoia * (1.0 + T5
                                             * model->BSIM4v7tnoia * pParam->BSIM4v7leff);
                                  npart_theta = model->BSIM4v7rnoib * (1.0 + T5
                                              * model->BSIM4v7tnoib * pParam->BSIM4v7leff);
                                  if(npart_theta > 0.9)
                                     npart_theta = 0.9;
                                  if(npart_theta > 0.9 * npart_beta)
                                     npart_theta = 0.9 * npart_beta; //4.6.2

                                  if (model->BSIM4v7rdsMod == 0)
                                  {   gspr = here->BSIM4v7sourceConductance;
                                      gdpr = here->BSIM4v7drainConductance;
                                  }
                                  else
                                  {   gspr = here->BSIM4v7gstot;
                                      gdpr = here->BSIM4v7gdtot;
                                  }

                                  if ((*(ckt->CKTstates[0] + here->BSIM4v7vds)) >= 0.0)
                                      gspr = gspr * (1.0 + npart_theta * npart_theta * gspr
                                           / here->BSIM4v7IdovVds);
                                  else
                                      gdpr = gdpr * (1.0 + npart_theta * npart_theta * gdpr
                                           / here->BSIM4v7IdovVds);
                              }
                              else
                              {   /* tnoiMod=2 (v4.7) */

                                  if (model->BSIM4v7rdsMod == 0)
                                  {   gspr = here->BSIM4v7sourceConductance;
                                      gdpr = here->BSIM4v7drainConductance;
                                  }
                                  else
                                  {   gspr = here->BSIM4v7gstot;
                                      gdpr = here->BSIM4v7gdtot;
                                  }

                              }

                              NevalSrc(&noizDens[BSIM4v7RDNOIZ],
                                       &lnNdens[BSIM4v7RDNOIZ], ckt, THERMNOISE,
                                       here->BSIM4v7dNodePrime, here->BSIM4v7dNode,
                                       gdpr * m);

                              NevalSrc(&noizDens[BSIM4v7RSNOIZ],
                                       &lnNdens[BSIM4v7RSNOIZ], ckt, THERMNOISE,
                                       here->BSIM4v7sNodePrime, here->BSIM4v7sNode,
                                       gspr * m);


                              if (here->BSIM4v7rgateMod == 1)
                              {   NevalSrc(&noizDens[BSIM4v7RGNOIZ],
                                       &lnNdens[BSIM4v7RGNOIZ], ckt, THERMNOISE,
                                       here->BSIM4v7gNodePrime, here->BSIM4v7gNodeExt,
                                       here->BSIM4v7grgeltd * m);
                              }
                              else if (here->BSIM4v7rgateMod == 2)
                              {
                                T0 = 1.0 + here->BSIM4v7grgeltd/here->BSIM4v7gcrg;
                                T1 = T0 * T0;
                                  NevalSrc(&noizDens[BSIM4v7RGNOIZ],
                                       &lnNdens[BSIM4v7RGNOIZ], ckt, THERMNOISE,
                                       here->BSIM4v7gNodePrime, here->BSIM4v7gNodeExt,
                                       here->BSIM4v7grgeltd * m / T1);
                              }
                              else if (here->BSIM4v7rgateMod == 3)
                              {   NevalSrc(&noizDens[BSIM4v7RGNOIZ],
                                       &lnNdens[BSIM4v7RGNOIZ], ckt, THERMNOISE,
                                       here->BSIM4v7gNodeMid, here->BSIM4v7gNodeExt,
                                       here->BSIM4v7grgeltd * m);
                              }
                              else
                              {    noizDens[BSIM4v7RGNOIZ] = 0.0;
                                   lnNdens[BSIM4v7RGNOIZ] =
                                          log(MAX(noizDens[BSIM4v7RGNOIZ], N_MINLOG));
                              }

                                    bodymode = 5;
                                    if (here->BSIM4v7rbodyMod == 2)
                                    {        if( ( !model->BSIM4v7rbps0Given) ||
                                      ( !model->BSIM4v7rbpd0Given) )
                                             bodymode = 1;
                                           else
                                     if( (!model->BSIM4v7rbsbx0Given && !model->BSIM4v7rbsby0Given) ||
                                          (!model->BSIM4v7rbdbx0Given && !model->BSIM4v7rbdby0Given) )
                                             bodymode = 3;
                                }

                              if (here->BSIM4v7rbodyMod)
                              {
                                if(bodymode == 5)
                                  {
                                    NevalSrc(&noizDens[BSIM4v7RBPSNOIZ],
                                             &lnNdens[BSIM4v7RBPSNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v7bNodePrime, here->BSIM4v7sbNode,
                                             here->BSIM4v7grbps * m);
                                    NevalSrc(&noizDens[BSIM4v7RBPDNOIZ],
                                             &lnNdens[BSIM4v7RBPDNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v7bNodePrime, here->BSIM4v7dbNode,
                                             here->BSIM4v7grbpd * m);
                                    NevalSrc(&noizDens[BSIM4v7RBPBNOIZ],
                                             &lnNdens[BSIM4v7RBPBNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v7bNodePrime, here->BSIM4v7bNode,
                                             here->BSIM4v7grbpb * m);
                                    NevalSrc(&noizDens[BSIM4v7RBSBNOIZ],
                                             &lnNdens[BSIM4v7RBSBNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v7bNode, here->BSIM4v7sbNode,
                                             here->BSIM4v7grbsb * m);
                                    NevalSrc(&noizDens[BSIM4v7RBDBNOIZ],
                                             &lnNdens[BSIM4v7RBDBNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v7bNode, here->BSIM4v7dbNode,
                                             here->BSIM4v7grbdb * m);
                                  }
                                if(bodymode == 3)
                                  {
                                    NevalSrc(&noizDens[BSIM4v7RBPSNOIZ],
                                             &lnNdens[BSIM4v7RBPSNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v7bNodePrime, here->BSIM4v7sbNode,
                                             here->BSIM4v7grbps * m);
                                    NevalSrc(&noizDens[BSIM4v7RBPDNOIZ],
                                             &lnNdens[BSIM4v7RBPDNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v7bNodePrime, here->BSIM4v7dbNode,
                                             here->BSIM4v7grbpd * m);
                                    NevalSrc(&noizDens[BSIM4v7RBPBNOIZ],
                                             &lnNdens[BSIM4v7RBPBNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v7bNodePrime, here->BSIM4v7bNode,
                                             here->BSIM4v7grbpb * m);
                                     noizDens[BSIM4v7RBSBNOIZ] = noizDens[BSIM4v7RBDBNOIZ] = 0.0;
                                     lnNdens[BSIM4v7RBSBNOIZ] =
                                       log(MAX(noizDens[BSIM4v7RBSBNOIZ], N_MINLOG));
                                     lnNdens[BSIM4v7RBDBNOIZ] =
                                       log(MAX(noizDens[BSIM4v7RBDBNOIZ], N_MINLOG));
                                  }
                                if(bodymode == 1)
                                  {
                                    NevalSrc(&noizDens[BSIM4v7RBPBNOIZ],
                                             &lnNdens[BSIM4v7RBPBNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v7bNodePrime, here->BSIM4v7bNode,
                                             here->BSIM4v7grbpb * m);
                                    noizDens[BSIM4v7RBPSNOIZ] = noizDens[BSIM4v7RBPDNOIZ] = 0.0;
                                    noizDens[BSIM4v7RBSBNOIZ] = noizDens[BSIM4v7RBDBNOIZ] = 0.0;
                                    lnNdens[BSIM4v7RBPSNOIZ] =
                                      log(MAX(noizDens[BSIM4v7RBPSNOIZ], N_MINLOG));
                                    lnNdens[BSIM4v7RBPDNOIZ] =
                                      log(MAX(noizDens[BSIM4v7RBPDNOIZ], N_MINLOG));
                                    lnNdens[BSIM4v7RBSBNOIZ] =
                                      log(MAX(noizDens[BSIM4v7RBSBNOIZ], N_MINLOG));
                                    lnNdens[BSIM4v7RBDBNOIZ] =
                                      log(MAX(noizDens[BSIM4v7RBDBNOIZ], N_MINLOG));
                                  }
                              }
                              else
                              {   noizDens[BSIM4v7RBPSNOIZ] = noizDens[BSIM4v7RBPDNOIZ] = 0.0;
                                  noizDens[BSIM4v7RBPBNOIZ] = 0.0;
                                  noizDens[BSIM4v7RBSBNOIZ] = noizDens[BSIM4v7RBDBNOIZ] = 0.0;
                                  lnNdens[BSIM4v7RBPSNOIZ] =
                                          log(MAX(noizDens[BSIM4v7RBPSNOIZ], N_MINLOG));
                                  lnNdens[BSIM4v7RBPDNOIZ] =
                                          log(MAX(noizDens[BSIM4v7RBPDNOIZ], N_MINLOG));
                                  lnNdens[BSIM4v7RBPBNOIZ] =
                                          log(MAX(noizDens[BSIM4v7RBPBNOIZ], N_MINLOG));
                                  lnNdens[BSIM4v7RBSBNOIZ] =
                                          log(MAX(noizDens[BSIM4v7RBSBNOIZ], N_MINLOG));
                                  lnNdens[BSIM4v7RBDBNOIZ] =
                                          log(MAX(noizDens[BSIM4v7RBDBNOIZ], N_MINLOG));
                              }

                              if(model->BSIM4v7tnoiMod == 2)
                              {
                                  eta = 1.0 - here->BSIM4v7Vdseff * here->BSIM4v7AbovVgst2Vtm;
                                  T0 = 1.0 - eta;
                                  T1 = 1.0 + eta;
                                  T2 = T1 + 2.0 * here->BSIM4v7Abulk * model->BSIM4v7vtm / here->BSIM4v7Vgsteff;
                                  Leff = pParam->BSIM4v7leff;
                                  Lvsat = Leff * (1.0 + here->BSIM4v7Vdseff / here->BSIM4v7EsatL);
                                  T6 = Leff / Lvsat;

                                  T5 = here->BSIM4v7Vgsteff / here->BSIM4v7EsatL;
                                  T5 = T5 * T5;
                                  gamma = T6 * (0.5 * T1 + T0 * T0 / (6.0 * T2));
                                  T3 = T2 * T2;
                                  T4 = T0 * T0;
                                  T5 = T3 * T3;
                                  delta = (T1 / T3 - (5.0 * T1 + T2) * T4 / (15.0 * T5) + T4 * T4 / (9.0 * T5 * T2)) / (6.0 * T6 * T6 * T6);
                                  T7 = T0 / T2;
                                  epsilon = (T7 - T7 * T7 * T7 / 3.0) / (6.0 * T6);

                                  T8 = here->BSIM4v7Vgsteff / here->BSIM4v7EsatL;
                                  T8 *= T8;
                                  npart_c = model->BSIM4v7rnoic * (1.0 + T8
                                          * model->BSIM4v7tnoic * Leff);
                                  ctnoi = epsilon / sqrt(gamma * delta)
                                      * (2.5316 * npart_c);

                                  npart_beta = model->BSIM4v7rnoia * (1.0 + T8
                                      * model->BSIM4v7tnoia * Leff);
                                  npart_theta = model->BSIM4v7rnoib * (1.0 + T8
                                      * model->BSIM4v7tnoib * Leff);
                                  gamma = gamma * (3.0 * npart_beta * npart_beta);
                                  delta = delta * (3.75 * npart_theta * npart_theta);

                                  GammaGd0 = gamma * here->BSIM4v7noiGd0;
                                  C0 = here->BSIM4v7Coxeff * pParam->BSIM4v7weffCV * here->BSIM4v7nf * pParam->BSIM4v7leffCV;
                                  T0 = C0 / here->BSIM4v7noiGd0;
                                  sigrat = T0 * sqrt(delta / gamma);
                              }
                              switch(model->BSIM4v7tnoiMod)
                              {  case 0:
                                      T0 = here->BSIM4v7ueff * fabs(here->BSIM4v7qinv);
                                      T1 = T0 * tmp + pParam->BSIM4v7leff
                                         * pParam->BSIM4v7leff;
                                      NevalSrc(&noizDens[BSIM4v7IDNOIZ],
                                               &lnNdens[BSIM4v7IDNOIZ], ckt,
                                               THERMNOISE, here->BSIM4v7dNodePrime,
                                               here->BSIM4v7sNodePrime,
                                               (T0 / T1) * model->BSIM4v7ntnoi * m);
                                      break;
                                 case 1:
                                      T0 = here->BSIM4v7gm + here->BSIM4v7gmbs + here->BSIM4v7gds;
                                      T0 *= T0;
                                      igsquare = npart_theta * npart_theta * T0 / here->BSIM4v7IdovVds;
                                      T1 = npart_beta * (here->BSIM4v7gm
                                         + here->BSIM4v7gmbs) + here->BSIM4v7gds;
                                      T2 = T1 * T1 / here->BSIM4v7IdovVds;
                                      NevalSrc(&noizDens[BSIM4v7IDNOIZ],
                                               &lnNdens[BSIM4v7IDNOIZ], ckt,
                                               THERMNOISE, here->BSIM4v7dNodePrime,
                                               here->BSIM4v7sNodePrime, (T2 - igsquare) * m);
                                      break;
                                  case 2:
                                      T2 = GammaGd0;
                                      T3 = ctnoi * ctnoi;
                                      T4 = 1.0 - T3;
                                      NevalSrc(&noizDens[BSIM4v7IDNOIZ],
                                               &lnNdens[BSIM4v7IDNOIZ], ckt,
                                               THERMNOISE, here->BSIM4v7dNodePrime,
                                               here->BSIM4v7sNodePrime, T2 * T4 * m);

                                     /* Evaluate output noise due to two correlated noise sources */
                                     omega = 2.0 * M_PI * data->freq;
                                     T5 = omega * sigrat;
                                     T6 = T5 * T5;
                                     T7 = T6 / (1.0 + T6);

                                     if (here->BSIM4v7mode >= 0)  {
                                         NevalSrc2(&noizDens[BSIM4v7CORLNOIZ],
                                               &lnNdens[BSIM4v7CORLNOIZ], ckt,
                                               THERMNOISE, here->BSIM4v7dNodePrime,
                                               here->BSIM4v7sNodePrime, T2 * T3 * m,
                                               here->BSIM4v7gNodePrime,
                                               here->BSIM4v7sNodePrime,
                                               T2 * T7 * m, 0.5 * M_PI);
                                     }
                                     else
                                     {
                                         NevalSrc2(&noizDens[BSIM4v7CORLNOIZ],
                                               &lnNdens[BSIM4v7CORLNOIZ], ckt,
                                               THERMNOISE, here->BSIM4v7sNodePrime,
                                               here->BSIM4v7dNodePrime, T2 * T3 * m,
                                               here->BSIM4v7gNodePrime,
                                               here->BSIM4v7dNodePrime,
                                               T2 * T7 * m, 0.5 * M_PI);
                                     }
                                     break;
                              }

                              NevalSrc(&noizDens[BSIM4v7FLNOIZ], (double*) NULL,
                                       ckt, N_GAIN, here->BSIM4v7dNodePrime,
                                       here->BSIM4v7sNodePrime, (double) 0.0);

                              switch(model->BSIM4v7fnoiMod)
                              {  case 0:
                                      noizDens[BSIM4v7FLNOIZ] *= m * model->BSIM4v7kf
                                            * exp(model->BSIM4v7af
                                            * log(MAX(fabs(here->BSIM4v7cd),
                                            N_MINLOG)))
                                            / (pow(data->freq, model->BSIM4v7ef)
                                            * pParam->BSIM4v7leff
                                            * pParam->BSIM4v7leff
                                            * model->BSIM4v7coxe);
                                      break;
                                 case 1:
                                      Vds = *(ckt->CKTstates[0] + here->BSIM4v7vds);
                                      if (Vds < 0.0)
                                          Vds = -Vds;

                                      Ssi = Eval1ovFNoise(Vds, model, here,
                                          data->freq, ckt->CKTtemp);
                                      T10 = model->BSIM4v7oxideTrapDensityA
                                          * CONSTboltz * ckt->CKTtemp;
                                      T11 = pParam->BSIM4v7weff * here->BSIM4v7nf * pParam->BSIM4v7leff
                                          * pow(data->freq, model->BSIM4v7ef) * 1.0e10
                                          * here->BSIM4v7nstar * here->BSIM4v7nstar;
                                      Swi = T10 / T11 * here->BSIM4v7cd
                                          * here->BSIM4v7cd;
                                      T1 = Swi + Ssi;
                                      if (T1 > 0.0)
                                          noizDens[BSIM4v7FLNOIZ] *= m * (Ssi * Swi) / T1;
                                      else
                                          noizDens[BSIM4v7FLNOIZ] *= 0.0;
                                      break;
                              }

                              lnNdens[BSIM4v7FLNOIZ] =
                                     log(MAX(noizDens[BSIM4v7FLNOIZ], N_MINLOG));


                        if(here->BSIM4v7mode >= 0) {  /* bugfix  */
                              NevalSrc(&noizDens[BSIM4v7IGSNOIZ],
                                   &lnNdens[BSIM4v7IGSNOIZ], ckt, SHOTNOISE,
                                   here->BSIM4v7gNodePrime, here->BSIM4v7sNodePrime,
                                   m * (here->BSIM4v7Igs + here->BSIM4v7Igcs));
                              NevalSrc(&noizDens[BSIM4v7IGDNOIZ],
                                   &lnNdens[BSIM4v7IGDNOIZ], ckt, SHOTNOISE,
                                   here->BSIM4v7gNodePrime, here->BSIM4v7dNodePrime,
                                   m * (here->BSIM4v7Igd + here->BSIM4v7Igcd));
                        } else {
                              NevalSrc(&noizDens[BSIM4v7IGSNOIZ],
                                   &lnNdens[BSIM4v7IGSNOIZ], ckt, SHOTNOISE,
                                   here->BSIM4v7gNodePrime, here->BSIM4v7sNodePrime,
                                   m * (here->BSIM4v7Igs + here->BSIM4v7Igcd));
                              NevalSrc(&noizDens[BSIM4v7IGDNOIZ],
                                   &lnNdens[BSIM4v7IGDNOIZ], ckt, SHOTNOISE,
                                   here->BSIM4v7gNodePrime, here->BSIM4v7dNodePrime,
                                   m * (here->BSIM4v7Igd + here->BSIM4v7Igcs));
                        }
                              NevalSrc(&noizDens[BSIM4v7IGBNOIZ],
                                   &lnNdens[BSIM4v7IGBNOIZ], ckt, SHOTNOISE,
                                   here->BSIM4v7gNodePrime, here->BSIM4v7bNodePrime,
                                   m * here->BSIM4v7Igb);


                              noizDens[BSIM4v7TOTNOIZ] = noizDens[BSIM4v7RDNOIZ]
                                     + noizDens[BSIM4v7RSNOIZ] + noizDens[BSIM4v7RGNOIZ]
                                     + noizDens[BSIM4v7RBPSNOIZ] + noizDens[BSIM4v7RBPDNOIZ]
                                     + noizDens[BSIM4v7RBPBNOIZ]
                                     + noizDens[BSIM4v7RBSBNOIZ] + noizDens[BSIM4v7RBDBNOIZ]
                                     + noizDens[BSIM4v7IDNOIZ] + noizDens[BSIM4v7FLNOIZ]
                                     + noizDens[BSIM4v7IGSNOIZ] + noizDens[BSIM4v7IGDNOIZ]
                                     + noizDens[BSIM4v7IGBNOIZ] + noizDens[BSIM4v7CORLNOIZ];
                              lnNdens[BSIM4v7TOTNOIZ] =
                                     log(MAX(noizDens[BSIM4v7TOTNOIZ], N_MINLOG));

                              *OnDens += noizDens[BSIM4v7TOTNOIZ];

                              if (data->delFreq == 0.0)
                              {   /* if we haven't done any previous
                                     integration, we need to initialize our
                                     "history" variables.
                                    */

                                  for (i = 0; i < BSIM4v7NSRCS; i++)
                                  {    here->BSIM4v7nVar[LNLSTDENS][i] =
                                             lnNdens[i];
                                  }

                                  /* clear out our integration variables
                                     if it's the first pass
                                   */
                                  if (data->freq ==
                                      job->NstartFreq)
                                  {   for (i = 0; i < BSIM4v7NSRCS; i++)
                                      {    here->BSIM4v7nVar[OUTNOIZ][i] = 0.0;
                                           here->BSIM4v7nVar[INNOIZ][i] = 0.0;
                                      }
                                  }
                              }
                              else
                              {   /* data->delFreq != 0.0,
                                     we have to integrate.
                                   */
                                  for (i = 0; i < BSIM4v7NSRCS; i++)
                                  {    if (i != BSIM4v7TOTNOIZ)
                                       {   tempOnoise = Nintegrate(noizDens[i],
                                                lnNdens[i],
                                                here->BSIM4v7nVar[LNLSTDENS][i],
                                                data);
                                           tempInoise = Nintegrate(noizDens[i]
                                                * data->GainSqInv, lnNdens[i]
                                                + data->lnGainInv,
                                                here->BSIM4v7nVar[LNLSTDENS][i]
                                                + data->lnGainInv, data);
                                           here->BSIM4v7nVar[LNLSTDENS][i] =
                                                lnNdens[i];
                                           data->outNoiz += tempOnoise;
                                           data->inNoise += tempInoise;
                                           if (job->NStpsSm != 0)
                                           {   here->BSIM4v7nVar[OUTNOIZ][i]
                                                     += tempOnoise;
                                               here->BSIM4v7nVar[OUTNOIZ][BSIM4v7TOTNOIZ]
                                                     += tempOnoise;
                                               here->BSIM4v7nVar[INNOIZ][i]
                                                     += tempInoise;
                                               here->BSIM4v7nVar[INNOIZ][BSIM4v7TOTNOIZ]
                                                     += tempInoise;
                                           }
                                       }
                                  }
                              }
                              if (data->prtSummary)
                              {   for (i = 0; i < BSIM4v7NSRCS; 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 < BSIM4v7NSRCS; i++)
                                  {    data->outpVector[data->outNumber++]
                                             = here->BSIM4v7nVar[OUTNOIZ][i];
                                       data->outpVector[data->outNumber++]
                                             = here->BSIM4v7nVar[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 */

    return(OK);
}
예제 #2
0
int
RESnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, 
          Ndata *data, double *OnDens)
{
    RESmodel *firstModel = (RESmodel *) genmodel;
    RESmodel *model;
    RESinstance *inst;
    char name[N_MXVLNTH];
    double tempOutNoise;
    double tempInNoise;
    double noizDens[RESNSRCS];
    double lnNdens[RESNSRCS];
    int i;

     /* define the names of the noise sources */

    static char *RESnNames[RESNSRCS] = {
	/* Note that we have to keep the order consistent with the
	 * strchr definitions in RESdefs.h */
	"_thermal",         /* Thermal noise */
	"_1overf",          /* flicker (1/f) noise */
	""                  /* total resistor noise */
    };

    
    for (model = firstModel; model != NULL; model = model->RESnextModel) {
	for (inst = model->RESinstances; inst != NULL; 
	        inst = inst->RESnextInstance) {
	    
	    if (inst->RESowner != ARCHme) continue;
            
	    if(!inst->RESnoisy) continue; /* Quiet resistors are skipped */
	    
	    switch (operation) {

	    case N_OPEN:

		/* 
		 * See if we have to to produce a summary report
		 * if so, name the noise generator 
		 */

		if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) {
		    switch (mode) {

		    case N_DENS:
		        for (i=0; i < RESNSRCS; i++) {
			(void)sprintf(name,"onoise_%s%s",
			              inst->RESname, RESnNames[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 < RESNSRCS; i++) {
			    (void)sprintf(name,"onoise_total_%s%s",
			                  inst->RESname, RESnNames[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->RESname,RESnNames[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:
		
		       NevalSrc2(&noizDens[RESTHNOIZ],&lnNdens[RESTHNOIZ],
		                ckt,THERMNOISE, inst->RESposNode,inst->RESnegNode,
			        inst->RESconduct * inst->RESm, inst->RESdtemp); 

                       NevalSrc2(&noizDens[RESFLNOIZ],(double*)NULL, ckt,
			        N_GAIN,inst->RESposNode, inst->RESnegNode,
				(double)0.0, (double)0.0);
				
#if 0
                       printf("DC current in resistor %s: %e\n",inst->RESname, inst->REScurrent);
#endif
	       	
		       noizDens[RESFLNOIZ] *= inst->RESm * model->RESfNcoef * exp(model->RESfNexp *
				              log(MAX(fabs(inst->REScurrent),
					      N_MINLOG))) / data->freq;
                       lnNdens[RESFLNOIZ]   = log(MAX(noizDens[RESFLNOIZ],N_MINLOG));

                       noizDens[RESTOTNOIZ] = noizDens[RESTHNOIZ] + noizDens[RESFLNOIZ];
		       lnNdens[RESTOTNOIZ]  = log(noizDens[RESTOTNOIZ]);		 

		    *OnDens += noizDens[RESTOTNOIZ];

		    if (data->delFreq == 0.0) { 

			/* if we haven't done any previous integration, we need to */
			/* initialize our "history" variables                      */

                        for (i=0; i < RESNSRCS; i++) {
			     inst->RESnVar[LNLSTDENS][i] = lnNdens[i];
                        }
			
			/* clear out our integration variable if it's the first pass */

			if (data->freq == ((NOISEAN*)ckt->CKTcurJob)->NstartFreq) {
			    for (i=0; i < RESNSRCS; i++) {
			    inst->RESnVar[OUTNOIZ][i] = 0.0; /* Clear output noise */
			    inst->RESnVar[INNOIZ][i] = 0.0;  /* Clear input noise */ 
			    }
			}
		    } else {   /* data->delFreq != 0.0 (we have to integrate) */
		    
/* In order to get the best curve fit, we have to integrate each component separately */

  			   for (i = 0; i < RESNSRCS; i++) {
			       if (i != RESTOTNOIZ) {		    
			           tempOutNoise = Nintegrate(noizDens[i], lnNdens[i],
			                          inst->RESnVar[LNLSTDENS][i], data);
			           tempInNoise = Nintegrate(noizDens[i] * 
			                                    data->GainSqInv ,lnNdens[i] 
					   		    + data->lnGainInv,
			                                    inst->RESnVar[LNLSTDENS][i] 
							    + data->lnGainInv,
			                                    data);
				   inst->RESnVar[LNLSTDENS][i] = lnNdens[i];
				   data->outNoiz += tempOutNoise;
			           data->inNoise += tempInNoise;			 
			           if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) {
				       inst->RESnVar[OUTNOIZ][i] += tempOutNoise;
				       inst->RESnVar[OUTNOIZ][RESTOTNOIZ] += tempOutNoise;
				       inst->RESnVar[INNOIZ][i] += tempInNoise;
				       inst->RESnVar[INNOIZ][RESTOTNOIZ] += tempInNoise;
                                }
			}
		}
			        
	}
	            if (data->prtSummary) {
			for (i=0; i < RESNSRCS; 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 < RESNSRCS; i++) {
			    data->outpVector[data->outNumber++] = inst->RESnVar[OUTNOIZ][i];
			    data->outpVector[data->outNumber++] = inst->RESnVar[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);
}