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

📄 mos6load.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1989 Takayasu Sakurai**********/#include "spice.h"#include <stdio.h>#include "cktdefs.h"#include "devdefs.h"#include "mos6defs.h"#include "util.h"#include "trandefs.h"#include "const.h"#include "sperror.h"#include "suffix.h"intMOS6load(inModel,ckt)    GENmodel *inModel;    register CKTcircuit *ckt;        /* actually load the current value into the          * sparse matrix previously provided          */{    register MOS6model *model = (MOS6model *) inModel;    register MOS6instance *here;    double betac;    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;    double xfact;    int xnrm;    int xrev;    double capgs;   /* total gate-source capacitance */    double capgd;   /* total gate-drain capacitance */    double capgb;   /* total gate-bulk capacitance */    int Check;#ifndef NOBYPASS    double tempv;#endif /*NOBYPASS*/    int error;#ifdef CAPBYPASS    int senflag;#endif /* CAPBYPASS */     int SenCond;#ifdef CAPBYPASS    senflag = 0;    if(ckt->CKTsenInfo && ckt->CKTsenInfo->SENstatus == PERTURBATION &&        (ckt->CKTsenInfo->SENmode & (ACSEN | TRANSEN))) {        senflag = 1;    }#endif /* CAPBYPASS */     /*  loop through all the MOS6 device models */    for( ; model != NULL; model = model->MOS6nextModel ) {        /* loop through all the instances of the model */        for (here = model->MOS6instances; here != NULL ;                here=here->MOS6nextInstance) {	    if (here->MOS6owner != ARCHme) continue;            vt = CONSTKoverQ * here->MOS6temp;            Check=1;            if(ckt->CKTsenInfo){#ifdef SENSDEBUG                printf("MOS6load \n");#endif /* SENSDEBUG */                if((ckt->CKTsenInfo->SENstatus == PERTURBATION)&&                    (here->MOS6senPertFlag == OFF))continue;            }            SenCond = ckt->CKTsenInfo && here->MOS6senPertFlag;/**/#ifdef DETAILPROFasm("   .globl mospta");asm("mospta:");#endif /*DETAILPROF*/            /* first, we compute a few useful values - these could be             * pre-computed, but for historical reasons are still done             * here.  They may be moved at the expense of instance size             */            EffectiveLength=here->MOS6l - 2*model->MOS6latDiff;            if( (here->MOS6tSatCurDens == 0) ||                     (here->MOS6drainArea == 0) ||                    (here->MOS6sourceArea == 0)) {                DrainSatCur = here->MOS6tSatCur;                SourceSatCur = here->MOS6tSatCur;            } else {                DrainSatCur = here->MOS6tSatCurDens *                         here->MOS6drainArea;                SourceSatCur = here->MOS6tSatCurDens *                         here->MOS6sourceArea;            }            GateSourceOverlapCap = model->MOS6gateSourceOverlapCapFactor *                     here->MOS6w;            GateDrainOverlapCap = model->MOS6gateDrainOverlapCapFactor *                     here->MOS6w;            GateBulkOverlapCap = model->MOS6gateBulkOverlapCapFactor *                     EffectiveLength;            betac = here->MOS6tKc * here->MOS6w/EffectiveLength;            OxideCap = model->MOS6oxideCapFactor * EffectiveLength *                     here->MOS6w;            /*              * ok - now to do the start-up operations             *             * we must get values for vbs, vds, and vgs from somewhere             * so we either predict them or recover them from last iteration             * These are the two most common cases - either a prediction             * step or the general iteration step and they             * share some code, so we put them first - others later on             */            if(SenCond){#ifdef SENSDEBUG                printf("MOS6senPertFlag = ON \n");#endif /* SENSDEBUG */                if((ckt->CKTsenInfo->SENmode == TRANSEN) &&                (ckt->CKTmode & MODEINITTRAN)) {                    vgs = *(ckt->CKTstate1 + here->MOS6vgs);                    vds = *(ckt->CKTstate1 + here->MOS6vds);                    vbs = *(ckt->CKTstate1 + here->MOS6vbs);                    vbd = *(ckt->CKTstate1 + here->MOS6vbd);                    vgb = vgs - vbs;                    vgd = vgs - vds;                }                else if (ckt->CKTsenInfo->SENmode == ACSEN){                    vgb = model->MOS6type * (                         *(ckt->CKTrhsOp+here->MOS6gNode) -                        *(ckt->CKTrhsOp+here->MOS6bNode));                    vbs = *(ckt->CKTstate0 + here->MOS6vbs);                    vbd = *(ckt->CKTstate0 + here->MOS6vbd);                    vgd = vgb + vbd ;                    vgs = vgb + vbs ;                    vds = vbs - vbd ;                }                else{                    vgs = *(ckt->CKTstate0 + here->MOS6vgs);                    vds = *(ckt->CKTstate0 + here->MOS6vds);                    vbs = *(ckt->CKTstate0 + here->MOS6vbs);                    vbd = *(ckt->CKTstate0 + here->MOS6vbd);                    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->MOS6off) )  ) {#ifndef PREDICTOR                if(ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) {                    /* predictor step */                    xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1];                    *(ckt->CKTstate0 + here->MOS6vbs) =                             *(ckt->CKTstate1 + here->MOS6vbs);                    vbs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS6vbs))                            -(xfact * (*(ckt->CKTstate2 + here->MOS6vbs)));                    *(ckt->CKTstate0 + here->MOS6vgs) =                             *(ckt->CKTstate1 + here->MOS6vgs);                    vgs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS6vgs))                            -(xfact * (*(ckt->CKTstate2 + here->MOS6vgs)));                    *(ckt->CKTstate0 + here->MOS6vds) =                             *(ckt->CKTstate1 + here->MOS6vds);                    vds = (1+xfact)* (*(ckt->CKTstate1 + here->MOS6vds))                            -(xfact * (*(ckt->CKTstate2 + here->MOS6vds)));                    *(ckt->CKTstate0 + here->MOS6vbd) =                             *(ckt->CKTstate0 + here->MOS6vbs)-                            *(ckt->CKTstate0 + here->MOS6vds);                } else {#endif /* PREDICTOR */                    /* general iteration */                    vbs = model->MOS6type * (                         *(ckt->CKTrhsOld+here->MOS6bNode) -                        *(ckt->CKTrhsOld+here->MOS6sNodePrime));                    vgs = model->MOS6type * (                         *(ckt->CKTrhsOld+here->MOS6gNode) -                        *(ckt->CKTrhsOld+here->MOS6sNodePrime));                    vds = model->MOS6type * (                         *(ckt->CKTrhsOld+here->MOS6dNodePrime) -                        *(ckt->CKTrhsOld+here->MOS6sNodePrime));#ifndef PREDICTOR                }#endif /* PREDICTOR */                /* now some common crunching for some more useful quantities */                vbd=vbs-vds;                vgd=vgs-vds;                vgdo = *(ckt->CKTstate0 + here->MOS6vgs) -                         *(ckt->CKTstate0 + here->MOS6vds);                delvbs = vbs - *(ckt->CKTstate0 + here->MOS6vbs);                delvbd = vbd - *(ckt->CKTstate0 + here->MOS6vbd);                delvgs = vgs - *(ckt->CKTstate0 + here->MOS6vgs);                delvds = vds - *(ckt->CKTstate0 + here->MOS6vds);                delvgd = vgd-vgdo;                /* these are needed for convergence testing */                if (here->MOS6mode >= 0) {                    cdhat=                        here->MOS6cd-                        here->MOS6gbd * delvbd +                        here->MOS6gmbs * delvbs +                        here->MOS6gm * delvgs +                         here->MOS6gds * delvds ;                } else {                    cdhat=                        here->MOS6cd -                        ( here->MOS6gbd -                        here->MOS6gmbs) * delvbd -                        here->MOS6gm * delvgd +                         here->MOS6gds * delvds ;                }                cbhat=                    here->MOS6cbs +                    here->MOS6cbd +                    here->MOS6gbd * delvbd +                    here->MOS6gbs * delvbs ;/**/#ifdef DETAILPROFasm("   .globl mosptb");asm("mosptb:");#endif /*DETAILPROF*/#ifndef NOBYPASS                /* now lets see if we can bypass (ugh) */                /* the following mess should be one if statement, but                 * many compilers can't handle it all at once, so it                 * is split into several successive if statements                 */                tempv = MAX(FABS(cbhat),FABS(here->MOS6cbs                        + here->MOS6cbd))+ckt->CKTabstol;                if((!(ckt->CKTmode & (MODEINITPRED|MODEINITTRAN|MODEINITSMSIG)                        )) && (ckt->CKTbypass) )                if ( (FABS(cbhat-(here->MOS6cbs +                         here->MOS6cbd)) < ckt->CKTreltol *                         tempv))                 if( (FABS(delvbs) < (ckt->CKTreltol * MAX(FABS(vbs),                        FABS(*(ckt->CKTstate0+here->MOS6vbs)))+                        ckt->CKTvoltTol)))                if ( (FABS(delvbd) < (ckt->CKTreltol * MAX(FABS(vbd),                        FABS(*(ckt->CKTstate0+here->MOS6vbd)))+                        ckt->CKTvoltTol)) )                if( (FABS(delvgs) < (ckt->CKTreltol * MAX(FABS(vgs),                        FABS(*(ckt->CKTstate0+here->MOS6vgs)))+                        ckt->CKTvoltTol)))                if ( (FABS(delvds) < (ckt->CKTreltol * MAX(FABS(vds),                        FABS(*(ckt->CKTstate0+here->MOS6vds)))+                        ckt->CKTvoltTol)) )                if( (FABS(cdhat- here->MOS6cd) <                        ckt->CKTreltol * MAX(FABS(cdhat),FABS(                        here->MOS6cd)) + 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->MOS6vbs);                    vbd = *(ckt->CKTstate0 + here->MOS6vbd);                    vgs = *(ckt->CKTstate0 + here->MOS6vgs);                    vds = *(ckt->CKTstate0 + here->MOS6vds);                    vgd = vgs - vds;                    vgb = vgs - vbs;                    cdrain = here->MOS6mode * (here->MOS6cd + here->MOS6cbd);                    if(ckt->CKTmode & (MODETRAN | MODETRANOP)) {                        capgs = ( *(ckt->CKTstate0+here->MOS6capgs)+                                   *(ckt->CKTstate1+here->MOS6capgs) +                                  GateSourceOverlapCap );                        capgd = ( *(ckt->CKTstate0+here->MOS6capgd)+                                   *(ckt->CKTstate1+here->MOS6capgd) +                                  GateDrainOverlapCap );                        capgb = ( *(ckt->CKTstate0+here->MOS6capgb)+                                   *(ckt->CKTstate1+here->MOS6capgb) +                                  GateBulkOverlapCap );                        if(ckt->CKTsenInfo){                            here->MOS6cgs = capgs;                            here->MOS6cgd = capgd;                            here->MOS6cgb = capgb;                        }                    }                    goto bypass;                }#endif /*NOBYPASS*//*

⌨️ 快捷键说明

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