46 #include <Xyce_config.h>
66 #include <N_ERH_ErrorMgr.h>
70 #include <N_LAS_Matrix.h>
71 #include <N_LAS_Vector.h>
146 "Initial condition of no voltage drops across device");
247 NULL,
U_OHM,
CAT_RES,
"Drain, source diffusion sheet resistance");
289 NULL,
U_NONE,
CAT_CAP,
"Bulk p-n forward-bias capacitance coefficient");
307 " 0 = aluminum, 1 = opposite of substrate)");
341 #ifdef Xyce_DEBUG_DEVICE
344 Xyce::dout() <<
" L = " <<
l << std::endl;
345 Xyce::dout() <<
" W = " <<
w<< std::endl;
346 Xyce::dout() <<
" drainArea = " <<
drainArea<< std::endl;
347 Xyce::dout() <<
" sourceArea = " <<
sourceArea<< std::endl;
348 Xyce::dout() <<
" drainSquares = " <<
drainSquares<< std::endl;
349 Xyce::dout() <<
" sourceSquares = " <<
sourceSquares<< std::endl;
350 Xyce::dout() <<
" drainPerimeter = " <<
drainPerimeter<< std::endl;
354 Xyce::dout() <<
" temp = " <<
temp<< std::endl;
377 :
DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
385 l(getDeviceOptions().defl),
386 w(getDeviceOptions().defw),
388 drainArea(getDeviceOptions().defad),
389 sourceArea(getDeviceOptions().defas),
393 sourcePerimeter(0.0),
394 sourceConductance(0.0),
395 drainConductance(0.0),
396 temp(getDeviceOptions().temp.getImmutableValue<double>()),
450 GateSourceOverlapCap(0),
451 GateDrainOverlapCap(0),
452 GateBulkOverlapCap(0),
464 ADrainEquDrainNodeOffset(-1),
465 ADrainEquDrainPrimeNodeOffset(-1),
467 AGateEquGateNodeOffset(-1),
468 AGateEquBulkNodeOffset(-1),
469 AGateEquDrainPrimeNodeOffset(-1),
470 AGateEquSourcePrimeNodeOffset(-1),
472 ASourceEquSourceNodeOffset(-1),
473 ASourceEquSourcePrimeNodeOffset(-1),
475 ABulkEquGateNodeOffset(-1),
476 ABulkEquBulkNodeOffset(-1),
477 ABulkEquDrainPrimeNodeOffset(-1),
478 ABulkEquSourcePrimeNodeOffset(-1),
480 ADrainPrimeEquDrainNodeOffset(-1),
481 ADrainPrimeEquGateNodeOffset(-1),
482 ADrainPrimeEquBulkNodeOffset(-1),
483 ADrainPrimeEquDrainPrimeNodeOffset(-1),
484 ADrainPrimeEquSourcePrimeNodeOffset(-1),
486 ASourcePrimeEquGateNodeOffset(-1),
487 ASourcePrimeEquSourceNodeOffset(-1),
488 ASourcePrimeEquBulkNodeOffset(-1),
489 ASourcePrimeEquDrainPrimeNodeOffset(-1),
490 ASourcePrimeEquSourcePrimeNodeOffset(-1),
495 f_DrainEquDrainNodePtr(0),
496 f_DrainEquDrainPrimeNodePtr(0),
498 f_GateEquGateNodePtr(0),
499 f_GateEquBulkNodePtr(0),
500 f_GateEquDrainPrimeNodePtr(0),
501 f_GateEquSourcePrimeNodePtr(0),
503 f_SourceEquSourceNodePtr(0),
504 f_SourceEquSourcePrimeNodePtr(0),
506 f_BulkEquGateNodePtr(0),
507 f_BulkEquBulkNodePtr(0),
508 f_BulkEquDrainPrimeNodePtr(0),
509 f_BulkEquSourcePrimeNodePtr(0),
511 f_DrainPrimeEquDrainNodePtr(0),
512 f_DrainPrimeEquGateNodePtr(0),
513 f_DrainPrimeEquBulkNodePtr(0),
514 f_DrainPrimeEquDrainPrimeNodePtr(0),
515 f_DrainPrimeEquSourcePrimeNodePtr(0),
517 f_SourcePrimeEquGateNodePtr(0),
518 f_SourcePrimeEquSourceNodePtr(0),
519 f_SourcePrimeEquBulkNodePtr(0),
520 f_SourcePrimeEquDrainPrimeNodePtr(0),
521 f_SourcePrimeEquSourcePrimeNodePtr(0),
524 q_DrainEquDrainNodePtr(0),
525 q_DrainEquDrainPrimeNodePtr(0),
527 q_GateEquGateNodePtr(0),
528 q_GateEquBulkNodePtr(0),
529 q_GateEquDrainPrimeNodePtr(0),
530 q_GateEquSourcePrimeNodePtr(0),
532 q_SourceEquSourceNodePtr(0),
533 q_SourceEquSourcePrimeNodePtr(0),
535 q_BulkEquGateNodePtr(0),
536 q_BulkEquBulkNodePtr(0),
537 q_BulkEquDrainPrimeNodePtr(0),
538 q_BulkEquSourcePrimeNodePtr(0),
540 q_DrainPrimeEquDrainNodePtr(0),
541 q_DrainPrimeEquGateNodePtr(0),
542 q_DrainPrimeEquBulkNodePtr(0),
543 q_DrainPrimeEquDrainPrimeNodePtr(0),
544 q_DrainPrimeEquSourcePrimeNodePtr(0),
546 q_SourcePrimeEquGateNodePtr(0),
547 q_SourcePrimeEquSourceNodePtr(0),
548 q_SourcePrimeEquBulkNodePtr(0),
549 q_SourcePrimeEquDrainPrimeNodePtr(0),
550 q_SourcePrimeEquSourcePrimeNodePtr(0),
729 UserError0(*
this) <<
"Effective channel length less than zero.";
762 const std::vector<int> & extLIDVecRef )
769 #ifdef Xyce_DEBUG_DEVICE
772 Xyce::dout() << section_divider << std::endl;
773 Xyce::dout() <<
" In Instance::register LIDs\n\n";
774 Xyce::dout() <<
" name = " <<
getName() << std::endl;
775 Xyce::dout() <<
" number of internal variables: " <<
numIntVars << std::endl;
776 Xyce::dout() <<
" number of external variables: " <<
numExtVars << std::endl;
805 #ifdef Xyce_DEBUG_DEVICE
808 Xyce::dout() <<
"\n variable local indices:\n";
809 Xyce::dout() <<
" li_Drain = " <<
li_Drain << std::endl;
810 Xyce::dout() <<
" li_DrainPrime = " <<
li_DrainPrime << std::endl;
811 Xyce::dout() <<
" li_Source = " <<
li_Source << std::endl;
812 Xyce::dout() <<
" li_SourcePrime = " <<
li_SourcePrime << std::endl;
813 Xyce::dout() <<
" li_Gate = " <<
li_Gate << std::endl;
814 Xyce::dout() <<
" li_Bulk = " <<
li_Bulk << std::endl;
816 Xyce::dout() << section_divider << std::endl;
839 tmpstr =
getName()+
"_drainprime";
846 tmpstr =
getName()+
"_sourceprime";
866 if( loadLeadCurrent && storeNameMap.empty ())
870 std::string modName(getName());
871 spiceInternalName(modName);
873 tmpstr = modName+
":DEV_ID";
874 storeNameMap[ li_store_dev_id ] = tmpstr;
875 tmpstr = modName+
":DEV_IG";
876 storeNameMap[ li_store_dev_ig ] = tmpstr;
877 tmpstr = modName+
":DEV_IS";
878 storeNameMap[ li_store_dev_is ] = tmpstr;
879 tmpstr = modName+
":DEV_IB";
880 storeNameMap[ li_store_dev_ib ] = tmpstr;
898 #ifdef Xyce_DEBUG_DEVICE
901 Xyce::dout() << std::endl;
902 Xyce::dout() << section_divider << std::endl;
903 Xyce::dout() <<
" In Instance::registerStateLIDs\n\n";
904 Xyce::dout() <<
" name = " <<
getName() << std::endl;
905 Xyce::dout() <<
" Number of State LIDs: " <<
numStateVars << std::endl;
925 #ifdef Xyce_DEBUG_DEVICE
928 Xyce::dout() <<
" State local indices:" << std::endl;
929 Xyce::dout() << std::endl;
931 Xyce::dout() <<
" li_state_qgs = " <<
li_state_qgs <<std::endl;
932 Xyce::dout() <<
" li_state_capgs = " <<
li_state_capgs<<std::endl;
933 Xyce::dout() <<
" li_state_capgd = " <<
li_state_capgd<<std::endl;
934 Xyce::dout() <<
" li_state_capgb = " <<
li_state_capgb<<std::endl;
935 Xyce::dout() <<
" li_state_qgd = " <<
li_state_qgd<<std::endl;
936 Xyce::dout() <<
" li_state_qgb = " <<
li_state_qgb<<std::endl;
937 Xyce::dout() <<
" li_state_qbs = " <<
li_state_qbs<<std::endl;
938 Xyce::dout() <<
" li_state_qbd = " <<
li_state_qbd<<std::endl;
939 Xyce::dout() << std::endl;
940 Xyce::dout() << section_divider << std::endl;
1008 std::vector<int> map;
1009 std::vector< std::vector<int> > map2;
1077 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
1162 double Qeqbs(0.0),Qeqbd(0.0),Qeqgb(0.0), Qeqgs(0.0), Qeqgd(0.0);
1171 Qeqbs = Dtype*(
qbs);
1172 Qeqbd = Dtype*(
qbd);
1175 Qeqgb = Dtype*(
qgb);
1176 Qeqgs = Dtype*(
qgs);
1177 Qeqgd = Dtype*(
qgd);
1180 coef = (Qeqgs+Qeqgd+Qeqgb);
1184 coef = Qeqbs + Qeqbd - Qeqgb;
1188 coef = -(Qeqbd + Qeqgd);
1192 coef = -(Qeqbs + Qeqgs);
1220 double gcgd, gcgs, gcgb, gcbs, gcbd;
1232 gcgd = 0.0; gcgs = 0.0; gcgb = 0.0; gcbs = 0.0; gcbd = 0.0;
1240 double coef_Jdxp4 = Dtype*(
1246 double coef_Jdxp5 = Dtype*(
1279 double ceqbs(0.0),ceqbd(0.0),ceqgb(0.0), ceqgs(0.0), ceqgd(0.0);
1286 ceqbs = Dtype*(
cbs);
1287 ceqbd = Dtype*(
cbd);
1302 coef = (ceqgs+ceqgd+ceqgb);
1313 coef = ceqbs + ceqbd - ceqgb;
1333 double coef_Jdxp4 = Dtype*(
1338 double coef_Jdxp5 = Dtype*(
1345 double coef_Jdxp6 = Dtype*(
1442 +(gcbd+gcgd)*numberParallel;
1449 +(gcbs+gcgs)*numberParallel;
1481 (
gbs+
gbd)*numberParallel;
1520 bool bsuccess =
true;
1539 double capgs_old(0.0);
1540 double capgd_old(0.0);
1541 double capgb_old(0.0);
1546 double vgs_save(0.0);
1547 double vgd_save(0.0);
1548 double vds_save(0.0);
1623 if ((*flagSolVectorPtr)[
li_Drain] == 0 || (*flagSolVectorPtr)[
li_Gate] == 0 ||
1689 #ifdef Xyce_DEBUG_DEVICE
1692 Xyce::dout() <<
" checking whether to limit voltages "<< std::endl;
1693 Xyce::dout() <<
" Von = " << Von << std::endl;
1694 Xyce::dout() <<
" Blim: vgd = " <<
vgd <<
" vgd old = " <<
vgd_old << std::endl;
1695 Xyce::dout() <<
" Blim: vgs = " <<
vgs <<
" vgs_old = " <<
vgs_old << std::endl;
1696 Xyce::dout() <<
" Blim: vds = " << vds <<
" vds_old = " <<
vds_old << std::endl;
1697 Xyce::dout() <<
" Blim: vbs = " <<
vbs <<
" vbs_old = " <<
vbs_old << std::endl;
1698 Xyce::dout() <<
" Blim: vbd = " <<
vbd <<
" vbd_old = " <<
vbd_old << std::endl;
1736 #ifdef Xyce_DEBUG_DEVICE
1739 Xyce::dout() <<
" Alim: vgd = " <<
vgd << std::endl;
1740 Xyce::dout() <<
" Alim: vgs = " <<
vgs << std::endl;
1741 Xyce::dout() <<
" Alim: vds = " << vds << std::endl;
1742 Xyce::dout() <<
" Alim: vbs = " <<
vbs << std::endl;
1743 Xyce::dout() <<
" Alim: vbd = " <<
vbd << std::endl;
1760 #ifdef Xyce_DEBUG_DEVICE
1765 Xyce::dout() <<
" Something modified the voltages. " << std::endl;
1766 Xyce::dout() <<
" Voltage before after diff " << std::endl;
1768 Xyce::dout() <<
" vds " <<
vds_orig <<
" " << vds <<
" " << vds-
vds_orig << std::endl;
1769 Xyce::dout() <<
" vbs " <<
vbs_orig <<
" " << vbs <<
" " << vbs-
vbs_orig << std::endl;
1822 double vdshere, vbsvbd;
1823 double idsat, lambda, vonbm;
1824 double vdst, vdst2, ivdst1, vdstg;
1872 sarg = sqrt(
tPhi - vbsvbd);
1877 sarg = sarg - vbsvbd / (sarg+sarg);
1878 sarg = Xycemax (0.0,sarg);
1881 vdshere = vds *
mode;
1885 vgon = (mode==1?
vgs:
vgd) - Von;
1904 if ((mode==1?vbs:
vbd) <= 0 )
1915 idsat = betac * exp(sarg *
model_.
nc);
1919 cdrain = idsat * (1 + lambda * vdshere);
1926 if (
vdsat > vdshere)
1929 vdst = vdshere /
vdsat;
1930 vdst2 = (2 - vdst) * vdst;
1932 ivdst1 =
cdrain * (2 - vdst - vdst);
1934 gm = gm * vdst2 + ivdst1 * vdstg;
1936 gmbs = gmbs * vdst2 + ivdst1 * vdstg * vonbm;
1991 sarg = sargsw = 1/sqrt(arg);
2010 sargsw = 1/sqrt(arg);
2051 sarg = sargsw = 1/sqrt(arg);
2065 sargsw = 1/sqrt(arg);
2315 double ratio,ratio4;
2323 double gmanew,gmaold;
2337 #ifdef Xyce_DEBUG_DEVICE
2340 Xyce::dout() << subsection_divider << std::endl;
2341 Xyce::dout() <<
" Begin of updateTemperature. \n";
2342 Xyce::dout() << std::endl;
2347 if (temp_tmp != -999.0)
temp = temp_tmp;
2357 #ifdef Xyce_DEBUG_DEVICE
2360 Xyce::dout() <<
"Temperature = "<<
temp << std::endl;
2361 Xyce::dout() <<
"tnom = " << tnom << std::endl;
2362 Xyce::dout() <<
"ratio = " << ratio << std::endl;
2372 pbfact = -2*
vt *(1.5*log(fact2)+
CONSTQ*arg);
2381 pbfact1 = -2*vtnom *(1.5*log(fact1)+
CONSTQ*arg1);
2383 #ifdef Xyce_DEBUG_DEVICE
2386 Xyce::dout() <<
"vt = " <<
vt << std::endl;
2387 Xyce::dout() <<
"ratio = " << ratio << std::endl;
2388 Xyce::dout() <<
"fact2 = " << fact2 << std::endl;
2389 Xyce::dout() <<
"kt = " << kt << std::endl;
2390 Xyce::dout() <<
"egfet = " << egfet << std::endl;
2391 Xyce::dout() <<
"arg = " << arg << std::endl;
2392 Xyce::dout() <<
"pbfact = " << pbfact << std::endl;
2406 ratio4 = ratio * sqrt(ratio);
2411 tPhi = fact2 * phio + pbfact;
2420 exp(-egfet/
vt+egfet1/vtnom);
2422 exp(-egfet/
vt+egfet1/vtnom);
2589 bool bsuccess =
true;
2596 double vgs1, vgd1, vbs1,vgb1, vds1;
2687 egfet1 = 1.16-(7.02e-4*tnom*
tnom)/(tnom+1108);
2690 #ifdef Xyce_DEBUG_DEVICE
2693 Xyce::dout() <<
" fact1 = " <<
fact1 << std::endl;
2694 Xyce::dout() <<
" vtnom = " <<
vtnom << std::endl;
2695 Xyce::dout() <<
" kt1 = " << kt1 << std::endl;
2696 Xyce::dout() <<
" egfet1 = " <<
egfet1 << std::endl;
2697 Xyce::dout() <<
" arg1 = " << arg1 << std::endl;
2698 Xyce::dout() <<
" pbfact1 = " <<
pbfact1 << std::endl;
2730 wkfng = 3.25 + .5 *
egfet1 - fermig;
2732 wkfngs = wkfng - (3.25 + .5 *
egfet1 +fermis);
2752 coeffDepLayWidth = sqrt(alpha);
2798 wkfng = 3.25 + .5 *
egfet1 - fermig;
2800 wkfngs = wkfng - (3.25 + .5 *
egfet1 +fermis);
2809 if(!
given(
"GAMMA1"))
2847 std::vector<Instance*>::iterator iter;
2851 for (iter=first; iter!=last; ++iter)
2853 (*iter)->processParams();
2871 :
DeviceModel(MB, configuration.getModelParameters(), factory_block),
2873 tnom(getDeviceOptions().tnom),
2875 jctSatCurDensity(0.0),
2877 drainResistance(0.0),
2878 sourceResistance(0.0),
2879 sheetResistance(0.0),
2886 gateSourceOverlapCapFactor(0.0),
2887 gateDrainOverlapCapFactor(0.0),
2888 gateBulkOverlapCapFactor(0.0),
2889 oxideCapFactor(0.0),
2894 sideWallCapFactor(0.0),
2895 bulkJctPotential(0.0),
2896 bulkJctBotGradingCoeff(0.0),
2897 bulkJctSideGradingCoeff(0.0),
2898 fwdCapDepCoeff(0.0),
2906 substrateDoping(0.0),
2908 surfaceStateDensity(0.0),
2909 oxideThickness(0.0),
2910 surfaceMobility(0.0),
2911 lambdaGiven (false),
2912 lambda0Given (false),
2913 lambda1Given (false),
2916 bulkCapFactorGiven(false),
2917 sideWallCapFactorGiven(false)
2925 else if (
getType() ==
"PMOS") {
2967 UserError0(*
this) <<
"You have specified both uo and u0, which is not allowed.";
2969 UserWarning0(*
this) <<
"You have specified the surface mobility as u0 instead of uo. This is supported, but ill-advised.";
2987 std::vector<Instance*>::iterator iter;
2991 for (iter=first; iter!=last; ++iter)
3008 std::vector<Instance*>::const_iterator iter;
3014 os <<
" name model name Parameters" << std::endl;
3015 for (i=0, iter=first; iter!=last; ++iter, ++i)
3017 os <<
" " << i <<
": " << (*iter)->getName() <<
"\t";
3042 for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
3061 bool bsuccess =
true;
3070 double vgs1(0.0), vgd1(0.0), vbs1(0.0),vgb1(0.0), vds1(0.0);
3073 bsuccess = bsuccess && btmp;
3155 double ceqbs(0.0),ceqbd(0.0),ceqgb(0.0), ceqgs(0.0), ceqgd(0.0);
3156 double Qeqbs(0.0),Qeqbd(0.0),Qeqgb(0.0), Qeqgs(0.0), Qeqgd(0.0);
3159 ceqbs = Dtype*(mi.
cbs);
3160 ceqbd = Dtype*(mi.
cbd);
3172 coef = (ceqgs+ceqgd+ceqgb);
3180 coef = ceqbs + ceqbd - ceqgb;
3190 Qeqbs = Dtype*(mi.
qbs);
3191 Qeqbd = Dtype*(mi.
qbd);
3194 Qeqgb = Dtype*(mi.
qgb);
3195 Qeqgs = Dtype*(mi.
qgs);
3196 Qeqgd = Dtype*(mi.
qgd);
3198 coef = (Qeqgs+Qeqgd+Qeqgb);
3201 coef = Qeqbs + Qeqbd - Qeqgb;
3204 coef = -(Qeqbd + Qeqgd);
3207 coef = -(Qeqbs + Qeqgs);
3214 double coef_Jdxp4 = Dtype*(
3218 double coef_Jdxp5 = Dtype*(
3224 double coef_Jdxp6 = Dtype*(
3240 double gcgd(0.0), gcgs(0.0), gcgb(0.0), gcbs(0.0), gcbd(0.0);
3252 gcgd = 0.0; gcgs = 0.0; gcgb = 0.0; gcbs = 0.0; gcbd = 0.0;
3259 double coef_Jdxp4 = Dtype*(
3264 double coef_Jdxp5 = Dtype*(
3269 double coef_Jdxp6 = Dtype*
3314 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
3463 bool bsuccess =
true;
3465 for (InstanceVector::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
3602 .registerDevice(
"m", 6)
3603 .registerModelType(
"pmos", 6)
3604 .registerModelType(
"nmos", 6);