hsm1noi.c
来自「ngspice又一个电子CAD仿真软件代码.功能更全」· C语言 代码 · 共 282 行
C
282 行
/*********************************************************************** HiSIM (Hiroshima University STARC IGFET Model) Copyright (C) 2003 STARC VERSION : HiSIM 1.2.0 FILE : hsm1noi.c of HiSIM 1.2.0 April 9, 2003 : released by STARC Physical Design Group***********************************************************************/#include "ngspice.h"#include "hsm1def.h"#include "cktdefs.h"#include "iferrmsg.h"#include "noisedef.h"#include "suffix.h"#include "const.h" /* jwan *//* * HSM1noise (mode, operation, firstModel, ckt, data, OnDens) * This routine names and evaluates all of the noise sources * associated with MOSFET's. It starts with the model *firstModel and * traverses all of its insts. It then proceeds to any other models * on the linked list. The total output noise density generated by * all of the MOSFET's is summed with the variable "OnDens". *//* Channel thermal and flicker noises are calculated based on the value of model->HSM1_noise. If model->HSM1_noise = 1, Channel thermal noise = SPICE2 model Flicker noise = SPICE2 model If model->HSM1_noise = 2, Channel thermal noise = HiSIM1 model corresponding to BSIM3 model Flicker noise = HiSIM1 model If model->HSM1_noise = 3, Channel thermal noise = SPICE2 model Flicker noise = HiSIM1 model If model->HSM1_noise = 4, Channel thermal noise = HiSIM1 model corresponding to BSIM3 model Flicker noise = SPICE2 model If model->HSM1_noise = 5, Channel thermal noise = NONE Flicker noise = HiSIM1 model */extern void NevalSrc();extern double Nintegrate();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);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?