📄 mos1load.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Thomas L. Quarles**********/#include "spice.h"#include <stdio.h>#include "cktdefs.h"#include "devdefs.h"#include "mos1defs.h"#include "util.h"#include "trandefs.h"#include "const.h"#include "sperror.h"#include "suffix.h"intMOS1load(inModel,ckt) GENmodel *inModel; register CKTcircuit *ckt; /* actually load the current value into the * sparse matrix previously provided */{ register MOS1model *model = (MOS1model *) inModel; register MOS1instance *here; double Beta; double DrainSatCur; double EffectiveLength; 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 tol; 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 vt; double xfact; int xnrm; int xrev; double capgs; /* total gate-source capacitance */ double capgd; /* total gate-drain capacitance */ double capgb; /* total gate-bulk capacitance */ int Check;#ifndef NOBYPASS double tempv;#endif /*NOBYPASS*/ int error;#ifdef CAPBYPASS int senflag;#endif /* CAPBYPASS */ int SenCond;#ifdef CAPBYPASS senflag = 0; if(ckt->CKTsenInfo && ckt->CKTsenInfo->SENstatus == PERTURBATION && (ckt->CKTsenInfo->SENmode & (ACSEN | TRANSEN))) { senflag = 1; }#endif /* CAPBYPASS */ /* loop through all the MOS1 device models */ for( ; model != NULL; model = model->MOS1nextModel ) { /* loop through all the instances of the model */ for (here = model->MOS1instances; here != NULL ; here=here->MOS1nextInstance) { if (here->MOS1owner != ARCHme) continue; vt = CONSTKoverQ * here->MOS1temp; Check=1; if(ckt->CKTsenInfo){#ifdef SENSDEBUG printf("MOS1load \n");#endif /* SENSDEBUG */ if((ckt->CKTsenInfo->SENstatus == PERTURBATION)&& (here->MOS1senPertFlag == OFF))continue; } SenCond = ckt->CKTsenInfo && here->MOS1senPertFlag;/**/#ifdef DETAILPROFasm(" .globl mospta");asm("mospta:");#endif /*DETAILPROF*/ /* 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 */ EffectiveLength=here->MOS1l - 2*model->MOS1latDiff; if( (here->MOS1tSatCurDens == 0) || (here->MOS1drainArea == 0) || (here->MOS1sourceArea == 0)) { DrainSatCur = here->MOS1tSatCur; SourceSatCur = here->MOS1tSatCur; } else { DrainSatCur = here->MOS1tSatCurDens * here->MOS1drainArea; SourceSatCur = here->MOS1tSatCurDens * here->MOS1sourceArea; } GateSourceOverlapCap = model->MOS1gateSourceOverlapCapFactor * here->MOS1w; GateDrainOverlapCap = model->MOS1gateDrainOverlapCapFactor * here->MOS1w; GateBulkOverlapCap = model->MOS1gateBulkOverlapCapFactor * EffectiveLength; Beta = here->MOS1tTransconductance * here->MOS1w/EffectiveLength; OxideCap = model->MOS1oxideCapFactor * EffectiveLength * here->MOS1w; /* * 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(SenCond){#ifdef SENSDEBUG printf("MOS1senPertFlag = ON \n");#endif /* SENSDEBUG */ if((ckt->CKTsenInfo->SENmode == TRANSEN) && (ckt->CKTmode & MODEINITTRAN)) { vgs = *(ckt->CKTstate1 + here->MOS1vgs); vds = *(ckt->CKTstate1 + here->MOS1vds); vbs = *(ckt->CKTstate1 + here->MOS1vbs); vbd = *(ckt->CKTstate1 + here->MOS1vbd); vgb = vgs - vbs; vgd = vgs - vds; } else if (ckt->CKTsenInfo->SENmode == ACSEN){ vgb = model->MOS1type * ( *(ckt->CKTrhsOp+here->MOS1gNode) - *(ckt->CKTrhsOp+here->MOS1bNode)); vbs = *(ckt->CKTstate0 + here->MOS1vbs); vbd = *(ckt->CKTstate0 + here->MOS1vbd); vgd = vgb + vbd ; vgs = vgb + vbs ; vds = vbs - vbd ; } else{ vgs = *(ckt->CKTstate0 + here->MOS1vgs); vds = *(ckt->CKTstate0 + here->MOS1vds); vbs = *(ckt->CKTstate0 + here->MOS1vbs); vbd = *(ckt->CKTstate0 + here->MOS1vbd); 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; } if((ckt->CKTmode & (MODEINITFLOAT | MODEINITPRED | MODEINITSMSIG | MODEINITTRAN)) || ( (ckt->CKTmode & MODEINITFIX) && (!here->MOS1off) ) ) {#ifndef PREDICTOR if(ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) { /* predictor step */ xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; *(ckt->CKTstate0 + here->MOS1vbs) = *(ckt->CKTstate1 + here->MOS1vbs); vbs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS1vbs)) -(xfact * (*(ckt->CKTstate2 + here->MOS1vbs))); *(ckt->CKTstate0 + here->MOS1vgs) = *(ckt->CKTstate1 + here->MOS1vgs); vgs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS1vgs)) -(xfact * (*(ckt->CKTstate2 + here->MOS1vgs))); *(ckt->CKTstate0 + here->MOS1vds) = *(ckt->CKTstate1 + here->MOS1vds); vds = (1+xfact)* (*(ckt->CKTstate1 + here->MOS1vds)) -(xfact * (*(ckt->CKTstate2 + here->MOS1vds))); *(ckt->CKTstate0 + here->MOS1vbd) = *(ckt->CKTstate0 + here->MOS1vbs)- *(ckt->CKTstate0 + here->MOS1vds); } else {#endif /* PREDICTOR */ /* general iteration */ vbs = model->MOS1type * ( *(ckt->CKTrhsOld+here->MOS1bNode) - *(ckt->CKTrhsOld+here->MOS1sNodePrime)); vgs = model->MOS1type * ( *(ckt->CKTrhsOld+here->MOS1gNode) - *(ckt->CKTrhsOld+here->MOS1sNodePrime)); vds = model->MOS1type * ( *(ckt->CKTrhsOld+here->MOS1dNodePrime) - *(ckt->CKTrhsOld+here->MOS1sNodePrime));#ifndef PREDICTOR }#endif /* PREDICTOR */ /* now some common crunching for some more useful quantities */ vbd=vbs-vds; vgd=vgs-vds; vgdo = *(ckt->CKTstate0 + here->MOS1vgs) - *(ckt->CKTstate0 + here->MOS1vds); delvbs = vbs - *(ckt->CKTstate0 + here->MOS1vbs); delvbd = vbd - *(ckt->CKTstate0 + here->MOS1vbd); delvgs = vgs - *(ckt->CKTstate0 + here->MOS1vgs); delvds = vds - *(ckt->CKTstate0 + here->MOS1vds); delvgd = vgd-vgdo; /* these are needed for convergence testing */ if (here->MOS1mode >= 0) { cdhat= here->MOS1cd- here->MOS1gbd * delvbd + here->MOS1gmbs * delvbs + here->MOS1gm * delvgs + here->MOS1gds * delvds ; } else { cdhat= here->MOS1cd - ( here->MOS1gbd - here->MOS1gmbs) * delvbd - here->MOS1gm * delvgd + here->MOS1gds * delvds ; } cbhat= here->MOS1cbs + here->MOS1cbd + here->MOS1gbd * delvbd + here->MOS1gbs * delvbs ;/**/#ifdef DETAILPROFasm(" .globl mosptb");asm("mosptb:");#endif /*DETAILPROF*/#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->MOS1cbs + here->MOS1cbd))+ckt->CKTabstol; if((!(ckt->CKTmode & (MODEINITPRED|MODEINITTRAN|MODEINITSMSIG) )) && (ckt->CKTbypass) ) if ( (FABS(cbhat-(here->MOS1cbs + here->MOS1cbd)) < ckt->CKTreltol * tempv)) if( (FABS(delvbs) < (ckt->CKTreltol * MAX(FABS(vbs), FABS(*(ckt->CKTstate0+here->MOS1vbs)))+ ckt->CKTvoltTol))) if ( (FABS(delvbd) < (ckt->CKTreltol * MAX(FABS(vbd), FABS(*(ckt->CKTstate0+here->MOS1vbd)))+ ckt->CKTvoltTol)) ) if( (FABS(delvgs) < (ckt->CKTreltol * MAX(FABS(vgs), FABS(*(ckt->CKTstate0+here->MOS1vgs)))+ ckt->CKTvoltTol))) if ( (FABS(delvds) < (ckt->CKTreltol * MAX(FABS(vds), FABS(*(ckt->CKTstate0+here->MOS1vds)))+ ckt->CKTvoltTol)) ) if( (FABS(cdhat- here->MOS1cd) < ckt->CKTreltol * MAX(FABS(cdhat),FABS( here->MOS1cd)) + 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->MOS1vbs); vbd = *(ckt->CKTstate0 + here->MOS1vbd); vgs = *(ckt->CKTstate0 + here->MOS1vgs); vds = *(ckt->CKTstate0 + here->MOS1vds); vgd = vgs - vds; vgb = vgs - vbs; cdrain = here->MOS1mode * (here->MOS1cd + here->MOS1cbd); if(ckt->CKTmode & (MODETRAN | MODETRANOP)) { capgs = ( *(ckt->CKTstate0+here->MOS1capgs)+ *(ckt->CKTstate1+here->MOS1capgs) + GateSourceOverlapCap ); capgd = ( *(ckt->CKTstate0+here->MOS1capgd)+ *(ckt->CKTstate1+here->MOS1capgd) + GateDrainOverlapCap ); capgb = ( *(ckt->CKTstate0+here->MOS1capgb)+ *(ckt->CKTstate1+here->MOS1capgb) + GateBulkOverlapCap ); if(ckt->CKTsenInfo){ here->MOS1cgs = capgs; here->MOS1cgd = capgd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -