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 + -
显示快捷键?