📄 mos9load.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Thomas L. QuarlesModified: Alan Gillespie**********/#include "ngspice.h"#include "cktdefs.h"#include "devdefs.h"#include "mos9defs.h"#include "trandefs.h"#include "const.h"#include "sperror.h"#include "suffix.h"intMOS9load(GENmodel *inModel, CKTcircuit *ckt) /* actually load the current value into the * sparse matrix previously provided */{ MOS9model *model = (MOS9model *)inModel; MOS9instance *here; double Beta; double DrainSatCur; double EffectiveLength; double EffectiveWidth; double GateBulkOverlapCap; double GateDrainOverlapCap; double GateSourceOverlapCap; double OxideCap; double SourceSatCur; double arg; double cbhat; double cdhat; double cdrain; double cdreq; double ceq; double ceqbd; double ceqbs; double ceqgb; double ceqgd; double ceqgs; double delvbd; double delvbs; double delvds; double delvgd; double delvgs; double evbd; double evbs; double gcgb; double gcgd; double gcgs; double geq; double sarg; double sargsw; double vbd; double vbs; double vds; double vdsat; double vgb1; double vgb; double vgd1; double vgd; double vgdo; double vgs1; double vgs; double von; double xfact = 0.0; int xnrm; int xrev; double capgs = 0.0; /* total gate-source capacitance */ double capgd = 0.0; /* total gate-drain capacitance */ double capgb = 0.0; /* total gate-bulk capacitance */ int Check;#ifndef NOBYPASS double tempv;#endif /*NOBYPASS*/ int error;#ifdef CAPBYPASS int senflag;#endif /* CAPBYPASS */ int SenCond; double vt; /* vt at instance temperature */#ifdef CAPBYPASS senflag = 0;#endif /* CAPBYPASS */ if(ckt->CKTsenInfo){ if(ckt->CKTsenInfo->SENstatus == PERTURBATION) { if((ckt->CKTsenInfo->SENmode == ACSEN)|| (ckt->CKTsenInfo->SENmode == TRANSEN)){#ifdef CAPBYPASS senflag = 1;#endif /* CAPBYPASS */ } goto next; } } /* loop through all the MOS9 device models */next: for( ; model != NULL; model = model->MOS9nextModel ) { /* loop through all the instances of the model */ for (here = model->MOS9instances; here != NULL ; here=here->MOS9nextInstance) { if (here->MOS9owner != ARCHme) continue; vt = CONSTKoverQ * here->MOS9temp; Check=1; if(ckt->CKTsenInfo){#ifdef SENSDEBUG printf("MOS9load \n");#endif /* SENSDEBUG */ if(ckt->CKTsenInfo->SENstatus == PERTURBATION) if(here->MOS9senPertFlag == OFF)continue; } SenCond = ckt->CKTsenInfo && here->MOS9senPertFlag; /* first, we compute a few useful values - these could be * pre-computed, but for historical reasons are still done * here. They may be moved at the expense of instance size */ EffectiveWidth=here->MOS9w-2*model->MOS9widthNarrow+ model->MOS9widthAdjust; EffectiveLength=here->MOS9l - 2*model->MOS9latDiff+ model->MOS9lengthAdjust; if( (here->MOS9tSatCurDens == 0) || (here->MOS9drainArea == 0) || (here->MOS9sourceArea == 0)) { DrainSatCur = here->MOS9m * here->MOS9tSatCur; SourceSatCur = here->MOS9m * here->MOS9tSatCur; } else { DrainSatCur = here->MOS9m * here->MOS9tSatCurDens * here->MOS9drainArea; SourceSatCur = here->MOS9m * here->MOS9tSatCurDens * here->MOS9sourceArea; } GateSourceOverlapCap = model->MOS9gateSourceOverlapCapFactor * here->MOS9m * EffectiveWidth; GateDrainOverlapCap = model->MOS9gateDrainOverlapCapFactor * here->MOS9m * EffectiveWidth; GateBulkOverlapCap = model->MOS9gateBulkOverlapCapFactor * here->MOS9m * EffectiveLength; Beta = here->MOS9tTransconductance * here->MOS9m * EffectiveWidth/EffectiveLength; OxideCap = model->MOS9oxideCapFactor * EffectiveLength * here->MOS9m * EffectiveWidth; if(SenCond){#ifdef SENSDEBUG printf("MOS9senPertFlag = ON \n");#endif /* SENSDEBUG */ if((ckt->CKTsenInfo->SENmode == TRANSEN) && (ckt->CKTmode & MODEINITTRAN)) { vgs = *(ckt->CKTstate1 + here->MOS9vgs); vds = *(ckt->CKTstate1 + here->MOS9vds); vbs = *(ckt->CKTstate1 + here->MOS9vbs); vbd = *(ckt->CKTstate1 + here->MOS9vbd); vgb = vgs - vbs; vgd = vgs - vds; } else if (ckt->CKTsenInfo->SENmode == ACSEN){ vgb = model->MOS9type * ( *(ckt->CKTrhsOp+here->MOS9gNode) - *(ckt->CKTrhsOp+here->MOS9bNode)); vbs = *(ckt->CKTstate0 + here->MOS9vbs); vbd = *(ckt->CKTstate0 + here->MOS9vbd); vgd = vgb + vbd ; vgs = vgb + vbs ; vds = vbs - vbd ; } else{ vgs = *(ckt->CKTstate0 + here->MOS9vgs); vds = *(ckt->CKTstate0 + here->MOS9vds); vbs = *(ckt->CKTstate0 + here->MOS9vbs); vbd = *(ckt->CKTstate0 + here->MOS9vbd); vgb = vgs - vbs; vgd = vgs - vds; }#ifdef SENSDEBUG printf(" vbs = %.7e ,vbd = %.7e,vgb = %.7e\n",vbs,vbd,vgb); printf(" vgs = %.7e ,vds = %.7e,vgd = %.7e\n",vgs,vds,vgd);#endif /* SENSDEBUG */ goto next1; } /* * ok - now to do the start-up operations * * we must get values for vbs, vds, and vgs from somewhere * so we either predict them or recover them from last iteration * These are the two most common cases - either a prediction * step or the general iteration step and they * share some code, so we put them first - others later on */ if((ckt->CKTmode & (MODEINITFLOAT | MODEINITPRED | MODEINITSMSIG | MODEINITTRAN)) || ( (ckt->CKTmode & MODEINITFIX) && (!here->MOS9off) ) ) {#ifndef PREDICTOR if(ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) { /* predictor step */ xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; *(ckt->CKTstate0 + here->MOS9vbs) = *(ckt->CKTstate1 + here->MOS9vbs); vbs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS9vbs)) -(xfact * (*(ckt->CKTstate2 + here->MOS9vbs))); *(ckt->CKTstate0 + here->MOS9vgs) = *(ckt->CKTstate1 + here->MOS9vgs); vgs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS9vgs)) -(xfact * (*(ckt->CKTstate2 + here->MOS9vgs))); *(ckt->CKTstate0 + here->MOS9vds) = *(ckt->CKTstate1 + here->MOS9vds); vds = (1+xfact)* (*(ckt->CKTstate1 + here->MOS9vds)) -(xfact * (*(ckt->CKTstate2 + here->MOS9vds))); *(ckt->CKTstate0 + here->MOS9vbd) = *(ckt->CKTstate0 + here->MOS9vbs)- *(ckt->CKTstate0 + here->MOS9vds); } else {#endif /*PREDICTOR*/ /* general iteration */ vbs = model->MOS9type * ( *(ckt->CKTrhsOld+here->MOS9bNode) - *(ckt->CKTrhsOld+here->MOS9sNodePrime)); vgs = model->MOS9type * ( *(ckt->CKTrhsOld+here->MOS9gNode) - *(ckt->CKTrhsOld+here->MOS9sNodePrime)); vds = model->MOS9type * ( *(ckt->CKTrhsOld+here->MOS9dNodePrime) - *(ckt->CKTrhsOld+here->MOS9sNodePrime));#ifndef PREDICTOR }#endif /*PREDICTOR*/ /* now some common crunching for some more useful quantities */ vbd=vbs-vds; vgd=vgs-vds; vgdo = *(ckt->CKTstate0 + here->MOS9vgs) - *(ckt->CKTstate0 + here->MOS9vds); delvbs = vbs - *(ckt->CKTstate0 + here->MOS9vbs); delvbd = vbd - *(ckt->CKTstate0 + here->MOS9vbd); delvgs = vgs - *(ckt->CKTstate0 + here->MOS9vgs); delvds = vds - *(ckt->CKTstate0 + here->MOS9vds); delvgd = vgd-vgdo; /* these are needed for convergence testing */ if (here->MOS9mode >= 0) { cdhat= here->MOS9cd- here->MOS9gbd * delvbd + here->MOS9gmbs * delvbs + here->MOS9gm * delvgs + here->MOS9gds * delvds ; } else { cdhat= here->MOS9cd - ( here->MOS9gbd - here->MOS9gmbs) * delvbd - here->MOS9gm * delvgd + here->MOS9gds * delvds ; } cbhat= here->MOS9cbs + here->MOS9cbd + here->MOS9gbd * delvbd + here->MOS9gbs * delvbs ;#ifndef NOBYPASS /* now lets see if we can bypass (ugh) */ /* the following mess should be one if statement, but * many compilers can't handle it all at once, so it * is split into several successive if statements */ tempv = MAX(fabs(cbhat),fabs(here->MOS9cbs + here->MOS9cbd))+ckt->CKTabstol; if((!(ckt->CKTmode & (MODEINITPRED|MODEINITTRAN|MODEINITSMSIG) )) && (ckt->CKTbypass) ) if ( (fabs(cbhat-(here->MOS9cbs + here->MOS9cbd)) < ckt->CKTreltol * tempv)) if( (fabs(delvbs) < (ckt->CKTreltol * MAX(fabs(vbs), fabs(*(ckt->CKTstate0+here->MOS9vbs)))+ ckt->CKTvoltTol))) if ( (fabs(delvbd) < (ckt->CKTreltol * MAX(fabs(vbd), fabs(*(ckt->CKTstate0+here->MOS9vbd)))+ ckt->CKTvoltTol)) ) if( (fabs(delvgs) < (ckt->CKTreltol * MAX(fabs(vgs), fabs(*(ckt->CKTstate0+here->MOS9vgs)))+ ckt->CKTvoltTol))) if ( (fabs(delvds) < (ckt->CKTreltol * MAX(fabs(vds), fabs(*(ckt->CKTstate0+here->MOS9vds)))+ ckt->CKTvoltTol)) ) if( (fabs(cdhat- here->MOS9cd) < ckt->CKTreltol * MAX(fabs(cdhat),fabs( here->MOS9cd)) + ckt->CKTabstol) ) { /* bypass code * * nothing interesting has changed since last * iteration on this device, so we just * copy all the values computed last iteration out * and keep going */ vbs = *(ckt->CKTstate0 + here->MOS9vbs); vbd = *(ckt->CKTstate0 + here->MOS9vbd); vgs = *(ckt->CKTstate0 + here->MOS9vgs); vds = *(ckt->CKTstate0 + here->MOS9vds); vgd = vgs - vds; vgb = vgs - vbs; cdrain = here->MOS9mode * (here->MOS9cd + here->MOS9cbd); if(ckt->CKTmode & (MODETRAN | MODETRANOP)) { capgs = ( *(ckt->CKTstate0+here->MOS9capgs)+ *(ckt->CKTstate1+here->MOS9capgs) +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -