📄 mos2dset.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1988 Jaijeet S Roychowdhury**********/#include <stdio.h>#include "spice.h"#include "util.h"#include "distodef.h"#include "devdefs.h"#include "cktdefs.h"#include "mos2defs.h"#include "trandefs.h"#include "const.h"#include "sperror.h"#include "suffix.h"/* assuming silicon - make definition for epsilon of silicon */#define EPSSIL (11.7 * 8.854214871e-12)static double sig1[4] = {1.0, -1.0, 1.0, -1.0};static double sig2[4] = {1.0, 1.0,-1.0, -1.0};intMOS2dSetup(inModel,ckt) GENmodel *inModel; register CKTcircuit *ckt; /* actually load the current value into the * sparse matrix previously provided */{ register MOS2model *model = (MOS2model *)inModel; register MOS2instance *here; double Beta; double DrainSatCur; double EffectiveLength; double GateBulkOverlapCap; double GateDrainOverlapCap; double GateSourceOverlapCap; double OxideCap; double SourceSatCur; double arg; double cdrain; double ebd; double evbs; double sarg; double sargsw; double vbd; double vbs; double vds; double vdsat; double vgb; double vgd; double vgs; double von; double vt; /* K * T / Q */ double lcapgs2; double lcapgd2; double lcapgb2; double lcapgs3; double lcapgd3; double lcapgb3; double lgbs, lgbs2, lgbs3; double lgbd, lgbd2, lgbd3; double vgst;double lcapbs, lcapbs2, lcapbs3;double lcapbd, lcapbd2, lcapbd3;double gm2, gb2, gds2;double gmb, gmds, gbds;double gm3, gb3, gds3;double gm2b, gm2ds, gmb2, gmds2, gbds2, gb2ds;double gmbds; Dderivs d_cdrain; /* loop through all the MOS2 device models */ for( ; model != NULL; model = model->MOS2nextModel ) { /* loop through all the instances of the model */ for (here = model->MOS2instances; here != NULL ; here=here->MOS2nextInstance) { if (here->MOS2owner != ARCHme) continue; vt = CONSTKoverQ * here->MOS2temp; EffectiveLength=here->MOS2l - 2*model->MOS2latDiff; if( (here->MOS2tSatCurDens == 0) || (here->MOS2drainArea == 0) || (here->MOS2sourceArea == 0)) { DrainSatCur = here->MOS2tSatCur; SourceSatCur = here->MOS2tSatCur; } else { DrainSatCur = here->MOS2tSatCurDens * here->MOS2drainArea; SourceSatCur = here->MOS2tSatCurDens * here->MOS2sourceArea; } GateSourceOverlapCap = model->MOS2gateSourceOverlapCapFactor * here->MOS2w; GateDrainOverlapCap = model->MOS2gateDrainOverlapCapFactor * here->MOS2w; GateBulkOverlapCap = model->MOS2gateBulkOverlapCapFactor * EffectiveLength; Beta = here->MOS2tTransconductance * here->MOS2w/EffectiveLength; OxideCap = model->MOS2oxideCapFactor * EffectiveLength * here->MOS2w; /* general iteration */ vbs = model->MOS2type * ( *(ckt->CKTrhsOld+here->MOS2bNode) - *(ckt->CKTrhsOld+here->MOS2sNodePrime)); vgs = model->MOS2type * ( *(ckt->CKTrhsOld+here->MOS2gNode) - *(ckt->CKTrhsOld+here->MOS2sNodePrime)); vds = model->MOS2type * ( *(ckt->CKTrhsOld+here->MOS2dNodePrime) - *(ckt->CKTrhsOld+here->MOS2sNodePrime)); /* now some common crunching for some more useful quantities */ vbd=vbs-vds; vgd=vgs-vds; /* now all the preliminaries are over - we can start doing the * real work */ 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->MOS2type *0.5 * (lgbs - ckt->CKTgmin)/vt; lgbs3 = model->MOS2type *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->MOS2type *0.5 * (lgbd - ckt->CKTgmin)/vt; lgbd3 = model->MOS2type *lgbd2/(vt*3); } if(vds >= 0) { /* normal mode */ here->MOS2mode = 1; } else { /* inverse mode */ here->MOS2mode = -1; } { /* moseq2(vds,vbs,vgs,gm,gds,gmbs,qg,qc,qb, * cggb,cgdb,cgsb,cbgb,cbdb,cbsb) */ /* note: cgdb, cgsb, cbdb, cbsb never used */ /* * this routine evaluates the drain current, its derivatives and * the charges associated with the gate, channel and bulk * for mosfets * */ double arg; double sarg; double a4[4],b4[4],x4[8],poly4[8]; double beta1; double sphi; /* square root of phi */ double sphi3; /* square root of phi cubed */ double barg; double factor; double eta; double vbin; double argd; double args; double argss; double argsd; double argxs; double argxd; double gamasd; double xwd; double xws; double gammad; double cfs; double cdonco; double xn; double argg; double sarg3; double sbiarg; double body; double udenom; double gammd2; double argv; double vgsx; double ufact; double ueff; double a1; double a3; double a; double b1; double b3; double b; double c1; double c; double d1; double fi; double p0; double p2; double p3; double p4; double p; double r3; double r; double ro; double s2; double s; double v1; double v2; double xv; double y3; double delta4; double xvalid; double bsarg; double bodys; double sargv; double xlfact; double xdv; double xlv; double xls; double clfact; double xleff; double deltal; double xwb; double vdson; double cdson; double expg; double xld; double xlamda = model->MOS2lambda; Dderivs d_xleff, d_delta1; Dderivs d_xlfact; Dderivs d_xlv, d_xls; Dderivs d_bsarg, d_bodys, d_vdsat, d_sargv; Dderivs d_delta4, d_a4[3], d_b4[3], d_x4[3], d_poly4[3]; Dderivs d_xvalid; Dderivs d_ro, d_fi, d_y3, d_p3, d_p4, d_a3, d_b3; Dderivs d_r3, d_s2, d_pee, d_p0, d_p2; Dderivs d_b1, d_c1, d_d1, d_a, d_b, d_c, d_arr, d_s; Dderivs d_xv, d_a1; Dderivs d_v1, d_v2; Dderivs d_argv,d_gammd2; Dderivs d_ufact; Dderivs d_udenom; Dderivs d_sarg3, d_body; Dderivs d_vgst; Dderivs d_argg; Dderivs d_cdonco,d_tmp,d_xn; Dderivs d_dbargs,d_dbargd,d_dgddvb; Dderivs d_dbxwd,d_dbxws; Dderivs d_dsrgdb, d_dbrgdb; Dderivs d_gamasd, d_gammad, d_args, d_argd; Dderivs d_argxs, d_argxd; Dderivs d_argss, d_argsd; Dderivs d_xwd, d_xws; Dderivs d_zero; Dderivs d_vbin; Dderivs d_barg; Dderivs d_sarg; Dderivs d_phiMinVbs; Dderivs d_p, d_q, d_r; Dderivs d_von, d_dummy, d_vgsx, d_arg, d_dumarg; Dderivs d_ueff, d_beta1, d_clfact, d_xlamda,d_mos2gds; Dderivs d_vdson, d_cdson, d_expg; double dsrgdb, dbrgdb, dbxwd, dbxws, dbargs, dbargd; double dgddvb;/* from now on, p=vgs, q=vbs, r=vds *//* * 'local' variables - these switch d & s around appropriately * so that we don't have to worry about vds < 0 */ double lvbs = here->MOS2mode==1?vbs:vbd; double lvds = here->MOS2mode*vds; double lvgs = here->MOS2mode==1?vgs:vgd; double phiMinVbs = here->MOS2tPhi - lvbs; double tmp; /* a temporary variable, not used for more than */ /* about 10 lines at a time */ int iknt; int jknt; int i; int j; /* * compute some useful quantities */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; EqualDeriv(&d_phiMinVbs,&d_q); d_phiMinVbs.value = phiMinVbs; d_phiMinVbs.d1_q = - d_phiMinVbs.d1_q; if (lvbs <= 0.0) { sarg = sqrt(phiMinVbs); SqrtDeriv(&d_sarg, &d_phiMinVbs); dsrgdb = -0.5/sarg; InvDeriv(&d_dsrgdb,&d_sarg); TimesDeriv(&d_dsrgdb,&d_dsrgdb,-0.5); } else { sphi = sqrt(here->MOS2tPhi); /*const*/ sphi3 = here->MOS2tPhi*sphi; /*const*/ sarg = sphi/(1.0+0.5*lvbs/here->MOS2tPhi); EqualDeriv(&d_sarg,&d_q); d_sarg.value = lvbs; TimesDeriv(&d_sarg,&d_sarg,0.5/here->MOS2tPhi); d_sarg.value += 1.0; InvDeriv(&d_sarg,&d_sarg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -