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

📄 devsup.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 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 + -