📄 soi3load.c
字号:
/**********STAG version 2.7Copyright 2000 owned by the United Kingdom Secretary of State for Defenceacting through the Defence Evaluation and Research Agency.Developed by : Jim Benson, Department of Electronics and Computer Science, University of Southampton, United Kingdom.With help from : Nele D'Halleweyn, Ketan Mistry, Bill Redman-White, and Craig Easson.Based on STAG version 2.1Developed by : Mike Lee,With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards and John Bunyan.Acknowledgements : Rupert Howes and Pete Mole.**********//********** Modified by Paolo Nenzi 2002ngspice integration**********/#include "ngspice.h"#include "cktdefs.h"#include "devdefs.h"#include "soi3defs.h"#include "trandefs.h"#include "const.h"#include "sperror.h"#include "suffix.h"extern double DEVsoipnjlim(double, double, double, double, int *);intSOI3load(GENmodel *inModel, CKTcircuit *ckt) /* actually load the current value into the * sparse matrix previously provided */{ SOI3model *model = (SOI3model *) inModel; SOI3instance *here; double Beta; double DrainSatCur; /* for drain pn junction */ double SourceSatCur; /* for source pn junction */ double DrainSatCur1; /* for 2nd drain pn junction */ double SourceSatCur1; /* for 2nd source pn junction */ double EffectiveLength,logL; double FrontGateBulkOverlapCap; double FrontGateDrainOverlapCap; double FrontGateSourceOverlapCap; double BackGateBulkOverlapCap; double BackGateDrainOverlapCap; double BackGateSourceOverlapCap; double Frontcapargs[6]; double Backcapargs[6]; double FrontOxideCap; double BackOxideCap; double arg; double ibhat; double idhat; double iPthat; /* needed for convergence */ double ieqPt; /* value of equivalent current source */ double idrain; double idreq; double ieq; double ieqct,ieqct1,ieqct2,ieqct3,ieqct4; double ieqbd; double ieqbs; double iMdbeq; double iMsbeq; double iBJTdbeq; double iBJTsbeq; double delvbd; double delvbs; double delvds; double delvgfd; double delvgfs; double delvgbd; double delvgbs; double deldeltaT; double evbd,evbd1; double evbs,evbs1; double rtargs[5]; double grt[5]; double gct[5]; int tnodeindex; double geq; double sarg; double vbd; double vbs; double vds;/* the next lot are so we can cast the problem with the body node as ref */ double vsb; double vdb; double vgbb;/* now back to our regular programming *//* vgfb exists already for gate cap calc */ double deltaT,deltaT1 = 0.0,deltaT2 = 0.0,deltaT3 = 0.0; double deltaT4 = 0.0,deltaT5 = 0.0; double vdsat_ext; double vgfb; double vgfd; double vgbd; double vgfdo; double vgbdo; double vgfs; double vgbs; double von; double vt; double xfact; int xnrm; int xrev;/* now stuff needed for new charge model */ double paramargs[10]; double Bfargs[2],alpha_args[5]; double psi_st0args[5]; double vGTargs[5]; double psi_sLargs[5],psi_s0args[5]; double ldargs[5]; double qgatef,qdrn,qsrc,qbody,qgateb; double ieqqgf,ieqqd,ieqqs,ieqqgb; double cgfgf,cgfd,cgfs,cgfdeltaT,cgfgb; double cdgf,cdd,cds,cddeltaT,cdgb; double csgf,csd,css,csdeltaT,csgb; double cbgf,cbd,cbs,cbdeltaT,cbgb; double cgbgf,cgbd,cgbs,cgbdeltaT,cgbgb; double gcgfgf,gcgfd,gcgfs,gcgfdeltaT,gcgfgb; double gcdgf,gcdd,gcds,gcddeltaT,gcdgb; double gcsgf,gcsd,gcss,gcsdeltaT,gcsgb; double gcbgf,gcbd,gcbs,gcbdeltaT,gcbgb; double gcgbgf,gcgbd,gcgbs,gcgbdeltaT,gcgbgb; double alphaBJT; double tauFBJTeff,tauRBJTeff; double ISts,IS1ts,IStd,IS1td; double ieqqBJTbs,ieqqBJTbd; double gcBJTbsbs,gcBJTbsdeltaT; double gcBJTbdbd,gcBJTbddeltaT; double ag0; int Check; int ByPass;#ifndef NOBYPASS double tempv;#endif /*NOBYPASS*/ int error;#ifdef CAPBYPASS int senflag;#endif /* CAPBYPASS */ double m; for( ; model != NULL; model = model->SOI3nextModel ) { /* loop through all the instances of the model */ for (here = model->SOI3instances; here != NULL ; here=here->SOI3nextInstance) { if (here->SOI3owner != ARCHme) continue; vt = CONSTKoverQ * here->SOI3temp; Check=1; ByPass=0; /* 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->SOI3l - 2*model->SOI3latDiff; logL = log(EffectiveLength); if (here->SOI3tSatCurDens == 0) { DrainSatCur = here->SOI3tSatCur; SourceSatCur = here->SOI3tSatCur; } else { DrainSatCur = here->SOI3tSatCurDens * here->SOI3w; SourceSatCur = here->SOI3tSatCurDens * here->SOI3w; } if (here->SOI3tSatCurDens1 == 0) { DrainSatCur1 = here->SOI3tSatCur1; SourceSatCur1 = here->SOI3tSatCur1; } else { DrainSatCur1 = here->SOI3tSatCurDens1 * here->SOI3w; SourceSatCur1 = here->SOI3tSatCurDens1 * here->SOI3w; }/* NB Junction sat. cur. density is NOW PER UNIT WIDTH */ /* JimB - can use basic device geometry to estimate front and back */ /* overlap capacitances to a first approximation. Use this default */ /* model if capacitance factors aren't given in model netlist. */ /* Calculate front gate overlap capacitances. */ if(model->SOI3frontGateSourceOverlapCapFactorGiven) { FrontGateSourceOverlapCap = model->SOI3frontGateSourceOverlapCapFactor * here->SOI3w; } else { FrontGateSourceOverlapCap = model->SOI3latDiff * here->SOI3w * model->SOI3frontOxideCapFactor; } if(model->SOI3frontGateDrainOverlapCapFactorGiven) { FrontGateDrainOverlapCap = model->SOI3frontGateDrainOverlapCapFactor * here->SOI3w; } else { FrontGateDrainOverlapCap = model->SOI3latDiff * here->SOI3w * model->SOI3frontOxideCapFactor; } if(model->SOI3frontGateBulkOverlapCapFactorGiven) { FrontGateBulkOverlapCap = model->SOI3frontGateBulkOverlapCapFactor * EffectiveLength; } else { FrontGateBulkOverlapCap = EffectiveLength * (0.1*1e-6*model->SOI3minimumFeatureSize) * model->SOI3frontOxideCapFactor; } /* Calculate back gate overlap capacitances. */ if( (model->SOI3backGateSourceOverlapCapAreaFactorGiven) && (!model->SOI3backGateSourceOverlapCapAreaFactor || here->SOI3asGiven) ) { BackGateSourceOverlapCap = model->SOI3backGateSourceOverlapCapAreaFactor * here->SOI3as; } else { BackGateSourceOverlapCap = (2*1e-6*model->SOI3minimumFeatureSize + model->SOI3latDiff) * here->SOI3w * model->SOI3backOxideCapFactor; } if( (model->SOI3backGateDrainOverlapCapAreaFactorGiven) && (!model->SOI3backGateDrainOverlapCapAreaFactor || here->SOI3adGiven) ) { BackGateDrainOverlapCap = model->SOI3backGateDrainOverlapCapAreaFactor * here->SOI3ad; } else { BackGateDrainOverlapCap = (2*1e-6*model->SOI3minimumFeatureSize + model->SOI3latDiff) * here->SOI3w * model->SOI3backOxideCapFactor; } if( (model->SOI3backGateBulkOverlapCapAreaFactorGiven) && (!model->SOI3backGateBulkOverlapCapAreaFactor || here->SOI3abGiven) ) { BackGateBulkOverlapCap = model->SOI3backGateBulkOverlapCapAreaFactor * here->SOI3ab; } else { BackGateBulkOverlapCap = EffectiveLength * (0.1*1e-6*model->SOI3minimumFeatureSize + here->SOI3w) * model->SOI3backOxideCapFactor; } Beta = here->SOI3tTransconductance * here->SOI3w/EffectiveLength; /* reset mu_eff to ambient temp value in SI units */ here->SOI3ueff = here->SOI3tTransconductance/ model->SOI3frontOxideCapFactor; FrontOxideCap = model->SOI3frontOxideCapFactor * EffectiveLength * here->SOI3w; BackOxideCap = model->SOI3backOxideCapFactor * EffectiveLength * here->SOI3w; /* * ok - now to do the start-up operations * * we must get values for vbs, vds, vgfs and vgbs 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 */ /* yeah, but we'll then use vsb and vdb for the real work *//* we will use conventional voltages to save * * work rewriting the convergence criteria */ if((ckt->CKTmode & (MODEINITFLOAT | MODEINITPRED | MODEINITSMSIG | MODEINITTRAN)) || ( (ckt->CKTmode & MODEINITFIX) && (!here->SOI3off) ) ) {#ifndef PREDICTOR if(ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) { /* predictor step */ xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; *(ckt->CKTstate0 + here->SOI3vbs) = *(ckt->CKTstate1 + here->SOI3vbs); vbs = (1+xfact)* (*(ckt->CKTstate1 + here->SOI3vbs))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -