⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devsup.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1985 Thomas L. QuarlesModified: 2000 AlansFixes**********//* support routines for device models */#include "ngspice.h"#include "devdefs.h"#include "cktdefs.h"#include "suffix.h"/*  * Limit the per-iteration change of VDS  */doubleDEVlimvds(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);}/*   * Limit the per-iteration change of PN junction voltages  * * This code has been fixed by Alan Gillespie adding limiting * for negative voltages. */doubleDEVpnjlim(double vnew, double vold, double vt, double vcrit, int *icheck){    double arg;    if((vnew > vcrit) && (fabs(vnew - vold) > (vt + vt))) {        if(vold > 0) {            arg = (vnew - vold) / vt;            if(arg > 0) {                vnew = vold + vt * (2+log(arg-2));            } else {                vnew = vold - vt * (2+log(2-arg));            }        } else {            vnew = vt *log(vnew/vt);        }        *icheck = 1;    } else {       if (vnew < 0) {           if (vold > 0) {               arg = -1*vold-1;           } else {               arg = 2*vold-1;           }           if (vnew < arg) {              vnew = arg;              *icheck = 1;           } else {              *icheck = 0;           };        } else {           *icheck = 0;        }    }    return(vnew);}/*  * Limit the per-iteration change of FET voltages  * * This code has been fixed by Alan Gillespie: a new * definition for vtstlo.  */doubleDEVfetlim(double vnew, double vold, double vto){    double vtsthi;    double vtstlo;    double vtox;    double delv;    double vtemp;    vtsthi = fabs(2*(vold-vto))+2;    vtstlo = fabs(vold-vto)+1;    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);}/* Compute the MOS overlap capacitances as functions of the device * terminal voltages * * PN 2002: As of ngspice this code is not used by any device.  */voidDEVcmeyer(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 */	  double *cgs,	  double *cgd,	  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;}/* Compute the MOS overlap capacitances as functions of the device * terminal voltages  * * PN 2002: This is the Meyer model used by  MOS1 MOS2 MOS3 MOS6 and MOS9 *          device models. */voidDEVqmeyer(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;#define MAGIC_VDS 0.025    vgst = vgs-von;    vdsat = MAX(vdsat, MAGIC_VDS);    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;        vds = vgs-vgd;        if (vds>=vdsat) {           *capgd = 0;        } else {            vddif  = 2.0*vdsat-vds;            vddif1 = vdsat-vds/*-1.0e-12*/;            vddif2 = vddif*vddif;            *capgd = *capgs*(1.0-vdsat*vdsat/vddif2);            *capgs = *capgs*(1.0-vddif1*vddif1/vddif2);        }    } else  {        vds = vgs-vgd;        vdsat = MAX(vdsat, MAGIC_VDS);        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  * PN 2002: This is industrial archaelology */voidDEVcap(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     */}#endif/* Predict a value for the capacitor at loct by extrapolating from * previous values */doubleDEVpred(CKTcircuit *ckt, int loct){#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 + -