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

📄 mos2load.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1985 Thomas L. Quarles**********/#include "spice.h"#include <stdio.h>#include "util.h"#include "devdefs.h"#include "cktdefs.h"#include "mos2defs.h"#include "trandefs.h"#include "const.h"#include "sperror.h"#include "suffix.h"/* assuming silicon - make definition for epsilon of silicon */#define EPSSIL (11.7 * 8.854214871e-12)static double sig1[4] = {1.0, -1.0, 1.0, -1.0};static double sig2[4] = {1.0,  1.0,-1.0, -1.0};intMOS2load(inModel,ckt)    GENmodel *inModel;    register CKTcircuit *ckt;        /* actually load the current value into the          * sparse matrix previously provided          */{    register MOS2model *model = (MOS2model *)inModel;    register MOS2instance *here;    int error;    double Beta;    double DrainSatCur;    double EffectiveLength;    double GateBulkOverlapCap;    double GateDrainOverlapCap;    double GateSourceOverlapCap;    double OxideCap;    double SourceSatCur;    double arg;    double cbhat;    double cdhat;    double cdrain;    double cdreq;    double ceq;    double ceqbd;    double ceqbs;    double ceqgb;    double ceqgd;    double ceqgs;    double delvbd;    double delvbs;    double delvds;    double delvgd;    double delvgs;    double evbd;    double evbs;    double gcgb;    double gcgd;    double gcgs;    double geq;    double sarg;    double sargsw;    double tol;    double vbd;    double vbs;    double vds;    double vdsat;    double vgb1;    double vgb;    double vgd1;    double vgd;    double vgdo;    double vgs1;    double vgs;    double von;    double vt;      /* K * T / Q */    double xfact;    double capgs;   /* total gate-source capacitance */    double capgd;   /* total gate-drain capacitance */    double capgb;   /* total gate-bulk capacitance */    int xnrm;    int xrev;    int Check;#ifndef NOBYPASS    double tempv;#endif /*NOBYPASS*/#ifdef CAPBYPASS    int senflag;#endif /* CAPBYPASS */    int SenCond=0;#ifdef CAPBYPASS    senflag = 0;    if(ckt->CKTsenInfo){        if(ckt->CKTsenInfo->SENstatus == PERTURBATION){            if((ckt->CKTsenInfo->SENmode == ACSEN)||                (ckt->CKTsenInfo->SENmode == TRANSEN)){                senflag = 1;            }        }    }#endif /* CAPBYPASS */    /*  loop through all the MOS2 device models */    for( ; model != NULL; model = model->MOS2nextModel ) {        /* loop through all the instances of the model */        for (here = model->MOS2instances; here != NULL ;                here=here->MOS2nextInstance) {	    if (here->MOS2owner != ARCHme) continue;            vt = CONSTKoverQ * here->MOS2temp;            Check=1;            if(ckt->CKTsenInfo){#ifdef SENSDEBUG                printf("MOS2load %s\n",here->MOS2name);#endif /* SENSDEBUG */                if(ckt->CKTsenInfo->SENstatus == PERTURBATION) {                    if(here->MOS2senPertFlag == OFF)continue;                }                SenCond = here->MOS2senPertFlag;            }            EffectiveLength=here->MOS2l - 2*model->MOS2latDiff;            if( (here->MOS2tSatCurDens == 0) ||                     (here->MOS2drainArea == 0) ||                    (here->MOS2sourceArea == 0)) {                DrainSatCur = here->MOS2tSatCur;                SourceSatCur = here->MOS2tSatCur;            } else {                DrainSatCur = here->MOS2tSatCurDens *                         here->MOS2drainArea;                SourceSatCur = here->MOS2tSatCurDens *                         here->MOS2sourceArea;            }            GateSourceOverlapCap = model->MOS2gateSourceOverlapCapFactor *                     here->MOS2w;            GateDrainOverlapCap = model->MOS2gateDrainOverlapCapFactor *                     here->MOS2w;            GateBulkOverlapCap = model->MOS2gateBulkOverlapCapFactor *                     EffectiveLength;            Beta = here->MOS2tTransconductance * here->MOS2w/EffectiveLength;            OxideCap = model->MOS2oxideCapFactor * EffectiveLength *                     here->MOS2w;            if(SenCond){#ifdef SENSDEBUG                printf("MOS2senPertFlag = ON \n");#endif /* SENSDEBUG */                if((ckt->CKTsenInfo->SENmode == TRANSEN) &&                (ckt->CKTmode & MODEINITTRAN)) {                    vgs = *(ckt->CKTstate1 + here->MOS2vgs);                    vds = *(ckt->CKTstate1 + here->MOS2vds);                    vbs = *(ckt->CKTstate1 + here->MOS2vbs);                    vbd = *(ckt->CKTstate1 + here->MOS2vbd);                    vgb = vgs - vbs;                    vgd = vgs - vds;                }                else if (ckt->CKTsenInfo->SENmode == ACSEN){                    vgb = model->MOS2type * (                         *(ckt->CKTrhsOp+here->MOS2gNode) -                        *(ckt->CKTrhsOp+here->MOS2bNode));                    vbs = *(ckt->CKTstate0 + here->MOS2vbs);                    vbd = *(ckt->CKTstate0 + here->MOS2vbd);                    vgd = vgb + vbd ;                    vgs = vgb + vbs ;                    vds = vbs - vbd ;                }                else{                    vgs = *(ckt->CKTstate0 + here->MOS2vgs);                    vds = *(ckt->CKTstate0 + here->MOS2vds);                    vbs = *(ckt->CKTstate0 + here->MOS2vbs);                    vbd = *(ckt->CKTstate0 + here->MOS2vbd);                    vgb = vgs - vbs;                    vgd = vgs - vds;                }#ifdef SENSDEBUG                printf(" vbs = %.7e ,vbd = %.7e,vgb = %.7e\n",vbs,vbd,vgb);                printf(" vgs = %.7e ,vds = %.7e,vgd = %.7e\n",vgs,vds,vgd);#endif /* SENSDEBUG */                goto next1;            }            if((ckt->CKTmode & (MODEINITFLOAT | MODEINITPRED |MODEINITSMSIG                    | MODEINITTRAN)) ||                    ( (ckt->CKTmode & MODEINITFIX) && (!here->MOS2off) )  ) {#ifndef PREDICTOR                if(ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) {                    /* predictor step */                    xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1];                    *(ckt->CKTstate0 + here->MOS2vbs) =                             *(ckt->CKTstate1 + here->MOS2vbs);                    vbs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS2vbs))                            -(xfact * (*(ckt->CKTstate2 + here->MOS2vbs)));                    *(ckt->CKTstate0 + here->MOS2vgs) =                             *(ckt->CKTstate1 + here->MOS2vgs);                    vgs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS2vgs))                            -(xfact * (*(ckt->CKTstate2 + here->MOS2vgs)));                    *(ckt->CKTstate0 + here->MOS2vds) =                             *(ckt->CKTstate1 + here->MOS2vds);                    vds = (1+xfact)* (*(ckt->CKTstate1 + here->MOS2vds))                            -(xfact * (*(ckt->CKTstate2 + here->MOS2vds)));                    *(ckt->CKTstate0 + here->MOS2vbd) =                             *(ckt->CKTstate0 + here->MOS2vbs)-                            *(ckt->CKTstate0 + here->MOS2vds);                } else {#endif /* PREDICTOR */                    /* general iteration */                    vbs = model->MOS2type * (                         *(ckt->CKTrhsOld+here->MOS2bNode) -                        *(ckt->CKTrhsOld+here->MOS2sNodePrime));                    vgs = model->MOS2type * (                         *(ckt->CKTrhsOld+here->MOS2gNode) -                        *(ckt->CKTrhsOld+here->MOS2sNodePrime));                    vds = model->MOS2type * (                         *(ckt->CKTrhsOld+here->MOS2dNodePrime) -                        *(ckt->CKTrhsOld+here->MOS2sNodePrime));#ifndef PREDICTOR                }#endif /* PREDICTOR */                /* now some common crunching for some more useful quantities */                    vbd=vbs-vds;                    vgd=vgs-vds;                    vgdo = *(ckt->CKTstate0 + here->MOS2vgs) -                             *(ckt->CKTstate0 + here->MOS2vds);                    delvbs = vbs - *(ckt->CKTstate0 + here->MOS2vbs);                    delvbd = vbd - *(ckt->CKTstate0 + here->MOS2vbd);                    delvgs = vgs - *(ckt->CKTstate0 + here->MOS2vgs);                    delvds = vds - *(ckt->CKTstate0 + here->MOS2vds);                    delvgd = vgd-vgdo;                    /* these are needed for convergence testing */                    if (here->MOS2mode >= 0) {                        cdhat=                            here->MOS2cd -                             here->MOS2gbd * delvbd +                            here->MOS2gmbs * delvbs +                            here->MOS2gm * delvgs +                             here->MOS2gds * delvds ;                    } else {                        cdhat=                            here->MOS2cd +                            ( here->MOS2gmbs -                              here->MOS2gbd) * delvbd -                            here->MOS2gm * delvgd +                             here->MOS2gds * delvds ;                    }                    cbhat=                        here->MOS2cbs +                        here->MOS2cbd +                        here->MOS2gbd * delvbd +                        here->MOS2gbs * delvbs ;                /* now lets see if we can bypass (ugh) */                /* the following massive if should all be one                 * single compound if statement, but most compilers                 * can't handle it in one piece, so it is broken up                 * into several stages here                 */#ifndef NOBYPASS                tempv = MAX(FABS(cbhat),FABS(here->MOS2cbs+here->MOS2cbd))+                        ckt->CKTabstol;                if((!(ckt->CKTmode & (MODEINITPRED|MODEINITTRAN|MODEINITSMSIG)                        )) && (ckt->CKTbypass) )                if ( (FABS(cbhat-(here->MOS2cbs + here->MOS2cbd))                        < ckt->CKTreltol * tempv))                if( (FABS(delvbs) < (ckt->CKTreltol * MAX(FABS(vbs),                        FABS(*(ckt->CKTstate0+here->MOS2vbs)))+                        ckt->CKTvoltTol)))                if ( (FABS(delvbd) < (ckt->CKTreltol * MAX(FABS(vbd),                        FABS(*(ckt->CKTstate0+here->MOS2vbd)))+                        ckt->CKTvoltTol)) )                if( (FABS(delvgs) < (ckt->CKTreltol * MAX(FABS(vgs),                        FABS(*(ckt->CKTstate0+here->MOS2vgs)))+                        ckt->CKTvoltTol)) )                if ( (FABS(delvds) < (ckt->CKTreltol * MAX(FABS(vds),                        FABS(*(ckt->CKTstate0+here->MOS2vds)))+                        ckt->CKTvoltTol)) )                if( (FABS(cdhat- here->MOS2cd) <                        ckt->CKTreltol * MAX(FABS(cdhat),FABS(                        here->MOS2cd)) + ckt->CKTabstol) ) {                    /* bypass code */                    /* nothing interesting has changed since last                      * iteration on this device, so we just                     * copy all the values computed last iteration                      * out and keep going                     */                    vbs = *(ckt->CKTstate0 + here->MOS2vbs);                    vbd = *(ckt->CKTstate0 + here->MOS2vbd);                    vgs = *(ckt->CKTstate0 + here->MOS2vgs);                    vds = *(ckt->CKTstate0 + here->MOS2vds);                    vgd = vgs - vds;                    vgb = vgs - vbs;                    cdrain = here->MOS2mode * (here->MOS2cd + here->MOS2cbd);                    if(ckt->CKTmode & (MODETRAN | MODETRANOP)) {                        capgs = ( *(ckt->CKTstate0 + here->MOS2capgs)+                                  *(ckt->CKTstate1 + here->MOS2capgs)+                                  GateSourceOverlapCap );                        capgd = ( *(ckt->CKTstate0 + here->MOS2capgd)+                                  *(ckt->CKTstate1 + here->MOS2capgd)+                                  GateDrainOverlapCap );                        capgb = ( *(ckt->CKTstate0 + here->MOS2capgb)+                                  *(ckt->CKTstate1 + here->MOS2capgb)+                                  GateBulkOverlapCap );                        if(ckt->CKTsenInfo){                            here->MOS2cgs = capgs;                            here->MOS2cgd = capgd;                            here->MOS2cgb = capgb;                        }                    }                    goto bypass;                }#endif /*NOBYPASS*/                /* ok - bypass is out, do it the hard way */                von = model->MOS2type * here->MOS2von;                /*                 * limiting                 * We want to keep device voltages from changing                 * so fast that the exponentials churn out overflows                  * and similar rudeness                 */                if(*(ckt->CKTstate0 + here->MOS2vds) >=0) {                    vgs = DEVfetlim(vgs,*(ckt->CKTstate0 + here->MOS2vgs)                            ,von);                    vds = vgs - vgd;                    vds = DEVlimvds(vds,*(ckt->CKTstate0 + here->MOS2vds));                    vgd = vgs - vds;                } else {                    vgd = DEVfetlim(vgd,vgdo,von);                    vds = vgs - vgd;                    if(!(ckt->CKTfixLimit)) {                        vds = -DEVlimvds(-vds,-(*(ckt->CKTstate0 +                                 here->MOS2vds)));                    }                    vgs = vgd + vds;                }                if(vds >= 0) {                    vbs = DEVpnjlim(vbs,*(ckt->CKTstate0 + here->MOS2vbs),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -