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;
826 tmpstr =
getName()+
"_drainprime";
833 tmpstr =
getName()+
"_sourceprime";
853 if( loadLeadCurrent && storeNameMap.empty ())
857 std::string modName(getName());
858 spiceInternalName(modName);
860 tmpstr = modName+
":DEV_ID";
861 storeNameMap[ li_store_dev_id ] = tmpstr;
862 tmpstr = modName+
":DEV_IG";
863 storeNameMap[ li_store_dev_ig ] = tmpstr;
864 tmpstr = modName+
":DEV_IS";
865 storeNameMap[ li_store_dev_is ] = tmpstr;
866 tmpstr = modName+
":DEV_IB";
867 storeNameMap[ li_store_dev_ib ] = tmpstr;
886 #ifdef Xyce_DEBUG_DEVICE
889 Xyce::dout() << std::endl;
890 Xyce::dout() << section_divider << std::endl;
891 Xyce::dout() <<
" In Instance::registerStateLIDs\n\n";
892 Xyce::dout() <<
" name = " <<
getName() << std::endl;
893 Xyce::dout() <<
" Number of State LIDs: " <<
numStateVars << std::endl;
914 #ifdef Xyce_DEBUG_DEVICE
917 Xyce::dout() <<
" State local indices:" << std::endl;
918 Xyce::dout() << std::endl;
927 Xyce::dout() << std::endl;
928 Xyce::dout() << section_divider << std::endl;
995 std::vector<int> map;
996 std::vector< std::vector<int> > map2;
1063 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
1150 double Qeqbs(0.0),Qeqbd(0.0),Qeqgb(0.0), Qeqgs(0.0), Qeqgd(0.0);
1159 Qeqbs = Dtype*(
qbs);
1160 Qeqbd = Dtype*(
qbd);
1163 Qeqgb = Dtype*(
qgb);
1164 Qeqgs = Dtype*(
qgs);
1165 Qeqgd = Dtype*(
qgd);
1168 coef = (Qeqgs+Qeqgd+Qeqgb);
1172 coef = Qeqbs + Qeqbd - Qeqgb;
1176 coef = -(Qeqbd + Qeqgd);
1180 coef = -(Qeqbs + Qeqgs);
1202 double gcgd, gcgs, gcgb, gcbs, gcbd;
1214 gcgd = 0.0; gcgs = 0.0; gcgb = 0.0; gcbs = 0.0; gcbd = 0.0;
1222 double coef_Jdxp4 = Dtype*(
1228 double coef_Jdxp5 = Dtype*(
1261 double ceqbs(0.0),ceqbd(0.0),ceqgb(0.0), ceqgs(0.0), ceqgd(0.0);
1268 ceqbs = Dtype*(
cbs);
1269 ceqbd = Dtype*(
cbd);
1284 coef = (ceqgs+ceqgd+ceqgb);
1295 coef = ceqbs + ceqbd - ceqgb;
1315 double coef_Jdxp4 = Dtype*(
1320 double coef_Jdxp5 = Dtype*(
1327 double coef_Jdxp6 = Dtype*(
1411 +(gcbd+gcgd)*numberParallel;
1418 +(gcbs+gcgs)*numberParallel;
1450 (
gbs+
gbd)*numberParallel;
1489 bool bsuccess =
true;
1591 if ((*flagSolVectorPtr)[
li_Drain] == 0 || (*flagSolVectorPtr)[
li_Gate] == 0 ||
1775 double coeff0 = 0.0631353e0;
1776 double coeff1 = 0.8013292e0;
1777 double coeff2 = -0.01110777e0;
1873 #ifdef Xyce_DEBUG_DEVICE
1876 Xyce::dout() <<
"HOMOTOPY INFO: gainscale = "
1878 Xyce::dout() <<
"HOMOTOPY INFO: before vds = " << vds << std::endl;
1879 Xyce::dout() <<
"HOMOTOPY INFO: before vgs = " <<
vgs << std::endl;
1920 #ifdef Xyce_DEBUG_DEVICE
1923 Xyce::dout() <<
"HOMOTOPY INFO: after vds = " << vds << std::endl;
1924 Xyce::dout() <<
"HOMOTOPY INFO: after vgs = " <<
vgs << std::endl;
1946 if ( (
mode==1?vbs:
vbd) <= 0.0 )
1949 sqphis = sqrt(
tPhi);
1952 sqphs3 =
tPhi*sqphis;
1954 sqphbs = sqrt(phibs);
1955 dsqdvb = -0.5/sqphbs;
1959 sqphis = sqrt(
tPhi);
1960 sqphs3 =
tPhi*sqphis;
1961 sqphbs = sqphis/(1.0+(
mode==1?vbs:
vbd)/
1963 phibs = sqphbs*sqphbs;
1964 dsqdvb = -phibs/(sqphs3+sqphs3);
1976 wponxj = wps*oneoverxj;
1977 wconxj = coeff0+coeff1*wponxj+coeff2*wponxj*wponxj;
1978 arga = wconxj+djonxj;
1979 argc = wponxj/(1.0+wponxj);
1980 argb = sqrt(1.0-argc*argc);
1981 fshort = 1.0-xjonxl*(arga*argb-djonxj);
1983 dadvb = (coeff1+coeff2*(wponxj+wponxj))*dwpdvb*oneoverxj;
1984 dbdvb = -argc*argc*(1.0-argc)*dwpdvb/(argb*wps);
1985 dfsdvb = -xjonxl*(dadvb*argb+arga*dbdvb);
1996 fbodys = 0.5*gammas/(sqphbs+sqphbs);
1999 onfbdy = 1.0/(1.0+fbody);
2000 dfbdvb = -fbodys*dsqdvb/sqphbs+fbodys*dfsdvb/fshort;
2002 dqbdvb = gammas*dsqdvb+
model_.
gamma*dfsdvb*sqphbs-
2023 cdonco = qbonco/(phibs+phibs);
2024 xn = 1.0+csonco+cdonco;
2026 dxndvb = dqbdvb/(phibs+phibs)-qbonco*dsqdvb/(phibs*sqphbs);
2028 dvodvb = dvtdvb+
vt*dxndvb;
2057 dfgdvd = -dfgdvg*dvtdvd;
2058 dfgdvb = -dfgdvg*dvtdvb;
2063 Vdsat = (vgsx-vth)*onfbdy;
2068 dvsdvd = -dvsdvg*dvtdvd;
2069 dvsdvb = -dvsdvg*dvtdvb-Vdsat*dfbdvb*onfbdy;
2075 arga = (vgsx-vth)*onfbdy;
2076 argb = sqrt(arga*arga+vdsc*vdsc);
2077 Vdsat = arga+vdsc-argb;
2078 dvsdga = (1.0-arga/argb)*onfbdy;
2079 dvsdvg = dvsdga-(1.0-vdsc/argb)*vdsc*dfgdvg*onfg;
2080 dvsdvd = -dvsdvg*dvtdvd;
2081 dvsdvb = -dvsdvg*dvtdvb-arga*dvsdga*dfbdvb;
2086 vdsx = Xycemin((
mode*vds),Vdsat);
2087 if ( vdsx == 0.0 )
goto line900;
2089 cdo = vgsx-vth-0.5*(1.0+fbody)*vdsx;
2090 dcodvb = -dvtdvb-0.5*dfbdvb*vdsx;
2098 gds = vgsx-vth-(1.0+fbody+dvtdvd)*vdsx;
2106 gm = Beta*
gm+dfgdvg*cd1;
2107 gds = Beta*
gds+dfgdvd*cd1;
2115 fdrain = 1.0/(1.0+vdsx*onvdsc);
2116 fd2 = fdrain*fdrain;
2117 arga = fd2*vdsx*onvdsc*onfg;
2118 dfddvg = -dfgdvg*arga;
2119 dfddvd = -dfgdvd*arga-fd2*onvdsc;
2120 dfddvb = -dfgdvb*arga;
2126 gmbs = fdrain*gmbs+dfddvb*
cdrain;
2134 if ( (
mode*vds) <= Vdsat )
goto line700;
2138 gdsat = cdsat*(1.0-fdrain)*onvdsc;
2139 gdsat = Xycemax(1.0e-12,gdsat);
2140 gdoncd = gdsat/cdsat;
2141 gdonfd = gdsat/(1.0-fdrain);
2142 gdonfg = gdsat*onfg;
2143 dgdvg = gdoncd*
gm-gdonfd*dfddvg+gdonfg*dfgdvg;
2144 dgdvd = gdoncd*
gds-gdonfd*dfddvd+gdonfg*dfgdvd;
2145 dgdvb = gdoncd*gmbs-gdonfd*dfddvb+gdonfg*dfgdvb;
2158 emoncd = emax/cdsat;
2159 emongd = emax/gdsat;
2160 demdvg = emoncd*
gm-emongd*dgdvg;
2161 demdvd = emoncd*
gds-emongd*dgdvd;
2162 demdvb = emoncd*gmbs-emongd*dgdvb;
2166 argb = sqrt(arga*arga+argc*((
mode*vds)-Vdsat));
2168 dldvd = argc/(argb+argb);
2170 ddldvg = dldem*demdvg;
2171 ddldvd = dldem*demdvd-dldvd;
2172 ddldvb = dldem*demdvb;
2177 dldvd = 0.5*delxl/((
mode*
vds)-Vdsat);
2191 ddldvg = ddldvg*arga;
2192 ddldvd = ddldvd*arga;
2193 ddldvb = ddldvb*arga;
2199 dlonxl = delxl*oneoverxl;
2200 xlfact = 1.0/(1.0-dlonxl);
2203 gm =
gm*xlfact+diddl*ddldvg;
2204 gds0 =
gds*xlfact+diddl*ddldvd;
2205 gmbs = gmbs*xlfact+diddl*ddldvb;
2206 gm =
gm+gds0*dvsdvg;
2207 gmbs = gmbs+gds0*dvsdvb;
2208 gds = gds0*dvsdvd+diddl*dldvd;
2214 if ( (
mode==1?
vgs:vgd) < Von )
2221 wfact = exp( ((
mode==1?
vgs:vgd)-Von)*ondvt );
2227 if ((
mode*vds) > Vdsat)
2229 gm =
gm+gds0*dvsdvg*wfact;
2231 gds =
gds*wfact+(gms-gmw)*dvodvd;
2232 gmbs = gmbs*wfact+(gms-gmw)*dvodvb-gmw*
2233 ((
mode==1?
vgs:vgd)-Von)*onxn*dxndvb;
2247 gds = Beta*(vgsx-vth);
2309 sarg = sargsw = 1/sqrt(arg);
2328 sargsw = 1/sqrt(arg);
2369 sarg = sargsw = 1/sqrt(arg);
2383 sargsw = 1/sqrt(arg);
2632 double ratio,ratio4;
2640 double gmanew,gmaold;
2645 #ifdef Xyce_DEBUG_DEVICE
2648 Xyce::dout() << subsection_divider << std::endl;
2649 Xyce::dout() <<
" Instance::Begin of updateTemperature. \n";
2650 Xyce::dout() <<
" name = " <<
getName() << std::endl;
2651 Xyce::dout() << std::endl;
2656 if (temp_tmp != -999.0)
temp = temp_tmp;
2666 #ifdef Xyce_DEBUG_DEVICE
2669 Xyce::dout() <<
"Temperature = "<<
temp << std::endl;
2670 Xyce::dout() <<
"tnom = " << tnom << std::endl;
2671 Xyce::dout() <<
"ratio = " << ratio << std::endl;
2681 pbfact = -2*
vt *(1.5*log(fact2)+
CONSTQ*arg);
2683 #ifdef Xyce_DEBUG_DEVICE
2686 Xyce::dout() <<
"vt = " <<
vt << std::endl;
2687 Xyce::dout() <<
"ratio = " << ratio << std::endl;
2688 Xyce::dout() <<
"fact2 = " << fact2 << std::endl;
2689 Xyce::dout() <<
"kt = " << kt << std::endl;
2690 Xyce::dout() <<
"egfet = " << egfet << std::endl;
2691 Xyce::dout() <<
"arg = " << arg << std::endl;
2692 Xyce::dout() <<
"pbfact = " << pbfact << std::endl;
2705 ratio4 = ratio * sqrt(ratio);
2709 tPhi = fact2 * phio + pbfact;
2906 double vgs1, vgd1, vbs1,vgb1, vds1;
2998 egfet1 = 1.16-(7.02e-4*tnom*
tnom)/(tnom+1108);
3029 wkfng = 3.25 + .5 *
egfet1 - fermig;
3031 wkfngs = wkfng - (3.25 + .5 *
egfet1 +fermis);
3076 std::vector<Instance*>::iterator iter;
3080 for (iter=first; iter!=last; ++iter)
3082 (*iter)->processParams();
3100 :
DeviceModel(MB, configuration.getModelParameters(), factory_block),
3102 tnom(getDeviceOptions().tnom),
3104 jctSatCurDensity(0.0),
3106 drainResistance(0.0),
3107 sourceResistance(0.0),
3108 sheetResistance(0.0),
3109 transconductance(0.0),
3110 gateSourceOverlapCapFactor(0.0),
3111 gateDrainOverlapCapFactor(0.0),
3112 gateBulkOverlapCapFactor(0.0),
3113 oxideCapFactor(0.0),
3118 sideWallCapFactor(0.0),
3119 bulkJctPotential(0.0),
3120 bulkJctBotGradingCoeff(0.0),
3121 bulkJctSideGradingCoeff(0.0),
3122 fwdCapDepCoeff(0.0),
3125 substrateDoping(0.0),
3127 surfaceStateDensity(0.0),
3128 oxideThickness(0.0),
3129 surfaceMobility(0.0),
3132 coeffDepLayWidth(0.0),
3135 fastSurfaceStateDensity(0.0),
3144 bulkCapFactorGiven(0),
3145 sideWallCapFactorGiven(0)
3152 else if (
getType() ==
"PMOS") {
3187 UserError0(*
this) <<
"You have specified both uo and u0, which is not allowed.";
3189 UserWarning0(*
this) <<
"You have specified the surface mobility as u0 instead of uo. This is supported, but ill-advised.";
3207 std::vector<Instance*>::iterator iter;
3211 for (iter=first; iter!=last; ++iter)
3228 std::vector<Instance*>::const_iterator iter;
3234 os <<
" name model name Parameters" << std::endl;
3235 for (i=0, iter=first; iter!=last; ++iter, ++i)
3237 os <<
" " << i <<
": " << (*iter)->getName() <<
"\t";
3262 for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
3281 bool bsuccess =
true;
3291 double vgs1(0.0), vgd1(0.0), vbs1(0.0),vgb1(0.0), vds1(0.0);
3294 bsuccess = bsuccess && btmp;
3377 double ceqbs(0.0),ceqbd(0.0),ceqgb(0.0), ceqgs(0.0), ceqgd(0.0);
3378 double Qeqbs(0.0),Qeqbd(0.0),Qeqgb(0.0), Qeqgs(0.0), Qeqgd(0.0);
3382 ceqbs = Dtype*(mi.
cbs);
3383 ceqbd = Dtype*(mi.
cbd);
3395 coef = (ceqgs+ceqgd+ceqgb);
3404 coef = ceqbs + ceqbd - ceqgb;
3417 Qeqbs = Dtype*(mi.
qbs);
3418 Qeqbd = Dtype*(mi.
qbd);
3421 Qeqgb = Dtype*(mi.
qgb);
3422 Qeqgs = Dtype*(mi.
qgs);
3423 Qeqgd = Dtype*(mi.
qgd);
3425 coef = (Qeqgs+Qeqgd+Qeqgb);
3429 coef = Qeqbs + Qeqbd - Qeqgb;
3433 coef = -(Qeqbd + Qeqgd);
3437 coef = -(Qeqbs + Qeqgs);
3445 double coef_Jdxp4 = Dtype*(
3449 double coef_Jdxp5 = Dtype*(
3455 double coef_Jdxp6 = Dtype*(
3468 double gcgd(0.0), gcgs(0.0), gcgb(0.0), gcbs(0.0), gcbd(0.0);
3480 gcgd = 0.0; gcgs = 0.0; gcgb = 0.0; gcbs = 0.0; gcbd = 0.0;
3487 double coef_Jdxp4 = Dtype*(
3492 double coef_Jdxp5 = Dtype*(
3497 double coef_Jdxp6 = Dtype*
3524 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
3672 int sizeInstances = instanceContainer_.size();
3673 for (
int i=0; i<sizeInstances; ++i)
3675 Instance & mi = *(instanceContainer_.at(i));
3791 .registerDevice(
"m", 3)
3792 .registerModelType(
"pmos", 3)
3793 .registerModelType(
"nmos", 3);