📄 mos2load.c
字号:
dudvds = 0.0; dudvbs = model->MOS2critFieldExp*ufact*dodvbs/vgst; goto line500;line410: ufact = 1.0; ueff = model->MOS2surfaceMobility * 1e-4 /*(m**2/cm**2) */ ; dudvgs = 0.0; dudvds = 0.0; dudvbs = 0.0; /* * evaluate saturation voltage and its derivatives according to * grove-frohman equation */line500: vgsx = lvgs; gammad = gamasd/eta; dgdvbs = dgddvb; if (model->MOS2fastSurfaceStateDensity != 0 && OxideCap != 0) { vgsx = MAX(lvgs,von); } if (gammad > 0) { gammd2 = gammad*gammad; argv = (vgsx-vbin)/eta+phiMinVbs; if (argv <= 0.0) { vdsat = 0.0; dsdvgs = 0.0; dsdvbs = 0.0; } else { arg = sqrt(1.0+4.0*argv/gammd2); vdsat = (vgsx-vbin)/eta+gammd2*(1.0-arg)/2.0; vdsat = MAX(vdsat,0.0); dsdvgs = (1.0-1.0/arg)/eta; dsdvbs = (gammad*(1.0-arg)+2.0*argv/(gammad*arg))/ eta*dgdvbs+1.0/arg+factor*dsdvgs; } } else { vdsat = (vgsx-vbin)/eta; vdsat = MAX(vdsat,0.0); dsdvgs = 1.0; dsdvbs = 0.0; } if (model->MOS2maxDriftVel > 0) { /* * evaluate saturation voltage and its derivatives * according to baum's theory of scattering velocity * saturation */ gammd2 = gammad*gammad; v1 = (vgsx-vbin)/eta+phiMinVbs; v2 = phiMinVbs; xv = model->MOS2maxDriftVel*EffectiveLength/ueff; a1 = gammad/0.75; b1 = -2.0*(v1+xv); c1 = -2.0*gammad*xv; d1 = 2.0*v1*(v2+xv)-v2*v2-4.0/3.0*gammad*sarg3; a = -b1; b = a1*c1-4.0*d1; c = -d1*(a1*a1-4.0*b1)-c1*c1; r = -a*a/3.0+b; s = 2.0*a*a*a/27.0-a*b/3.0+c; r3 = r*r*r; s2 = s*s; p = s2/4.0+r3/27.0; p0 = FABS(p); p2 = sqrt(p0); if (p < 0) { ro = sqrt(s2/4.0+p0); ro = log(ro)/3.0; ro = exp(ro); fi = atan(-2.0*p2/s); y3 = 2.0*ro*cos(fi/3.0)-a/3.0; } else { p3 = (-s/2.0+p2); p3 = exp(log(FABS(p3))/3.0); p4 = (-s/2.0-p2); p4 = exp(log(FABS(p4))/3.0); y3 = p3+p4-a/3.0; } iknt = 0; a3 = sqrt(a1*a1/4.0-b1+y3); b3 = sqrt(y3*y3/4.0-d1); for(i = 1;i<=4;i++) { a4[i-1] = a1/2.0+sig1[i-1]*a3; b4[i-1] = y3/2.0+sig2[i-1]*b3; delta4 = a4[i-1]*a4[i-1]/4.0-b4[i-1]; if (delta4 < 0) continue; iknt = iknt+1; tmp = sqrt(delta4); x4[iknt-1] = -a4[i-1]/2.0+tmp; iknt = iknt+1; x4[iknt-1] = -a4[i-1]/2.0-tmp; } jknt = 0; for(j = 1;j<=iknt;j++) { if (x4[j-1] <= 0) continue; /* XXX implement this sanely */ poly4[j-1] = x4[j-1]*x4[j-1]*x4[j-1]*x4[j-1]+a1*x4[j-1]* x4[j-1]*x4[j-1]; poly4[j-1] = poly4[j-1]+b1*x4[j-1]*x4[j-1]+c1*x4[j-1]+d1; if (FABS(poly4[j-1]) > 1.0e-6) continue; jknt = jknt+1; if (jknt <= 1) { xvalid = x4[j-1]; } if (x4[j-1] > xvalid) continue; xvalid = x4[j-1]; } if (jknt > 0) { vdsat = xvalid*xvalid-phiMinVbs; } } /* * evaluate effective channel length and its derivatives */ if (lvds != 0.0) { gammad = gamasd; if ((lvbs-vdsat) <= 0) { bsarg = sqrt(vdsat+phiMinVbs); dbsrdb = -0.5/bsarg; } else { bsarg = sphi/(1.0+0.5*(lvbs-vdsat)/here->MOS2tPhi); dbsrdb = -0.5*bsarg*bsarg/sphi3; } bodys = bsarg*bsarg*bsarg-sarg3; gdbdvs = 2.0*gammad*(bsarg*bsarg*dbsrdb-sarg*sarg*dsrgdb); if (model->MOS2maxDriftVel <= 0) { if (model->MOS2substrateDoping == 0.0) goto line610; if (xlamda > 0.0) goto line610; argv = (lvds-vdsat)/4.0; sargv = sqrt(1.0+argv*argv); arg = sqrt(argv+sargv); xlfact = model->MOS2xd/(EffectiveLength*lvds); xlamda = xlfact*arg; dldsat = lvds*xlamda/(8.0*sargv); } else { argv = (vgsx-vbin)/eta-vdsat; xdv = model->MOS2xd/sqrt(model->MOS2channelCharge); xlv = model->MOS2maxDriftVel*xdv/(2.0*ueff); vqchan = argv-gammad*bsarg; dqdsat = -1.0+gammad*dbsrdb; vl = model->MOS2maxDriftVel*EffectiveLength; dfunds = vl*dqdsat-ueff*vqchan; dfundg = (vl-ueff*vdsat)/eta; dfundb = -vl*(1.0+dqdsat-factor/eta)+ueff* (gdbdvs-dgdvbs*bodys/1.5)/eta; dsdvgs = -dfundg/dfunds; dsdvbs = -dfundb/dfunds; if (model->MOS2substrateDoping == 0.0) goto line610; if (xlamda > 0.0) goto line610; argv = lvds-vdsat; argv = MAX(argv,0.0); xls = sqrt(xlv*xlv+argv); dldsat = xdv/(2.0*xls); xlfact = xdv/(EffectiveLength*lvds); xlamda = xlfact*(xls-xlv); dldsat = dldsat/EffectiveLength; } dldvgs = dldsat*dsdvgs; dldvds = -xlamda+dldsat; dldvbs = dldsat*dsdvbs; } else {line610: dldvgs = 0.0; dldvds = 0.0; dldvbs = 0.0; } /* * limit channel shortening at punch-through */ xwb = model->MOS2xd*sbiarg; xld = EffectiveLength-xwb; clfact = 1.0-xlamda*lvds; dldvds = -xlamda-dldvds; xleff = EffectiveLength*clfact; deltal = xlamda*lvds*EffectiveLength; if (model->MOS2substrateDoping == 0.0) xwb = 0.25e-6; if (xleff < xwb) { xleff = xwb/(1.0+(deltal-xld)/xwb); clfact = xleff/EffectiveLength; dfact = xleff*xleff/(xwb*xwb); dldvgs = dfact*dldvgs; dldvds = dfact*dldvds; dldvbs = dfact*dldvbs; } /* * evaluate effective beta (effective kp) */ beta1 = Beta*ufact/clfact; /* * test for mode of operation and branch appropriately */ gammad = gamasd; dgdvbs = dgddvb; if (lvds <= 1.0e-10) { if (lvgs <= von) { if ((model->MOS2fastSurfaceStateDensity == 0.0) || (OxideCap == 0.0)) { here->MOS2gds = 0.0; goto line1050; } here->MOS2gds = beta1*(von-vbin-gammad*sarg)*exp(argg* (lvgs-von)); goto line1050; } here->MOS2gds = beta1*(lvgs-vbin-gammad*sarg); goto line1050; } if (lvgs > von) goto line900; /* * subthreshold region */ if (vdsat <= 0) { here->MOS2gds = 0.0; if (lvgs > vth) goto doneval; goto line1050; } vdson = MIN(vdsat,lvds); if (lvds > vdsat) { barg = bsarg; dbrgdb = dbsrdb; body = bodys; gdbdv = gdbdvs; } cdson = beta1*((von-vbin-eta*vdson*0.5)*vdson-gammad*body/1.5); didvds = beta1*(von-vbin-eta*vdson-gammad*barg); gdson = -cdson*dldvds/clfact-beta1*dgdvds*body/1.5; if (lvds < vdsat) gdson = gdson+didvds; gbson = -cdson*dldvbs/clfact+beta1* (dodvbs*vdson+factor*vdson-dgdvbs*body/1.5-gdbdv); if (lvds > vdsat) gbson = gbson+didvds*dsdvbs; expg = exp(argg*(lvgs-von)); cdrain = cdson*expg; gmw = cdrain*argg; here->MOS2gm = gmw; if (lvds > vdsat) here->MOS2gm = gmw+didvds*dsdvgs*expg; tmp = gmw*(lvgs-von)/xn; here->MOS2gds = gdson*expg-here->MOS2gm*dodvds-tmp*dxndvd; here->MOS2gmbs = gbson*expg-here->MOS2gm*dodvbs-tmp*dxndvb; goto doneval;line900: if (lvds <= vdsat) { /* * linear region */ cdrain = beta1*((lvgs-vbin-eta*lvds/2.0)*lvds-gammad*body/1.5); arg = cdrain*(dudvgs/ufact-dldvgs/clfact); here->MOS2gm = arg+beta1*lvds; arg = cdrain*(dudvds/ufact-dldvds/clfact); here->MOS2gds = arg+beta1*(lvgs-vbin-eta* lvds-gammad*barg-dgdvds*body/1.5); arg = cdrain*(dudvbs/ufact-dldvbs/clfact); here->MOS2gmbs = arg-beta1*(gdbdv+dgdvbs*body/1.5-factor*lvds); } else { /* * saturation region */ cdrain = beta1*((lvgs-vbin-eta* vdsat/2.0)*vdsat-gammad*bodys/1.5); arg = cdrain*(dudvgs/ufact-dldvgs/clfact); here->MOS2gm = arg+beta1*vdsat+beta1*(lvgs- vbin-eta*vdsat-gammad*bsarg)*dsdvgs; here->MOS2gds = -cdrain*dldvds/clfact-beta1*dgdvds*bodys/1.5; arg = cdrain*(dudvbs/ufact-dldvbs/clfact); here->MOS2gmbs = arg-beta1*(gdbdvs+dgdvbs*bodys/1.5-factor* vdsat)+beta1* (lvgs-vbin-eta*vdsat-gammad*bsarg)*dsdvbs; } /* * compute charges for "on" region */ goto doneval; /* * finish special cases */line1050: cdrain = 0.0; here->MOS2gm = 0.0; here->MOS2gmbs = 0.0; /* * finished */ }doneval: here->MOS2von = model->MOS2type * von; here->MOS2vdsat = model->MOS2type * vdsat; /* * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE */ here->MOS2cd=here->MOS2mode * cdrain - here->MOS2cbd; 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->MOS2vbs)))+ ckt->CKTvoltTol)|| senflag)#endif /*CAPBYPASS*/ { /* can't bypass the diode capacitance calculations */#ifdef CAPZEROBYPASS if(here->MOS2Cbs != 0 || here->MOS2Cbssw != 0) {#endif /*CAPZEROBYPASS*/ if (vbs < here->MOS2tDepCap){ arg=1-vbs/here->MOS2tBulkPot; /* * 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->MOS2bulkJctBotGradingCoeff == model->MOS2bulkJctSideGradingCoeff) { if(model->MOS2bulkJctBotGradingCoeff == .5) { sarg = sargsw = 1/sqrt(arg); } else { sarg = sargsw = exp(-model->MOS2bulkJctBotGradingCoeff* log(arg)); } } else { if(model->MOS2bulkJctBotGradingCoeff == .5) { sarg = 1/sqrt(arg); } else {#endif /*NOSQRT*/ sarg = exp(-model->MOS2bulkJctBotGradingCoeff* log(arg));#ifndef NOSQRT } if(model->MOS2bulkJctSideGradingCoeff == .5) { sargsw = 1/sqrt(arg); } else {#endif /*NOSQRT*/ sargsw =exp(-model->MOS2bulkJctSideGradingCoeff* log(arg));#ifndef NOSQRT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -