46 #include <Xyce_config.h>
67 #include <N_ERH_ErrorMgr.h>
71 #include <N_LAS_Matrix.h>
72 #include <N_LAS_Vector.h>
147 "Initial condition of no voltage drops across device");
217 U_OHM,
CAT_RES,
"Drain, source diffusion sheet resistance"),
259 U_NONE,
CAT_CAP,
"Bulk p-n forward-bias capacitance coefficient"),
313 " 0 = aluminum, 1 = opposite of substrate)");
366 :
DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
374 l(getDeviceOptions().defl),
375 w(getDeviceOptions().defw),
377 drainArea(getDeviceOptions().defad),
378 sourceArea(getDeviceOptions().defas),
382 sourcePerimeter(0.0),
383 sourceConductance(0.0),
384 drainConductance(0.0),
385 temp(getDeviceOptions().temp.getImmutableValue<double>()),
387 tTransconductance(0.0),
438 GateSourceOverlapCap(0),
439 GateDrainOverlapCap(0),
440 GateBulkOverlapCap(0),
452 ADrainEquDrainNodeOffset(-1),
453 ADrainEquDrainPrimeNodeOffset(-1),
455 AGateEquGateNodeOffset(-1),
456 AGateEquBulkNodeOffset(-1),
457 AGateEquDrainPrimeNodeOffset(-1),
458 AGateEquSourcePrimeNodeOffset(-1),
460 ASourceEquSourceNodeOffset(-1),
461 ASourceEquSourcePrimeNodeOffset(-1),
463 ABulkEquGateNodeOffset(-1),
464 ABulkEquBulkNodeOffset(-1),
465 ABulkEquDrainPrimeNodeOffset(-1),
466 ABulkEquSourcePrimeNodeOffset(-1),
468 ADrainPrimeEquDrainNodeOffset(-1),
469 ADrainPrimeEquGateNodeOffset(-1),
470 ADrainPrimeEquBulkNodeOffset(-1),
471 ADrainPrimeEquDrainPrimeNodeOffset(-1),
472 ADrainPrimeEquSourcePrimeNodeOffset(-1),
474 ASourcePrimeEquGateNodeOffset(-1),
475 ASourcePrimeEquSourceNodeOffset(-1),
476 ASourcePrimeEquBulkNodeOffset(-1),
477 ASourcePrimeEquDrainPrimeNodeOffset(-1),
478 ASourcePrimeEquSourcePrimeNodeOffset(-1),
483 f_DrainEquDrainNodePtr(0),
484 f_DrainEquDrainPrimeNodePtr(0),
486 f_GateEquGateNodePtr(0),
487 f_GateEquBulkNodePtr(0),
488 f_GateEquDrainPrimeNodePtr(0),
489 f_GateEquSourcePrimeNodePtr(0),
491 f_SourceEquSourceNodePtr(0),
492 f_SourceEquSourcePrimeNodePtr(0),
494 f_BulkEquGateNodePtr(0),
495 f_BulkEquBulkNodePtr(0),
496 f_BulkEquDrainPrimeNodePtr(0),
497 f_BulkEquSourcePrimeNodePtr(0),
499 f_DrainPrimeEquDrainNodePtr(0),
500 f_DrainPrimeEquGateNodePtr(0),
501 f_DrainPrimeEquBulkNodePtr(0),
502 f_DrainPrimeEquDrainPrimeNodePtr(0),
503 f_DrainPrimeEquSourcePrimeNodePtr(0),
505 f_SourcePrimeEquGateNodePtr(0),
506 f_SourcePrimeEquSourceNodePtr(0),
507 f_SourcePrimeEquBulkNodePtr(0),
508 f_SourcePrimeEquDrainPrimeNodePtr(0),
509 f_SourcePrimeEquSourcePrimeNodePtr(0),
512 q_DrainEquDrainNodePtr(0),
513 q_DrainEquDrainPrimeNodePtr(0),
515 q_GateEquGateNodePtr(0),
516 q_GateEquBulkNodePtr(0),
517 q_GateEquDrainPrimeNodePtr(0),
518 q_GateEquSourcePrimeNodePtr(0),
520 q_SourceEquSourceNodePtr(0),
521 q_SourceEquSourcePrimeNodePtr(0),
523 q_BulkEquGateNodePtr(0),
524 q_BulkEquBulkNodePtr(0),
525 q_BulkEquDrainPrimeNodePtr(0),
526 q_BulkEquSourcePrimeNodePtr(0),
528 q_DrainPrimeEquDrainNodePtr(0),
529 q_DrainPrimeEquGateNodePtr(0),
530 q_DrainPrimeEquBulkNodePtr(0),
531 q_DrainPrimeEquDrainPrimeNodePtr(0),
532 q_DrainPrimeEquSourcePrimeNodePtr(0),
534 q_SourcePrimeEquGateNodePtr(0),
535 q_SourcePrimeEquSourceNodePtr(0),
536 q_SourcePrimeEquBulkNodePtr(0),
537 q_SourcePrimeEquDrainPrimeNodePtr(0),
538 q_SourcePrimeEquSourcePrimeNodePtr(0),
716 UserError0(*
this) <<
"Effective channel length less than zero.";
749 const std::vector<int> & extLIDVecRef )
756 #ifdef Xyce_DEBUG_DEVICE
759 Xyce::dout() << section_divider << std::endl;
760 Xyce::dout() <<
" In Instance::register LIDs\n\n";
761 Xyce::dout() <<
" name = " <<
getName() << std::endl;
762 Xyce::dout() <<
" number of internal variables: " <<
numIntVars << std::endl;
763 Xyce::dout() <<
" number of external variables: " <<
numExtVars << std::endl;
792 #ifdef Xyce_DEBUG_DEVICE
795 Xyce::dout() <<
"\n variable local indices:\n";
796 Xyce::dout() <<
" li_Drain = " <<
li_Drain << std::endl;
797 Xyce::dout() <<
" li_DrainPrime = " <<
li_DrainPrime << std::endl;
798 Xyce::dout() <<
" li_Source = " <<
li_Source << std::endl;
799 Xyce::dout() <<
" li_SourcePrime = " <<
li_SourcePrime << std::endl;
800 Xyce::dout() <<
" li_Gate = " <<
li_Gate << std::endl;
801 Xyce::dout() <<
" li_Bulk = " <<
li_Bulk << std::endl;
803 Xyce::dout() << section_divider << std::endl;
847 if( loadLeadCurrent && storeNameMap.empty ())
871 #ifdef Xyce_DEBUG_DEVICE
874 Xyce::dout() << std::endl;
875 Xyce::dout() << section_divider << std::endl;
876 Xyce::dout() <<
" In Instance::registerStateLIDs\n\n";
877 Xyce::dout() <<
" name = " <<
getName() << std::endl;
878 Xyce::dout() <<
" Number of State LIDs: " <<
numStateVars << std::endl;
899 #ifdef Xyce_DEBUG_DEVICE
902 Xyce::dout() <<
" State local indices:" << std::endl;
903 Xyce::dout() << std::endl;
912 Xyce::dout() << std::endl;
913 Xyce::dout() << section_divider << std::endl;
980 std::vector<int> map;
981 std::vector< std::vector<int> > map2;
1048 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
1135 double Qeqbs(0.0),Qeqbd(0.0),Qeqgb(0.0), Qeqgs(0.0), Qeqgd(0.0);
1144 Qeqbs = Dtype*(
qbs);
1145 Qeqbd = Dtype*(
qbd);
1148 Qeqgb = Dtype*(
qgb);
1149 Qeqgs = Dtype*(
qgs);
1150 Qeqgd = Dtype*(
qgd);
1153 coef = (Qeqgs+Qeqgd+Qeqgb);
1157 coef = Qeqbs + Qeqbd - Qeqgb;
1161 coef = -(Qeqbd + Qeqgd);
1165 coef = -(Qeqbs + Qeqgs);
1187 double gcgd, gcgs, gcgb, gcbs, gcbd;
1199 gcgd = 0.0; gcgs = 0.0; gcgb = 0.0; gcbs = 0.0; gcbd = 0.0;
1207 double coef_Jdxp4 = Dtype*(
1213 double coef_Jdxp5 = Dtype*(
1246 double ceqbs(0.0),ceqbd(0.0),ceqgb(0.0), ceqgs(0.0), ceqgd(0.0);
1253 ceqbs = Dtype*(
cbs);
1254 ceqbd = Dtype*(
cbd);
1269 coef = (ceqgs+ceqgd+ceqgb);
1280 coef = ceqbs + ceqbd - ceqgb;
1300 double coef_Jdxp4 = Dtype*(
1305 double coef_Jdxp5 = Dtype*(
1312 double coef_Jdxp6 = Dtype*(
1396 +(gcbd+gcgd)*numberParallel;
1403 +(gcbs+gcgs)*numberParallel;
1435 (
gbs+
gbd)*numberParallel;
1474 bool bsuccess =
true;
1576 if ((*flagSolVectorPtr)[
li_Drain] == 0 || (*flagSolVectorPtr)[
li_Gate] == 0 ||
1760 double coeff0 = 0.0631353e0;
1761 double coeff1 = 0.8013292e0;
1762 double coeff2 = -0.01110777e0;
1858 #ifdef Xyce_DEBUG_DEVICE
1861 Xyce::dout() <<
"HOMOTOPY INFO: gainscale = "
1863 Xyce::dout() <<
"HOMOTOPY INFO: before vds = " << vds << std::endl;
1864 Xyce::dout() <<
"HOMOTOPY INFO: before vgs = " <<
vgs << std::endl;
1905 #ifdef Xyce_DEBUG_DEVICE
1908 Xyce::dout() <<
"HOMOTOPY INFO: after vds = " << vds << std::endl;
1909 Xyce::dout() <<
"HOMOTOPY INFO: after vgs = " <<
vgs << std::endl;
1931 if ( (
mode==1?vbs:
vbd) <= 0.0 )
1934 sqphis = sqrt(
tPhi);
1937 sqphs3 =
tPhi*sqphis;
1939 sqphbs = sqrt(phibs);
1940 dsqdvb = -0.5/sqphbs;
1944 sqphis = sqrt(
tPhi);
1945 sqphs3 =
tPhi*sqphis;
1946 sqphbs = sqphis/(1.0+(
mode==1?vbs:
vbd)/
1948 phibs = sqphbs*sqphbs;
1949 dsqdvb = -phibs/(sqphs3+sqphs3);
1961 wponxj = wps*oneoverxj;
1962 wconxj = coeff0+coeff1*wponxj+coeff2*wponxj*wponxj;
1963 arga = wconxj+djonxj;
1964 argc = wponxj/(1.0+wponxj);
1965 argb = sqrt(1.0-argc*argc);
1966 fshort = 1.0-xjonxl*(arga*argb-djonxj);
1968 dadvb = (coeff1+coeff2*(wponxj+wponxj))*dwpdvb*oneoverxj;
1969 dbdvb = -argc*argc*(1.0-argc)*dwpdvb/(argb*wps);
1970 dfsdvb = -xjonxl*(dadvb*argb+arga*dbdvb);
1981 fbodys = 0.5*gammas/(sqphbs+sqphbs);
1984 onfbdy = 1.0/(1.0+fbody);
1985 dfbdvb = -fbodys*dsqdvb/sqphbs+fbodys*dfsdvb/fshort;
1987 dqbdvb = gammas*dsqdvb+
model_.
gamma*dfsdvb*sqphbs-
2008 cdonco = qbonco/(phibs+phibs);
2009 xn = 1.0+csonco+cdonco;
2011 dxndvb = dqbdvb/(phibs+phibs)-qbonco*dsqdvb/(phibs*sqphbs);
2013 dvodvb = dvtdvb+
vt*dxndvb;
2042 dfgdvd = -dfgdvg*dvtdvd;
2043 dfgdvb = -dfgdvg*dvtdvb;
2048 Vdsat = (vgsx-vth)*onfbdy;
2053 dvsdvd = -dvsdvg*dvtdvd;
2054 dvsdvb = -dvsdvg*dvtdvb-Vdsat*dfbdvb*onfbdy;
2060 arga = (vgsx-vth)*onfbdy;
2061 argb = sqrt(arga*arga+vdsc*vdsc);
2062 Vdsat = arga+vdsc-argb;
2063 dvsdga = (1.0-arga/argb)*onfbdy;
2064 dvsdvg = dvsdga-(1.0-vdsc/argb)*vdsc*dfgdvg*onfg;
2065 dvsdvd = -dvsdvg*dvtdvd;
2066 dvsdvb = -dvsdvg*dvtdvb-arga*dvsdga*dfbdvb;
2072 if ( vdsx == 0.0 )
goto line900;
2074 cdo = vgsx-vth-0.5*(1.0+fbody)*vdsx;
2075 dcodvb = -dvtdvb-0.5*dfbdvb*vdsx;
2083 gds = vgsx-vth-(1.0+fbody+dvtdvd)*vdsx;
2091 gm = Beta*
gm+dfgdvg*cd1;
2092 gds = Beta*
gds+dfgdvd*cd1;
2100 fdrain = 1.0/(1.0+vdsx*onvdsc);
2101 fd2 = fdrain*fdrain;
2102 arga = fd2*vdsx*onvdsc*onfg;
2103 dfddvg = -dfgdvg*arga;
2104 dfddvd = -dfgdvd*arga-fd2*onvdsc;
2105 dfddvb = -dfgdvb*arga;
2111 gmbs = fdrain*gmbs+dfddvb*
cdrain;
2119 if ( (
mode*vds) <= Vdsat )
goto line700;
2123 gdsat = cdsat*(1.0-fdrain)*onvdsc;
2124 gdsat =
Xycemax(1.0e-12,gdsat);
2125 gdoncd = gdsat/cdsat;
2126 gdonfd = gdsat/(1.0-fdrain);
2127 gdonfg = gdsat*onfg;
2128 dgdvg = gdoncd*
gm-gdonfd*dfddvg+gdonfg*dfgdvg;
2129 dgdvd = gdoncd*
gds-gdonfd*dfddvd+gdonfg*dfgdvd;
2130 dgdvb = gdoncd*gmbs-gdonfd*dfddvb+gdonfg*dfgdvb;
2143 emoncd = emax/cdsat;
2144 emongd = emax/gdsat;
2145 demdvg = emoncd*
gm-emongd*dgdvg;
2146 demdvd = emoncd*
gds-emongd*dgdvd;
2147 demdvb = emoncd*gmbs-emongd*dgdvb;
2151 argb = sqrt(arga*arga+argc*((
mode*vds)-Vdsat));
2153 dldvd = argc/(argb+argb);
2155 ddldvg = dldem*demdvg;
2156 ddldvd = dldem*demdvd-dldvd;
2157 ddldvb = dldem*demdvb;
2162 dldvd = 0.5*delxl/((
mode*
vds)-Vdsat);
2176 ddldvg = ddldvg*arga;
2177 ddldvd = ddldvd*arga;
2178 ddldvb = ddldvb*arga;
2184 dlonxl = delxl*oneoverxl;
2185 xlfact = 1.0/(1.0-dlonxl);
2188 gm =
gm*xlfact+diddl*ddldvg;
2189 gds0 =
gds*xlfact+diddl*ddldvd;
2190 gmbs = gmbs*xlfact+diddl*ddldvb;
2191 gm =
gm+gds0*dvsdvg;
2192 gmbs = gmbs+gds0*dvsdvb;
2193 gds = gds0*dvsdvd+diddl*dldvd;
2199 if ( (
mode==1?
vgs:vgd) < Von )
2206 wfact = exp( ((
mode==1?
vgs:vgd)-Von)*ondvt );
2212 if ((
mode*vds) > Vdsat)
2214 gm =
gm+gds0*dvsdvg*wfact;
2216 gds =
gds*wfact+(gms-gmw)*dvodvd;
2217 gmbs = gmbs*wfact+(gms-gmw)*dvodvb-gmw*
2218 ((
mode==1?
vgs:vgd)-Von)*onxn*dxndvb;
2232 gds = Beta*(vgsx-vth);
2294 sarg = sargsw = 1/sqrt(arg);
2313 sargsw = 1/sqrt(arg);
2354 sarg = sargsw = 1/sqrt(arg);
2368 sargsw = 1/sqrt(arg);
2617 double ratio,ratio4;
2625 double gmanew,gmaold;
2630 #ifdef Xyce_DEBUG_DEVICE
2633 Xyce::dout() << subsection_divider << std::endl;
2634 Xyce::dout() <<
" Instance::Begin of updateTemperature. \n";
2635 Xyce::dout() <<
" name = " <<
getName() << std::endl;
2636 Xyce::dout() << std::endl;
2641 if (temp_tmp != -999.0)
temp = temp_tmp;
2651 #ifdef Xyce_DEBUG_DEVICE
2654 Xyce::dout() <<
"Temperature = "<<
temp << std::endl;
2655 Xyce::dout() <<
"tnom = " << tnom << std::endl;
2656 Xyce::dout() <<
"ratio = " << ratio << std::endl;
2666 pbfact = -2*
vt *(1.5*log(fact2)+
CONSTQ*arg);
2668 #ifdef Xyce_DEBUG_DEVICE
2671 Xyce::dout() <<
"vt = " <<
vt << std::endl;
2672 Xyce::dout() <<
"ratio = " << ratio << std::endl;
2673 Xyce::dout() <<
"fact2 = " << fact2 << std::endl;
2674 Xyce::dout() <<
"kt = " << kt << std::endl;
2675 Xyce::dout() <<
"egfet = " << egfet << std::endl;
2676 Xyce::dout() <<
"arg = " << arg << std::endl;
2677 Xyce::dout() <<
"pbfact = " << pbfact << std::endl;
2690 ratio4 = ratio * sqrt(ratio);
2694 tPhi = fact2 * phio + pbfact;
2891 double vgs1, vgd1, vbs1,vgb1, vds1;
2983 egfet1 = 1.16-(7.02e-4*tnom*
tnom)/(tnom+1108);
3014 wkfng = 3.25 + .5 *
egfet1 - fermig;
3016 wkfngs = wkfng - (3.25 + .5 *
egfet1 +fermis);
3061 std::vector<Instance*>::iterator iter;
3065 for (iter=first; iter!=last; ++iter)
3067 (*iter)->processParams();
3085 :
DeviceModel(MB, configuration.getModelParameters(), factory_block),
3087 tnom(getDeviceOptions().tnom),
3089 jctSatCurDensity(0.0),
3091 drainResistance(0.0),
3092 sourceResistance(0.0),
3093 sheetResistance(0.0),
3094 transconductance(0.0),
3095 gateSourceOverlapCapFactor(0.0),
3096 gateDrainOverlapCapFactor(0.0),
3097 gateBulkOverlapCapFactor(0.0),
3098 oxideCapFactor(0.0),
3103 sideWallCapFactor(0.0),
3104 bulkJctPotential(0.0),
3105 bulkJctBotGradingCoeff(0.0),
3106 bulkJctSideGradingCoeff(0.0),
3107 fwdCapDepCoeff(0.0),
3110 substrateDoping(0.0),
3112 surfaceStateDensity(0.0),
3113 oxideThickness(0.0),
3114 surfaceMobility(0.0),
3117 coeffDepLayWidth(0.0),
3120 fastSurfaceStateDensity(0.0),
3129 bulkCapFactorGiven(0),
3130 sideWallCapFactorGiven(0)
3137 else if (
getType() ==
"PMOS") {
3172 UserError0(*
this) <<
"Both uo and u0 have been specified and, which is not allowed";
3174 UserWarning0(*
this) <<
"Surface mobility has been specified as u0 instead of uo, uo is the preferred syntax";
3192 std::vector<Instance*>::iterator iter;
3196 for (iter=first; iter!=last; ++iter)
3213 std::vector<Instance*>::const_iterator iter;
3219 os <<
" name model name Parameters" << std::endl;
3220 for (i=0, iter=first; iter!=last; ++iter, ++i)
3222 os <<
" " << i <<
": " << (*iter)->getName() <<
"\t";
3247 for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
3266 bool bsuccess =
true;
3276 double vgs1(0.0), vgd1(0.0), vbs1(0.0),vgb1(0.0), vds1(0.0);
3279 bsuccess = bsuccess && btmp;
3353 bool Master::loadDAEVectors (
double * solVec,
double * fVec,
double *qVec,
double * bVec,
double * storeLeadF,
double * storeLeadQ)
3362 double ceqbs(0.0),ceqbd(0.0),ceqgb(0.0), ceqgs(0.0), ceqgd(0.0);
3363 double Qeqbs(0.0),Qeqbd(0.0),Qeqgb(0.0), Qeqgs(0.0), Qeqgd(0.0);
3367 ceqbs = Dtype*(mi.
cbs);
3368 ceqbd = Dtype*(mi.
cbd);
3380 coef = (ceqgs+ceqgd+ceqgb);
3389 coef = ceqbs + ceqbd - ceqgb;
3402 Qeqbs = Dtype*(mi.
qbs);
3403 Qeqbd = Dtype*(mi.
qbd);
3406 Qeqgb = Dtype*(mi.
qgb);
3407 Qeqgs = Dtype*(mi.
qgs);
3408 Qeqgd = Dtype*(mi.
qgd);
3410 coef = (Qeqgs+Qeqgd+Qeqgb);
3414 coef = Qeqbs + Qeqbd - Qeqgb;
3418 coef = -(Qeqbd + Qeqgd);
3422 coef = -(Qeqbs + Qeqgs);
3430 double coef_Jdxp4 = Dtype*(
3434 double coef_Jdxp5 = Dtype*(
3440 double coef_Jdxp6 = Dtype*(
3453 double gcgd(0.0), gcgs(0.0), gcgb(0.0), gcbs(0.0), gcbd(0.0);
3465 gcgd = 0.0; gcgs = 0.0; gcgb = 0.0; gcbs = 0.0; gcbd = 0.0;
3472 double coef_Jdxp4 = Dtype*(
3477 double coef_Jdxp5 = Dtype*(
3482 double coef_Jdxp6 = Dtype*
3509 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
3657 int sizeInstances = instanceContainer_.size();
3658 for (
int i=0; i<sizeInstances; ++i)
3660 Instance & mi = *(instanceContainer_.at(i));
3776 .registerDevice(
"m", 3)
3777 .registerModelType(
"pmos", 3)
3778 .registerModelType(
"nmos", 3);