mos3load.c
来自「ngspice又一个电子CAD仿真软件代码.功能更全」· C语言 代码 · 共 1,286 行 · 第 1/3 页
C
1,286 行
here->MOS3gm = 0.0; here->MOS3gds = Beta*(vgsx-vth); here->MOS3gmbs = 0.0; if ( (model->MOS3fastSurfaceStateDensity != 0.0) && ((here->MOS3mode==1?vgs:vgd) < von) ) { here->MOS3gds *=exp(((here->MOS3mode==1?vgs:vgd)-von)/(vt*xn)); }innerline1000:; /* *.....done */ } /* now deal with n vs p polarity */ here->MOS3von = model->MOS3type * von; here->MOS3vdsat = model->MOS3type * vdsat; /* line 490 */ /* * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE */ here->MOS3cd=here->MOS3mode * cdrain - here->MOS3cbd; if (ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG)) { /* * now we do the hard part of the bulk-drain and bulk-source * diode - we evaluate the non-linear capacitance and * charge * * the basic equations are not hard, but the implementation * is somewhat long in an attempt to avoid log/exponential * evaluations */ /* * charge storage elements * *.. bulk-drain and bulk-source depletion capacitances */#ifdef CAPBYPASS if(((ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) || fabs(delvbs) >= ckt->CKTreltol * MAX(fabs(vbs), fabs(*(ckt->CKTstate0+here->MOS3vbs)))+ ckt->CKTvoltTol)|| senflag )#endif /*CAPBYPASS*/ { /* can't bypass the diode capacitance calculations */#ifdef CAPZEROBYPASS if(here->MOS3Cbs != 0 || here->MOS3Cbssw != 0 ) {#endif /*CAPZEROBYPASS*/ if (vbs < here->MOS3tDepCap){ arg=1-vbs/here->MOS3tBulkPot; /* * the following block looks somewhat long and messy, * but since most users use the default grading * coefficients of .5, and sqrt is MUCH faster than an * exp(log()) we use this special case code to buy time. * (as much as 10% of total job time!) */#ifndef NOSQRT if(model->MOS3bulkJctBotGradingCoeff == model->MOS3bulkJctSideGradingCoeff) { if(model->MOS3bulkJctBotGradingCoeff == .5) { sarg = sargsw = 1/sqrt(arg); } else { sarg = sargsw = exp(-model->MOS3bulkJctBotGradingCoeff* log(arg)); } } else { if(model->MOS3bulkJctBotGradingCoeff == .5) { sarg = 1/sqrt(arg); } else {#endif /*NOSQRT*/ sarg = exp(-model->MOS3bulkJctBotGradingCoeff* log(arg));#ifndef NOSQRT } if(model->MOS3bulkJctSideGradingCoeff == .5) { sargsw = 1/sqrt(arg); } else {#endif /*NOSQRT*/ sargsw =exp(-model->MOS3bulkJctSideGradingCoeff* log(arg));#ifndef NOSQRT } }#endif /*NOSQRT*/ *(ckt->CKTstate0 + here->MOS3qbs) = here->MOS3tBulkPot*(here->MOS3Cbs* (1-arg*sarg)/(1-model->MOS3bulkJctBotGradingCoeff) +here->MOS3Cbssw* (1-arg*sargsw)/ (1-model->MOS3bulkJctSideGradingCoeff)); here->MOS3capbs=here->MOS3Cbs*sarg+ here->MOS3Cbssw*sargsw; } else { *(ckt->CKTstate0 + here->MOS3qbs) = here->MOS3f4s + vbs*(here->MOS3f2s+vbs*(here->MOS3f3s/2)); here->MOS3capbs=here->MOS3f2s+here->MOS3f3s*vbs; }#ifdef CAPZEROBYPASS } else { *(ckt->CKTstate0 + here->MOS3qbs) = 0; here->MOS3capbs=0; }#endif /*CAPZEROBYPASS*/ }#ifdef CAPBYPASS if(((ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) || fabs(delvbd) >= ckt->CKTreltol * MAX(fabs(vbd), fabs(*(ckt->CKTstate0+here->MOS3vbd)))+ ckt->CKTvoltTol)|| senflag )#endif /*CAPBYPASS*/ /* can't bypass the diode capacitance calculations */ {#ifdef CAPZEROBYPASS if(here->MOS3Cbd != 0 || here->MOS3Cbdsw != 0 ) {#endif /*CAPZEROBYPASS*/ if (vbd < here->MOS3tDepCap) { arg=1-vbd/here->MOS3tBulkPot; /* * the following block looks somewhat long and messy, * but since most users use the default grading * coefficients of .5, and sqrt is MUCH faster than an * exp(log()) we use this special case code to buy time. * (as much as 10% of total job time!) */#ifndef NOSQRT if(model->MOS3bulkJctBotGradingCoeff == .5 && model->MOS3bulkJctSideGradingCoeff == .5) { sarg = sargsw = 1/sqrt(arg); } else { if(model->MOS3bulkJctBotGradingCoeff == .5) { sarg = 1/sqrt(arg); } else {#endif /*NOSQRT*/ sarg = exp(-model->MOS3bulkJctBotGradingCoeff* log(arg));#ifndef NOSQRT } if(model->MOS3bulkJctSideGradingCoeff == .5) { sargsw = 1/sqrt(arg); } else {#endif /*NOSQRT*/ sargsw =exp(-model->MOS3bulkJctSideGradingCoeff* log(arg));#ifndef NOSQRT } }#endif /*NOSQRT*/ *(ckt->CKTstate0 + here->MOS3qbd) = here->MOS3tBulkPot*(here->MOS3Cbd* (1-arg*sarg) /(1-model->MOS3bulkJctBotGradingCoeff) +here->MOS3Cbdsw* (1-arg*sargsw) /(1-model->MOS3bulkJctSideGradingCoeff)); here->MOS3capbd=here->MOS3Cbd*sarg+ here->MOS3Cbdsw*sargsw; } else { *(ckt->CKTstate0 + here->MOS3qbd) = here->MOS3f4d + vbd * (here->MOS3f2d + vbd * here->MOS3f3d/2); here->MOS3capbd=here->MOS3f2d + vbd * here->MOS3f3d; }#ifdef CAPZEROBYPASS } else { *(ckt->CKTstate0 + here->MOS3qbd) = 0; here->MOS3capbd = 0; }#endif /*CAPZEROBYPASS*/ } if(SenCond && (ckt->CKTsenInfo->SENmode==TRANSEN)) goto next2; if ( ckt->CKTmode & MODETRAN ) { /* (above only excludes tranop, since we're only at this * point if tran or tranop ) */ /* * calculate equivalent conductances and currents for * depletion capacitors */ /* integrate the capacitors and save results */ error = NIintegrate(ckt,&geq,&ceq,here->MOS3capbd, here->MOS3qbd); if(error) return(error); here->MOS3gbd += geq; here->MOS3cbd += *(ckt->CKTstate0 + here->MOS3cqbd); here->MOS3cd -= *(ckt->CKTstate0 + here->MOS3cqbd); error = NIintegrate(ckt,&geq,&ceq,here->MOS3capbs, here->MOS3qbs); if(error) return(error); here->MOS3gbs += geq; here->MOS3cbs += *(ckt->CKTstate0 + here->MOS3cqbs); } } if(SenCond) goto next2; /* * check convergence */ if ( (here->MOS3off == 0) || (!(ckt->CKTmode & (MODEINITFIX|MODEINITSMSIG))) ){ if (Check == 1) { ckt->CKTnoncon++; ckt->CKTtroubleElt = (GENinstance *) here; } } /* save things away for next time */ next2: *(ckt->CKTstate0 + here->MOS3vbs) = vbs; *(ckt->CKTstate0 + here->MOS3vbd) = vbd; *(ckt->CKTstate0 + here->MOS3vgs) = vgs; *(ckt->CKTstate0 + here->MOS3vds) = vds; /* * meyer's capacitor model */ if ( ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG) ) { /* * calculate meyer's capacitors */ /* * new cmeyer - this just evaluates at the current time, * expects you to remember values from previous time * returns 1/2 of non-constant portion of capacitance * you must add in the other half from previous time * and the constant part */ if (here->MOS3mode > 0){ DEVqmeyer (vgs,vgd,vgb,von,vdsat, (ckt->CKTstate0 + here->MOS3capgs), (ckt->CKTstate0 + here->MOS3capgd), (ckt->CKTstate0 + here->MOS3capgb), here->MOS3tPhi,OxideCap); } else { DEVqmeyer (vgd,vgs,vgb,von,vdsat, (ckt->CKTstate0 + here->MOS3capgd), (ckt->CKTstate0 + here->MOS3capgs), (ckt->CKTstate0 + here->MOS3capgb), here->MOS3tPhi,OxideCap); } vgs1 = *(ckt->CKTstate1 + here->MOS3vgs); vgd1 = vgs1 - *(ckt->CKTstate1 + here->MOS3vds); vgb1 = vgs1 - *(ckt->CKTstate1 + here->MOS3vbs); if(ckt->CKTmode & MODETRANOP) { capgs = 2 * *(ckt->CKTstate0+here->MOS3capgs)+ GateSourceOverlapCap ; capgd = 2 * *(ckt->CKTstate0+here->MOS3capgd)+ GateDrainOverlapCap ; capgb = 2 * *(ckt->CKTstate0+here->MOS3capgb)+ GateBulkOverlapCap ; } else { capgs = ( *(ckt->CKTstate0+here->MOS3capgs)+ *(ckt->CKTstate1+here->MOS3capgs) + GateSourceOverlapCap ); capgd = ( *(ckt->CKTstate0+here->MOS3capgd)+ *(ckt->CKTstate1+here->MOS3capgd) + GateDrainOverlapCap ); capgb = ( *(ckt->CKTstate0+here->MOS3capgb)+ *(ckt->CKTstate1+here->MOS3capgb) + GateBulkOverlapCap ); } if(ckt->CKTsenInfo){ here->MOS3cgs = capgs; here->MOS3cgd = capgd; here->MOS3cgb = capgb; } /* * store small-signal parameters (for meyer's model) * all parameters already stored, so done... */ if(SenCond){ if(ckt->CKTsenInfo->SENmode & (DCSEN|ACSEN)) { continue; } }#ifndef PREDICTOR if (ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) { *(ckt->CKTstate0 + here->MOS3qgs) = (1+xfact) * *(ckt->CKTstate1 + here->MOS3qgs) - xfact * *(ckt->CKTstate2 + here->MOS3qgs); *(ckt->CKTstate0 + here->MOS3qgd) = (1+xfact) * *(ckt->CKTstate1 + here->MOS3qgd) - xfact * *(ckt->CKTstate2 + here->MOS3qgd); *(ckt->CKTstate0 + here->MOS3qgb) = (1+xfact) * *(ckt->CKTstate1 + here->MOS3qgb) - xfact * *(ckt->CKTstate2 + here->MOS3qgb); } else {#endif /*PREDICTOR*/ if(ckt->CKTmode & MODETRAN) { *(ckt->CKTstate0 + here->MOS3qgs) = (vgs-vgs1)*capgs + *(ckt->CKTstate1 + here->MOS3qgs) ; *(ckt->CKTstate0 + here->MOS3qgd) = (vgd-vgd1)*capgd + *(ckt->CKTstate1 + here->MOS3qgd) ; *(ckt->CKTstate0 + here->MOS3qgb) = (vgb-vgb1)*capgb + *(ckt->CKTstate1 + here->MOS3qgb) ; } else { /* TRANOP only */ *(ckt->CKTstate0 + here->MOS3qgs) = vgs*capgs; *(ckt->CKTstate0 + here->MOS3qgd) = vgd*capgd; *(ckt->CKTstate0 + here->MOS3qgb) = vgb*capgb; }#ifndef PREDICTOR }#endif /*PREDICTOR*/ } bypass: if(SenCond) continue; if ( (ckt->CKTmode & (MODEINITTRAN)) || (! (ckt->CKTmode & (MODETRAN)) ) ) { /* * initialize to zero charge conductances * and current */ gcgs=0; ceqgs=0; gcgd=0; ceqgd=0; gcgb=0; ceqgb=0; } else { if(capgs == 0) *(ckt->CKTstate0 + here->MOS3cqgs) =0; if(capgd == 0) *(ckt->CKTstate0 + here->MOS3cqgd) =0; if(capgb == 0) *(ckt->CKTstate0 + here->MOS3cqgb) =0; /* * calculate equivalent conductances and currents for * meyer"s capacitors */ error = NIintegrate(ckt,&gcgs,&ceqgs,capgs,here->MOS3qgs); if(error) return(error); error = NIintegrate(ckt,&gcgd,&ceqgd,capgd,here->MOS3qgd); if(error) return(error); error = NIintegrate(ckt,&gcgb,&ceqgb,capgb,here->MOS3qgb); if(error) return(error); ceqgs=ceqgs-gcgs*vgs+ckt->CKTag[0]* *(ckt->CKTstate0 + here->MOS3qgs); ceqgd=ceqgd-gcgd*vgd+ckt->CKTag[0]* *(ckt->CKTstate0 + here->MOS3qgd); ceqgb=ceqgb-gcgb*vgb+ckt->CKTag[0]* *(ckt->CKTstate0 + here->MOS3qgb); } /* * store charge storage info for meyer's cap in lx table */ /* * load current vector */ ceqbs = model->MOS3type * (here->MOS3cbs-(here->MOS3gbs)*vbs); ceqbd = model->MOS3type * (here->MOS3cbd-(here->MOS3gbd)*vbd); if (here->MOS3mode >= 0) { xnrm=1; xrev=0; cdreq=model->MOS3type*(cdrain-here->MOS3gds*vds- here->MOS3gm*vgs-here->MOS3gmbs*vbs); } else { xnrm=0; xrev=1; cdreq = -(model->MOS3type)*(cdrain-here->MOS3gds*(-vds)- here->MOS3gm*vgd-here->MOS3gmbs*vbd); } *(ckt->CKTrhs + here->MOS3gNode) -= (model->MOS3type * (ceqgs + ceqgb + ceqgd)); *(ckt->CKTrhs + here->MOS3bNode) -= (ceqbs + ceqbd - model->MOS3type * ceqgb); *(ckt->CKTrhs + here->MOS3dNodePrime) += (ceqbd - cdreq + model->MOS3type * ceqgd); *(ckt->CKTrhs + here->MOS3sNodePrime) += cdreq + ceqbs + model->MOS3type * ceqgs; /* * load y matrix */#if 0printf(" loading %s at time %g\n",here->MOS3name,ckt->CKTtime);printf("%g %g %g %g %g\n", here->MOS3drainConductance,gcgd+gcgs+gcgb, here->MOS3sourceConductance,here->MOS3gbd,here->MOS3gbs);printf("%g %g %g %g %g\n",-gcgb,0.0,0.0,here->MOS3gds,here->MOS3gm);printf("%g %g %g %g %g\n", here->MOS3gds,here->MOS3gmbs,gcgd,-gcgs,-gcgd);printf("%g %g %g %g %g\n", -gcgs,-gcgd,0.0,-gcgs,0.0);#endif *(here->MOS3DdPtr) += (here->MOS3drainConductance); *(here->MOS3GgPtr) += ((gcgd+gcgs+gcgb)); *(here->MOS3SsPtr) += (here->MOS3sourceConductance); *(here->MOS3BbPtr) += (here->MOS3gbd+here->MOS3gbs+gcgb); *(here->MOS3DPdpPtr) += (here->MOS3drainConductance+here->MOS3gds+ here->MOS3gbd+xrev*(here->MOS3gm+here->MOS3gmbs)+gcgd); *(here->MOS3SPspPtr) += (here->MOS3sourceConductance+here->MOS3gds+ here->MOS3gbs+xnrm*(here->MOS3gm+here->MOS3gmbs)+gcgs); *(here->MOS3DdpPtr) += (-here->MOS3drainConductance); *(here->MOS3GbPtr) -= gcgb; *(here->MOS3GdpPtr) -= gcgd; *(here->MOS3GspPtr) -= gcgs; *(here->MOS3SspPtr) += (-here->MOS3sourceConductance); *(here->MOS3BgPtr) -= gcgb; *(here->MOS3BdpPtr) -= here->MOS3gbd; *(here->MOS3BspPtr) -= here->MOS3gbs; *(here->MOS3DPdPtr) += (-here->MOS3drainConductance); *(here->MOS3DPgPtr) += ((xnrm-xrev)*here->MOS3gm-gcgd); *(here->MOS3DPbPtr) += (-here->MOS3gbd+(xnrm-xrev)*here->MOS3gmbs); *(here->MOS3DPspPtr) += (-here->MOS3gds- xnrm*(here->MOS3gm+here->MOS3gmbs)); *(here->MOS3SPgPtr) += (-(xnrm-xrev)*here->MOS3gm-gcgs); *(here->MOS3SPsPtr) += (-here->MOS3sourceConductance); *(here->MOS3SPbPtr) += (-here->MOS3gbs-(xnrm-xrev)*here->MOS3gmbs); *(here->MOS3SPdpPtr) += (-here->MOS3gds- xrev*(here->MOS3gm+here->MOS3gmbs)); } } return(OK);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?