📄 mos2load.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Thomas L. Quarles**********/#include "spice.h"#include <stdio.h>#include "util.h"#include "devdefs.h"#include "cktdefs.h"#include "mos2defs.h"#include "trandefs.h"#include "const.h"#include "sperror.h"#include "suffix.h"/* assuming silicon - make definition for epsilon of silicon */#define EPSSIL (11.7 * 8.854214871e-12)static double sig1[4] = {1.0, -1.0, 1.0, -1.0};static double sig2[4] = {1.0, 1.0,-1.0, -1.0};intMOS2load(inModel,ckt) GENmodel *inModel; register CKTcircuit *ckt; /* actually load the current value into the * sparse matrix previously provided */{ register MOS2model *model = (MOS2model *)inModel; register MOS2instance *here; int error; 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; /* K * T / Q */ double xfact; double capgs; /* total gate-source capacitance */ double capgd; /* total gate-drain capacitance */ double capgb; /* total gate-bulk capacitance */ int xnrm; int xrev; int Check;#ifndef NOBYPASS double tempv;#endif /*NOBYPASS*/#ifdef CAPBYPASS int senflag;#endif /* CAPBYPASS */ int SenCond=0;#ifdef CAPBYPASS senflag = 0; if(ckt->CKTsenInfo){ if(ckt->CKTsenInfo->SENstatus == PERTURBATION){ if((ckt->CKTsenInfo->SENmode == ACSEN)|| (ckt->CKTsenInfo->SENmode == TRANSEN)){ senflag = 1; } } }#endif /* CAPBYPASS */ /* loop through all the MOS2 device models */ for( ; model != NULL; model = model->MOS2nextModel ) { /* loop through all the instances of the model */ for (here = model->MOS2instances; here != NULL ; here=here->MOS2nextInstance) { if (here->MOS2owner != ARCHme) continue; vt = CONSTKoverQ * here->MOS2temp; Check=1; if(ckt->CKTsenInfo){#ifdef SENSDEBUG printf("MOS2load %s\n",here->MOS2name);#endif /* SENSDEBUG */ if(ckt->CKTsenInfo->SENstatus == PERTURBATION) { if(here->MOS2senPertFlag == OFF)continue; } SenCond = here->MOS2senPertFlag; } EffectiveLength=here->MOS2l - 2*model->MOS2latDiff; if( (here->MOS2tSatCurDens == 0) || (here->MOS2drainArea == 0) || (here->MOS2sourceArea == 0)) { DrainSatCur = here->MOS2tSatCur; SourceSatCur = here->MOS2tSatCur; } else { DrainSatCur = here->MOS2tSatCurDens * here->MOS2drainArea; SourceSatCur = here->MOS2tSatCurDens * here->MOS2sourceArea; } GateSourceOverlapCap = model->MOS2gateSourceOverlapCapFactor * here->MOS2w; GateDrainOverlapCap = model->MOS2gateDrainOverlapCapFactor * here->MOS2w; GateBulkOverlapCap = model->MOS2gateBulkOverlapCapFactor * EffectiveLength; Beta = here->MOS2tTransconductance * here->MOS2w/EffectiveLength; OxideCap = model->MOS2oxideCapFactor * EffectiveLength * here->MOS2w; if(SenCond){#ifdef SENSDEBUG printf("MOS2senPertFlag = ON \n");#endif /* SENSDEBUG */ if((ckt->CKTsenInfo->SENmode == TRANSEN) && (ckt->CKTmode & MODEINITTRAN)) { vgs = *(ckt->CKTstate1 + here->MOS2vgs); vds = *(ckt->CKTstate1 + here->MOS2vds); vbs = *(ckt->CKTstate1 + here->MOS2vbs); vbd = *(ckt->CKTstate1 + here->MOS2vbd); vgb = vgs - vbs; vgd = vgs - vds; } else if (ckt->CKTsenInfo->SENmode == ACSEN){ vgb = model->MOS2type * ( *(ckt->CKTrhsOp+here->MOS2gNode) - *(ckt->CKTrhsOp+here->MOS2bNode)); vbs = *(ckt->CKTstate0 + here->MOS2vbs); vbd = *(ckt->CKTstate0 + here->MOS2vbd); vgd = vgb + vbd ; vgs = vgb + vbs ; vds = vbs - vbd ; } else{ vgs = *(ckt->CKTstate0 + here->MOS2vgs); vds = *(ckt->CKTstate0 + here->MOS2vds); vbs = *(ckt->CKTstate0 + here->MOS2vbs); vbd = *(ckt->CKTstate0 + here->MOS2vbd); 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->MOS2off) ) ) {#ifndef PREDICTOR if(ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) { /* predictor step */ xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; *(ckt->CKTstate0 + here->MOS2vbs) = *(ckt->CKTstate1 + here->MOS2vbs); vbs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS2vbs)) -(xfact * (*(ckt->CKTstate2 + here->MOS2vbs))); *(ckt->CKTstate0 + here->MOS2vgs) = *(ckt->CKTstate1 + here->MOS2vgs); vgs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS2vgs)) -(xfact * (*(ckt->CKTstate2 + here->MOS2vgs))); *(ckt->CKTstate0 + here->MOS2vds) = *(ckt->CKTstate1 + here->MOS2vds); vds = (1+xfact)* (*(ckt->CKTstate1 + here->MOS2vds)) -(xfact * (*(ckt->CKTstate2 + here->MOS2vds))); *(ckt->CKTstate0 + here->MOS2vbd) = *(ckt->CKTstate0 + here->MOS2vbs)- *(ckt->CKTstate0 + here->MOS2vds); } else {#endif /* PREDICTOR */ /* general iteration */ vbs = model->MOS2type * ( *(ckt->CKTrhsOld+here->MOS2bNode) - *(ckt->CKTrhsOld+here->MOS2sNodePrime)); vgs = model->MOS2type * ( *(ckt->CKTrhsOld+here->MOS2gNode) - *(ckt->CKTrhsOld+here->MOS2sNodePrime)); vds = model->MOS2type * ( *(ckt->CKTrhsOld+here->MOS2dNodePrime) - *(ckt->CKTrhsOld+here->MOS2sNodePrime));#ifndef PREDICTOR }#endif /* PREDICTOR */ /* now some common crunching for some more useful quantities */ vbd=vbs-vds; vgd=vgs-vds; vgdo = *(ckt->CKTstate0 + here->MOS2vgs) - *(ckt->CKTstate0 + here->MOS2vds); delvbs = vbs - *(ckt->CKTstate0 + here->MOS2vbs); delvbd = vbd - *(ckt->CKTstate0 + here->MOS2vbd); delvgs = vgs - *(ckt->CKTstate0 + here->MOS2vgs); delvds = vds - *(ckt->CKTstate0 + here->MOS2vds); delvgd = vgd-vgdo; /* these are needed for convergence testing */ if (here->MOS2mode >= 0) { cdhat= here->MOS2cd - here->MOS2gbd * delvbd + here->MOS2gmbs * delvbs + here->MOS2gm * delvgs + here->MOS2gds * delvds ; } else { cdhat= here->MOS2cd + ( here->MOS2gmbs - here->MOS2gbd) * delvbd - here->MOS2gm * delvgd + here->MOS2gds * delvds ; } cbhat= here->MOS2cbs + here->MOS2cbd + here->MOS2gbd * delvbd + here->MOS2gbs * delvbs ; /* now lets see if we can bypass (ugh) */ /* the following massive if should all be one * single compound if statement, but most compilers * can't handle it in one piece, so it is broken up * into several stages here */#ifndef NOBYPASS tempv = MAX(FABS(cbhat),FABS(here->MOS2cbs+here->MOS2cbd))+ ckt->CKTabstol; if((!(ckt->CKTmode & (MODEINITPRED|MODEINITTRAN|MODEINITSMSIG) )) && (ckt->CKTbypass) ) if ( (FABS(cbhat-(here->MOS2cbs + here->MOS2cbd)) < ckt->CKTreltol * tempv)) if( (FABS(delvbs) < (ckt->CKTreltol * MAX(FABS(vbs), FABS(*(ckt->CKTstate0+here->MOS2vbs)))+ ckt->CKTvoltTol))) if ( (FABS(delvbd) < (ckt->CKTreltol * MAX(FABS(vbd), FABS(*(ckt->CKTstate0+here->MOS2vbd)))+ ckt->CKTvoltTol)) ) if( (FABS(delvgs) < (ckt->CKTreltol * MAX(FABS(vgs), FABS(*(ckt->CKTstate0+here->MOS2vgs)))+ ckt->CKTvoltTol)) ) if ( (FABS(delvds) < (ckt->CKTreltol * MAX(FABS(vds), FABS(*(ckt->CKTstate0+here->MOS2vds)))+ ckt->CKTvoltTol)) ) if( (FABS(cdhat- here->MOS2cd) < ckt->CKTreltol * MAX(FABS(cdhat),FABS( here->MOS2cd)) + 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->MOS2vbs); vbd = *(ckt->CKTstate0 + here->MOS2vbd); vgs = *(ckt->CKTstate0 + here->MOS2vgs); vds = *(ckt->CKTstate0 + here->MOS2vds); vgd = vgs - vds; vgb = vgs - vbs; cdrain = here->MOS2mode * (here->MOS2cd + here->MOS2cbd); if(ckt->CKTmode & (MODETRAN | MODETRANOP)) { capgs = ( *(ckt->CKTstate0 + here->MOS2capgs)+ *(ckt->CKTstate1 + here->MOS2capgs)+ GateSourceOverlapCap ); capgd = ( *(ckt->CKTstate0 + here->MOS2capgd)+ *(ckt->CKTstate1 + here->MOS2capgd)+ GateDrainOverlapCap ); capgb = ( *(ckt->CKTstate0 + here->MOS2capgb)+ *(ckt->CKTstate1 + here->MOS2capgb)+ GateBulkOverlapCap ); if(ckt->CKTsenInfo){ here->MOS2cgs = capgs; here->MOS2cgd = capgd; here->MOS2cgb = capgb; } } goto bypass; }#endif /*NOBYPASS*/ /* ok - bypass is out, do it the hard way */ von = model->MOS2type * here->MOS2von; /* * limiting * We want to keep device voltages from changing * so fast that the exponentials churn out overflows * and similar rudeness */ if(*(ckt->CKTstate0 + here->MOS2vds) >=0) { vgs = DEVfetlim(vgs,*(ckt->CKTstate0 + here->MOS2vgs) ,von); vds = vgs - vgd; vds = DEVlimvds(vds,*(ckt->CKTstate0 + here->MOS2vds)); vgd = vgs - vds; } else { vgd = DEVfetlim(vgd,vgdo,von); vds = vgs - vgd; if(!(ckt->CKTfixLimit)) { vds = -DEVlimvds(-vds,-(*(ckt->CKTstate0 + here->MOS2vds))); } vgs = vgd + vds; } if(vds >= 0) { vbs = DEVpnjlim(vbs,*(ckt->CKTstate0 + here->MOS2vbs),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -