📄 soi3load.c
字号:
* many compilers can't handle it all at once, so it * is split into several successive if statements */ /* bypass just needs to check any four voltages have not changed so leave as before to avoid hassle */ tempv = MAX(fabs(ibhat),fabs(here->SOI3ibs + here->SOI3ibd-here->SOI3iMsb - here->SOI3iMdb - here->SOI3iBJTdb - here->SOI3iBJTsb))+ckt->CKTabstol; if((!(ckt->CKTmode & (MODEINITPRED|MODEINITTRAN|MODEINITSMSIG) )) && (ckt->CKTbypass) ) if ( (fabs(ibhat-(here->SOI3ibs + here->SOI3ibd-here->SOI3iMdb - here->SOI3iMsb - here->SOI3iBJTdb - here->SOI3iBJTsb)) < ckt->CKTreltol * tempv)) if( (fabs(delvbs) < (ckt->CKTreltol * MAX(fabs(vbs), fabs(*(ckt->CKTstate0+here->SOI3vbs)))+ ckt->CKTvoltTol))) if ( (fabs(delvbd) < (ckt->CKTreltol * MAX(fabs(vbd), fabs(*(ckt->CKTstate0+here->SOI3vbd)))+ ckt->CKTvoltTol)) ) if( (fabs(delvgfs) < (ckt->CKTreltol * MAX(fabs(vgfs), fabs(*(ckt->CKTstate0+here->SOI3vgfs)))+ ckt->CKTvoltTol))) if( (fabs(delvgbs) < (ckt->CKTreltol * MAX(fabs(vgbs), fabs(*(ckt->CKTstate0+here->SOI3vgbs)))+ ckt->CKTvoltTol))) if ( (fabs(delvds) < (ckt->CKTreltol * MAX(fabs(vds), fabs(*(ckt->CKTstate0+here->SOI3vds)))+ ckt->CKTvoltTol)) ) if ( (fabs(deldeltaT) < (ckt->CKTreltol * MAX(fabs(deltaT), fabs(*(ckt->CKTstate0+here->SOI3deltaT)))+ ckt->CKTvoltTol)) ) if( (fabs(iPthat- here->SOI3iPt) < ckt->CKTreltol * MAX(fabs(iPthat),fabs( here->SOI3iPt)) + ckt->CKTabstol) ) if( (fabs(idhat- here->SOI3id) < ckt->CKTreltol * MAX(fabs(idhat),fabs( here->SOI3id)) + ckt->CKTabstol) ) { /* bypass code */ /* nothing interesting has changed since last * iteration on this device, so we just * copy all the values computed last iteration out * and keep going */ vbs = *(ckt->CKTstate0 + here->SOI3vbs); vbd = *(ckt->CKTstate0 + here->SOI3vbd); vgfs = *(ckt->CKTstate0 + here->SOI3vgfs); vgbs = *(ckt->CKTstate0 + here->SOI3vgbs); vds = *(ckt->CKTstate0 + here->SOI3vds); deltaT = *(ckt->CKTstate0 + here->SOI3deltaT); deltaT1 = *(ckt->CKTstate0 + here->SOI3deltaT1); deltaT2 = *(ckt->CKTstate0 + here->SOI3deltaT2); deltaT3 = *(ckt->CKTstate0 + here->SOI3deltaT3); deltaT4 = *(ckt->CKTstate0 + here->SOI3deltaT4); deltaT5 = *(ckt->CKTstate0 + here->SOI3deltaT5); /* and now the extra ones */ vsb=-vbs; vdb=-vbd; vgfb = vgfs - vbs; vgbb = vgbs - vbs; /* JimB - 15/9/99 */ /* Code for multiple thermal time constants. Start by moving all */ /* rt constants into arrays. */ rtargs[0]=here->SOI3rt; rtargs[1]=here->SOI3rt1; rtargs[2]=here->SOI3rt2; rtargs[3]=here->SOI3rt3; rtargs[4]=here->SOI3rt4; /* Set all conductance components to zero. */ grt[0]=grt[1]=grt[2]=grt[3]=grt[4]=0.0; /* Now calculate conductances from rt. */ /* Don't need to worry about divide by zero when calculating */ /* grt components, as soi3setup() only creates a thermal node */ /* if corresponding rt is greater than zero. */ for(tnodeindex=0;tnodeindex<here->SOI3numThermalNodes;tnodeindex++) { grt[tnodeindex]=1/rtargs[tnodeindex]; } /* End JimB */ vgfd = vgfs - vds; vgbd = vgbs - vds; if (here->SOI3mode==1) { idrain = here->SOI3id + here->SOI3ibd - here->SOI3iMdb - here->SOI3iBJTdb; } else { idrain = -here->SOI3id - here->SOI3ibd + here->SOI3iBJTdb; } /* Pt doesn't need changing as it's in here->SOI3iPt */ if((ckt->CKTmode & (MODETRAN | MODEAC)) || (ckt->CKTmode & MODETRANOP)) { cgfgf = *(ckt->CKTstate0 + here->SOI3cgfgf); cgfd = *(ckt->CKTstate0 + here->SOI3cgfd); cgfs = *(ckt->CKTstate0 + here->SOI3cgfs); cgfdeltaT = *(ckt->CKTstate0 + here->SOI3cgfdeltaT); cgfgb = *(ckt->CKTstate0 + here->SOI3cgfgb); csgf = *(ckt->CKTstate0 + here->SOI3csgf); csd = *(ckt->CKTstate0 + here->SOI3csd); css = *(ckt->CKTstate0 + here->SOI3css); csdeltaT = *(ckt->CKTstate0 + here->SOI3csdeltaT); csgb = *(ckt->CKTstate0 + here->SOI3csgb); cdgf = *(ckt->CKTstate0 + here->SOI3cdgf); cdd = *(ckt->CKTstate0 + here->SOI3cdd); cds = *(ckt->CKTstate0 + here->SOI3cds); cddeltaT = *(ckt->CKTstate0 + here->SOI3cddeltaT); cdgb = *(ckt->CKTstate0 + here->SOI3cdgb); cgbgf = *(ckt->CKTstate0 + here->SOI3cgbgf); cgbd = *(ckt->CKTstate0 + here->SOI3cgbd); cgbs = *(ckt->CKTstate0 + here->SOI3cgbs); cgbdeltaT = *(ckt->CKTstate0 + here->SOI3cgbdeltaT); cgbgb = *(ckt->CKTstate0 + here->SOI3cgbgb); cbgf = -(cgfgf + cdgf + csgf + cgbgf); cbd = -(cgfd + cdd + csd + cgbd); cbs = -(cgfs + cds + css + cgbs); cbdeltaT = -(cgfdeltaT + cddeltaT + csdeltaT + cgbdeltaT); cbgb = -(cgfgb + cdgb + csgb + cgbgb); qgatef = *(ckt->CKTstate0 + here->SOI3qgf); qdrn = *(ckt->CKTstate0 + here->SOI3qd); qsrc = *(ckt->CKTstate0 + here->SOI3qs); qgateb = *(ckt->CKTstate0 + here->SOI3qgb); qbody = -(qgatef + qdrn + qsrc + qgateb); ByPass = 1; goto bypass1; } goto bypass2; }#endif /*NOBYPASS*/ /* ok - bypass is out, do it the hard way */ von = model->SOI3type * here->SOI3von;#ifndef NODELIMITING /* * limiting * we want to keep device voltages from changing * so fast that the exponentials churn out overflows * and similar rudeness */ if(*(ckt->CKTstate0 + here->SOI3vds) >=0) { vgfs = DEVfetlim(vgfs,*(ckt->CKTstate0 + here->SOI3vgfs) ,von); vds = vgfs - vgfd; vds = DEVlimvds(vds,*(ckt->CKTstate0 + here->SOI3vds)); vgfd = vgfs - vds; } else { vgfd = DEVfetlim(vgfd,vgfdo,von); vds = vgfs - vgfd; if(!(ckt->CKTfixLimit)) { vds = -DEVlimvds(-vds,-(*(ckt->CKTstate0 + here->SOI3vds))); } vgfs = vgfd + vds; } if(vds >= 0) { vbs = DEVsoipnjlim(vbs,*(ckt->CKTstate0 + here->SOI3vbs), vt,here->SOI3sourceVcrit,&Check); vbd = vbs-vds; } else { vbd = DEVsoipnjlim(vbd,*(ckt->CKTstate0 + here->SOI3vbd), vt,here->SOI3drainVcrit,&Check); vbs = vbd + vds; } /* and now some limiting of the temperature rise */ if (deltaT>(10 + *(ckt->CKTstate0 + here->SOI3deltaT))) { deltaT = 10 + *(ckt->CKTstate0 + here->SOI3deltaT); /* need limiting, therefore must also impose limits on other thermal voltages. */ /* JimB - 19/5/99 */ if (here->SOI3numThermalNodes == 0) { deltaT1=deltaT2=deltaT3=deltaT4=deltaT5=0; } if (here->SOI3numThermalNodes == 1) { deltaT1=deltaT; deltaT2=deltaT3=deltaT4=deltaT5=0; } if (here->SOI3numThermalNodes == 2) { deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node)); deltaT1 = deltaT - deltaT2; deltaT3=deltaT4=deltaT5=0; } if (here->SOI3numThermalNodes == 3) { deltaT3 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout2Node)); deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node) - deltaT3); deltaT1 = deltaT - deltaT2 - deltaT3; deltaT4=deltaT5=0; } if (here->SOI3numThermalNodes == 4) { deltaT4 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout3Node)); deltaT3 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout2Node) - deltaT4); deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node) - deltaT3 - deltaT4); deltaT1 = deltaT - deltaT2 - deltaT3 - deltaT4; deltaT5=0; } if (here->SOI3numThermalNodes == 5) { deltaT5 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout4Node)); deltaT4 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout3Node) - deltaT5); deltaT3 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout2Node) - deltaT4 - deltaT5); deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node) - deltaT3 - deltaT4 - deltaT5); deltaT1 = deltaT - deltaT2 - deltaT3 - deltaT4 - deltaT5; } Check = 1; }#endif /*NODELIMITING*/ } else { /* ok - not one of the simple cases, so we have to * look at all of the possibilities for why we were * called. We still just initialize the three voltages */ if((ckt->CKTmode & MODEINITJCT) && !here->SOI3off) { vds= model->SOI3type * here->SOI3icVDS; vgfs= model->SOI3type * here->SOI3icVGFS; vgbs= model->SOI3type * here->SOI3icVGBS; vbs= model->SOI3type * here->SOI3icVBS; deltaT=deltaT1=deltaT2=deltaT3=deltaT4=deltaT5=0.0; if((vds==0) && (vgfs==0) && (vbs==0) && (vgbs==0) && ((ckt->CKTmode & (MODETRAN|MODEDCOP|MODEDCTRANCURVE)) || (!(ckt->CKTmode & MODEUIC)))) { vbs = -1; vgfs = model->SOI3type * here->SOI3tVto; vds = 0; vgbs = 0; deltaT=deltaT1=deltaT2=deltaT3=deltaT4=deltaT5=0.0; } } else { vbs=vgfs=vds=vgbs=deltaT=deltaT1=deltaT2=deltaT3=deltaT4=deltaT5=0.0; } } /* * now all the preliminaries are over - we can start doing the * real work */ vbd = vbs - vds; vgfd = vgfs - vds; vgbd = vgbs - vds; vgfb = vgfs - vbs; vgbb = vgbs - vbs; vsb = -vbs; vdb = -vbd; /* now to determine whether the user was able to correctly * identify the source and drain of his device */ if(vds >= 0) { /* normal mode */ here->SOI3mode = 1; } else { /* inverse mode */ here->SOI3mode = -1; } { /* begin block */ /* * This block works out drain current and derivatives. * It does this via the calculation of the surface potential
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -