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

📄 b1dset.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1985 Hong J. Park, Thomas L. Quarles**********/#include "spice.h"#include <stdio.h>#include "util.h"#include "cktdefs.h"#include "bsim1def.h"#include "trandefs.h"#include "distodef.h"#include "const.h"#include "sperror.h"#include "suffix.h"#include "devdefs.h"intB1dSetup(inModel,ckt)    GENmodel *inModel;    register CKTcircuit *ckt;{    register B1model* model = (B1model*)inModel;    register B1instance *here;    double DrainSatCurrent;    double EffectiveLength;    double GateBulkOverlapCap;    double GateDrainOverlapCap;    double GateSourceOverlapCap;    double SourceSatCurrent;    double DrainArea;    double SourceArea;    double DrainPerimeter;    double SourcePerimeter;    double vt0;    double evbs;    double lgbs1, lgbs2, lgbs3;    double czbd, czbs, czbdsw, czbssw;    double PhiB, MJ, MJSW, PhiBSW;    double arg, argsw, sarg, sargsw;    double capbs1, capbs2, capbs3;    double capbd1, capbd2, capbd3;    double qg;    double qb;    double qd;    double Vfb;    double Phi;    double K1;    double K2;    double Vdd;    double Ugs;    double Uds;    double Leff;    double Eta;    double Vpb;    double SqrtVpb;    double Von;    double Vth;    double DrCur;    double G;    double A;    double Arg;    double Beta;    double Beta_Vds_0;    double BVdd;    double Beta0;    double VddSquare;    double C1;    double C2;    double VdsSat;    double Argl1;    double Argl2;    double Vc;    double Term1;    double K;    double Args1;    double Args2;    double Args3;    double Warg1;    double Vcut;    double N;    double N0;    double NB;    double ND;    double Warg2;    double Wds;    double Wgs;    double Ilimit;    double Iexp;    double Vth0;    double Arg1;    double Arg2;    double Arg3;    double Arg5;    double Ent;    double Vcom;    double Vgb;    double Vgb_Vfb;    double VdsPinchoff;    double EntSquare;    double VgsVthSquare;    double Argl5;    double Argl6;    double Argl7;    double WLCox;    double Vtsquare;    int ChargeComputationNeeded;    double co4v15;double VgsVth  = 0.0;double lgbd1, lgbd2, lgbd3, evbd; double vbd = 0.0;double vgd = 0.0;double vgb = 0.0;double vds = 0.0;double vgs = 0.0;	    double vbs = 0.0;	    double dBVdddVds;	    Dderivs d_Argl6;	    Dderivs d_Vgb, d_Vgb_Vfb, d_EntSquare, d_Argl5, d_Argl7;	    Dderivs d_Arg5, d_Ent, d_Vcom, d_VdsPinchoff;	    Dderivs d_qb, d_qd, d_Vth0, d_Arg1, d_Arg2, d_Arg3;	    Dderivs d_dummy, d_Vth, d_BVdd, d_Warg1, d_qg;	    Dderivs d_N, d_Wds, d_Wgs, d_Iexp;	    Dderivs d_Argl1, d_Argl2, d_Args1, d_Args2, d_Args3;	    Dderivs d_Beta, d_Vc, d_Term1, d_K, d_VdsSat;	    Dderivs d_Beta_Vds_0, d_C1, d_C2, d_Beta0;	    Dderivs d_VgsVth, d_G, d_A, d_Arg, d_DrCur;	    Dderivs d_Ugs, d_Uds, d_Eta, d_Vpb, d_SqrtVpb, d_Von;	    Dderivs d_p, d_q, d_r, d_zero;    /*  loop through all the B1 device models */    for( ; model != NULL; model = model->B1nextModel ) {        /* loop through all the instances of the model */        for (here = model->B1instances; here != NULL ;                here=here->B1nextInstance) {	    if (here->B1owner != ARCHme) continue;                    EffectiveLength=here->B1l - model->B1deltaL * 1.e-6;/* m */            DrainArea = here->B1drainArea;            SourceArea = here->B1sourceArea;            DrainPerimeter = here->B1drainPerimeter;            SourcePerimeter = here->B1sourcePerimeter;            if( (DrainSatCurrent=DrainArea*model->B1jctSatCurDensity)                     < 1e-15){                DrainSatCurrent = 1.0e-15;            }            if( (SourceSatCurrent=SourceArea*model->B1jctSatCurDensity)                    <1.0e-15){                SourceSatCurrent = 1.0e-15;            }            GateSourceOverlapCap = model->B1gateSourceOverlapCap *here->B1w;            GateDrainOverlapCap = model->B1gateDrainOverlapCap * here->B1w;            GateBulkOverlapCap = model->B1gateBulkOverlapCap *EffectiveLength;            vt0 = model->B1type * here->B1vt0;                    vbs = model->B1type * (                         *(ckt->CKTrhsOld+here->B1bNode) -                        *(ckt->CKTrhsOld+here->B1sNodePrime));                    vgs = model->B1type * (                         *(ckt->CKTrhsOld+here->B1gNode) -                        *(ckt->CKTrhsOld+here->B1sNodePrime));                    vds = model->B1type * (                         *(ckt->CKTrhsOld+here->B1dNodePrime) -                        *(ckt->CKTrhsOld+here->B1sNodePrime));            if(vds >= 0) {                /* normal mode */                here->B1mode = 1;            } else {                /* inverse mode */                here->B1mode = -1;		vds = -vds;		vgs = vgs + vds; /* these are the local(fake) values now */		vbs = vbs + vds;            }            vgb = vgs - vbs;            vgd = vgs - vds;            vbd = vbs - vds;            if(vbs <= 0.0 ) {                lgbs1 = SourceSatCurrent / CONSTvt0 + ckt->CKTgmin;		lgbs2 = lgbs3 = 0.0;            } else {                evbs = exp(vbs/CONSTvt0);                lgbs1 = SourceSatCurrent*evbs/CONSTvt0 + ckt->CKTgmin;		lgbs2 = (lgbs1 - ckt->CKTgmin)/(CONSTvt0*2);		lgbs3 = lgbs2/(CONSTvt0*3);            }            if(vbd <= 0.0) {                lgbd1 = DrainSatCurrent / CONSTvt0 + ckt->CKTgmin;		lgbd2 = lgbd3 = 0.0;            } else {                evbd = exp(vbd/CONSTvt0);                lgbd1 = DrainSatCurrent*evbd/CONSTvt0 +ckt->CKTgmin;		lgbd2 = (lgbd1 - ckt->CKTgmin)/(CONSTvt0*2);		lgbd3 = lgbd2/(CONSTvt0*3);            }            /* line 400 */            /* call B1evaluate to calculate drain current and its              * derivatives and charge and capacitances related to gate             * drain, and bulk             */          /* check quadratic interpolation for beta0 ; line 360 *//* * Copyright (c) 1985 Hong J. Park, Thomas L. Quarles * modified 1988 Jaijeet Roychowdhury  *//* This routine evaluates the drain current, its derivatives and the * charges associated with the gate,bulk and drain terminal * using the B1 (Berkeley Short-Channel IGFET Model) Equations. */ /* as usual p=vgs, q=vbs, r=vds */ {        ChargeComputationNeeded  =  1;    Vfb  =  here->B1vfb;    Phi  =  here->B1phi;    K1   =  here->B1K1;    K2   =  here->B1K2;    Vdd  =  model->B1vdd;d_p.value = 0.0;d_p.d1_p = 1.0;d_p.d1_q = 0.0;d_p.d1_r = 0.0;d_p.d2_p2 = 0.0;d_p.d2_q2 = 0.0;d_p.d2_r2 = 0.0;d_p.d2_pq = 0.0;d_p.d2_qr = 0.0;d_p.d2_pr = 0.0;d_p.d3_p3 = 0.0;d_p.d3_q3 = 0.0;d_p.d3_r3 = 0.0;d_p.d3_p2r = 0.0;d_p.d3_p2q = 0.0;d_p.d3_q2r = 0.0;d_p.d3_pq2 = 0.0;d_p.d3_pr2 = 0.0;d_p.d3_qr2 = 0.0;d_p.d3_pqr = 0.0;	EqualDeriv(&d_q,&d_p);	EqualDeriv(&d_r,&d_p);	EqualDeriv(&d_zero,&d_p);    d_q.d1_p = d_r.d1_p = d_zero.d1_p = 0.0;    d_q.d1_q = d_r.d1_r = 1.0;    d_p.value = vgs; d_q.value = vbs; d_r.value = vds;    if((Ugs  =  here->B1ugs + here->B1ugsB * vbs) <= 0 ) {        Ugs = 0;	EqualDeriv(&d_Ugs,&d_zero);    } else {    EqualDeriv(&d_Ugs,&d_q);    d_Ugs.value = Ugs;    d_Ugs.d1_q = here->B1ugsB;    }    if((Uds  =  here->B1uds + here->B1udsB * vbs +             here->B1udsD*(vds-Vdd)) <= 0 ) {            Uds = 0.0;	EqualDeriv(&d_Uds,&d_zero);    } else {        Leff  =  here->B1l * 1.e6 - model->B1deltaL; /* Leff in um */	/*const*/        Uds  =  Uds / Leff;	/* Uds = (here->B1uds + here->B1udsB * vbs here->B1udsD*		(vds-Vdd))/Leff */	EqualDeriv(&d_Uds,&d_r);	d_Uds.value = Uds;	d_Uds.d1_r = here->B1udsD/Leff;	d_Uds.d1_q = here->B1udsB/Leff;    }    Eta  =  here->B1eta + here->B1etaB * vbs + here->B1etaD *         (vds - Vdd);	EqualDeriv(&d_Eta,&d_r);	d_Eta.value = Eta;	d_Eta.d1_r = here->B1etaD;	d_Eta.d1_q = here->B1etaB;    if( Eta <= 0 ) {           Eta  = 0;         EqualDeriv(&d_Eta,&d_zero);    } else if ( Eta > 1 ) {        Eta = 1;	EqualDeriv(&d_Eta,&d_zero);	d_Eta.value = 1.0;    }     if( vbs < 0 ) {        Vpb  =  Phi - vbs;	EqualDeriv(&d_Vpb,&d_q);	d_Vpb.value = Vpb;	d_Vpb.d1_q = -1;    } else {        Vpb  =  Phi;	EqualDeriv(&d_Vpb,&d_zero);	d_Vpb.value = Phi;    }    SqrtVpb  =  sqrt( Vpb );    SqrtDeriv(&d_SqrtVpb,&d_Vpb);    Von  = Vfb + Phi + K1 * SqrtVpb - K2 * Vpb - Eta * vds;    EqualDeriv(&d_dummy,&d_r);    d_dummy.value = -Eta*vds;    d_dummy.d1_r = -Eta;    TimesDeriv(&d_Von,&d_Vpb,-K2);    PlusDeriv(&d_Von,&d_Von,&d_dummy);    TimesDeriv(&d_dummy,&d_SqrtVpb,K1);    PlusDeriv(&d_Von,&d_dummy,&d_Von);    d_Von.value = Von;    Vth = Von;    EqualDeriv(&d_Vth,&d_Von);    VgsVth  =  vgs - Vth;    TimesDeriv(&d_VgsVth,&d_Vth,-1.0);    d_VgsVth.value = VgsVth;    d_VgsVth.d1_p += 1.0;    G  =   1./(1.744+0.8364 * Vpb);    TimesDeriv(&d_G,&d_Vpb,0.8364);    d_G.value += 1.744;    InvDeriv(&d_G,&d_G);    G = 1 - G;    TimesDeriv(&d_G,&d_G,-1.0);    d_G.value += 1.0;    A  =  G/SqrtVpb;    DivDeriv(&d_A,&d_G,&d_SqrtVpb);    A = 1.0 + 0.5*K1*A;    TimesDeriv(&d_A,&d_A,0.5*K1);    d_A.value += 1.0;    A = MAX( A, 1.0);   /* Modified */    if (A <= 1.0) {    EqualDeriv(&d_A,&d_zero);    d_A.value = 1.0;    }    Arg  = MAX(( 1 + Ugs * VgsVth), 1.0);    MultDeriv(&d_dummy,&d_Ugs,&d_VgsVth);    d_dummy.value += 1.0;    if (d_dummy.value <= 1.0) {    EqualDeriv(&d_Arg,&d_zero);    d_Arg.value = 1.0;    }     else    EqualDeriv(&d_Arg,&d_dummy);    if( VgsVth < 0 ) {        /* cutoff */        DrCur  = 0;	EqualDeriv(&d_DrCur,&d_zero);        goto SubthresholdComputation;    }    /* Quadratic Interpolation for Beta0 (Beta at vgs  =  0, vds=Vds) */    Beta_Vds_0  =  (here->B1betaZero + here->B1betaZeroB * vbs);    EqualDeriv(&d_Beta_Vds_0,&d_q);    d_Beta_Vds_0.value = Beta_Vds_0;    d_Beta_Vds_0.d1_q = here->B1betaZeroB;    BVdd  =  (here->B1betaVdd + here->B1betaVddB * vbs);    EqualDeriv(&d_BVdd,&d_q);    d_BVdd.value = BVdd;    d_BVdd.d1_q = here->B1betaVddB;    dBVdddVds = MAX( here->B1betaVddD, 0.0);    /* is the above wrong ?!? */    if( vds > Vdd ) {        Beta0  =  BVdd + dBVdddVds * (vds - Vdd);	EqualDeriv(&d_Beta0,&d_r); d_Beta0.value = vds - Vdd;	TimesDeriv(&d_Beta0,&d_Beta0,dBVdddVds);	PlusDeriv(&d_Beta0,&d_Beta0,&d_BVdd);	/* dBVdddVds = const */	/* and this stuff here? */    } else {        VddSquare  =  Vdd * Vdd; /* const */        C1  =  ( -BVdd + Beta_Vds_0 + dBVdddVds * Vdd) / VddSquare;	TimesDeriv(&d_C1,&d_BVdd,-1.0);	PlusDeriv(&d_C1,&d_C1,&d_Beta_Vds_0);	d_C1.value += dBVdddVds * Vdd;	TimesDeriv(&d_C1,&d_C1,1/VddSquare);        C2  =  2 * (BVdd - Beta_Vds_0) / Vdd - dBVdddVds;	TimesDeriv(&d_C2,&d_Beta_Vds_0,-1.0);	PlusDeriv(&d_C2,&d_C2,&d_BVdd);	TimesDeriv(&d_C2,&d_C2,2/Vdd);	d_C2.value -= dBVdddVds;        Beta0  =  (C1 * vds + C2) * vds + Beta_Vds_0;	MultDeriv(&d_Beta0,&d_r,&d_C1);	PlusDeriv(&d_Beta0,&d_Beta0,&d_C2);	MultDeriv(&d_Beta0,&d_Beta0,&d_dummy);	PlusDeriv(&d_Beta0,&d_Beta0,&d_Beta_Vds_0);	/*        dBeta0dVds  =  2*C1*vds + C2;        dBeta0dVbs  =  dC1dVbs * vds * vds + dC2dVbs * vds + dBeta_Vds_0_dVbs;	maybe we'll need these later */    }    /*Beta  =  Beta0 / ( 1 + Ugs * VgsVth );*/    Beta = Beta0 / Arg ;    DivDeriv(&d_Beta,&d_Beta0,&d_Arg);    /*VdsSat  = MAX( VgsVth / ( A + Uds * VgsVth ),  0.0);*/    Vc  =  Uds * VgsVth / A;    DivDeriv(&d_Vc,&d_VgsVth,&d_A);    MultDeriv(&d_Vc,&d_Vc,&d_Uds);    if(Vc < 0.0 ) {    EqualDeriv(&d_Vc,&d_zero);    Vc=0.0;    }    Term1  =  sqrt( 1 + 2 * Vc );    TimesDeriv(&d_Term1,&d_Vc,2.0);    d_Term1.value += 1.0;    SqrtDeriv(&d_Term1,&d_Term1);    K  =  0.5 * ( 1 + Vc + Term1 );    PlusDeriv(&d_K,&d_Vc,&d_Term1);    d_K.value += 1.0;    TimesDeriv(&d_K,&d_K,0.5);    VdsSat = VgsVth / ( A * sqrt(K));    if (VdsSat < 0.0) {    EqualDeriv(&d_VdsSat,&d_zero);    VdsSat = 0.0;    }    else    {

⌨️ 快捷键说明

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