Example #1
0
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);
}
Example #2
0
int
BJTnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, 
          Ndata *data, double *OnDens)
{
    NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

    BJTmodel *firstModel = (BJTmodel *) genmodel;
    BJTmodel *model;
    BJTinstance *inst;
    double tempOnoise;
    double tempInoise;
    double noizDens[BJTNSRCS];
    double lnNdens[BJTNSRCS];
    int i;

    /* define the names of the noise sources */

    static char *BJTnNames[BJTNSRCS] = {
	/* Note that we have to keep the order consistent with the
	  strchr definitions in BJTdefs.h */
	"_rc",              /* noise due to rc */
	"_rb",              /* noise due to rb */
	"_re",              /* noise due to re */
	"_ic",              /* noise due to ic */
	"_ib",              /* noise due to ib */
	"_1overf",          /* flicker (1/f) noise */
	""                  /* total transistor noise */
    };

for (model=firstModel; model != NULL; model=BJTnextModel(model)) {
	for (inst=BJTinstances(model); inst != NULL;
		inst=BJTnextInstance(inst)) {

	    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 < BJTNSRCS; i++) {
			    NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->BJTname, BJTnNames[i]);
			}
			break;

		    case INT_NOIZ:
			for (i=0; i < BJTNSRCS; i++) {
			    NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->BJTname, BJTnNames[i]);
			    NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->BJTname, BJTnNames[i]);
			}
			break;
		    }
		}
		break;

	    case N_CALC:
		switch (mode) {

		case N_DENS:
		    NevalSrc(&noizDens[BJTRCNOIZ],&lnNdens[BJTRCNOIZ],
				 ckt,THERMNOISE,inst->BJTcolPrimeNode,inst->BJTcolNode,
				 inst->BJTtcollectorConduct * inst->BJTarea * inst->BJTm);

		    NevalSrc(&noizDens[BJTRBNOIZ],&lnNdens[BJTRBNOIZ],
				 ckt,THERMNOISE,inst->BJTbasePrimeNode,inst->BJTbaseNode,
				 *(ckt->CKTstate0 + inst->BJTgx) * inst->BJTm);

		    NevalSrc(&noizDens[BJT_RE_NOISE],&lnNdens[BJT_RE_NOISE],
				 ckt,THERMNOISE,inst->BJTemitPrimeNode,inst->BJTemitNode,
				 inst->BJTtemitterConduct * inst->BJTarea * inst-> BJTm);

		    NevalSrc(&noizDens[BJTICNOIZ],&lnNdens[BJTICNOIZ],
			         ckt,SHOTNOISE,inst->BJTcolPrimeNode, inst->BJTemitPrimeNode,
				 *(ckt->CKTstate0 + inst->BJTcc) * inst->BJTm);

		    NevalSrc(&noizDens[BJTIBNOIZ],&lnNdens[BJTIBNOIZ],
				 ckt,SHOTNOISE,inst->BJTbasePrimeNode, inst->BJTemitPrimeNode,
				 *(ckt->CKTstate0 + inst->BJTcb) * inst->BJTm);

		    NevalSrc(&noizDens[BJTFLNOIZ], NULL, ckt,
				 N_GAIN,inst->BJTbasePrimeNode, inst->BJTemitPrimeNode,
				 (double)0.0);
		    noizDens[BJTFLNOIZ] *= inst->BJTm * model->BJTfNcoef * 
				 exp(model->BJTfNexp *
				 log(MAX(fabs(*(ckt->CKTstate0 + inst->BJTcb)),N_MINLOG))) /
				 data->freq;
		    lnNdens[BJTFLNOIZ] = 
				 log(MAX(noizDens[BJTFLNOIZ],N_MINLOG));

		    noizDens[BJTTOTNOIZ] = noizDens[BJTRCNOIZ] +
						    noizDens[BJTRBNOIZ] +
						    noizDens[BJT_RE_NOISE] +
						    noizDens[BJTICNOIZ] +
						    noizDens[BJTIBNOIZ] +
						    noizDens[BJTFLNOIZ];
		    lnNdens[BJTTOTNOIZ] = 
				 log(noizDens[BJTTOTNOIZ]);

		    *OnDens += noizDens[BJTTOTNOIZ];

		    if (data->delFreq == 0.0) { 

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

			for (i=0; i < BJTNSRCS; i++) {
			    inst->BJTnVar[LNLSTDENS][i] = lnNdens[i];
			}

			/* clear out our integration variables if it's the first pass */

			if (data->freq == job->NstartFreq) {
			    for (i=0; i < BJTNSRCS; i++) {
				inst->BJTnVar[OUTNOIZ][i] = 0.0;
				inst->BJTnVar[INNOIZ][i] = 0.0;
			    }
			}
		    } 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 < BJTNSRCS; i++) {
			    if (i != BJTTOTNOIZ) {
				tempOnoise = Nintegrate(noizDens[i], lnNdens[i],
				      inst->BJTnVar[LNLSTDENS][i], data);
				tempInoise = Nintegrate(noizDens[i] * data->GainSqInv ,
				      lnNdens[i] + data->lnGainInv,
				      inst->BJTnVar[LNLSTDENS][i] + data->lnGainInv,
				      data);
				inst->BJTnVar[LNLSTDENS][i] = lnNdens[i];
				data->outNoiz += tempOnoise;
				data->inNoise += tempInoise;
				if (job->NStpsSm != 0) {
				    inst->BJTnVar[OUTNOIZ][i] += tempOnoise;
				    inst->BJTnVar[OUTNOIZ][BJTTOTNOIZ] += tempOnoise;
				    inst->BJTnVar[INNOIZ][i] += tempInoise;
				    inst->BJTnVar[INNOIZ][BJTTOTNOIZ] += tempInoise;
                                }
			    }
			}
		    }
		    if (data->prtSummary) {
			for (i=0; i < BJTNSRCS; 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 < BJTNSRCS; i++) {
			    data->outpVector[data->outNumber++] = inst->BJTnVar[OUTNOIZ][i];
			    data->outpVector[data->outNumber++] = inst->BJTnVar[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);
}
Example #3
0
int HSMHV2noise (
     int mode, int operation,
     GENmodel *inModel,
     CKTcircuit *ckt,
     Ndata *data,
     double *OnDens)
{
  HSMHV2model *model = (HSMHV2model *)inModel;
  HSMHV2instance *here;
  char name[N_MXVLNTH];
  double tempOnoise=0.0 ;
  double tempInoise=0.0 ;
  double noizDens[HSMHV2NSRCS] ;
  double lnNdens[HSMHV2NSRCS] ;
  int i;
  double G =0.0 ;
  double TTEMP = 0.0 ;

  /* define the names of the noise sources */
  static char * HSMHV2nNames[HSMHV2NSRCS] = {
    /* Note that we have to keep the order
       consistent with the index definitions 
       in hsmhvdefs.h */
    ".rd",              /* noise due to rd */
    ".rs",              /* noise due to rs */
    ".id",              /* noise due to id */
    ".1ovf",            /* flicker (1/f) noise */
    ".ign",             /* induced gate noise component at the drain node */
    ""                  /* total transistor noise */
  };
  
  for ( ;model != NULL; model = model->HSMHV2nextModel ) {
    for ( here = model->HSMHV2instances; here != NULL;
	  here = here->HSMHV2nextInstance ) {
      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 < HSMHV2NSRCS; i++ ) { 
	      (void) sprintf(name, "onoise.%s%s", 
			     (char *)here->HSMHV2name, HSMHV2nNames[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);
	    }
	    break;
	  case INT_NOIZ:
	    for ( i = 0; i < HSMHV2NSRCS; i++ ) {
	      (void) sprintf(name, "onoise_total.%s%s", 
			     (char *)here->HSMHV2name, HSMHV2nNames[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);
	      
	      (void) sprintf(name, "inoise_total.%s%s", 
			     (char *)here->HSMHV2name, HSMHV2nNames[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);
	    }
	    break;
	  }
	}
	break;
      case N_CALC:
	switch (mode) {
	case N_DENS:

         /* temperature */
         TTEMP = ckt->CKTtemp;
         if ( here->HSMHV2_dtemp_Given ) { TTEMP = TTEMP + here->HSMHV2_dtemp ; }
         TTEMP = TTEMP + *(ckt->CKTstate0 + here->HSMHV2deltemp) ;

         /* rs/rd thermal noise */
	  if ( model->HSMHV2_corsrd == 1 || model->HSMHV2_corsrd == 3 ||  model->HSMHV2_cordrift == 1 ) {
	    NevalSrc(&noizDens[HSMHV2RDNOIZ], NULL,
		     ckt, N_GAIN,
		     here->HSMHV2dNodePrime, here->HSMHV2dNode,
		     0.0);
	    noizDens[HSMHV2RDNOIZ] *= 4 * C_KB * TTEMP * here->HSMHV2drainConductance ;
            lnNdens[HSMHV2RDNOIZ] = log( MAX(noizDens[HSMHV2RDNOIZ],N_MINLOG) );
	    
	    NevalSrc(&noizDens[HSMHV2RSNOIZ], NULL,
		     ckt, N_GAIN,
		     here->HSMHV2sNodePrime, here->HSMHV2sNode,
		     0.0);
	    noizDens[HSMHV2RSNOIZ] *= 4 * C_KB * TTEMP * here->HSMHV2sourceConductance ;
            lnNdens[HSMHV2RSNOIZ] = log( MAX(noizDens[HSMHV2RSNOIZ],N_MINLOG) );
	  } else {
	    noizDens[HSMHV2RDNOIZ] = 0e0 ;
	    lnNdens[HSMHV2RDNOIZ] = N_MINLOG ;
	    noizDens[HSMHV2RSNOIZ] = 0e0 ;
	    lnNdens[HSMHV2RSNOIZ] = N_MINLOG ;
	  }

	  /* channel thermal noise */
	  NevalSrc(&noizDens[HSMHV2IDNOIZ], NULL,
		   ckt, N_GAIN,
		   here->HSMHV2dNodePrime, here->HSMHV2sNodePrime,
		   0.0);
	  switch( model->HSMHV2_noise ) {
	  case 1:
	    /* HiSIMHV model */
	    G = here->HSMHV2_noithrml ;
	    noizDens[HSMHV2IDNOIZ] *= 4 * C_KB * TTEMP * G ;
	    lnNdens[HSMHV2IDNOIZ] = log( MAX(noizDens[HSMHV2IDNOIZ],N_MINLOG) );
	    break;
	  }

	  /* flicker noise */
	  NevalSrc(&noizDens[HSMHV2FLNOIZ], NULL,
		   ckt, N_GAIN,
		   here->HSMHV2dNodePrime, here->HSMHV2sNodePrime, 
		   0.0);
	  switch ( model->HSMHV2_noise ) {
	  case 1:
	    /* HiSIM model */
	    noizDens[HSMHV2FLNOIZ] *= here->HSMHV2_noiflick / pow(data->freq, model->HSMHV2_falph) ; 
	    lnNdens[HSMHV2FLNOIZ] = log(MAX(noizDens[HSMHV2FLNOIZ], N_MINLOG));
	    break;
	  }	  

	  /* induced gate noise */
	  NevalSrc(&noizDens[HSMHV2IGNOIZ], NULL,
		   ckt, N_GAIN, 
		   here->HSMHV2dNodePrime, here->HSMHV2sNodePrime, 
		   0.0);
	  switch ( model->HSMHV2_noise ) {
	  case 1:
	    /* HiSIM model */
	    noizDens[HSMHV2IGNOIZ] *= here->HSMHV2_noiigate * here->HSMHV2_noicross * here->HSMHV2_noicross * data->freq * data->freq;
	    lnNdens[HSMHV2IGNOIZ] = log(MAX(noizDens[HSMHV2IGNOIZ], N_MINLOG));
	    break;
	  }

	  /* total */
	  noizDens[HSMHV2TOTNOIZ] = noizDens[HSMHV2RDNOIZ] + noizDens[HSMHV2RSNOIZ]
	    + noizDens[HSMHV2IDNOIZ] + noizDens[HSMHV2FLNOIZ] + noizDens[HSMHV2IGNOIZ];
	  lnNdens[HSMHV2TOTNOIZ] = log(MAX(noizDens[HSMHV2TOTNOIZ], N_MINLOG));
	  
	  *OnDens += noizDens[HSMHV2TOTNOIZ];
	  
	  if ( data->delFreq == 0.0 ) {
	    /* if we haven't done any previous 
	       integration, we need to initialize our
	       "history" variables.
	    */
	    
	    for ( i = 0; i < HSMHV2NSRCS; i++ ) 
	      here->HSMHV2nVar[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 < HSMHV2NSRCS; i++) {
		here->HSMHV2nVar[OUTNOIZ][i] = 0.0;
		here->HSMHV2nVar[INNOIZ][i] = 0.0;
	      }
	    }
	  }
	  else {
	    /* data->delFreq != 0.0,
	       we have to integrate.
	    */
	    for ( i = 0; i < HSMHV2NSRCS; i++ ) {
	      if ( i != HSMHV2TOTNOIZ ) {
		tempOnoise = 
		  Nintegrate(noizDens[i], lnNdens[i],
			     here->HSMHV2nVar[LNLSTDENS][i], data);
		tempInoise = 
		  Nintegrate(noizDens[i] * data->GainSqInv, 
			     lnNdens[i] + data->lnGainInv,
			     here->HSMHV2nVar[LNLSTDENS][i] + data->lnGainInv,
			     data);
		here->HSMHV2nVar[LNLSTDENS][i] = lnNdens[i];
		data->outNoiz += tempOnoise;
		data->inNoise += tempInoise;
		if ( ((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0 ) {
		  here->HSMHV2nVar[OUTNOIZ][i] += tempOnoise;
		  here->HSMHV2nVar[OUTNOIZ][HSMHV2TOTNOIZ] += tempOnoise;
		  here->HSMHV2nVar[INNOIZ][i] += tempInoise;
		  here->HSMHV2nVar[INNOIZ][HSMHV2TOTNOIZ] += tempInoise;
		}
	      }
	    }
	  }
	  if ( data->prtSummary ) {
	    for (i = 0; i < HSMHV2NSRCS; 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 < HSMHV2NSRCS; i++ ) {
	      data->outpVector[data->outNumber++] = here->HSMHV2nVar[OUTNOIZ][i];
	      data->outpVector[data->outNumber++] = here->HSMHV2nVar[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);
}
Example #4
0
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);
}
Example #5
0
int
VDMOSnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt,
           Ndata *data, double *OnDens)
{
    NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

    VDMOSmodel *firstModel = (VDMOSmodel *) genmodel;
    VDMOSmodel *model;
    VDMOSinstance *inst;
    double coxSquared;
    double tempOnoise;
    double tempInoise;
    double noizDens[VDMOSNSRCS];
    double lnNdens[VDMOSNSRCS];
    int i;

    /* define the names of the noise sources */

    static char *VDMOSnNames[VDMOSNSRCS] = {       /* Note that we have to keep the order */
    "_rd",              /* noise due to rd */        /* consistent with thestrchr definitions */
    "_rs",              /* noise due to rs */        /* in VDMOSdefs.h */
    "_id",              /* noise due to id */
    "_1overf",          /* flicker (1/f) noise */
    ""                  /* total transistor noise */
    };

    for (model=firstModel; model != NULL; model=VDMOSnextModel(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 */

    if (model->VDMOSoxideCapFactor == 0.0) {
        coxSquared = 3.9 * 8.854214871e-12 / 1e-7;
        } else {
        coxSquared = model->VDMOSoxideCapFactor;
        }
    coxSquared *= coxSquared;
    for (inst=VDMOSinstances(model); inst != NULL; inst=VDMOSnextInstance(inst)) {
        
        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 < VDMOSNSRCS; i++) {
                NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->VDMOSname, VDMOSnNames[i]);
            }
            break;

            case INT_NOIZ:
            for (i=0; i < VDMOSNSRCS; i++) {
                NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->VDMOSname, VDMOSnNames[i]);
                NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->VDMOSname, VDMOSnNames[i]);
            }
            break;
            }
        }
        break;

        case N_CALC:
        switch (mode) {

        case N_DENS:
            NevalSrc(&noizDens[VDMOSRDNOIZ],&lnNdens[VDMOSRDNOIZ],
                 ckt,THERMNOISE,inst->VDMOSdNodePrime,inst->VDMOSdNode,
                 inst->VDMOSdrainConductance);

            NevalSrc(&noizDens[VDMOSRSNOIZ],&lnNdens[VDMOSRSNOIZ],
                 ckt,THERMNOISE,inst->VDMOSsNodePrime,inst->VDMOSsNode,
                 inst->VDMOSsourceConductance);

            NevalSrc(&noizDens[VDMOSIDNOIZ],&lnNdens[VDMOSIDNOIZ],
                 ckt,THERMNOISE,inst->VDMOSdNodePrime,inst->VDMOSsNodePrime,
                                 (2.0/3.0 * fabs(inst->VDMOSgm)));

            NevalSrc(&noizDens[VDMOSFLNOIZ], NULL, ckt,
                 N_GAIN,inst->VDMOSdNodePrime, inst->VDMOSsNodePrime,
                 (double)0.0);
            noizDens[VDMOSFLNOIZ] *= model->VDMOSfNcoef * 
                 exp(model->VDMOSfNexp *
                 log(MAX(fabs(inst->VDMOScd),N_MINLOG))) /
                 (data->freq * inst->VDMOSw * 
                 inst->VDMOSm *
                 inst->VDMOSl * coxSquared);
            lnNdens[VDMOSFLNOIZ] = 
                 log(MAX(noizDens[VDMOSFLNOIZ],N_MINLOG));

            noizDens[VDMOSTOTNOIZ] = noizDens[VDMOSRDNOIZ] +
                             noizDens[VDMOSRSNOIZ] +
                             noizDens[VDMOSIDNOIZ] +
                             noizDens[VDMOSFLNOIZ];
            lnNdens[VDMOSTOTNOIZ] = 
                 log(MAX(noizDens[VDMOSTOTNOIZ], N_MINLOG));

            *OnDens += noizDens[VDMOSTOTNOIZ];

            if (data->delFreq == 0.0) { 

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

            for (i=0; i < VDMOSNSRCS; i++) {
                inst->VDMOSnVar[LNLSTDENS][i] = lnNdens[i];
            }

            /* clear out our integration variables if it's the first pass */

            if (data->freq == job->NstartFreq) {
                for (i=0; i < VDMOSNSRCS; i++) {
                inst->VDMOSnVar[OUTNOIZ][i] = 0.0;
                inst->VDMOSnVar[INNOIZ][i] = 0.0;
                }
            }
            } else {   /* data->delFreq != 0.0 (we have to integrate) */
            for (i=0; i < VDMOSNSRCS; i++) {
                if (i != VDMOSTOTNOIZ) {
                tempOnoise = Nintegrate(noizDens[i], lnNdens[i],
                      inst->VDMOSnVar[LNLSTDENS][i], data);
                tempInoise = Nintegrate(noizDens[i] * data->GainSqInv ,
                      lnNdens[i] + data->lnGainInv,
                      inst->VDMOSnVar[LNLSTDENS][i] + data->lnGainInv,
                      data);
                inst->VDMOSnVar[LNLSTDENS][i] = lnNdens[i];
                data->outNoiz += tempOnoise;
                data->inNoise += tempInoise;
                if (job->NStpsSm != 0) {
                    inst->VDMOSnVar[OUTNOIZ][i] += tempOnoise;
                    inst->VDMOSnVar[OUTNOIZ][VDMOSTOTNOIZ] += tempOnoise;
                    inst->VDMOSnVar[INNOIZ][i] += tempInoise;
                    inst->VDMOSnVar[INNOIZ][VDMOSTOTNOIZ] += tempInoise;
                                }
                }
            }
            }
            if (data->prtSummary) {
            for (i=0; i < VDMOSNSRCS; 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 < VDMOSNSRCS; i++) {
                data->outpVector[data->outNumber++] = inst->VDMOSnVar[OUTNOIZ][i];
                data->outpVector[data->outNumber++] = inst->VDMOSnVar[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);
}
Example #6
0
int
MESnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, Ndata *data,
          double *OnDens)
{
    NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

    MESmodel *firstModel = (MESmodel *) genmodel;
    MESmodel *model;
    MESinstance *inst;
    char name[N_MXVLNTH];
    double tempOnoise;
    double tempInoise;
    double noizDens[MESNSRCS];
    double lnNdens[MESNSRCS];
    int i;

    /* define the names of the noise sources */

    static char *MESnNames[MESNSRCS] = {       /* Note that we have to keep the order */
	"_rd",              /* noise due to rd */        /* consistent with thestrchr definitions */
	"_rs",              /* noise due to rs */        /* in MESdefs.h */
	"_id",              /* noise due to id */
	"_1overf",          /* flicker (1/f) noise */
	""                  /* total transistor noise */
    };

    for (model=firstModel; model != NULL; model=model->MESnextModel) {
	for (inst=model->MESinstances; inst != NULL; inst=inst->MESnextInstance) {

	    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 < MESNSRCS; i++) {
			    (void)sprintf(name,"onoise_%s%s",inst->MESname,MESnNames[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 < MESNSRCS; i++) {
			    (void)sprintf(name,"onoise_total_%s%s",inst->MESname,MESnNames[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",inst->MESname,MESnNames[i]);

			    /*
			    OUTname(name,SV_INPUT_NOISE_V_SQ);
			    data->numPlots += 2; 
			    */

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:
		switch (mode) {

		case N_DENS:
		    NevalSrc(&noizDens[MESRDNOIZ],&lnNdens[MESRDNOIZ],
				 ckt,THERMNOISE,inst->MESdrainPrimeNode,inst->MESdrainNode,
				 model->MESdrainConduct * inst->MESarea * inst->MESm);

		    NevalSrc(&noizDens[MESRSNOIZ],&lnNdens[MESRSNOIZ],
				 ckt,THERMNOISE,inst->MESsourcePrimeNode,inst->MESsourceNode,
				 model->MESsourceConduct * inst->MESarea * inst->MESm);

		    NevalSrc(&noizDens[MESIDNOIZ],&lnNdens[MESIDNOIZ],
				 ckt,THERMNOISE,inst->MESdrainPrimeNode,
				 inst->MESsourcePrimeNode,
                                 (2.0/3.0 * inst->MESm * fabs(*(ckt->CKTstate0 + inst->MESgm))));

		    NevalSrc(&noizDens[MESFLNOIZ], NULL, ckt,
				 N_GAIN,inst->MESdrainPrimeNode, inst->MESsourcePrimeNode,
				 (double)0.0);
		    noizDens[MESFLNOIZ] *= inst->MESm * model->MESfNcoef * 
				 exp(model->MESfNexp *
				 log(MAX(fabs(*(ckt->CKTstate0 + inst->MEScd)),N_MINLOG))) /
				 data->freq;
		    lnNdens[MESFLNOIZ] = 
				 log(MAX(noizDens[MESFLNOIZ],N_MINLOG));

		    noizDens[MESTOTNOIZ] = noizDens[MESRDNOIZ] +
						    noizDens[MESRSNOIZ] +
						    noizDens[MESIDNOIZ] +
						    noizDens[MESFLNOIZ];
		    lnNdens[MESTOTNOIZ] = 
				 log(MAX(noizDens[MESTOTNOIZ], N_MINLOG));

		    *OnDens += noizDens[MESTOTNOIZ];

		    if (data->delFreq == 0.0) { 

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

			for (i=0; i < MESNSRCS; i++) {
			    inst->MESnVar[LNLSTDENS][i] = lnNdens[i];
			}

			/* clear out our integration variables if it's the first pass */

			if (data->freq == job->NstartFreq) {
			    for (i=0; i < MESNSRCS; i++) {
				inst->MESnVar[OUTNOIZ][i] = 0.0;
				inst->MESnVar[INNOIZ][i] = 0.0;
			    }
			}
		    } else {   /* data->delFreq != 0.0 (we have to integrate) */
			for (i=0; i < MESNSRCS; i++) {
			    if (i != MESTOTNOIZ) {
				tempOnoise = Nintegrate(noizDens[i], lnNdens[i],
				      inst->MESnVar[LNLSTDENS][i], data);
				tempInoise = Nintegrate(noizDens[i] * data->GainSqInv ,
				      lnNdens[i] + data->lnGainInv,
				      inst->MESnVar[LNLSTDENS][i] + data->lnGainInv,
				      data);
				inst->MESnVar[LNLSTDENS][i] = lnNdens[i];
				data->outNoiz += tempOnoise;
				data->inNoise += tempInoise;
				if (job->NStpsSm != 0) {
				    inst->MESnVar[OUTNOIZ][i] += tempOnoise;
				    inst->MESnVar[OUTNOIZ][MESTOTNOIZ] += tempOnoise;
				    inst->MESnVar[INNOIZ][i] += tempInoise;
				    inst->MESnVar[INNOIZ][MESTOTNOIZ] += tempInoise;
                                }
			    }
			}
		    }
		    if (data->prtSummary) {
			for (i=0; i < MESNSRCS; 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 < MESNSRCS; i++) {
			    data->outpVector[data->outNumber++] = inst->MESnVar[OUTNOIZ][i];
			    data->outpVector[data->outNumber++] = inst->MESnVar[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);
}
Example #7
0
int HSM2noise (
     int mode, int operation,
     GENmodel *inModel,
     CKTcircuit *ckt,
     Ndata *data,
     double *OnDens)
{
  HSM2model *model = (HSM2model *)inModel;
  HSM2instance *here;
  char name[N_MXVLNTH];
  double tempOnoise;
  double tempInoise;
  double noizDens[HSM2NSRCS];
  double lnNdens[HSM2NSRCS];
  int i;
  double G = 0.0 ;
  double TTEMP = 0.0 ;
 
  /* for induced gate noise calculation: */
  double omega = ckt->CKTomega;
  double sid, ci, sigrat, Qdrat;
  double realXds, imagXds, realXgs, imagXgs ;

  /* define the names of the noise sources */
  static char * HSM2nNames[HSM2NSRCS] = {
    /* Note that we have to keep the order
       consistent with the index definitions 
       in hsm2defs.h */
    ".rd",              /* noise due to rd */
    ".rs",              /* noise due to rs */
    ".id",              /* noise due to id */
    ".1ovf",            /* flicker (1/f) noise */
    ".igs",             /* shot noise due to Igs */
    ".igd",             /* shot noise due to Igd */
    ".igb",             /* shot noise due to Igb */
    ".ign",             /* induced gate noise component at the drain node */
    ""                  /* total transistor noise */
  };
  
  for ( ;model != NULL; model = model->HSM2nextModel ) {
    for ( here = model->HSM2instances; here != NULL;
	  here = here->HSM2nextInstance ) {
      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 < HSM2NSRCS; i++ ) { 
	      (void) sprintf(name, "onoise.%s%s", 
			     (char *)here->HSM2name, HSM2nNames[i]);
	      data->namelist = 
		(IFuid *) trealloc((char *) data->namelist,
				   ((long unsigned int)data->numPlots + 1) * sizeof(IFuid));
	      if (!data->namelist)
		return(E_NOMEM);
	      (*(SPfrontEnd->IFnewUid)) 
		(ckt, &(data->namelist[data->numPlots++]),
		 (IFuid) NULL, name, UID_OTHER, NULL);
	    }
	    break;
	  case INT_NOIZ:
	    for ( i = 0; i < HSM2NSRCS; i++ ) {
	      (void) sprintf(name, "onoise_total.%s%s", 
			     (char *)here->HSM2name, HSM2nNames[i]);
	      data->namelist = 
		(IFuid *) trealloc((char *) data->namelist,
				   ((long unsigned int)data->numPlots + 1) * sizeof(IFuid));
	      if (!data->namelist)
		return(E_NOMEM);
	      (*(SPfrontEnd->IFnewUid)) 
		(ckt, &(data->namelist[data->numPlots++]),
		 (IFuid) NULL, name, UID_OTHER, NULL);
	      
	      (void) sprintf(name, "inoise_total.%s%s", 
			     (char *)here->HSM2name, HSM2nNames[i]);
	      data->namelist = 
		(IFuid *) trealloc((char *) data->namelist,
				   ((long unsigned int)data->numPlots + 1) * sizeof(IFuid));
	      if (!data->namelist)
		return(E_NOMEM);
	      (*(SPfrontEnd->IFnewUid)) 
		(ckt, &(data->namelist[data->numPlots++]),
		 (IFuid) NULL, name, UID_OTHER, NULL);
	    }
	    break;
	  }
	}
	break;
      case N_CALC:
	switch (mode) {
	case N_DENS:

	  /* temperature */
	  TTEMP = ckt->CKTtemp ;
	  if ( here->HSM2_temp_Given ) TTEMP = here->HSM2_ktemp ;
	  if ( here->HSM2_dtemp_Given ) {
	    TTEMP = TTEMP + here->HSM2_dtemp ;
	  }

         /* rs/rd thermal noise */
         if ( model->HSM2_corsrd < 0 ) {
           NevalSrc(&noizDens[HSM2RDNOIZ], (double*) NULL,
                    ckt, N_GAIN,
                    here->HSM2dNodePrime, here->HSM2dNode,
                    (double) 0.0);
           noizDens[HSM2RDNOIZ] *= 4 * CONSTboltz * TTEMP * here->HSM2drainConductance ;
	   lnNdens[HSM2RDNOIZ] = log( MAX(noizDens[HSM2RDNOIZ],N_MINLOG) ) ;

           NevalSrc(&noizDens[HSM2RSNOIZ], (double*) NULL,
                    ckt, N_GAIN,
                    here->HSM2sNodePrime, here->HSM2sNode,
                    (double) 0.0);
           noizDens[HSM2RSNOIZ] *= 4 * CONSTboltz * TTEMP * here->HSM2sourceConductance ;
	   lnNdens[HSM2RSNOIZ] = log( MAX(noizDens[HSM2RSNOIZ],N_MINLOG) ) ;

           /*
           NevalSrc(&noizDens[HSM2RDNOIZ], &lnNdens[HSM2RDNOIZ],
		     ckt, THERMNOISE,
		     here->HSM2dNodePrime, here->HSM2dNode,
		     here->HSM2_weff / model->HSM2_rsh);
	    
	    NevalSrc(&noizDens[HSM2RSNOIZ], &lnNdens[HSM2RSNOIZ], 
		     ckt, THERMNOISE,
		     here->HSM2sNodePrime, here->HSM2sNode,
		     here->HSM2_weff / model->HSM2_rsh);
	    */
	  } else {
	    noizDens[HSM2RDNOIZ] = 0e0 ;
	    lnNdens[HSM2RDNOIZ] = N_MINLOG ;
	    noizDens[HSM2RSNOIZ] = 0e0 ;
	    lnNdens[HSM2RSNOIZ] = N_MINLOG ;
	  }

	  /* channel thermal noise */
	  switch( model->HSM2_noise ) {
	  case 1:
           /* HiSIM2 model */
         if ( model->HSM2_corsrd <= 0 || here->HSM2internalGd <= 0.0 ) {
           G = here->HSM2_noithrml ;
         } else {
           if ( here->HSM2_noithrml * here->HSM2internalGd * here->HSM2internalGs > 0.0 ) {
              G = here->HSM2_noithrml * here->HSM2internalGd * here->HSM2internalGs
              / ( here->HSM2_noithrml * here->HSM2internalGd
                + here->HSM2internalGd * here->HSM2internalGs
                + here->HSM2_noithrml * here->HSM2internalGs );
           } else {
              G = 0.0;
           }
         }
           NevalSrc(&noizDens[HSM2IDNOIZ], (double*) NULL,
                    ckt, N_GAIN,
                    here->HSM2dNodePrime, here->HSM2sNodePrime,
                    (double) 0.0);
           noizDens[HSM2IDNOIZ] *= 4 * CONSTboltz * TTEMP * G ;
           lnNdens[HSM2IDNOIZ] = log( MAX(noizDens[HSM2IDNOIZ],N_MINLOG) );
           break;
         }

         /* flicker noise */
         NevalSrc(&noizDens[HSM2FLNOIZ], (double*) NULL,
                  ckt, N_GAIN,
                  here->HSM2dNodePrime, here->HSM2sNodePrime,
                  (double) 0.0);
         switch ( model->HSM2_noise ) {
         case 1:
           /* HiSIM model */
           noizDens[HSM2FLNOIZ] *= here->HSM2_noiflick / pow(data->freq, model->HSM2_falph) ;
           break;
         }
         lnNdens[HSM2FLNOIZ] = log(MAX(noizDens[HSM2FLNOIZ], N_MINLOG));

         /* shot noise */
	 NevalSrc(&noizDens[HSM2IGSNOIZ],
		  &lnNdens[HSM2IGSNOIZ], ckt, SHOTNOISE,
		  here->HSM2gNodePrime, here->HSM2sNodePrime,
		  here->HSM2_igs);
	 NevalSrc(&noizDens[HSM2IGDNOIZ],
		  &lnNdens[HSM2IGDNOIZ], ckt, SHOTNOISE,
		  here->HSM2gNodePrime, here->HSM2dNodePrime,
		  here->HSM2_igd);
	 NevalSrc(&noizDens[HSM2IGBNOIZ],
		  &lnNdens[HSM2IGBNOIZ], ckt, SHOTNOISE,
		  here->HSM2gNodePrime, here->HSM2bNodePrime,
		  here->HSM2_igb);

	  /* induced gate noise */
	  switch ( model->HSM2_noise ) {
	  case 1:
	    /* HiSIM model */
            sid = 4.0 * CONSTboltz * TTEMP * here->HSM2_noithrml ;
            ci  = here->HSM2_noicross ;
            sigrat = (sid > 0.0 && here->HSM2_noiigate > 0.0) ? sqrt(here->HSM2_noiigate/sid) : 0.0 ;
            Qdrat  = here->HSM2_Qdrat ;

            realXds = *(ckt->CKTrhs +here->HSM2dNodePrime) - *(ckt->CKTrhs +here->HSM2sNodePrime);
            imagXds = *(ckt->CKTirhs+here->HSM2dNodePrime) - *(ckt->CKTirhs+here->HSM2sNodePrime);
            realXgs = *(ckt->CKTrhs +here->HSM2gNodePrime) - *(ckt->CKTrhs +here->HSM2sNodePrime);
            imagXgs = *(ckt->CKTirhs+here->HSM2gNodePrime) - *(ckt->CKTirhs+here->HSM2sNodePrime);

            noizDens[HSM2IGNOIZ] = 2.0 * omega * ci * sigrat * sid * ( realXgs*imagXds - realXds*imagXgs ) 
                                  + omega*omega * sigrat*sigrat * sid * ( (realXgs-Qdrat*realXds) * (realXgs-Qdrat*realXds)
                                                                         +(imagXgs-Qdrat*imagXds) * (imagXgs-Qdrat*imagXds) ) ;
	    lnNdens[HSM2IGNOIZ] = log(MAX(noizDens[HSM2IGNOIZ], N_MINLOG));
	    break;
	  }

	  /* total */
	  noizDens[HSM2TOTNOIZ] = noizDens[HSM2RDNOIZ] + noizDens[HSM2RSNOIZ]
	    + noizDens[HSM2IDNOIZ] + noizDens[HSM2FLNOIZ]
	    + noizDens[HSM2IGSNOIZ] + noizDens[HSM2IGDNOIZ] + noizDens[HSM2IGBNOIZ]
	    + noizDens[HSM2IGNOIZ];
	  lnNdens[HSM2TOTNOIZ] = log(MAX(noizDens[HSM2TOTNOIZ], N_MINLOG));
/*       printf("f %e Sid %.16e Srd %.16e Srs %.16e Sflick %.16e Stherm %.16e Sign %.16e\n", */
/*              data->freq,noizDens[HSM2TOTNOIZ],noizDens[HSM2RDNOIZ],noizDens[HSM2RSNOIZ],noizDens[HSM2FLNOIZ],noizDens[HSM2IDNOIZ],noizDens[HSM2IGNOIZ]); */
	  
	  *OnDens += noizDens[HSM2TOTNOIZ];
	  
	  if ( data->delFreq == 0.0 ) {
	    /* if we haven't done any previous 
	       integration, we need to initialize our
	       "history" variables.
	    */
	    
	    for ( i = 0; i < HSM2NSRCS; i++ ) 
	      here->HSM2nVar[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 < HSM2NSRCS; i++) {
		here->HSM2nVar[OUTNOIZ][i] = 0.0;
		here->HSM2nVar[INNOIZ][i] = 0.0;
	      }
	    }
	  }
	  else {
	    /* data->delFreq != 0.0,
	       we have to integrate.
	    */
	    for ( i = 0; i < HSM2NSRCS; i++ ) {
	      if ( i != HSM2TOTNOIZ ) {
		tempOnoise = 
		  Nintegrate(noizDens[i], lnNdens[i],
			     here->HSM2nVar[LNLSTDENS][i], data);
		tempInoise = 
		  Nintegrate(noizDens[i] * data->GainSqInv, 
			     lnNdens[i] + data->lnGainInv,
			     here->HSM2nVar[LNLSTDENS][i] + data->lnGainInv,
			     data);
		here->HSM2nVar[LNLSTDENS][i] = lnNdens[i];
		data->outNoiz += tempOnoise;
		data->inNoise += tempInoise;
		if ( ((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0 ) {
		  here->HSM2nVar[OUTNOIZ][i] += tempOnoise;
		  here->HSM2nVar[OUTNOIZ][HSM2TOTNOIZ] += tempOnoise;
		  here->HSM2nVar[INNOIZ][i] += tempInoise;
		  here->HSM2nVar[INNOIZ][HSM2TOTNOIZ] += tempInoise;
		}
	      }
	    }
	  }
	  if ( data->prtSummary ) {
	    for (i = 0; i < HSM2NSRCS; 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 < HSM2NSRCS; i++ ) {
	      data->outpVector[data->outNumber++] = here->HSM2nVar[OUTNOIZ][i];
	      data->outpVector[data->outNumber++] = here->HSM2nVar[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);
}
Example #8
0
int 
HSM1noise (int mode, int operation, GENmodel *inModel, CKTcircuit *ckt,
           register Ndata *data, double *OnDens)
{
  register HSM1model *model = (HSM1model *)inModel;
  register HSM1instance *here;
  char name[N_MXVLNTH];
  double tempOnoise;
  double tempInoise;
  double noizDens[HSM1NSRCS];
  double lnNdens[HSM1NSRCS];
  register int i;

  /* define the names of the noise sources */
  static char * HSM1nNames[HSM1NSRCS] = {
    /* Note that we have to keep the order
       consistent with the index definitions 
       in hsm1defs.h */
    ".rd",              /* noise due to rd */
    ".rs",              /* noise due to rs */
    ".id",              /* noise due to id */
    ".1ovf",            /* flicker (1/f) noise */
    ""                  /* total transistor noise */
  };
  
  for ( ;model != NULL; model = model->HSM1nextModel ) {
    for ( here = model->HSM1instances; here != NULL;
	  here = here->HSM1nextInstance ) {
		  
      if (here->HSM1owner != 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 < HSM1NSRCS; i++ ) { 
	      (void) sprintf(name, "onoise.%s%s", 
			     (char *)here->HSM1name, HSM1nNames[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);
	    }
	    break;
	  case INT_NOIZ:
	    for ( i = 0; i < HSM1NSRCS; i++ ) {
	      (void) sprintf(name, "onoise_total.%s%s", 
			     (char *)here->HSM1name, HSM1nNames[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);
	      
	      (void) sprintf(name, "inoise_total.%s%s", 
			     (char *)here->HSM1name, HSM1nNames[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);
	    }
	    break;
	  }
	}
	break;
      case N_CALC:
	switch (mode) {
	case N_DENS:
	  NevalSrc(&noizDens[HSM1RDNOIZ], &lnNdens[HSM1RDNOIZ], 
		   ckt, THERMNOISE,
		   here->HSM1dNodePrime, here->HSM1dNode,
		   here->HSM1drainConductance  * here->HSM1_m);
	  
	  NevalSrc(&noizDens[HSM1RSNOIZ], &lnNdens[HSM1RSNOIZ], 
		   ckt, THERMNOISE,
		   here->HSM1sNodePrime, here->HSM1sNode,
		   here->HSM1sourceConductance * here->HSM1_m);

	  switch( model->HSM1_noise ) {
	    double I;
	  case 1:
	  case 3:
	    I = here->HSM1_gm + here->HSM1_gds + here->HSM1_gmbs;
	    I *= (I < 0.0) ? -1.0 : 1.0;
	    I *= 2.0/3.0;
	    I *=  here->HSM1_m; /* PN */    
	    NevalSrc(&noizDens[HSM1IDNOIZ], &lnNdens[HSM1IDNOIZ], 
		     ckt, THERMNOISE, 
		     here->HSM1dNodePrime, here->HSM1sNodePrime, I);
	    break;
	  case 2:
	  case 4:
	    I = -1.0 * (here->HSM1_qg + here->HSM1_qb)
	      / (here->HSM1_weff * here->HSM1_leff);
	    I *= (I < 0.0) ? -1.0 : 1.0;
	    I *= here->HSM1_mu;
	    I *=  here->HSM1_m; /* PN */  
	    NevalSrc(&noizDens[HSM1IDNOIZ], &lnNdens[HSM1IDNOIZ], 
		     ckt, THERMNOISE, 
		     here->HSM1dNodePrime, here->HSM1sNodePrime, I);
	    break;
	  case 5:
	    NevalSrc(&noizDens[HSM1IDNOIZ], &lnNdens[HSM1IDNOIZ], 
		     ckt, THERMNOISE, 
		     here->HSM1dNodePrime, here->HSM1sNodePrime, 0.0);
	    break;
	  }
	  NevalSrc(&noizDens[HSM1FLNOIZ], (double*) NULL,
		   ckt, N_GAIN, 
		   here->HSM1dNodePrime, here->HSM1sNodePrime, 
		   (double) 0.0);
	  
	  /* flicker noise */
	  switch ( model->HSM1_noise ) {
	  case 1:
	  case 4: /* SPICE2 model */
	    noizDens[HSM1FLNOIZ] *= here->HSM1_m * model->HSM1_kf
	      * exp(model->HSM1_af * log(MAX(fabs(here->HSM1_ids), N_MINLOG)))
	      / (pow(data->freq, model->HSM1_ef) * here->HSM1_leff
		 * here->HSM1_leff * (3.453133e-11 / model->HSM1_tox));
	    /*                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cox  */
	    break;
	  case 2:
	  case 3:
	  case 5:
	    /* from HiSIM */
	    noizDens[HSM1FLNOIZ] *= here->HSM1_nfc / data->freq; 
	    break;
	  }
	  
	  lnNdens[HSM1FLNOIZ] = log(MAX(noizDens[HSM1FLNOIZ], N_MINLOG));
	  
	  noizDens[HSM1TOTNOIZ] = noizDens[HSM1RDNOIZ] + noizDens[HSM1RSNOIZ]
	    + noizDens[HSM1IDNOIZ] + noizDens[HSM1FLNOIZ];
	  lnNdens[HSM1TOTNOIZ] = log(MAX(noizDens[HSM1TOTNOIZ], N_MINLOG));
	  
	  *OnDens += noizDens[HSM1TOTNOIZ];
	  
	  if ( data->delFreq == 0.0 ) {
	    /* if we haven't done any previous 
	       integration, we need to initialize our
	       "history" variables.
	    */
	    
	    for ( i = 0; i < HSM1NSRCS; i++ ) 
	      here->HSM1nVar[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 < HSM1NSRCS; i++) {
		here->HSM1nVar[OUTNOIZ][i] = 0.0;
		here->HSM1nVar[INNOIZ][i] = 0.0;
	      }
	    }
	  }
	  else {
	    /* data->delFreq != 0.0,
	       we have to integrate.
	    */
	    for ( i = 0; i < HSM1NSRCS; i++ ) {
	      if ( i != HSM1TOTNOIZ ) {
		tempOnoise = 
		  Nintegrate(noizDens[i], lnNdens[i],
			     here->HSM1nVar[LNLSTDENS][i], data);
		tempInoise = 
		  Nintegrate(noizDens[i] * data->GainSqInv, 
			     lnNdens[i] + data->lnGainInv,
			     here->HSM1nVar[LNLSTDENS][i] + data->lnGainInv,
			     data);
		here->HSM1nVar[LNLSTDENS][i] = lnNdens[i];
		data->outNoiz += tempOnoise;
		data->inNoise += tempInoise;
		if ( ((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0 ) {
		  here->HSM1nVar[OUTNOIZ][i] += tempOnoise;
		  here->HSM1nVar[OUTNOIZ][HSM1TOTNOIZ] += tempOnoise;
		  here->HSM1nVar[INNOIZ][i] += tempInoise;
		  here->HSM1nVar[INNOIZ][HSM1TOTNOIZ] += tempInoise;
		}
	      }
	    }
	  }
	  if ( data->prtSummary ) {
	    for (i = 0; i < HSM1NSRCS; 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 < HSM1NSRCS; i++ ) {
	      data->outpVector[data->outNumber++] = here->HSM1nVar[OUTNOIZ][i];
	      data->outpVector[data->outNumber++] = here->HSM1nVar[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);
}
Example #9
0
int
SWnoise(int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, Ndata *data, double *OnDens)
{
    NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

    SWmodel *firstModel = (SWmodel *) genmodel;
    SWmodel *model;
    SWinstance *inst;
    double tempOutNoise;
    double tempInNoise;
    double noizDens;
    double lnNdens;
    int current_state;

    for (model = firstModel; model; model = SWnextModel(model))
        for (inst = SWinstances(model); inst; inst = SWnextInstance(inst)) {

            switch (operation) {

            case N_OPEN:

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

                if (job->NStpsSm != 0)
                    switch (mode) {
                    case N_DENS:
                        NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->SWname, "");
                        break;
                    case INT_NOIZ:
                        NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->SWname, "");
                        NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->SWname, "");
                        break;
                    }
                break;

            case N_CALC:
                switch (mode) {

                case N_DENS:
                    current_state = (int) ckt->CKTstate0[inst->SWswitchstate];
                    NevalSrc(&noizDens, &lnNdens, ckt, THERMNOISE,
                             inst->SWposNode, inst->SWnegNode,
                             current_state ? model->SWonConduct : model->SWoffConduct);

                    *OnDens += noizDens;

                    if (data->delFreq == 0.0) {

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

                        inst->SWnVar[LNLSTDENS] = lnNdens;

                        /* clear out our integration variable if it's the first pass */

                        if (data->freq == job->NstartFreq)
                            inst->SWnVar[OUTNOIZ] = 0.0;
                    } else {   /* data->delFreq != 0.0 (we have to integrate) */
                        tempOutNoise = Nintegrate(noizDens, lnNdens,
                                                  inst->SWnVar[LNLSTDENS], data);
                        tempInNoise = Nintegrate(noizDens *
                                                 data->GainSqInv, lnNdens + data->lnGainInv,
                                                 inst->SWnVar[LNLSTDENS] + data->lnGainInv,
                                                 data);
                        inst->SWnVar[OUTNOIZ] += tempOutNoise;
                        inst->SWnVar[INNOIZ] += tempInNoise;
                        data->outNoiz += tempOutNoise;
                        data->inNoise += tempInNoise;
                        inst->SWnVar[LNLSTDENS] = lnNdens;
                    }
                    if (data->prtSummary)
                        data->outpVector[data->outNumber++] = noizDens;
                    break;

                case INT_NOIZ:        /* already calculated, just output */
                    if (job->NStpsSm != 0) {
                        data->outpVector[data->outNumber++] = inst->SWnVar[OUTNOIZ];
                        data->outpVector[data->outNumber++] = inst->SWnVar[INNOIZ];
                    }
                    break;
                }
                break;

            case N_CLOSE:
                return OK;         /* do nothing, the main calling routine will close */
                break;             /* the plots */
            }
        }

    return OK;
}
Example #10
0
int
JFETnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, Ndata *data,
           double *OnDens)
{
    NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

    JFETmodel *firstModel = (JFETmodel *) genmodel;
    JFETmodel *model;
    JFETinstance *inst;
    double tempOnoise;
    double tempInoise;
    double noizDens[JFETNSRCS];
    double lnNdens[JFETNSRCS];
    int i;
    double vgs, vds, vgst, alpha, beta;

    /* define the names of the noise sources */

    static char *JFETnNames[JFETNSRCS] = {       /* Note that we have to keep the order */
        "_rd",              /* noise due to rd */        /* consistent with thestrchr definitions */
        "_rs",              /* noise due to rs */        /* in JFETdefs.h */
        "_id",              /* noise due to id */
        "_1overf",          /* flicker (1/f) noise */
        ""                  /* total transistor noise */
    };

    for (model=firstModel; model != NULL; model=JFETnextModel(model)) {
        for (inst=JFETinstances(model); inst != NULL; inst=JFETnextInstance(inst)) {

            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 < JFETNSRCS; i++) {
                            NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->JFETname, JFETnNames[i]);
                        }
                        break;

                    case INT_NOIZ:
                        for (i=0; i < JFETNSRCS; i++) {
                            NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->JFETname, JFETnNames[i]);
                            NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->JFETname, JFETnNames[i]);
                        }
                        break;
                    }
                }
                break;

            case N_CALC:
                switch (mode) {

                case N_DENS:
                    NevalSrc(&noizDens[JFETRDNOIZ],&lnNdens[JFETRDNOIZ],
                                 ckt,THERMNOISE,inst->JFETdrainPrimeNode,inst->JFETdrainNode,
                                 model->JFETdrainConduct * inst->JFETarea * inst->JFETm);

                    NevalSrc(&noizDens[JFETRSNOIZ],&lnNdens[JFETRSNOIZ],
                                 ckt,THERMNOISE,inst->JFETsourcePrimeNode,
                                 inst->JFETsourceNode,model->JFETsourceConduct
                                 * inst->JFETarea * inst->JFETm);

                    if (model->JFETnlev < 3) {
                        NevalSrc(&noizDens[JFETIDNOIZ],&lnNdens[JFETIDNOIZ],
                                     ckt,THERMNOISE,inst->JFETdrainPrimeNode,
                                     inst->JFETsourcePrimeNode,
                                     (2.0/3.0 * inst->JFETm * fabs(*(ckt->CKTstate0 + inst->JFETgm))));
                    } else {
                        vgs = *(ckt->CKTstate0 + inst->JFETvgs);
                        vds = vgs - *(ckt->CKTstate0 + inst->JFETvgd);
                        vgst = vgs - inst->JFETtThreshold;
                        if (vgst >= vds)
                            alpha = 1 - vds/vgst; /* linear region */
                        else
                            alpha = 0;        /* saturation region */
                        beta = inst->JFETtBeta * inst->JFETarea * inst->JFETm;

                        NevalSrc(&noizDens[JFETIDNOIZ],&lnNdens[JFETIDNOIZ],
                                     ckt,THERMNOISE,inst->JFETdrainPrimeNode,
                                     inst->JFETsourcePrimeNode,
                                     (2.0/3.0 * beta*vgst*(1+alpha+alpha*alpha)/(1+alpha)*model->JFETgdsnoi));
                    }

                    NevalSrc(&noizDens[JFETFLNOIZ], NULL, ckt,
                                 N_GAIN,inst->JFETdrainPrimeNode,
                                 inst->JFETsourcePrimeNode, (double)0.0);
                    noizDens[JFETFLNOIZ] *= inst->JFETm * model->JFETfNcoef *
                                 exp(model->JFETfNexp *
                                 log(MAX(fabs(*(ckt->CKTstate0 + inst->JFETcd)),N_MINLOG))) /
                                 data->freq;
                    lnNdens[JFETFLNOIZ] =
                                 log(MAX(noizDens[JFETFLNOIZ],N_MINLOG));

                    noizDens[JFETTOTNOIZ] = noizDens[JFETRDNOIZ] +
                                                     noizDens[JFETRSNOIZ] +
                                                     noizDens[JFETIDNOIZ] +
                                                     noizDens[JFETFLNOIZ];
                    lnNdens[JFETTOTNOIZ] =
                                 log(MAX(noizDens[JFETTOTNOIZ], N_MINLOG));

                    *OnDens += noizDens[JFETTOTNOIZ];

                    if (data->delFreq == 0.0) {

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

                        for (i=0; i < JFETNSRCS; i++) {
                            inst->JFETnVar[LNLSTDENS][i] = lnNdens[i];
                        }

                        /* clear out our integration variables if it's the first pass */

                        if (data->freq == job->NstartFreq) {
                            for (i=0; i < JFETNSRCS; i++) {
                                inst->JFETnVar[OUTNOIZ][i] = 0.0;
                                inst->JFETnVar[INNOIZ][i] = 0.0;
                            }
                        }
                    } else {   /* data->delFreq != 0.0 (we have to integrate) */
                        for (i=0; i < JFETNSRCS; i++) {
                            if (i != JFETTOTNOIZ) {
                                tempOnoise = Nintegrate(noizDens[i], lnNdens[i],
                                      inst->JFETnVar[LNLSTDENS][i], data);
                                tempInoise = Nintegrate(noizDens[i] * data->GainSqInv ,
                                      lnNdens[i] + data->lnGainInv,
                                      inst->JFETnVar[LNLSTDENS][i] + data->lnGainInv,
                                      data);
                                inst->JFETnVar[LNLSTDENS][i] = lnNdens[i];
                                data->outNoiz += tempOnoise;
                                data->inNoise += tempInoise;
                                if (job->NStpsSm != 0) {
                                    inst->JFETnVar[OUTNOIZ][i] += tempOnoise;
                                    inst->JFETnVar[OUTNOIZ][JFETTOTNOIZ] += tempOnoise;
                                    inst->JFETnVar[INNOIZ][i] += tempInoise;
                                    inst->JFETnVar[INNOIZ][JFETTOTNOIZ] += tempInoise;
                                }
                            }
                        }
                    }
                    if (data->prtSummary) {
                        for (i=0; i < JFETNSRCS; 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 < JFETNSRCS; i++) {
                            data->outpVector[data->outNumber++] = inst->JFETnVar[OUTNOIZ][i];
                            data->outpVector[data->outNumber++] = inst->JFETnVar[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);
}
Example #11
0
int
BSIM4v5noise (
int mode, int operation,
GENmodel *inModel,
CKTcircuit *ckt,
Ndata *data,
double *OnDens)
{
NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

BSIM4v5model *model = (BSIM4v5model *)inModel;
BSIM4v5instance *here;
struct bsim4v5SizeDependParam *pParam;
char name[N_MXVLNTH];
double tempOnoise;
double tempInoise;
double noizDens[BSIM4v5NSRCS];
double lnNdens[BSIM4v5NSRCS];

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

double m;

int i;

    /* define the names of the noise sources */
    static char *BSIM4v5nNames[BSIM4v5NSRCS] =
    {   /* 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 */
        ".1overf",          /* flicker (1/f) noise */
        ".igs",             /* shot noise due to IGS */
        ".igd",             /* shot noise due to IGD */
        ".igb",             /* shot noise due to IGB */
        ""                  /* total transistor noise */
    };

    for (; model != NULL; model = model->BSIM4v5nextModel)
    {    for (here = model->BSIM4v5instances; here != NULL;
              here = here->BSIM4v5nextInstance)
         {    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 < BSIM4v5NSRCS; i++)
                                  {    (void) sprintf(name, "onoise.%s%s",
                                                      here->BSIM4v5name,
                                                      BSIM4v5nNames[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 < BSIM4v5NSRCS; i++)
                                  {    (void) sprintf(name, "onoise_total.%s%s",
                                                      here->BSIM4v5name,
                                                      BSIM4v5nNames[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->BSIM4v5name,
                                                      BSIM4v5nNames[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->BSIM4v5m;
                      switch (mode)
                      {  case N_DENS:
                              if (model->BSIM4v5tnoiMod == 0)
                              {   if (model->BSIM4v5rdsMod == 0)
                                  {   gspr = here->BSIM4v5sourceConductance;
                                      gdpr = here->BSIM4v5drainConductance;
                                      if (here->BSIM4v5grdsw > 0.0)
                                          tmp = 1.0 / here->BSIM4v5grdsw; /* tmp used below */ 
                                      else
                                          tmp = 0.0;
                                  }
                                  else
                                  {   gspr = here->BSIM4v5gstot;
                                      gdpr = here->BSIM4v5gdtot;
                                      tmp = 0.0;
                                  }
                              }
                              else
                              {   T5 = here->BSIM4v5Vgsteff / here->BSIM4v5EsatL;
                                  T5 *= T5;
                                  npart_beta = model->BSIM4v5rnoia * (1.0 + T5
                                             * model->BSIM4v5tnoia * pParam->BSIM4v5leff);
                                  npart_theta = model->BSIM4v5rnoib * (1.0 + T5
                                              * model->BSIM4v5tnoib * pParam->BSIM4v5leff);

                                  if (model->BSIM4v5rdsMod == 0)
                                  {   gspr = here->BSIM4v5sourceConductance;
                                      gdpr = here->BSIM4v5drainConductance;
                                  }
                                  else
                                  {   gspr = here->BSIM4v5gstot;
                                      gdpr = here->BSIM4v5gdtot;
                                  }

                                  if ((*(ckt->CKTstates[0] + here->BSIM4v5vds)) >= 0.0)
                                      gspr = gspr / (1.0 + npart_theta * npart_theta * gspr
                                            / here->BSIM4v5IdovVds);  /* bugfix */
                                  else
                                      gdpr = gdpr / (1.0 + npart_theta * npart_theta * gdpr
                                           / here->BSIM4v5IdovVds);
                              } 

                              NevalSrc(&noizDens[BSIM4v5RDNOIZ],
                                       &lnNdens[BSIM4v5RDNOIZ], ckt, THERMNOISE,
                                       here->BSIM4v5dNodePrime, here->BSIM4v5dNode,
                                       gdpr * m);

                              NevalSrc(&noizDens[BSIM4v5RSNOIZ],
                                       &lnNdens[BSIM4v5RSNOIZ], ckt, THERMNOISE,
                                       here->BSIM4v5sNodePrime, here->BSIM4v5sNode,
                                       gspr * m);


                              if ((here->BSIM4v5rgateMod == 1) || (here->BSIM4v5rgateMod == 2))
                              {   NevalSrc(&noizDens[BSIM4v5RGNOIZ],
                                       &lnNdens[BSIM4v5RGNOIZ], ckt, THERMNOISE,
                                       here->BSIM4v5gNodePrime, here->BSIM4v5gNodeExt,
                                       here->BSIM4v5grgeltd * m);
                              }
                              else if (here->BSIM4v5rgateMod == 3)
                              {   NevalSrc(&noizDens[BSIM4v5RGNOIZ],
                                       &lnNdens[BSIM4v5RGNOIZ], ckt, THERMNOISE,
                                       here->BSIM4v5gNodeMid, here->BSIM4v5gNodeExt,
                                       here->BSIM4v5grgeltd * m);
                              }
                              else
                              {    noizDens[BSIM4v5RGNOIZ] = 0.0;
                                   lnNdens[BSIM4v5RGNOIZ] =
                                          log(MAX(noizDens[BSIM4v5RGNOIZ], N_MINLOG));
                              }

                                    bodymode = 5;
                                    if (here->BSIM4v5rbodyMod == 2)
                                    {        if( ( !model->BSIM4v5rbps0Given) || 
                                      ( !model->BSIM4v5rbpd0Given) )
                                             bodymode = 1;
                                           else 
                                     if( (!model->BSIM4v5rbsbx0Given && !model->BSIM4v5rbsby0Given) ||
                                          (!model->BSIM4v5rbdbx0Given && !model->BSIM4v5rbdby0Given) )
                                             bodymode = 3;
                                }

                              if (here->BSIM4v5rbodyMod)
                              { 
                                if(bodymode == 5)
                                  {
                                    NevalSrc(&noizDens[BSIM4v5RBPSNOIZ],
                                             &lnNdens[BSIM4v5RBPSNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v5bNodePrime, here->BSIM4v5sbNode,
                                             here->BSIM4v5grbps * m);
                                    NevalSrc(&noizDens[BSIM4v5RBPDNOIZ],
                                             &lnNdens[BSIM4v5RBPDNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v5bNodePrime, here->BSIM4v5dbNode,
                                             here->BSIM4v5grbpd * m);
                                    NevalSrc(&noizDens[BSIM4v5RBPBNOIZ],
                                             &lnNdens[BSIM4v5RBPBNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v5bNodePrime, here->BSIM4v5bNode,
                                             here->BSIM4v5grbpb * m);
                                    NevalSrc(&noizDens[BSIM4v5RBSBNOIZ],
                                             &lnNdens[BSIM4v5RBSBNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v5bNode, here->BSIM4v5sbNode,
                                             here->BSIM4v5grbsb * m);
                                    NevalSrc(&noizDens[BSIM4v5RBDBNOIZ],
                                             &lnNdens[BSIM4v5RBDBNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v5bNode, here->BSIM4v5dbNode,
                                             here->BSIM4v5grbdb * m);
                                  }
                                if(bodymode == 3)
                                  {
                                    NevalSrc(&noizDens[BSIM4v5RBPSNOIZ],
                                             &lnNdens[BSIM4v5RBPSNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v5bNodePrime, here->BSIM4v5sbNode,
                                             here->BSIM4v5grbps * m);
                                    NevalSrc(&noizDens[BSIM4v5RBPDNOIZ],
                                             &lnNdens[BSIM4v5RBPDNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v5bNodePrime, here->BSIM4v5dbNode,
                                             here->BSIM4v5grbpd * m);
                                    NevalSrc(&noizDens[BSIM4v5RBPBNOIZ],
                                             &lnNdens[BSIM4v5RBPBNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v5bNodePrime, here->BSIM4v5bNode,
                                             here->BSIM4v5grbpb * m);
                                     noizDens[BSIM4v5RBSBNOIZ] = noizDens[BSIM4v5RBDBNOIZ] = 0.0;
                                     lnNdens[BSIM4v5RBSBNOIZ] =
                                       log(MAX(noizDens[BSIM4v5RBSBNOIZ], N_MINLOG));
                                     lnNdens[BSIM4v5RBDBNOIZ] =
                                       log(MAX(noizDens[BSIM4v5RBDBNOIZ], N_MINLOG));                                     
                                  }
                                if(bodymode == 1)
                                  {
                                    NevalSrc(&noizDens[BSIM4v5RBPBNOIZ],
                                             &lnNdens[BSIM4v5RBPBNOIZ], ckt, THERMNOISE,
                                             here->BSIM4v5bNodePrime, here->BSIM4v5bNode,
                                             here->BSIM4v5grbpb * m);                                    
                                    noizDens[BSIM4v5RBPSNOIZ] = noizDens[BSIM4v5RBPDNOIZ] = 0.0;                                    
                                    noizDens[BSIM4v5RBSBNOIZ] = noizDens[BSIM4v5RBDBNOIZ] = 0.0;
                                    lnNdens[BSIM4v5RBPSNOIZ] =
                                      log(MAX(noizDens[BSIM4v5RBPSNOIZ], N_MINLOG));
                                    lnNdens[BSIM4v5RBPDNOIZ] =
                                      log(MAX(noizDens[BSIM4v5RBPDNOIZ], N_MINLOG));
                                    lnNdens[BSIM4v5RBSBNOIZ] =
                                      log(MAX(noizDens[BSIM4v5RBSBNOIZ], N_MINLOG));
                                    lnNdens[BSIM4v5RBDBNOIZ] =
                                      log(MAX(noizDens[BSIM4v5RBDBNOIZ], N_MINLOG));
                                  }
                              }
                              else
                              {   noizDens[BSIM4v5RBPSNOIZ] = noizDens[BSIM4v5RBPDNOIZ] = 0.0;   
                                  noizDens[BSIM4v5RBPBNOIZ] = 0.0;
                                  noizDens[BSIM4v5RBSBNOIZ] = noizDens[BSIM4v5RBDBNOIZ] = 0.0;
                                  lnNdens[BSIM4v5RBPSNOIZ] =
                                          log(MAX(noizDens[BSIM4v5RBPSNOIZ], N_MINLOG));
                                  lnNdens[BSIM4v5RBPDNOIZ] =
                                          log(MAX(noizDens[BSIM4v5RBPDNOIZ], N_MINLOG));
                                  lnNdens[BSIM4v5RBPBNOIZ] =
                                          log(MAX(noizDens[BSIM4v5RBPBNOIZ], N_MINLOG));
                                  lnNdens[BSIM4v5RBSBNOIZ] =
                                          log(MAX(noizDens[BSIM4v5RBSBNOIZ], N_MINLOG));
                                  lnNdens[BSIM4v5RBDBNOIZ] =
                                          log(MAX(noizDens[BSIM4v5RBDBNOIZ], N_MINLOG));
                              }


                              switch(model->BSIM4v5tnoiMod)
                              {  case 0:
                                      T0 = here->BSIM4v5ueff * fabs(here->BSIM4v5qinv);
                                      T1 = T0 * tmp + pParam->BSIM4v5leff
                                         * pParam->BSIM4v5leff;
                                      NevalSrc(&noizDens[BSIM4v5IDNOIZ],
                                               &lnNdens[BSIM4v5IDNOIZ], ckt,
                                               THERMNOISE, here->BSIM4v5dNodePrime,
                                               here->BSIM4v5sNodePrime,
                                               m * (T0 / T1) * model->BSIM4v5ntnoi);
                                      break;
                                 case 1:
                                      T0 = here->BSIM4v5gm + here->BSIM4v5gmbs + here->BSIM4v5gds;
                                      T0 *= T0;
                                      igsquare = npart_theta * npart_theta * T0 / here->BSIM4v5IdovVds;
                                      T1 = npart_beta * (here->BSIM4v5gm
                                         + here->BSIM4v5gmbs) + here->BSIM4v5gds;
                                      T2 = T1 * T1 / here->BSIM4v5IdovVds;
                                      NevalSrc(&noizDens[BSIM4v5IDNOIZ],
                                               &lnNdens[BSIM4v5IDNOIZ], ckt,
                                               THERMNOISE, here->BSIM4v5dNodePrime,
                                               here->BSIM4v5sNodePrime, m * (T2 - igsquare));
                                      break;
                              }

                              NevalSrc(&noizDens[BSIM4v5FLNOIZ], NULL,
                                       ckt, N_GAIN, here->BSIM4v5dNodePrime,
                                       here->BSIM4v5sNodePrime, (double) 0.0);

                              switch(model->BSIM4v5fnoiMod)
                              {  case 0:
                                      noizDens[BSIM4v5FLNOIZ] *= m * model->BSIM4v5kf
                                            * exp(model->BSIM4v5af
                                            * log(MAX(fabs(here->BSIM4v5cd),
                                            N_MINLOG)))
                                            / (pow(data->freq, model->BSIM4v5ef)
                                            * pParam->BSIM4v5leff
                                            * pParam->BSIM4v5leff
                                            * model->BSIM4v5coxe);
                                      break;
                                 case 1:
                                      Vds = *(ckt->CKTstates[0] + here->BSIM4v5vds);
                                      if (Vds < 0.0)
                                          Vds = -Vds;

                                      Ssi = BSIM4v5Eval1ovFNoise(Vds, model, here,
                                          data->freq, ckt->CKTtemp);
                                      T10 = model->BSIM4v5oxideTrapDensityA
                                          * CONSTboltz * ckt->CKTtemp;
                                      T11 = pParam->BSIM4v5weff * here->BSIM4v5nf * pParam->BSIM4v5leff
                                          * pow(data->freq, model->BSIM4v5ef) * 1.0e10
                                          * here->BSIM4v5nstar * here->BSIM4v5nstar;
                                      Swi = T10 / T11 * here->BSIM4v5cd
                                          * here->BSIM4v5cd;
                                      T1 = Swi + Ssi;
                                      if (T1 > 0.0)
                                          noizDens[BSIM4v5FLNOIZ] *= m * (Ssi * Swi) / T1;
                                      else
                                          noizDens[BSIM4v5FLNOIZ] *= 0.0;
                                      break;
                              }

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


                               if(here->BSIM4v5mode >= 0) {  /* bugfix  */
                              NevalSrc(&noizDens[BSIM4v5IGSNOIZ],
                                   &lnNdens[BSIM4v5IGSNOIZ], ckt, SHOTNOISE,
                                   here->BSIM4v5gNodePrime, here->BSIM4v5sNodePrime,
                                   m * (here->BSIM4v5Igs + here->BSIM4v5Igcs));
                              NevalSrc(&noizDens[BSIM4v5IGDNOIZ],
                                   &lnNdens[BSIM4v5IGDNOIZ], ckt, SHOTNOISE,
                                   here->BSIM4v5gNodePrime, here->BSIM4v5dNodePrime,
                                   m * (here->BSIM4v5Igd + here->BSIM4v5Igcd));
                        } else {
                              NevalSrc(&noizDens[BSIM4v5IGSNOIZ],
                                   &lnNdens[BSIM4v5IGSNOIZ], ckt, SHOTNOISE,
                                   here->BSIM4v5gNodePrime, here->BSIM4v5sNodePrime,
                                   m * (here->BSIM4v5Igs + here->BSIM4v5Igcd));
                              NevalSrc(&noizDens[BSIM4v5IGDNOIZ],
                                   &lnNdens[BSIM4v5IGDNOIZ], ckt, SHOTNOISE,
                                   here->BSIM4v5gNodePrime, here->BSIM4v5dNodePrime,
                                   m * (here->BSIM4v5Igd + here->BSIM4v5Igcs));
                        }
                              NevalSrc(&noizDens[BSIM4v5IGBNOIZ],
                                   &lnNdens[BSIM4v5IGBNOIZ], ckt, SHOTNOISE,
                                   here->BSIM4v5gNodePrime, here->BSIM4v5bNodePrime,
                                   m * here->BSIM4v5Igb);


                              noizDens[BSIM4v5TOTNOIZ] = noizDens[BSIM4v5RDNOIZ]
                                     + noizDens[BSIM4v5RSNOIZ] + noizDens[BSIM4v5RGNOIZ]
                                     + noizDens[BSIM4v5RBPSNOIZ] + noizDens[BSIM4v5RBPDNOIZ]
                                     + noizDens[BSIM4v5RBPBNOIZ]
                                     + noizDens[BSIM4v5RBSBNOIZ] + noizDens[BSIM4v5RBDBNOIZ]
                                     + noizDens[BSIM4v5IDNOIZ] + noizDens[BSIM4v5FLNOIZ]
                                     + noizDens[BSIM4v5IGSNOIZ] + noizDens[BSIM4v5IGDNOIZ]
                                     + noizDens[BSIM4v5IGBNOIZ];
                              lnNdens[BSIM4v5TOTNOIZ] = 
                                     log(MAX(noizDens[BSIM4v5TOTNOIZ], N_MINLOG));

                              *OnDens += noizDens[BSIM4v5TOTNOIZ];

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

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

                                  /* clear out our integration variables
                                     if it's the first pass
                                   */
                                  if (data->freq ==
                                      job->NstartFreq)
                                  {   for (i = 0; i < BSIM4v5NSRCS; i++)
                                      {    here->BSIM4v5nVar[OUTNOIZ][i] = 0.0;
                                           here->BSIM4v5nVar[INNOIZ][i] = 0.0;
                                      }
                                  }
                              }
                              else
                              {   /* data->delFreq != 0.0,
                                     we have to integrate.
                                   */
                                  for (i = 0; i < BSIM4v5NSRCS; i++)
                                  {    if (i != BSIM4v5TOTNOIZ)
                                       {   tempOnoise = Nintegrate(noizDens[i],
                                                lnNdens[i],
                                                here->BSIM4v5nVar[LNLSTDENS][i],
                                                data);
                                           tempInoise = Nintegrate(noizDens[i]
                                                * data->GainSqInv, lnNdens[i]
                                                + data->lnGainInv,
                                                here->BSIM4v5nVar[LNLSTDENS][i]
                                                + data->lnGainInv, data);
                                           here->BSIM4v5nVar[LNLSTDENS][i] =
                                                lnNdens[i];
                                           data->outNoiz += tempOnoise;
                                           data->inNoise += tempInoise;
                                           if (job->NStpsSm != 0)
                                           {   here->BSIM4v5nVar[OUTNOIZ][i]
                                                     += tempOnoise;
                                               here->BSIM4v5nVar[OUTNOIZ][BSIM4v5TOTNOIZ]
                                                     += tempOnoise;
                                               here->BSIM4v5nVar[INNOIZ][i]
                                                     += tempInoise;
                                               here->BSIM4v5nVar[INNOIZ][BSIM4v5TOTNOIZ]
                                                     += tempInoise;
                                           }
                                       }
                                  }
                              }
                              if (data->prtSummary)
                              {   for (i = 0; i < BSIM4v5NSRCS; 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 < BSIM4v5NSRCS; i++)
                                  {    data->outpVector[data->outNumber++]
                                             = here->BSIM4v5nVar[OUTNOIZ][i];
                                       data->outpVector[data->outNumber++]
                                             = here->BSIM4v5nVar[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);
}
Example #12
0
int
BSIM3v0noise (int mode, int operation, GENmodel *inModel, CKTcircuit *ckt, 
              Ndata *data, double *OnDens)
{
BSIM3v0model *model = (BSIM3v0model *)inModel;
BSIM3v0instance *here;
struct bsim3v0SizeDependParam *pParam;
char name[N_MXVLNTH];
double tempOnoise;
double tempInoise;
double noizDens[BSIM3v0NSRCS];
double lnNdens[BSIM3v0NSRCS];

double vgs, vds, Slimit;
double T1, T10, T11;
double Ssi, Swi;

int i;

    /* define the names of the noise sources */
    static char *BSIM3v0nNames[BSIM3v0NSRCS] =
    {   /* Note that we have to keep the order */
	".rd",              /* noise due to rd */
			    /* consistent with the index definitions */
	".rs",              /* noise due to rs */
			    /* in BSIM3v0defs.h */
	".id",              /* noise due to id */
	".1overf",          /* flicker (1/f) noise */
	""                  /* total transistor noise */
    };

    for (; model != NULL; model = model->BSIM3v0nextModel)
    {    for (here = model->BSIM3v0instances; here != NULL;
	      here = here->BSIM3v0nextInstance)
	 {    
	 
              if (here->BSIM3v0owner != ARCHme)
                      continue;

	      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 < BSIM3v0NSRCS; i++)
				  {    (void) sprintf(name, "onoise.%s%s",
					              here->BSIM3v0name,
						      BSIM3v0nNames[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 < BSIM3v0NSRCS; i++)
				  {    (void) sprintf(name, "onoise_total.%s%s",
						      here->BSIM3v0name,
						      BSIM3v0nNames[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",
						      here->BSIM3v0name,
						      BSIM3v0nNames[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[BSIM3v0RDNOIZ],
				       &lnNdens[BSIM3v0RDNOIZ], ckt, THERMNOISE,
				       here->BSIM3v0dNodePrime, here->BSIM3v0dNode,
				       here->BSIM3v0drainConductance * here->BSIM3v0m);

		              NevalSrc(&noizDens[BSIM3v0RSNOIZ],
				       &lnNdens[BSIM3v0RSNOIZ], ckt, THERMNOISE,
				       here->BSIM3v0sNodePrime, here->BSIM3v0sNode,
				       here->BSIM3v0sourceConductance * here->BSIM3v0m);

                              if (model->BSIM3v0noiMod == 2)
		              {   NevalSrc(&noizDens[BSIM3v0IDNOIZ],
				         &lnNdens[BSIM3v0IDNOIZ], ckt, THERMNOISE,
				         here->BSIM3v0dNodePrime,
                                         here->BSIM3v0sNodePrime, (here->BSIM3v0ueff
					 * fabs((here->BSIM3v0qinv * here->BSIM3v0m)
					 / (pParam->BSIM3v0leff
					 *  pParam->BSIM3v0leff))));
		              }
                              else
			      {   NevalSrc(&noizDens[BSIM3v0IDNOIZ],
				       &lnNdens[BSIM3v0IDNOIZ], ckt, THERMNOISE,
				       here->BSIM3v0dNodePrime,
				       here->BSIM3v0sNodePrime,
                                       (2.0 / 3.0 * fabs(here->BSIM3v0gm
				       + here->BSIM3v0gds) * here->BSIM3v0m));

			      }
		              NevalSrc(&noizDens[BSIM3v0FLNOIZ], (double*) NULL,
				       ckt, N_GAIN, here->BSIM3v0dNodePrime,
				       here->BSIM3v0sNodePrime, (double) 0.0);

                              if (model->BSIM3v0noiMod == 2)
			      {   vgs = *(ckt->CKTstates[0] + here->BSIM3v0vgs);
		                  vds = *(ckt->CKTstates[0] + here->BSIM3v0vds);
			          if (vds < 0.0)
			          {   vds = -vds;
				      vgs = vgs + vds;
			          }
                                  if (vgs >= here->BSIM3v0von + 0.1)
			          {   Ssi = StrongInversionNoiseEval(vgs, vds,
					    model, here, data->freq,
					    ckt->CKTtemp);
                                      noizDens[BSIM3v0FLNOIZ] *= Ssi;
			          }
                                  else 
			          {   pParam = here->pParam;
				      T10 = model->BSIM3v0oxideTrapDensityA
					  * 8.62e-5 * (ckt->CKTtemp + CONSTCtoK);
		                      T11 = pParam->BSIM3v0weff * here->BSIM3v0m * pParam->BSIM3v0leff
				          * pow(data->freq, model->BSIM3v0ef)
				          * 4.0e36;
		                      Swi = T10 / T11 * here->BSIM3v0cd * here->BSIM3v0m
				          * here->BSIM3v0cd * here->BSIM3v0m;
                                      Slimit = StrongInversionNoiseEval(
				           here->BSIM3v0von + 0.1,
				           vds, model, here,
				           data->freq, ckt->CKTtemp);
				      T1 = Swi + Slimit;
				      if (T1 > 0.0)
                                          noizDens[BSIM3v0FLNOIZ] *= (Slimit * Swi)
							        / T1; 
				      else
                                          noizDens[BSIM3v0FLNOIZ] *= 0.0;
			          }
		              }
                              else
			      {    noizDens[BSIM3v0FLNOIZ] *= model->BSIM3v0kf * 
				            exp(model->BSIM3v0af
					    * log(MAX(fabs(here->BSIM3v0cd * here->BSIM3v0m),
					    N_MINLOG)))
					    / (pow(data->freq, model->BSIM3v0ef)
					    * pParam->BSIM3v0leff
				            * pParam->BSIM3v0leff
					    * model->BSIM3v0cox);
			      }

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

		              noizDens[BSIM3v0TOTNOIZ] = noizDens[BSIM3v0RDNOIZ]
						     + noizDens[BSIM3v0RSNOIZ]
						     + noizDens[BSIM3v0IDNOIZ]
						     + noizDens[BSIM3v0FLNOIZ];
		              lnNdens[BSIM3v0TOTNOIZ] = 
				     log(MAX(noizDens[BSIM3v0TOTNOIZ], N_MINLOG));

		              *OnDens += noizDens[BSIM3v0TOTNOIZ];

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

			          for (i = 0; i < BSIM3v0NSRCS; i++)
				  {    here->BSIM3v0nVar[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 < BSIM3v0NSRCS; i++)
				      {    here->BSIM3v0nVar[OUTNOIZ][i] = 0.0;
				           here->BSIM3v0nVar[INNOIZ][i] = 0.0;
			              }
			          }
		              }
			      else
			      {   /* data->delFreq != 0.0,
				     we have to integrate.
				   */
			          for (i = 0; i < BSIM3v0NSRCS; i++)
				  {    if (i != BSIM3v0TOTNOIZ)
				       {   tempOnoise = Nintegrate(noizDens[i],
						lnNdens[i],
				                here->BSIM3v0nVar[LNLSTDENS][i],
						data);
				           tempInoise = Nintegrate(noizDens[i]
						* data->GainSqInv, lnNdens[i]
						+ data->lnGainInv,
				                here->BSIM3v0nVar[LNLSTDENS][i]
						+ data->lnGainInv, data);
				           here->BSIM3v0nVar[LNLSTDENS][i] =
						lnNdens[i];
				           data->outNoiz += tempOnoise;
				           data->inNoise += tempInoise;
				           if (((NOISEAN*)
					       ckt->CKTcurJob)->NStpsSm != 0)
					   {   here->BSIM3v0nVar[OUTNOIZ][i]
						     += tempOnoise;
				               here->BSIM3v0nVar[OUTNOIZ][BSIM3v0TOTNOIZ]
						     += tempOnoise;
				               here->BSIM3v0nVar[INNOIZ][i]
						     += tempInoise;
				               here->BSIM3v0nVar[INNOIZ][BSIM3v0TOTNOIZ]
						     += tempInoise;
                                           }
			               }
			          }
		              }
		              if (data->prtSummary)
			      {   for (i = 0; i < BSIM3v0NSRCS; 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 < BSIM3v0NSRCS; i++)
				  {    data->outpVector[data->outNumber++]
					     = here->BSIM3v0nVar[OUTNOIZ][i];
			               data->outpVector[data->outNumber++]
					     = here->BSIM3v0nVar[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);
}
Example #13
0
int
B3SOIDDnoise (int mode, int operation, GENmodel *inModel, CKTcircuit *ckt, 
              Ndata *data, double *OnDens)
{
NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

B3SOIDDmodel *model = (B3SOIDDmodel *)inModel;
B3SOIDDinstance *here;
struct b3soiddSizeDependParam *pParam;
double tempOnoise;
double tempInoise;
double noizDens[B3SOIDDNSRCS];
double lnNdens[B3SOIDDNSRCS];

double vgs, vds, Slimit;
double T1, T10, T11;
double Ssi, Swi;

int i;

    /* define the names of the noise sources */
    static char *B3SOIDDnNames[B3SOIDDNSRCS] =
    {   /* Note that we have to keep the order */
	".rd",              /* noise due to rd */
			    /* consistent with the index definitions */
	".rs",              /* noise due to rs */
			    /* in B3SOIDDdefs.h */
	".id",              /* noise due to id */
	".1overf",          /* flicker (1/f) noise */
        ".fb", 		    /* noise due to floating body */
	""                  /* total transistor noise */
    };

    for (; model != NULL; model = B3SOIDDnextModel(model))
    {    for (here = B3SOIDDinstances(model); here != NULL;
	      here = B3SOIDDnextInstance(here))
	 {
	      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 < B3SOIDDNSRCS; i++)
				  {    NOISE_ADD_OUTVAR(ckt, data, "onoise.%s%s", here->B3SOIDDname, B3SOIDDnNames[i]);
			          }
			          break;
		             case INT_NOIZ:
			          for (i = 0; i < B3SOIDDNSRCS; i++)
				  {    NOISE_ADD_OUTVAR(ckt, data, "onoise_total.%s%s", here->B3SOIDDname, B3SOIDDnNames[i]);
			               NOISE_ADD_OUTVAR(ckt, data, "inoise_total.%s%s", here->B3SOIDDname, B3SOIDDnNames[i]);
			          }
			          break;
		          }
		      }
		      break;
	         case N_CALC:
		      switch (mode)
		      {  case N_DENS:
		              NevalSrc(&noizDens[B3SOIDDRDNOIZ],
				       &lnNdens[B3SOIDDRDNOIZ], ckt, THERMNOISE,
				       here->B3SOIDDdNodePrime, here->B3SOIDDdNode,
				       here->B3SOIDDdrainConductance * here->B3SOIDDm);

		              NevalSrc(&noizDens[B3SOIDDRSNOIZ],
				       &lnNdens[B3SOIDDRSNOIZ], ckt, THERMNOISE,
				       here->B3SOIDDsNodePrime, here->B3SOIDDsNode,
				       here->B3SOIDDsourceConductance * here->B3SOIDDm);

                              switch( model->B3SOIDDnoiMod )
			      {  case 1:
			         case 3:
			              NevalSrc(&noizDens[B3SOIDDIDNOIZ],
				               &lnNdens[B3SOIDDIDNOIZ], ckt, 
					       THERMNOISE, here->B3SOIDDdNodePrime,
				               here->B3SOIDDsNodePrime,
                                               (2.0 / 3.0 * fabs(here->B3SOIDDm * (here->B3SOIDDgm
				               + here->B3SOIDDgds
					       + here->B3SOIDDgmbs))));
				      break;
			         case 2:
			         case 4:
		                      NevalSrc(&noizDens[B3SOIDDIDNOIZ],
				               &lnNdens[B3SOIDDIDNOIZ], ckt,
					       THERMNOISE, here->B3SOIDDdNodePrime,
                                               here->B3SOIDDsNodePrime,
					       (here->B3SOIDDueff
					       * fabs((here->B3SOIDDqinv * here->B3SOIDDm)
					       / (pParam->B3SOIDDleff
					       * pParam->B3SOIDDleff))));
				      break;
			      }
		              NevalSrc(&noizDens[B3SOIDDFLNOIZ], NULL,
				       ckt, N_GAIN, here->B3SOIDDdNodePrime,
				       here->B3SOIDDsNodePrime, (double) 0.0);

                              switch( model->B3SOIDDnoiMod )
			      {  case 1:
			         case 4:
			              noizDens[B3SOIDDFLNOIZ] *= model->B3SOIDDkf
					    * exp(model->B3SOIDDaf
					    * log(MAX(fabs(here->B3SOIDDcd * here->B3SOIDDm),
					    N_MINLOG)))
					    / (pow(data->freq, model->B3SOIDDef)
					    * pParam->B3SOIDDleff
				            * pParam->B3SOIDDleff
					    * model->B3SOIDDcox);
				      break;
			         case 2:
			         case 3:
			              vgs = *(ckt->CKTstates[0] + here->B3SOIDDvgs);
		                      vds = *(ckt->CKTstates[0] + here->B3SOIDDvds);
			              if (vds < 0.0)
			              {   vds = -vds;
				          vgs = vgs + vds;
			              }
                                      if (vgs >= here->B3SOIDDvon + 0.1)
			              {   Ssi = B3SOIDDStrongInversionNoiseEval(vgs,
					      vds, model, here, data->freq,
					      ckt->CKTtemp);
                                          noizDens[B3SOIDDFLNOIZ] *= Ssi;
			              }
                                      else 
			              {   pParam = here->pParam;
				          T10 = model->B3SOIDDoxideTrapDensityA
					      * 8.62e-5 * ckt->CKTtemp;
		                          T11 = pParam->B3SOIDDweff * here->B3SOIDDm
					      * pParam->B3SOIDDleff
				              * pow(data->freq, model->B3SOIDDef)
				              * 4.0e36;
		                          Swi = T10 / T11 * here->B3SOIDDcd * here->B3SOIDDm
				              * here->B3SOIDDcd * here->B3SOIDDm;
                                          Slimit = B3SOIDDStrongInversionNoiseEval(
				               here->B3SOIDDvon + 0.1, vds, model,
					       here, data->freq, ckt->CKTtemp);
				          T1 = Swi + Slimit;
				          if (T1 > 0.0)
                                              noizDens[B3SOIDDFLNOIZ] *= (Slimit
								    * Swi) / T1; 
				          else
                                              noizDens[B3SOIDDFLNOIZ] *= 0.0;
			              }
				      break;
			      }

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

			      /* Low frequency excess noise due to FBE */
		              NevalSrc(&noizDens[B3SOIDDFBNOIZ], &lnNdens[B3SOIDDFBNOIZ],
				          ckt, SHOTNOISE, here->B3SOIDDsNodePrime,
				          here->B3SOIDDbNode, 
                                          2.0 * model->B3SOIDDnoif * here->B3SOIDDibs *
					  here->B3SOIDDm);

		              noizDens[B3SOIDDTOTNOIZ] = noizDens[B3SOIDDRDNOIZ]
						     + noizDens[B3SOIDDRSNOIZ]
						     + noizDens[B3SOIDDIDNOIZ]
						     + noizDens[B3SOIDDFLNOIZ]
						     + noizDens[B3SOIDDFBNOIZ];
		              lnNdens[B3SOIDDTOTNOIZ] = 
				     log(MAX(noizDens[B3SOIDDTOTNOIZ], N_MINLOG));

		              *OnDens += noizDens[B3SOIDDTOTNOIZ];

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

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

			          /* clear out our integration variables
				     if it's the first pass
				   */
			          if (data->freq ==
				      job->NstartFreq)
				  {   for (i = 0; i < B3SOIDDNSRCS; i++)
				      {    here->B3SOIDDnVar[OUTNOIZ][i] = 0.0;
				           here->B3SOIDDnVar[INNOIZ][i] = 0.0;
			              }
			          }
		              }
			      else
			      {   /* data->delFreq != 0.0,
				     we have to integrate.
				   */
			          for (i = 0; i < B3SOIDDNSRCS; i++)
				  {    if (i != B3SOIDDTOTNOIZ)
				       {   tempOnoise = Nintegrate(noizDens[i],
						lnNdens[i],
				                here->B3SOIDDnVar[LNLSTDENS][i],
						data);
				           tempInoise = Nintegrate(noizDens[i]
						* data->GainSqInv, lnNdens[i]
						+ data->lnGainInv,
				                here->B3SOIDDnVar[LNLSTDENS][i]
						+ data->lnGainInv, data);
				           here->B3SOIDDnVar[LNLSTDENS][i] =
						lnNdens[i];
				           data->outNoiz += tempOnoise;
				           data->inNoise += tempInoise;
				           if (job->NStpsSm != 0)
					   {   here->B3SOIDDnVar[OUTNOIZ][i]
						     += tempOnoise;
				               here->B3SOIDDnVar[OUTNOIZ][B3SOIDDTOTNOIZ]
						     += tempOnoise;
				               here->B3SOIDDnVar[INNOIZ][i]
						     += tempInoise;
				               here->B3SOIDDnVar[INNOIZ][B3SOIDDTOTNOIZ]
						     += tempInoise;
                                           }
			               }
			          }
		              }
		              if (data->prtSummary)
			      {   for (i = 0; i < B3SOIDDNSRCS; 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 < B3SOIDDNSRCS; i++)
				  {    data->outpVector[data->outNumber++]
					     = here->B3SOIDDnVar[OUTNOIZ][i];
			               data->outpVector[data->outNumber++]
					     = here->B3SOIDDnVar[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);
}
Example #14
0
File: b1noi.c Project: imr/ngspice
int
B1noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, 
           Ndata *data, double *OnDens)
{
    NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

    B1model *firstModel = (B1model *) genmodel;
    B1model *model;
    B1instance *inst;
    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=B1nextModel(model)) {
	for (inst=B1instances(model); inst != NULL; inst=B1nextInstance(inst)) {
        
	    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 < B1NSRCS; i++) {
			    NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", inst->B1name, B1nNames[i]);
			}
			break;

		    case INT_NOIZ:
			for (i=0; i < B1NSRCS; i++) {
			    NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", inst->B1name, B1nNames[i]);
			    NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", inst->B1name, B1nNames[i]);
			}
			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], 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 == job->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 (job->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 (job->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);
}
Example #15
0
int
BSIM3v32noise (int mode, int operation, GENmodel *inModel, CKTcircuit *ckt,
            Ndata *data, double *OnDens)
{
NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

BSIM3v32model *model = (BSIM3v32model *)inModel;
BSIM3v32instance *here;
struct bsim3v32SizeDependParam *pParam;
char name[N_MXVLNTH];
double tempOnoise;
double tempInoise;
double noizDens[BSIM3v32NSRCS];
double lnNdens[BSIM3v32NSRCS];

double vgs, vds, Slimit;
double T1, T10, T11;
double Ssi, Swi;

double m;

int i;

    /* define the names of the noise sources */
    static char *BSIM3v32nNames[BSIM3v32NSRCS] =
    {   /* Note that we have to keep the order */
        ".rd",              /* noise due to rd */
                            /* consistent with the index definitions */
        ".rs",              /* noise due to rs */
                            /* in BSIM3v32defs.h */
        ".id",              /* noise due to id */
        ".1overf",          /* flicker (1/f) noise */
        ""                  /* total transistor noise */
    };

    for (; model != NULL; model = model->BSIM3v32nextModel)
    {    for (here = model->BSIM3v32instances; here != NULL;
              here = here->BSIM3v32nextInstance)
         {    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 < BSIM3v32NSRCS; i++)
                                  {    (void) sprintf(name, "onoise.%s%s",
                                                      here->BSIM3v32name,
                                                      BSIM3v32nNames[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 < BSIM3v32NSRCS; i++)
                                  {    (void) sprintf(name, "onoise_total.%s%s",
                                                      here->BSIM3v32name,
                                                      BSIM3v32nNames[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->BSIM3v32name,
                                                      BSIM3v32nNames[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->BSIM3v32m;
                      switch (mode)
                      {  case N_DENS:
                              NevalSrc(&noizDens[BSIM3v32RDNOIZ],
                                       &lnNdens[BSIM3v32RDNOIZ], ckt, THERMNOISE,
                                       here->BSIM3v32dNodePrime, here->BSIM3v32dNode,
                                       here->BSIM3v32drainConductance * m);

                              NevalSrc(&noizDens[BSIM3v32RSNOIZ],
                                       &lnNdens[BSIM3v32RSNOIZ], ckt, THERMNOISE,
                                       here->BSIM3v32sNodePrime, here->BSIM3v32sNode,
                                       here->BSIM3v32sourceConductance * m);

                              switch( model->BSIM3v32noiMod )
                              {  case 1:
                                 case 3:
                                      NevalSrc(&noizDens[BSIM3v32IDNOIZ],
                                               &lnNdens[BSIM3v32IDNOIZ], ckt,
                                               THERMNOISE, here->BSIM3v32dNodePrime,
                                               here->BSIM3v32sNodePrime,
                                               (2.0 / 3.0 * fabs(here->BSIM3v32gm
                                               + here->BSIM3v32gds
                                               + here->BSIM3v32gmbs)) * m);
                                      break;
                                 case 2:
                                 case 4:
                                            /* Added revision dependent code */
                                            if (model->BSIM3v32intVersion == BSIM3v32V324)
                                      {
                                        NevalSrc(&noizDens[BSIM3v32IDNOIZ],
                                               &lnNdens[BSIM3v32IDNOIZ], ckt,
                                               THERMNOISE, here->BSIM3v32dNodePrime,
                                               here->BSIM3v32sNodePrime,
                                               (m * here->BSIM3v32ueff
                                               * fabs(here->BSIM3v32qinv)
                                               / (pParam->BSIM3v32leff * pParam->BSIM3v32leff
                                                + here->BSIM3v32ueff * fabs(here->BSIM3v32qinv)
                                                * here->BSIM3v32rds)));    /* bugfix */
                                      }
                                            else
                                      {        /* for all versions lower then 3.2.4 */
                                        NevalSrc(&noizDens[BSIM3v32IDNOIZ],
                                               &lnNdens[BSIM3v32IDNOIZ], ckt,
                                               THERMNOISE, here->BSIM3v32dNodePrime,
                                               here->BSIM3v32sNodePrime,
                                               (m * here->BSIM3v32ueff
                                               * fabs(here->BSIM3v32qinv
                                               / (pParam->BSIM3v32leff
                                               * pParam->BSIM3v32leff))));
                                      }
                                      break;
                              }
                              NevalSrc(&noizDens[BSIM3v32FLNOIZ], NULL,
                                       ckt, N_GAIN, here->BSIM3v32dNodePrime,
                                       here->BSIM3v32sNodePrime, (double) 0.0);

                              switch( model->BSIM3v32noiMod )
                              {  case 1:
                                 case 4:
                                      noizDens[BSIM3v32FLNOIZ] *= m * model->BSIM3v32kf
                                            * exp(model->BSIM3v32af
                                            * log(MAX(fabs(here->BSIM3v32cd),
                                            N_MINLOG)))
                                            / (pow(data->freq, model->BSIM3v32ef)
                                            * pParam->BSIM3v32leff
                                            * pParam->BSIM3v32leff
                                            * model->BSIM3v32cox);
                                      break;
                                 case 2:
                                 case 3:
                                      vgs = *(ckt->CKTstates[0] + here->BSIM3v32vgs);
                                            vds = *(ckt->CKTstates[0] + here->BSIM3v32vds);
                                      if (vds < 0.0)
                                      {   vds = -vds;
                                          vgs = vgs + vds;
                                      }
                                            /* Added revision dependent code */
                                            if (model->BSIM3v32intVersion == BSIM3v32V324)
                                      {
                                        Ssi = StrongInversionNoiseEvalNew(vds, model,
                                                      here, data->freq, ckt->CKTtemp);
                                        T10 = model->BSIM3v32oxideTrapDensityA
                                            * 8.62e-5 * ckt->CKTtemp;
                                        T11 = pParam->BSIM3v32weff
                                            * pParam->BSIM3v32leff
                                            * pow(data->freq, model->BSIM3v32ef)
                                            * 4.0e36;
                                        Swi = T10 / T11 * here->BSIM3v32cd
                                            * here->BSIM3v32cd;
                                        T1 = Swi + Ssi;
                                        if (T1 > 0.0)
                                            noizDens[BSIM3v32FLNOIZ] *= m * (Ssi * Swi) / T1;
                                        else
                                            noizDens[BSIM3v32FLNOIZ] *= 0.0;
                                      }
                                            else
                                      {        /* for all versions lower then 3.2.4 */
                                        if (vgs >= here->BSIM3v32von + 0.1)
                                          {
                                            Ssi = StrongInversionNoiseEvalOld(vgs, vds, model,
                                                        here, data->freq, ckt->CKTtemp);
                                            noizDens[BSIM3v32FLNOIZ] *= m * Ssi;
                                          }
                                        else
                                          {
                                            pParam = here->pParam;
                                            T10 = model->BSIM3v32oxideTrapDensityA
                                                  * 8.62e-5 * ckt->CKTtemp;
                                            T11 = pParam->BSIM3v32weff
                                                  * pParam-> BSIM3v32leff
                                                  * pow (data->freq, model->BSIM3v32ef)
                                                  * 4.0e36;
                                            Swi = T10 / T11 * here->BSIM3v32cd * here->BSIM3v32cd;

                                            Slimit = StrongInversionNoiseEvalOld(
                                                 here->BSIM3v32von + 0.1, vds, model,
                                                 here, data->freq, ckt->CKTtemp);
                                            T1 = Swi + Slimit;
                                            if (T1 > 0.0)
                                                        noizDens[BSIM3v32FLNOIZ] *= m * (Slimit * Swi) / T1;
                                            else
                                                        noizDens[BSIM3v32FLNOIZ] *= 0.0;
                                          }
                                        }
                                        break;
                              }

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

                              noizDens[BSIM3v32TOTNOIZ] = noizDens[BSIM3v32RDNOIZ]
                                                     + noizDens[BSIM3v32RSNOIZ]
                                                     + noizDens[BSIM3v32IDNOIZ]
                                                     + noizDens[BSIM3v32FLNOIZ];
                              lnNdens[BSIM3v32TOTNOIZ] =
                                     log(MAX(noizDens[BSIM3v32TOTNOIZ], N_MINLOG));

                              *OnDens += noizDens[BSIM3v32TOTNOIZ];

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

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

                                  /* clear out our integration variables
                                     if it's the first pass
                                   */
                                  if (data->freq ==
                                      job->NstartFreq)
                                  {   for (i = 0; i < BSIM3v32NSRCS; i++)
                                      {    here->BSIM3v32nVar[OUTNOIZ][i] = 0.0;
                                           here->BSIM3v32nVar[INNOIZ][i] = 0.0;
                                      }
                                  }
                              }
                              else
                              {   /* data->delFreq != 0.0,
                                     we have to integrate.
                                   */
                                  for (i = 0; i < BSIM3v32NSRCS; i++)
                                  {    if (i != BSIM3v32TOTNOIZ)
                                       {   tempOnoise = Nintegrate(noizDens[i],
                                                lnNdens[i],
                                                here->BSIM3v32nVar[LNLSTDENS][i],
                                                data);
                                           tempInoise = Nintegrate(noizDens[i]
                                                * data->GainSqInv, lnNdens[i]
                                                + data->lnGainInv,
                                                here->BSIM3v32nVar[LNLSTDENS][i]
                                                + data->lnGainInv, data);
                                           here->BSIM3v32nVar[LNLSTDENS][i] =
                                                lnNdens[i];
                                           data->outNoiz += tempOnoise;
                                           data->inNoise += tempInoise;
                                           if (job->NStpsSm != 0)
                                           {   here->BSIM3v32nVar[OUTNOIZ][i]
                                                     += tempOnoise;
                                               here->BSIM3v32nVar[OUTNOIZ][BSIM3v32TOTNOIZ]
                                                     += tempOnoise;
                                               here->BSIM3v32nVar[INNOIZ][i]
                                                     += tempInoise;
                                               here->BSIM3v32nVar[INNOIZ][BSIM3v32TOTNOIZ]
                                                     += tempInoise;
                                           }
                                       }
                                  }
                              }
                              if (data->prtSummary)
                              {   for (i = 0; i < BSIM3v32NSRCS; 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 < BSIM3v32NSRCS; i++)
                                  {    data->outpVector[data->outNumber++]
                                             = here->BSIM3v32nVar[OUTNOIZ][i];
                                       data->outpVector[data->outNumber++]
                                             = here->BSIM3v32nVar[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);
}
Example #16
0
int
VBICnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, Ndata *data, double *OnDens)
{
    NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

    VBICmodel *firstModel = (VBICmodel *) genmodel;
    VBICmodel *model;
    VBICinstance *inst;
    char name[N_MXVLNTH];
    double tempOnoise;
    double tempInoise;
    double noizDens[VBICNSRCS];
    double lnNdens[VBICNSRCS];
    int i;

    /* define the names of the noise sources */

    static char *VBICnNames[VBICNSRCS] = {
        /* Note that we have to keep the order consistent with the
          strchr definitions in VBICdefs.h */
        "_rc",              /* noise due to rc */
        "_rci",             /* noise due to rci */
        "_rb",              /* noise due to rb */
        "_rbi",             /* noise due to rbi */
        "_re",              /* noise due to re */
        "_rbp",             /* noise due to rbp */
        "_rs",              /* noise due to rs */
        "_ic",              /* noise due to ic */
        "_ib",              /* noise due to ib */
        "_ibep",            /* noise due to ibep */
        "_iccp",            /* noise due to iccp */
        "_1overfbe",        /* flicker (1/f) noise ibe */
        "_1overfbep",       /* flicker (1/f) noise ibep */
        ""                  /* total transistor noise */
    };

    for (model=firstModel; model != NULL; model=model->VBICnextModel) {
        for (inst=model->VBICinstances; inst != NULL;
                inst=inst->VBICnextInstance) {

            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 < VBICNSRCS; i++) {
                            (void)sprintf(name,"onoise_%s%s",
                                inst->VBICname,VBICnNames[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 < VBICNSRCS; i++) {
                            (void)sprintf(name,"onoise_total_%s%s",
                                inst->VBICname,VBICnNames[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",
                                inst->VBICname,VBICnNames[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:
                switch (mode) {

                case N_DENS:
                    NevalSrc(&noizDens[VBICRCNOIZ],&lnNdens[VBICRCNOIZ],
                                 ckt,THERMNOISE,inst->VBICcollCXNode,inst->VBICcollNode,
                                 *(ckt->CKTstate0 + inst->VBICircx_Vrcx));

                    NevalSrc(&noizDens[VBICRCINOIZ],&lnNdens[VBICRCINOIZ],
                                 ckt,THERMNOISE,inst->VBICcollCXNode,inst->VBICcollCINode,
                                 *(ckt->CKTstate0 + inst->VBICirci_Vrci));

                    NevalSrc(&noizDens[VBICRBNOIZ],&lnNdens[VBICRBNOIZ],
                                 ckt,THERMNOISE,inst->VBICbaseBXNode,inst->VBICbaseNode,
                                 *(ckt->CKTstate0 + inst->VBICirbx_Vrbx));

                    NevalSrc(&noizDens[VBICRBINOIZ],&lnNdens[VBICRBINOIZ],
                                 ckt,THERMNOISE,inst->VBICbaseBXNode,inst->VBICbaseBINode,
                                 *(ckt->CKTstate0 + inst->VBICirbi_Vrbi));

                    NevalSrc(&noizDens[VBICRENOIZ],&lnNdens[VBICRENOIZ],
                                 ckt,THERMNOISE,inst->VBICemitEINode,inst->VBICemitNode,
                                 *(ckt->CKTstate0 + inst->VBICire_Vre));

                    NevalSrc(&noizDens[VBICRBPNOIZ],&lnNdens[VBICRBPNOIZ],
                                 ckt,THERMNOISE,inst->VBICemitEINode,inst->VBICemitNode,
                                 *(ckt->CKTstate0 + inst->VBICirbp_Vrbp));

                    NevalSrc(&noizDens[VBICRSNOIZ],&lnNdens[VBICRSNOIZ],
                                 ckt,THERMNOISE,inst->VBICsubsSINode,inst->VBICsubsNode,
                                 *(ckt->CKTstate0 + inst->VBICirs_Vrs));


                    NevalSrc(&noizDens[VBICICNOIZ],&lnNdens[VBICICNOIZ],
                                 ckt,SHOTNOISE,inst->VBICcollCINode, inst->VBICemitEINode,
                                 *(ckt->CKTstate0 + inst->VBICitzf));

                    NevalSrc(&noizDens[VBICIBNOIZ],&lnNdens[VBICIBNOIZ],
                                 ckt,SHOTNOISE,inst->VBICbaseBINode, inst->VBICemitEINode,
                                 *(ckt->CKTstate0 + inst->VBICibe));

                    NevalSrc(&noizDens[VBICIBEPNOIZ],&lnNdens[VBICIBEPNOIZ],
                                 ckt,SHOTNOISE,inst->VBICbaseBXNode, inst->VBICbaseBPNode,
                                 *(ckt->CKTstate0 + inst->VBICibep));

                    NevalSrc(&noizDens[VBICICCPNOIZ],&lnNdens[VBICICCPNOIZ],
                                 ckt,SHOTNOISE,inst->VBICbaseBXNode, inst->VBICsubsSINode,
                                 *(ckt->CKTstate0 + inst->VBICiccp));


                    NevalSrc(&noizDens[VBICFLBENOIZ], NULL, ckt,
                                 N_GAIN,inst->VBICbaseBINode, inst->VBICemitEINode,
                                 (double)0.0);
                    noizDens[VBICFLBENOIZ] *= inst->VBICm * model->VBICfNcoef * 
                                 exp(model->VBICfNexpA *
                                 log(MAX(fabs(*(ckt->CKTstate0 + inst->VBICibe)/inst->VBICm),N_MINLOG))) /
                                 pow(data->freq, model->VBICfNexpB);
                    lnNdens[VBICFLBENOIZ] = 
                                 log(MAX(noizDens[VBICFLBENOIZ],N_MINLOG));

                    NevalSrc(&noizDens[VBICFLBEPNOIZ], NULL, ckt,
                                 N_GAIN,inst->VBICbaseBXNode, inst->VBICbaseBPNode,
                                 (double)0.0);
                    noizDens[VBICFLBEPNOIZ] *= inst->VBICm * model->VBICfNcoef * 
                                 exp(model->VBICfNexpA *
                                 log(MAX(fabs(*(ckt->CKTstate0 + inst->VBICibep)/inst->VBICm),N_MINLOG))) /
                                 pow(data->freq, model->VBICfNexpB);
                    lnNdens[VBICFLBEPNOIZ] = 
                                 log(MAX(noizDens[VBICFLBEPNOIZ],N_MINLOG));


                    noizDens[VBICTOTNOIZ] = noizDens[VBICRCNOIZ] +
                                            noizDens[VBICRCINOIZ] +
                                            noizDens[VBICRBNOIZ] +
                                            noizDens[VBICRBINOIZ] +
                                            noizDens[VBICRENOIZ] +
                                            noizDens[VBICRBPNOIZ] +
                                            noizDens[VBICICNOIZ] +
                                            noizDens[VBICIBNOIZ] +
                                            noizDens[VBICIBEPNOIZ] +
                                            noizDens[VBICFLBENOIZ] +
                                            noizDens[VBICFLBEPNOIZ];

                    lnNdens[VBICTOTNOIZ] = 
                                 log(noizDens[VBICTOTNOIZ]);

                    *OnDens += noizDens[VBICTOTNOIZ];

                    if (data->delFreq == 0.0) { 

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

                        for (i=0; i < VBICNSRCS; i++) {
                            inst->VBICnVar[LNLSTDENS][i] = lnNdens[i];
                        }

                        /* clear out our integration variables if it's the first pass */

                        if (data->freq == job->NstartFreq) {
                            for (i=0; i < VBICNSRCS; i++) {
                                inst->VBICnVar[OUTNOIZ][i] = 0.0;
                                inst->VBICnVar[INNOIZ][i] = 0.0;
                            }
                        }
                    } 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 < VBICNSRCS; i++) {
                            if (i != VBICTOTNOIZ) {
                                tempOnoise = Nintegrate(noizDens[i], lnNdens[i],
                                      inst->VBICnVar[LNLSTDENS][i], data);
                                tempInoise = Nintegrate(noizDens[i] * data->GainSqInv ,
                                      lnNdens[i] + data->lnGainInv,
                                      inst->VBICnVar[LNLSTDENS][i] + data->lnGainInv,
                                      data);
                                inst->VBICnVar[LNLSTDENS][i] = lnNdens[i];
                                data->outNoiz += tempOnoise;
                                data->inNoise += tempInoise;
                                if (job->NStpsSm != 0) {
                                    inst->VBICnVar[OUTNOIZ][i] += tempOnoise;
                                    inst->VBICnVar[OUTNOIZ][VBICTOTNOIZ] += tempOnoise;
                                    inst->VBICnVar[INNOIZ][i] += tempInoise;
                                    inst->VBICnVar[INNOIZ][VBICTOTNOIZ] += tempInoise;
                                }
                            }
                        }
                    }
                    if (data->prtSummary) {
                        for (i=0; i < VBICNSRCS; 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 < VBICNSRCS; i++) {
                            data->outpVector[data->outNumber++] = inst->VBICnVar[OUTNOIZ][i];
                            data->outpVector[data->outNumber++] = inst->VBICnVar[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);
}
Example #17
0
int
SWnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, Ndata *data, double *OnDens)
{
    NOISEAN *job = (NOISEAN *) ckt->CKTcurJob;

    SWmodel *firstModel = (SWmodel *) genmodel;
    SWmodel *model;
    SWinstance *inst;
    char name[N_MXVLNTH];
    double tempOutNoise;
    double tempInNoise;
    double noizDens;
    double lnNdens;
    int current_state;


    for (model=firstModel; model != NULL; model=model->SWnextModel) {
        for (inst=model->SWinstances; inst != NULL; inst=inst->SWnextInstance) {

            switch (operation) {

            case N_OPEN:

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

                if (job->NStpsSm != 0) {
                    switch (mode) {

                    case N_DENS:
                        (void)sprintf(name,"onoise_%s",inst->SWname);


                        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:
                        (void)sprintf(name,"onoise_total_%s",inst->SWname);


                        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",inst->SWname);


                        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:
                switch (mode) {

                case N_DENS:
                    current_state = (int)*(ckt->CKTstate0 + inst->SWstate);
                    NevalSrc(&noizDens,&lnNdens,ckt,THERMNOISE,
                             inst->SWposNode,inst->SWnegNode,
                             current_state?(model->SWonConduct):(model->SWoffConduct));

                    *OnDens += noizDens;

                    if (data->delFreq == 0.0) {

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

                        inst->SWnVar[LNLSTDENS] = lnNdens;

                        /* clear out our integration variable if it's the first pass */

                        if (data->freq == job->NstartFreq) {
                            inst->SWnVar[OUTNOIZ] = 0.0;
                        }
                    } else {   /* data->delFreq != 0.0 (we have to integrate) */
                        tempOutNoise = Nintegrate(noizDens, lnNdens,
                                                  inst->SWnVar[LNLSTDENS], data);
                        tempInNoise = Nintegrate(noizDens *
                                                 data->GainSqInv ,lnNdens + data->lnGainInv,
                                                 inst->SWnVar[LNLSTDENS] + data->lnGainInv,
                                                 data);
                        inst->SWnVar[OUTNOIZ] += tempOutNoise;
                        inst->SWnVar[INNOIZ] += tempInNoise;
                        data->outNoiz += tempOutNoise;
                        data->inNoise += tempInNoise;
                        inst->SWnVar[LNLSTDENS] = lnNdens;
                    }
                    if (data->prtSummary) {
                        data->outpVector[data->outNumber++] = noizDens;
                    }
                    break;

                case INT_NOIZ:        /* already calculated, just output */
                    if (job->NStpsSm != 0) {
                        data->outpVector[data->outNumber++] = inst->SWnVar[OUTNOIZ];
                        data->outpVector[data->outNumber++] = inst->SWnVar[INNOIZ];
                    }    /* 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);
}
Example #18
0
int
BJT2noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, 
           Ndata *data, double *OnDens)
{
    BJT2model *firstModel = (BJT2model *) genmodel;
    BJT2model *model;
    BJT2instance *inst;
    char name[N_MXVLNTH];
    double tempOnoise;
    double tempInoise;
    double noizDens[BJT2NSRCS];
    double lnNdens[BJT2NSRCS];
    int i;

    /* define the names of the noise sources */

    static char *BJT2nNames[BJT2NSRCS] = {       /* Note that we have to keep the order */
	"_rc",              /* noise due to rc */        /* consistent with the index definitions */
	"_rb",              /* noise due to rb */        /* in BJT2defs.h */
	"_re",              /* noise due to re */
	"_ic",              /* noise due to ic */
	"_ib",              /* noise due to ib */
	"_1overf",          /* flicker (1/f) noise */
	""                  /* total transistor noise */
    };

    for (model=firstModel; model != NULL; model=model->BJT2nextModel) {
	for (inst=model->BJT2instances; inst != NULL; inst=inst->BJT2nextInstance) {
	     if (inst->BJT2owner != 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 < BJT2NSRCS; i++) {
			    (void)sprintf(name,"onoise_%s%s",
				inst->BJT2name,BJT2nNames[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 < BJT2NSRCS; i++) {
			    (void)sprintf(name,"onoise_total_%s%s",
				inst->BJT2name,BJT2nNames[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->BJT2name,BJT2nNames[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[BJT2RCNOIZ],&lnNdens[BJT2RCNOIZ],
				 ckt,THERMNOISE,inst->BJT2colPrimeNode,inst->BJT2colNode,
				 model->BJT2collectorConduct * inst->BJT2area * inst->BJT2m);

		    NevalSrc(&noizDens[BJT2RBNOIZ],&lnNdens[BJT2RBNOIZ],
				 ckt,THERMNOISE,inst->BJT2basePrimeNode,inst->BJT2baseNode,
				 *(ckt->CKTstate0 + inst->BJT2gx) * inst->BJT2m);

		    NevalSrc(&noizDens[BJT2_RE_NOISE],&lnNdens[BJT2_RE_NOISE],
				 ckt,THERMNOISE,inst->BJT2emitPrimeNode,inst->BJT2emitNode,
				 model->BJT2emitterConduct * inst->BJT2area * inst->BJT2m);

		    NevalSrc(&noizDens[BJT2ICNOIZ],&lnNdens[BJT2ICNOIZ],
			         ckt,SHOTNOISE,inst->BJT2colPrimeNode, inst->BJT2emitPrimeNode,
				 *(ckt->CKTstate0 + inst->BJT2cc) * inst->BJT2m);

		    NevalSrc(&noizDens[BJT2IBNOIZ],&lnNdens[BJT2IBNOIZ],
				 ckt,SHOTNOISE,inst->BJT2basePrimeNode, inst->BJT2emitPrimeNode,
				 *(ckt->CKTstate0 + inst->BJT2cb) * inst->BJT2m);

		    NevalSrc(&noizDens[BJT2FLNOIZ],(double*)NULL,ckt,
				 N_GAIN,inst->BJT2basePrimeNode, inst->BJT2emitPrimeNode,
				 (double)0.0);
		    noizDens[BJT2FLNOIZ] *= inst->BJT2m * model->BJT2fNcoef * 
				 exp(model->BJT2fNexp *
				 log(MAX(fabs(*(ckt->CKTstate0 + inst->BJT2cb)),N_MINLOG))) /
				 data->freq;
		    lnNdens[BJT2FLNOIZ] = 
				 log(MAX(noizDens[BJT2FLNOIZ],N_MINLOG));

		    noizDens[BJT2TOTNOIZ] = noizDens[BJT2RCNOIZ] +
						    noizDens[BJT2RBNOIZ] +
						    noizDens[BJT2_RE_NOISE] +
						    noizDens[BJT2ICNOIZ] +
						    noizDens[BJT2IBNOIZ] +
						    noizDens[BJT2FLNOIZ];
		    lnNdens[BJT2TOTNOIZ] = 
				 log(noizDens[BJT2TOTNOIZ]);

		    *OnDens += noizDens[BJT2TOTNOIZ];

		    if (data->delFreq == 0.0) { 

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

			for (i=0; i < BJT2NSRCS; i++) {
			    inst->BJT2nVar[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 < BJT2NSRCS; i++) {
				inst->BJT2nVar[OUTNOIZ][i] = 0.0;
				inst->BJT2nVar[INNOIZ][i] = 0.0;
			    }
			}
		    } 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 < BJT2NSRCS; i++) {
			    if (i != BJT2TOTNOIZ) {
				tempOnoise = Nintegrate(noizDens[i], lnNdens[i],
				      inst->BJT2nVar[LNLSTDENS][i], data);
				tempInoise = Nintegrate(noizDens[i] * data->GainSqInv ,
				      lnNdens[i] + data->lnGainInv,
				      inst->BJT2nVar[LNLSTDENS][i] + data->lnGainInv,
				      data);
				inst->BJT2nVar[LNLSTDENS][i] = lnNdens[i];
				data->outNoiz += tempOnoise;
				data->inNoise += tempInoise;
				if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) {
				    inst->BJT2nVar[OUTNOIZ][i] += tempOnoise;
				    inst->BJT2nVar[OUTNOIZ][BJT2TOTNOIZ] += tempOnoise;
				    inst->BJT2nVar[INNOIZ][i] += tempInoise;
				    inst->BJT2nVar[INNOIZ][BJT2TOTNOIZ] += tempInoise;
                                }
			    }
			}
		    }
		    if (data->prtSummary) {
			for (i=0; i < BJT2NSRCS; 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 < BJT2NSRCS; i++) {
			    data->outpVector[data->outNumber++] = inst->BJT2nVar[OUTNOIZ][i];
			    data->outpVector[data->outNumber++] = inst->BJT2nVar[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);
}