📄 mos3dset.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1988 Jaijeet S Roychowdhury**********/#include "spice.h"#include <stdio.h>#include "cktdefs.h"#include "devdefs.h"#include "mos3defs.h"#include "util.h"#include "trandefs.h"#include "distodef.h"#include "const.h"#include "sperror.h"#include "suffix.h"intMOS3dSetup(inModel,ckt) GENmodel *inModel; register CKTcircuit *ckt; /* actually load the current value into the * sparse matrix previously provided */{ register MOS3model *model = (MOS3model *)inModel; register MOS3instance *here; double Beta; double DrainSatCur; double EffectiveLength; double GateBulkOverlapCap; double GateDrainOverlapCap; double GateSourceOverlapCap; double OxideCap; double SourceSatCur; double arg; double cdrain; double evbs; double sarg; double sargsw; double lvgs; double vbd; double vbs; double vds; double vdsat; double vgb; double vgd; double vgs; double von; double lcapgs2,lcapgs3; /* total gate-source capacitance */ double lcapgd2,lcapgd3; /* total gate-drain capacitance */ double lcapgb2,lcapgb3; /* total gate-bulk capacitance */ double lgbs, lgbs2, lgbs3; double lgbd, lgbd2, lgbd3; double gm2, gb2, gds2, gmb, gmds, gbds; double gm3, gb3, gds3, gm2ds, gm2b, gb2ds, gbds2, gmb2, gmds2, gmbds; double lcapbd, lcapbd2, lcapbd3; double lcapbs, lcapbs2, lcapbs3; double ebd; double vt; /* vt at instance temperature */ Dderivs d_cdrain; /* loop through all the MOS3 device models */next: for( ; model != NULL; model = model->MOS3nextModel ) { /* loop through all the instances of the model */ for (here = model->MOS3instances; here != NULL ; here=here->MOS3nextInstance) { vt = CONSTKoverQ * here->MOS3temp; /* 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->MOS3l - 2*model->MOS3latDiff; if( (here->MOS3tSatCurDens == 0) || (here->MOS3drainArea == 0) || (here->MOS3sourceArea == 0)) { DrainSatCur = here->MOS3tSatCur; SourceSatCur = here->MOS3tSatCur; } else { DrainSatCur = here->MOS3tSatCurDens * here->MOS3drainArea; SourceSatCur = here->MOS3tSatCurDens * here->MOS3sourceArea; } GateSourceOverlapCap = model->MOS3gateSourceOverlapCapFactor * here->MOS3w; GateDrainOverlapCap = model->MOS3gateDrainOverlapCapFactor * here->MOS3w; GateBulkOverlapCap = model->MOS3gateBulkOverlapCapFactor * EffectiveLength; Beta = here->MOS3tTransconductance * here->MOS3w/EffectiveLength; OxideCap = model->MOS3oxideCapFactor * EffectiveLength * here->MOS3w; /* * 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 */ /* general iteration */ vbs = model->MOS3type * ( *(ckt->CKTrhsOld+here->MOS3bNode) - *(ckt->CKTrhsOld+here->MOS3sNodePrime)); vgs = model->MOS3type * ( *(ckt->CKTrhsOld+here->MOS3gNode) - *(ckt->CKTrhsOld+here->MOS3sNodePrime)); vds = model->MOS3type * ( *(ckt->CKTrhsOld+here->MOS3dNodePrime) - *(ckt->CKTrhsOld+here->MOS3sNodePrime)); /* now some common crunching for some more useful quantities */ /* * now all the preliminaries are over - we can start doing the * real work */ vbd = vbs - vds; vgd = vgs - vds; vgb = vgs - vbs; /* bulk-source and bulk-drain doides * here we just evaluate the ideal diode current and the * correspoinding derivative (conductance). */next1: if(vbs <= 0) { lgbs = SourceSatCur/vt; lgbs += ckt->CKTgmin; lgbs2 = lgbs3 = 0; } else { evbs = exp(MIN(MAX_EXP_ARG,vbs/vt)); lgbs = SourceSatCur*evbs/vt + ckt->CKTgmin; lgbs2 = model->MOS3type *0.5 * (lgbs - ckt->CKTgmin)/vt; lgbs3 = model->MOS3type *lgbs2/(vt*3); } if(vbd <= 0) { lgbd = DrainSatCur/vt; lgbd += ckt->CKTgmin; lgbd2 = lgbd3 = 0; } else { ebd = exp(MIN(MAX_EXP_ARG,vbd/vt)); lgbd = DrainSatCur*ebd/vt +ckt->CKTgmin; lgbd2 = model->MOS3type *0.5 * (lgbd - ckt->CKTgmin)/vt; lgbd3 = model->MOS3type *lgbd2/(vt*3); } /* now to determine whether the user was able to correctly * identify the source and drain of his device */ if(vds >= 0) { /* normal mode */ here->MOS3mode = 1; } else { /* inverse mode */ here->MOS3mode = -1; } { /* * subroutine moseq3(vds,vbs,vgs,gm,gds,gmbs, * qg,qc,qb,cggb,cgdb,cgsb,cbgb,cbdb,cbsb) */ /* * this routine evaluates the drain current, its derivatives and * the charges associated with the gate, channel and bulk * for mosfets based on semi-empirical equations */ /* common /mosarg/ vto,beta,gamma,phi,phib,cox,xnsub,xnfs,xd,xj,xld, 1 xlamda,uo,uexp,vbp,utra,vmax,xneff,xl,xw,vbi,von,vdsat,qspof, 2 beta0,beta1,cdrain,xqco,xqc,fnarrw,fshort,lev common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet, 1 xmu,sfactr,mode,modedc,icalc,initf,method,iord,maxord,noncon, 2 iterno,itemno,nosolv,modac,ipiv,ivmflg,ipostp,iscrch,iofile common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok, 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox, 2 pivtol,pivrel */ /* equivalence (xlamda,alpha),(vbp,theta),(uexp,eta),(utra,xkappa)*/ double coeff0 = 0.0631353e0; double coeff1 = 0.8013292e0; double coeff2 = -0.01110777e0; double oneoverxl; /* 1/effective length */ double eta; /* eta from model after length factor */ double phibs; /* phi - vbs */ double sqphbs; /* square root of phibs */ double sqphis; /* square root of phi */ double wps; double oneoverxj; /* 1/junction depth */ double xjonxl; /* junction depth/effective length */ double djonxj; double wponxj; double arga; double argb; double argc; double gammas; double fbodys; double fbody; double onfbdy; double qbonco; double vbix; double wconxj; double vth; double csonco; double cdonco; double vgsx; double onfg; double fgate; double us; double xn; double vdsc; double onvdsc; double vdsx; double cdnorm; double cdo; double fdrain; double gdsat; double cdsat; double emax; double delxl; double dlonxl; double xlfact; double ondvt; double onxn; double wfact; double fshort; double lvds, lvbs, lvbd; Dderivs d_onxn, d_ondvt, d_wfact, d_MOS3gds; Dderivs d_emax, d_delxl, d_dlonxl, d_xlfact; Dderivs d_cdonco, d_fdrain, d_cdsat, d_gdsat; Dderivs d_vdsx, d_cdo, d_cdnorm, d_Beta, d_dummy; Dderivs d_vdsc, d_onvdsc, d_arga, d_argb; Dderivs d_onfg, d_fgate, d_us, d_vgsx; Dderivs d_von, d_xn, d_vth, d_onfbdy, d_qbonco, d_vbix; Dderivs d_argc, d_fshort, d_gammas, d_fbodys, d_fbody; Dderivs d_wps, d_wconxj, d_wponxj; Dderivs d_phibs, d_sqphbs; Dderivs d_p, d_q, d_r, d_zero, d_vdsat; /* * bypasses the computation of charges */ if (here->MOS3mode == 1) { lvgs = vgs; lvds = vds; lvbs = vbs; lvbd = vbd; } else { lvgs = vgd; lvds = -vds; lvbs = vbd; lvbd = vbs; } /* * reference cdrain equations to source and * charge equations to bulk */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; vdsat = 0.0; EqualDeriv(&d_vdsat,&d_zero); oneoverxl = 1.0/EffectiveLength;/*const*/ eta = model->MOS3eta * 8.15e-22/(model->MOS3oxideCapFactor* EffectiveLength*EffectiveLength*EffectiveLength);/*const*/ /* *.....square root term */ if ( lvbs <= 0.0 ) { phibs = here->MOS3tPhi-lvbs; EqualDeriv(&d_phibs,&d_q); d_phibs.value = lvbs; TimesDeriv(&d_phibs,&d_phibs,-1.0); d_phibs.value += here->MOS3tPhi; sqphbs = sqrt(phibs); SqrtDeriv(&d_sqphbs,&d_phibs); } else { sqphis = sqrt(here->MOS3tPhi);/*const*/ /*sqphs3 = here->MOS3tPhi*sqphis;const*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -