📄 mesdset.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 + -