📄 mos1dset.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 "mos1defs.h"#include "util.h"#include "distodef.h"#include "const.h"#include "sperror.h"#include "suffix.h"intMOS1dSetup(inModel,ckt) GENmodel *inModel; register CKTcircuit *ckt; /* actually load the current value into the * sparse matrix previously provided */{ register MOS1model *model = (MOS1model *) inModel; register MOS1instance *here; double Beta; double DrainSatCur; double EffectiveLength; double GateBulkOverlapCap; double GateDrainOverlapCap; double GateSourceOverlapCap; double OxideCap; double SourceSatCur; double gm; double gds; double gb; double ebd; double vgst; double evbs; double sargsw; double vbd; double vbs; double vds; double arg; double sarg; double vdsat; double vgd; double vgs; double von; double vt; double lgbs; double lgbs2; double lgbs3; double lgbd; double lgbd2; double lgbd3; double gm2; double gds2; double gb2; double gmds; double gmb; double gbds; double gm3; double gds3; double gb3; double gm2ds; double gmds2; double gm2b; double gmb2; double gb2ds; double gbds2; double lcapgb2; double lcapgb3; double lcapgs2; double lcapgs3; double lcapgd2; double lcapgd3; double lcapbs2; double lcapbs3; double lcapbd2; double lcapbd3; double gmbds;#ifndef NOBYPASS#endif /*NOBYPASS*/ /* loop through all the MOS1 device models */ for( ; model != NULL; model = model->MOS1nextModel ) { /* loop through all the instances of the model */ for (here = model->MOS1instances; here != NULL ; here=here->MOS1nextInstance) { if (here->MOS1owner != ARCHme) continue; vt = CONSTKoverQ * here->MOS1temp; EffectiveLength=here->MOS1l - 2*model->MOS1latDiff; if( (here->MOS1tSatCurDens == 0) || (here->MOS1drainArea == 0) || (here->MOS1sourceArea == 0)) { DrainSatCur = here->MOS1tSatCur; SourceSatCur = here->MOS1tSatCur; } else { DrainSatCur = here->MOS1tSatCurDens * here->MOS1drainArea; SourceSatCur = here->MOS1tSatCurDens * here->MOS1sourceArea; } GateSourceOverlapCap = model->MOS1gateSourceOverlapCapFactor * here->MOS1w; GateDrainOverlapCap = model->MOS1gateDrainOverlapCapFactor * here->MOS1w; GateBulkOverlapCap = model->MOS1gateBulkOverlapCapFactor * EffectiveLength; Beta = here->MOS1tTransconductance * here->MOS1w/EffectiveLength; OxideCap = model->MOS1oxideCapFactor * EffectiveLength * here->MOS1w; vbs = model->MOS1type * ( *(ckt->CKTrhsOld+here->MOS1bNode) - *(ckt->CKTrhsOld+here->MOS1sNodePrime)); vgs = model->MOS1type * ( *(ckt->CKTrhsOld+here->MOS1gNode) - *(ckt->CKTrhsOld+here->MOS1sNodePrime)); vds = model->MOS1type * ( *(ckt->CKTrhsOld+here->MOS1dNodePrime) - *(ckt->CKTrhsOld+here->MOS1sNodePrime)); /* now some common crunching for some more useful quantities */ vbd=vbs-vds; vgd=vgs-vds; /* * bulk-source and bulk-drain diodes * here we just evaluate the ideal diode current and the * corresponding 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->MOS1type *0.5 * (lgbs - ckt->CKTgmin)/vt; lgbs3 = model->MOS1type *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->MOS1type *0.5 * (lgbd - ckt->CKTgmin)/vt; lgbd3 = model->MOS1type *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->MOS1mode = 1; } else { /* inverse mode */ here->MOS1mode = -1; } /* * this block of code evaluates the drain current and its * derivatives using the shichman-hodges model and the * charges associated with the gate, channel and bulk for * mosfets * */ /* the following variables are local to this code block until * it is obvious that they can be made global */ { double betap; double dvondvbs; double d2vondvbs2; double d3vondvbs3; if ((here->MOS1mode==1?vbs:vbd) <= 0 ) { sarg=sqrt(here->MOS1tPhi-(here->MOS1mode==1?vbs:vbd)); if (-model->MOS1gamma != 0.0) { dvondvbs = -model->MOS1gamma*0.5/sarg; d2vondvbs2 = - dvondvbs*0.5/(sarg*sarg); d3vondvbs3 = 1.5*d2vondvbs2/(sarg*sarg); } else { dvondvbs = d2vondvbs2 = d3vondvbs3 = 0.0; } } else { sarg=sqrt(here->MOS1tPhi); if (model->MOS1gamma != 0.0) { dvondvbs = -model->MOS1gamma/(sarg+sarg); } else { dvondvbs = 0.0; } d2vondvbs2 = d3vondvbs3 = 0; sarg=sarg-(here->MOS1mode==1?vbs:vbd)/(sarg+sarg); sarg=MAX(0,sarg); dvondvbs = (sarg<=0?0:dvondvbs); } von=(here->MOS1tVbi*model->MOS1type)+model->MOS1gamma*sarg; vgst=(here->MOS1mode==1?vgs:vgd)-von; vdsat=MAX(vgst,0);/* if (sarg <= 0) { arg=0; } else { arg=model->MOS1gamma/(sarg+sarg); } */ if (vgst <= 0) { /* * cutoff region */ /* cdrain = 0 */ gm=0; gds=0; gb=0; gm2=gb2=gds2=0; gmds=gbds=gmb=0; gm3=gb3=gds3=0; gm2ds=gmds2=gm2b=gmb2=gb2ds=gbds2=0; } else{ /* * saturation region */ betap=Beta*(1+model->MOS1lambda*(vds*here->MOS1mode)); /* cdrain = betap * vgst * vgst * 0.5; */ if (vgst <= (vds*here->MOS1mode)){ gm=betap*vgst; gds=model->MOS1lambda*Beta*vgst*vgst*.5; /* gb=here->MOS1gm*arg; */ gb= -gm*dvondvbs; gm2 = betap; gds2 = 0; gb2 = -(gm*d2vondvbs2 - betap*dvondvbs*dvondvbs); gmds = vgst*model->MOS1lambda*Beta; gbds = - gmds*dvondvbs; gmb = -betap*dvondvbs; gm3 = 0; gb3 = -(gmb*d2vondvbs2 + gm*d3vondvbs3 - betap*2*dvondvbs*d2vondvbs2); gds3 = 0; gm2ds = Beta * model->MOS1lambda; gm2b = 0; gmb2 = -betap*d2vondvbs2; gb2ds = -(gmds*d2vondvbs2 - dvondvbs*dvondvbs* Beta * model->MOS1lambda); gmds2 = 0; gbds2 = 0; gmbds = -Beta * model->MOS1lambda*dvondvbs; } else { /* * linear region */ /* cdrain = betap * vds * (vgst - vds/2); */ gm=betap*(vds*here->MOS1mode); gds= Beta * model->MOS1lambda*(vgst* vds*here->MOS1mode - vds*vds*0.5) + betap*(vgst - vds*here->MOS1mode); /* gb=gm*arg; */ gb = - gm*dvondvbs; gm2 = 0; gb2 = -(gm*d2vondvbs2); gds2 = 2*Beta * model->MOS1lambda*(vgst - vds*here->MOS1mode) - betap; gmds = Beta * model->MOS1lambda* vds * here->MOS1mode + betap; gbds = - gmds*dvondvbs; gmb=0; gm3=0; gb3 = -gm*d3vondvbs3; gds3 = -Beta*model->MOS1lambda*3.; gm2ds=gm2b=gmb2=0; gmds2 = 2*model->MOS1lambda*Beta; gb2ds = -(gmds*d2vondvbs2); gbds2 = -gmds2*dvondvbs; gmbds = 0; } } /* * finished */ } /* code block */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -