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

📄 mesdset.c

📁 linux平台下类似著名的电路板作图软件 Spice的源代码
💻 C
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1988 Jaijeet Roychowdhury**********/#include "spice.h"#include <stdio.h>#include "util.h"#include "devdefs.h"#include "cktdefs.h"#include "mesdefs.h"#include "distodef.h"#include "const.h"#include "sperror.h"#include "suffix.h"intMESdSetup(inModel,ckt)    GENmodel *inModel;    CKTcircuit *ckt;        /* actually load the current resistance value into the          * sparse matrix previously provided          */{    register MESmodel *model = (MESmodel*)inModel;    register MESinstance *here;    double afact;    double beta;    double betap;    double cdrain;    double cg;    double cgd;    double csat;    double czgd;    double czgs;    double denom;    double evgd;    double evgs;    double gdpr;    double gspr;    double invdenom;    double lfact;    double phib;    double prod;    double vcap;    double vcrit;    double vds;    double vgd;    double vgs;    double vgst;    double vto;                double lggd1;		double lggd2;		double lggd3;                double lggs1;		double lggs2;		double lggs3;		Dderivs d_cdrain, d_qgs, d_qgd;	    Dderivs d_p, d_q, d_r, d_zero;    /*  loop through all the models */    for( ; model != NULL; model = model->MESnextModel ) {        /* loop through all the instances of the model */        for (here = model->MESinstances; here != NULL ;                here=here->MESnextInstance) {            /*             *  dc model parameters              */            beta = model->MESbeta * here->MESarea;            gdpr = model->MESdrainConduct * here->MESarea;            gspr = model->MESsourceConduct * here->MESarea;            csat = model->MESgateSatCurrent * here->MESarea;            vcrit = model->MESvcrit;            vto = model->MESthreshold;            /*             *    initialization             */                    /*                     *  compute new nonlinear branch voltages                      */                    vgs = model->MEStype*                        (*(ckt->CKTrhsOld+ here->MESgateNode)-                        *(ckt->CKTrhsOld+                         here->MESsourcePrimeNode));                    vgd = model->MEStype*                        (*(ckt->CKTrhsOld+here->MESgateNode)-                        *(ckt->CKTrhsOld+                        here->MESdrainPrimeNode));                            /*             *   determine dc current and derivatives              */            vds = vgs-vgd;            if (vgs <= -5*CONSTvt0) {                lggs1 = -csat/vgs+ckt->CKTgmin;		lggs2=lggs3=0;                cg = lggs1*vgs;            } else {                evgs = exp(vgs/CONSTvt0);                lggs1 = csat*evgs/CONSTvt0+ckt->CKTgmin;		lggs2 = (lggs1-ckt->CKTgmin)/(CONSTvt0*2);		lggs3 = lggs2/(3*CONSTvt0);                cg = csat*(evgs-1)+ckt->CKTgmin*vgs;            }            if (vgd <= -5*CONSTvt0) {                lggd1 = -csat/vgd+ckt->CKTgmin;		lggd2=lggd3=0;                cgd = lggd1*vgd;            } else {                evgd = exp(vgd/CONSTvt0);                lggd1 = csat*evgd/CONSTvt0+ckt->CKTgmin;		lggd2 = (lggd1-ckt->CKTgmin)/(CONSTvt0*2);		lggd3 = lggd2/(3*CONSTvt0);                cgd = csat*(evgd-1)+ckt->CKTgmin*vgd;            }            cg = cg+cgd;            /*             *   compute drain current and derivitives for normal mode              */	    /* until now, we were using the real vgs, vgd, and vds */            {	    /* converting (temporarily) to local vgs, vgd, and vds */	    double vgsreal=vgs;	    double vgdreal=vgd;	    double vdsreal=vds;	    Dderivs d_afact, d_lfact;	    Dderivs d_betap, d_denom, d_invdenom;	    Dderivs d_prod;	    Dderivs d_vgst;	    if (vdsreal < 0.0) {		vgs = vgdreal;		vgd = vgsreal;		vds = -vdsreal;		here->MESmode = -1;		/* source-drain  interchange */		}		else 			here->MESmode = 1;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_r.value = vds;    /* p =vgs; q= nothing in particular ; r = vds */                vgst = vgs-model->MESthreshold;		EqualDeriv(&d_vgst,&d_p);		d_vgst.value = vgst;                /*                 *   normal mode, cutoff region                  */                if (vgst <= 0) {                    cdrain = 0;		    EqualDeriv(&d_cdrain,&d_zero);                } else {                    prod = 1 + model->MESlModulation * vds;		    TimesDeriv(&d_prod,&d_r,model->MESlModulation);		    d_prod.value = prod;                    betap = beta * prod;		    TimesDeriv(&d_betap,&d_prod,beta);                    denom = 1 + model->MESb * vgst;		    TimesDeriv(&d_denom,&d_vgst,model->MESb);		    d_denom.value = denom;                    invdenom = 1 / denom;		    InvDeriv(&d_invdenom,&d_denom);                            /*                             *   normal mode, saturation region                              */                        cdrain = betap * vgst * vgst * invdenom;			MultDeriv(&d_cdrain,&d_betap,&d_vgst);			MultDeriv(&d_cdrain,&d_cdrain,&d_vgst);			MultDeriv(&d_cdrain,&d_cdrain,&d_invdenom);                    if (vds < ( 3 / model->MESalpha ) ) {                        /*                         *   normal mode, linear region                          */                        afact = 1 - model->MESalpha * vds / 3;			TimesDeriv(&d_afact,&d_r,-model->MESalpha/3.0);			d_afact.value = afact;                        lfact = 1 - afact * afact * afact;			CubeDeriv(&d_lfact,&d_afact);			TimesDeriv(&d_lfact,&d_lfact,-1.0);			d_lfact.value += 1.0;			cdrain = betap*vgst*vgst*invdenom*lfact;			MultDeriv(&d_cdrain,&d_betap,&d_vgst);			MultDeriv(&d_cdrain,&d_cdrain,&d_vgst);			MultDeriv(&d_cdrain,&d_cdrain,&d_invdenom);			MultDeriv(&d_cdrain,&d_cdrain,&d_lfact);                    }                }		/* converting back to real vgs, vgd, vds */		if (here->MESmode == -1) {			vgs = vgsreal;			vgd = vgdreal;			vds = vdsreal;			}		}                /*                  *    charge storage elements                  */{ /* code block */czgs = model->MEScapGS * here->MESarea;czgd = model->MEScapGD * here->MESarea;phib = model->MESgatePotential;vcap = 1 / model->MESalpha;/* * qgga = qggnew(vgs,vgd,phib,vcap,vto,czgs,czgd,&cgsna,&cgdna); *//* function qggnew  - private, used by MESload*/{    double veroot,veff1,veff2,del,vnroot,vnew1,vnew3,vmax,ext;    double qroot,par1,cfact,cplus,cminus;    Dderivs d_vnroot;    Dderivs d_cgsnew, d_cgdnew, d_dummy, d_dummy2;    Dderivs d_ext, d_qroot, d_par1, d_cfact, d_cplus, d_cminus;    Dderivs d_veroot, d_veff1, d_veff2, d_vnew1, d_vnew3;/* now p=vgs, q=vgd, r= nothing */    d_q.value = vgd; d_p.value = vgs;     veroot = sqrt( (vgs - vgd) * (vgs - vgd) + vcap*vcap );    TimesDeriv(&d_veroot,&d_q,-1.0);    PlusDeriv(&d_veroot,&d_veroot,&d_p);    MultDeriv(&d_veroot,&d_veroot,&d_veroot);    d_veroot.value += vcap*vcap;    SqrtDeriv(&d_veroot,&d_veroot);    veff1 = 0.5 * (vgs + vgd + veroot);    PlusDeriv(&d_veff1,&d_veroot,&d_p);    PlusDeriv(&d_veff1,&d_veff1,&d_q);    TimesDeriv(&d_veff1,&d_veff1,0.5);    veff2 = veff1 - veroot;    TimesDeriv(&d_veff2,&d_veroot,-1.0);    PlusDeriv(&d_veff2,&d_veff2,&d_veff1);    del = 0.2;/*const*/    vnroot = sqrt( (veff1 - vto)*(veff1 - vto) + del * del );    EqualDeriv(&d_vnroot,&d_veff1);    d_vnroot.value -= vto;    MultDeriv(&d_vnroot,&d_vnroot,&d_vnroot);    d_vnroot.value += del*del;    SqrtDeriv(&d_vnroot,&d_vnroot);    vnew1 = 0.5 * (veff1 + vto + vnroot);    PlusDeriv(&d_vnew1,&d_veff1,&d_vnroot);    d_vnew1.value += vto;    TimesDeriv(&d_vnew1,&d_vnew1,0.5);    vnew3 = vnew1;    EqualDeriv(&d_vnew3,&d_vnew1);    vmax = 0.5;/*const*/    if ( vnew1 < vmax ) {        ext=0;	EqualDeriv(&d_ext,&d_zero);    } else {        vnew1 = vmax;	EqualDeriv(&d_vnew1,&d_zero);	d_vnew1.value = vmax;        ext = (vnew3 - vmax)/sqrt(1 - vmax/phib);	EqualDeriv(&d_ext,&d_vnew3);	d_ext.value -= vmax;	TimesDeriv(&d_ext,&d_ext,1/sqrt(1 - vmax/phib));    }    qroot = sqrt(1 - vnew1/phib);    TimesDeriv(&d_qroot,&d_vnew1,-1/phib);    d_qroot.value += 1.0;    SqrtDeriv(&d_qroot,&d_qroot);    /*     * qggval = czgs * (2*phib*(1-qroot) + ext) + czgd*veff2;     */    par1 = 0.5 * ( 1 + (veff1-vto)/vnroot);    EqualDeriv(&d_par1,&d_veff1);    d_par1.value -= vto;    DivDeriv(&d_par1,&d_par1,&d_vnroot);    d_par1.value += 1.0;    TimesDeriv(&d_par1,&d_par1,0.5);    cfact = (vgs- vgd)/veroot;    TimesDeriv(&d_cfact,&d_q,-1.0);    PlusDeriv(&d_cfact,&d_cfact,&d_p);    DivDeriv(&d_cfact,&d_cfact,&d_veroot);    cplus = 0.5 * (1 + cfact);    TimesDeriv(&d_cplus,&d_cfact,0.5);    d_cplus.value += 0.5;    cminus = cplus - cfact;    TimesDeriv(&d_cminus,&d_cfact,-0.5);    d_cminus.value += 0.5;    /*     *cgsnew = czgs/qroot*par1*cplus + czgd*cminus;     *cgdnew = czgs/qroot*par1*cminus + czgd*cplus;     *     * assuming qgs = vgs*cgsnew     * and      qgd = vgd*cgsnew     *     * This is probably wrong but then so is the a.c. analysis      * routine and everything else     *     */     MultDeriv(&d_dummy,&d_qroot,&d_par1);     InvDeriv(&d_dummy,&d_dummy);     TimesDeriv(&d_dummy,&d_dummy,czgs);     TimesDeriv(&d_cgsnew,&d_cminus,czgd);     MultDeriv(&d_dummy2,&d_dummy,&d_cplus);     PlusDeriv(&d_cgsnew,&d_cgsnew,&d_dummy2);     TimesDeriv(&d_cgdnew,&d_cplus,czgd);     MultDeriv(&d_dummy2,&d_dummy,&d_cminus);     PlusDeriv(&d_cgdnew,&d_cgdnew,&d_dummy2);     MultDeriv(&d_qgs,&d_cgsnew,&d_p);     MultDeriv(&d_qgd,&d_cgdnew,&d_q);}}	if (here->MESmode == 1)		{		/* normal mode - no source-drain interchange */here->cdr_x = d_cdrain.d1_p;here->cdr_z = d_cdrain.d1_r;here->cdr_x2 = d_cdrain.d2_p2;here->cdr_z2 = d_cdrain.d2_r2;here->cdr_xz = d_cdrain.d2_pr;here->cdr_x3 = d_cdrain.d3_p3;here->cdr_z3 = d_cdrain.d3_r3;;here->cdr_x2z = d_cdrain.d3_p2r;here->cdr_xz2 = d_cdrain.d3_pr2;} else {		/*		 * inverse mode - source and drain interchanged		 */here->cdr_x = -d_cdrain.d1_p;here->cdr_z = d_cdrain.d1_p + d_cdrain.d1_r;here->cdr_x2 = -d_cdrain.d2_p2;here->cdr_z2 = -(d_cdrain.d2_p2 + d_cdrain.d2_r2 + 2*d_cdrain.d2_pr);here->cdr_xz = d_cdrain.d2_p2 + d_cdrain.d2_pr;here->cdr_x3 = -d_cdrain.d3_p3;here->cdr_z3 = d_cdrain.d3_p3 + d_cdrain.d3_r3 + 3*(d_cdrain.d3_p2r + d_cdrain.d3_pr2 ) ;here->cdr_x2z = d_cdrain.d3_p3 + d_cdrain.d3_p2r;here->cdr_xz2 = -(d_cdrain.d3_p3 + 2*d_cdrain.d3_p2r + d_cdrain.d3_pr2);}/* now to adjust for type and multiply by factors to convert to Taylor coeffs. */here->cdr_x2 = 0.5*model->MEStype*here->cdr_x2;here->cdr_z2 = 0.5*model->MEStype*here->cdr_z2;here->cdr_xz = model->MEStype*here->cdr_xz;here->cdr_x3 = here->cdr_x3/6.;here->cdr_z3 = here->cdr_z3/6.;here->cdr_x2z = 0.5*here->cdr_x2z;here->cdr_xz2 = 0.5*here->cdr_xz2;here->ggs3 = lggs3;here->ggd3 = lggd3;here->ggs2 = model->MEStype*lggs2;here->ggd2 = model->MEStype*lggd2;here->qgs_x2 = 0.5*model->MEStype*d_qgs.d2_p2;here->qgs_y2 = 0.5*model->MEStype*d_qgs.d2_q2;here->qgs_xy = model->MEStype*d_qgs.d2_pq;here->qgs_x3 = d_qgs.d3_p3/6.;here->qgs_y3 = d_qgs.d3_q3/6.;here->qgs_x2y = 0.5*d_qgs.d3_p2q;here->qgs_xy2 = 0.5*d_qgs.d3_pq2;here->qgd_x2 = 0.5*model->MEStype*d_qgd.d2_p2;here->qgd_y2 = 0.5*model->MEStype*d_qgd.d2_q2;here->qgd_xy = model->MEStype*d_qgd.d2_pq;here->qgd_x3 = d_qgd.d3_p3/6.;here->qgd_y3 = d_qgd.d3_q3/6.;here->qgd_x2y = 0.5*d_qgd.d3_p2q;here->qgd_xy2 = 0.5*d_qgd.d3_pq2;        }    }    return(OK);}

⌨️ 快捷键说明

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