📄 devsup.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Thomas L. Quarles**********/ /* support routines for device models */#include "spice.h"#include "devdefs.h"#include "cktdefs.h"#include "util.h"#include "suffix.h" /* DEVlimvds(vnew,vold) * limit the per-iteration change of VDS */doubleDEVlimvds(vnew,vold) double vnew; double vold;{ if(vold >= 3.5) { if(vnew > vold) { vnew = MIN(vnew,(3 * vold) +2); } else { if (vnew < 3.5) { vnew = MAX(vnew,2); } } } else { if(vnew > vold) { vnew = MIN(vnew,4); } else { vnew = MAX(vnew,-.5); } } return(vnew);} /* DEVpnjlim(vnew,vold,vt,vcrit,icheck) * limit the per-iteration change of PN junction voltages */doubleDEVpnjlim(vnew,vold,vt,vcrit,icheck) double vnew; double vold; double vt; double vcrit; int *icheck;{ double arg; if((vnew > vcrit) && (FABS(vnew - vold) > (vt + vt))) { if(vold > 0) { arg = 1 + (vnew - vold) / vt; if(arg > 0) { vnew = vold + vt * log(arg); } else { vnew = vcrit; } } else { vnew = vt *log(vnew/vt); } *icheck = 1; } else { *icheck = 0; } return(vnew);} /* * DEVfetlim(vnew,vold.vto) * * limit the per-iteration change of FET voltages */doubleDEVfetlim(vnew,vold,vto) double vnew; double vold; double vto;{ double vtsthi; double vtstlo; double vtox; double delv; double vtemp; vtsthi = FABS(2*(vold-vto))+2; vtstlo = vtsthi/2 +2; vtox = vto + 3.5; delv = vnew-vold; if (vold >= vto) { if(vold >= vtox) { if(delv <= 0) { /* going off */ if(vnew >= vtox) { if(-delv >vtstlo) { vnew = vold - vtstlo; } } else { vnew = MAX(vnew,vto+2); } } else { /* staying on */ if(delv >= vtsthi) { vnew = vold + vtsthi; } } } else { /* middle region */ if(delv <= 0) { /* decreasing */ vnew = MAX(vnew,vto-.5); } else { /* increasing */ vnew = MIN(vnew,vto+4); } } } else { /* off */ if(delv <= 0) { if(-delv >vtsthi) { vnew = vold - vtsthi; } } else { vtemp = vto + .5; if(vnew <= vtemp) { if(delv >vtstlo) { vnew = vold + vtstlo; } } else { vnew = vtemp; } } } return(vnew);} /* * DEVcmeyer(vgs0,vgd0,vgb0,von0,vdsat0, * vgs1,vgd1,vgb1,covlgs,covlgd,covlgb, * cgs0,cgd0,cgb0, * von,vdsat) * * Compute the MOS overlap capacitances as functions of the * device terminal voltages */voidDEVcmeyer(vgs0,vgd0,vgb0,von0,vdsat0, vgs1,vgd1,vgb1,covlgs,covlgd,covlgb, cgs,cgd,cgb, phi,cox,von,vdsat)double vgs0; /* initial voltage gate-source */double vgd0; /* initial voltage gate-drain */double vgb0; /* initial voltage gate-bulk */double von0;double vdsat0;double vgs1; /* final voltage gate-source */double vgd1; /* final voltage gate-drain */double vgb1; /* final voltage gate-bulk */double covlgs; /* overlap capacitance gate-source */double covlgd; /* overlap capacitance gate-drain */double covlgb; /* overlap capacitance gate-bulk */register double *cgs;register double *cgd;register double *cgb;double phi;double cox;double von;double vdsat;{ double vdb; double vdbsat; double vddif; double vddif1; double vddif2; double vgbt; *cgs = 0; *cgd = 0; *cgb = 0; vgbt = vgs1-von; if (vgbt <= -phi) { *cgb = cox; } else if (vgbt <= -phi/2) { *cgb = -vgbt*cox/phi; } else if (vgbt <= 0) { *cgb = -vgbt*cox/phi; *cgs = cox/(7.5e-1*phi)*vgbt+cox/1.5; } else { vdbsat = vdsat-(vgs1-vgb1); vdb = vgb1-vgd1; if (vdbsat <= vdb) { *cgs = cox/1.5; } else { vddif = 2.0*vdbsat-vdb; vddif1 = vdbsat-vdb-1.0e-12; vddif2 = vddif*vddif; *cgd = cox*(1.0-vdbsat*vdbsat/vddif2)/1.5; *cgs = cox*(1.0-vddif1*vddif1/vddif2)/1.5; } } vgbt = vgs0-von0; if (vgbt <= -phi) { *cgb += cox; } else if (vgbt <= -phi/2) { *cgb += -vgbt*cox/phi; } else if (vgbt <= 0) { *cgb += -vgbt*cox/phi; *cgs += cox/(7.5e-1*phi)*vgbt+cox/1.5; } else { vdbsat = vdsat0-(vgs0-vgb0); vdb = vgb0-vgd0; if (vdbsat <= vdb) { *cgs += cox/1.5; } else { vddif = 2.0*vdbsat-vdb; vddif1 = vdbsat-vdb-1.0e-12; vddif2 = vddif*vddif; *cgd += cox*(1.0-vdbsat*vdbsat/vddif2)/1.5; *cgs += cox*(1.0-vddif1*vddif1/vddif2)/1.5; } } *cgs = *cgs *.5 + covlgs; *cgd = *cgd *.5 + covlgd; *cgb = *cgb *.5 + covlgb;} /* * DEVqmeyer(vgs,vgd,vgb,von,vdsat,capgs,capgd,capgb,phi,cox) * * * * Compute the MOS overlap capacitances as functions of the * device terminal voltages *//* ARGSUSED */ /* because vgb is no longer used */voidDEVqmeyer(vgs,vgd,vgb,von,vdsat,capgs,capgd,capgb,phi,cox)double vgs; /* initial voltage gate-source */double vgd; /* initial voltage gate-drain */double vgb; /* initial voltage gate-bulk */double von;double vdsat;double *capgs; /* non-constant portion of g-s overlap capacitance */double *capgd; /* non-constant portion of g-d overlap capacitance */double *capgb; /* non-constant portion of g-b overlap capacitance */double phi;double cox; /* oxide capactiance */{ double vds; double vddif; double vddif1; double vddif2; double vgst; vgst = vgs-von; if (vgst <= -phi) { *capgb = cox/2; *capgs = 0; *capgd = 0; } else if (vgst <= -phi/2) { *capgb = -vgst*cox/(2*phi); *capgs = 0; *capgd = 0; } else if (vgst <= 0) { *capgb = -vgst*cox/(2*phi); *capgs = vgst*cox/(1.5*phi)+cox/3; *capgd = 0; } else { vds = vgs-vgd; if (vdsat <= vds) { *capgs = cox/3; *capgd = 0; *capgb = 0; } else { vddif = 2.0*vdsat-vds; vddif1 = vdsat-vds/*-1.0e-12*/; vddif2 = vddif*vddif; *capgd = cox*(1.0-vdsat*vdsat/vddif2)/3; *capgs = cox*(1.0-vddif1*vddif1/vddif2)/3; *capgb = 0; } }}#ifdef notdef/* XXX This is no longer used, apparently */voidDEVcap(ckt,vgd,vgs,vgb,covlgd,covlgs,covlgb, capbd,capbs,cggb,cgdb,cgsb,cbgb,cbdb,cbsb, gcggb,gcgdb,gcgsb,gcbgb,gcbdb,gcbsb, gcdgb,gcddb,gcdsb,gcsgb,gcsdb,gcssb, qgate,qchan,qbulk,qdrn,qsrc,xqc)register CKTcircuit *ckt; double vgd; double vgs; double vgb; double covlgd; double covlgs; double covlgb; double capbd; double capbs; double cggb; double cgdb; double cgsb; double cbgb; double cbdb; double cbsb; double *gcggb; double *gcgdb; double *gcgsb; double *gcbgb; double *gcbdb; double *gcbsb; double *gcdgb; double *gcddb; double *gcdsb; double *gcsgb; double *gcsdb; double *gcssb; double qgate; double qchan; double qbulk; double *qdrn; double *qsrc; double xqc; /* * compute equivalent conductances * divide up the channel charge (1-xqc)/xqc to source and drain */{ double gcd; double gcdxd; double gcdxs; double gcg; double gcgxd; double gcgxs; double gcs; double gcsxd; double gcsxs; double qgb; double qgd; double qgs; gcg = (cggb+cbgb)*ckt->CKTag[1]; gcd = (cgdb+cbdb)*ckt->CKTag[1]; gcs = (cgsb+cbsb)*ckt->CKTag[1]; gcgxd = -xqc*gcg; gcgxs = -(1-xqc)*gcg; gcdxd = -xqc*gcd; gcdxs = -(1-xqc)*gcd; gcsxd = -xqc*gcs; gcsxs = -(1-xqc)*gcs; *gcdgb = gcgxd-covlgd*ckt->CKTag[1]; *gcddb = gcdxd+(capbd+covlgd)*ckt->CKTag[1]; *gcdsb = gcsxd; *gcsgb = gcgxs-covlgs*ckt->CKTag[1]; *gcsdb = gcdxs; *gcssb = gcsxs+(capbs+covlgs)*ckt->CKTag[1]; *gcggb = (cggb+covlgd+covlgs+covlgb)*ckt->CKTag[1]; *gcgdb = (cgdb-covlgd)*ckt->CKTag[1]; *gcgsb = (cgsb-covlgs)*ckt->CKTag[1]; *gcbgb = (cbgb-covlgb)*ckt->CKTag[1]; *gcbdb = (cbdb-capbd)*ckt->CKTag[1]; *gcbsb = (cbsb-capbs)*ckt->CKTag[1]; /* * compute total terminal charges */ qgd = covlgd*vgd; qgs = covlgs*vgs; qgb = covlgb*vgb; qgate = qgate+qgd+qgs+qgb; qbulk = qbulk-qgb; *qdrn = xqc*qchan-qgd; *qsrc = (1-xqc)*qchan-qgs; /* * finished */}#endifdouble DEVpred(ckt,loct) CKTcircuit *ckt; int loct;{ /* predict a value for the capacitor at loct by * extrapolating from previous values */#ifndef NEWTRUNC double xfact; xfact = ckt->CKTdelta/ckt->CKTdeltaOld[1]; return( ( (1+xfact) * *(ckt->CKTstate1+loct) ) - ( xfact * *(ckt->CKTstate2+loct) ) );#endif /*NEWTRUNC*/}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -