45 #include <Xyce_config.h>
62 #include <N_ERH_ErrorMgr.h>
64 #include <N_LAS_Matrix.h>
65 #include <N_LAS_Vector.h>
75 .setDescription(
"Area scaling value (scales IS, ISR, IKF, RS, CJ0, and IBV)");
83 .setDescription(
"Device temperature");
88 .setDescription(
"Initial voltage drop across device set to zero");
92 .setDescription(
"Option to solve diode equations with the Lambert-W function");
100 .setDescription(
"Saturation current");
106 .setDescription(
"Saturation current");
112 .setDescription(
"Parasitic resistance");
116 .setOriginalValueStored(
true)
117 .setDescription(
"Emission coefficient");
122 .setDescription(
"Recombination current parameter (level 2)");
126 .setDescription(
"Emission coefficient for ISR (level 2)");
131 .setDescription(
"High-injection \"knee\" current (level 2)");
136 .setDescription(
"Transit time");
142 .setDescription(
"Zero-bias p-n depletion capacitance");
149 .setDescription(
"Zero-bias p-n depletion capacitance");
155 .setDescription(
"Zero-bias p-n depletion capacitance");
160 .setDescription(
"Potential for p-n junction");
164 .setDescription(
"Grading parameter for p-n junction");
169 .setDescription(
"Bandgap voltage (barrier height)");
173 .setDescription(
"IS temperature exponent");
178 .setDescription(
"IKF temperature coefficient (linear) (level 2)");
183 .setDescription(
"BV temperature coefficient (linear) (level 2)");
188 .setDescription(
"BV temperature coefficient (quadratic) (level 2)");
193 .setDescription(
"RS temperature coefficient (linear) (level 2)");
198 .setDescription(
"RS temperature coefficient (quadratic) (level 2)");
202 .setDescription(
"Forward-bias depletion capacitance coefficient");
208 .setDescription(
"Reverse breakdown \"knee\" voltage");
215 .setDescription(
"Reverse breakdown \"knee\" voltage");
220 .setDescription(
"Reverse breakdown \"knee\" current");
224 .setDescription(
"Reverse current fitting factor");
228 .setDescription(
"Reverse breakdown ideality factor (level 2)");
233 .setDescription(
"Low-level reverse breakdown \"knee\" current (level 2)");
237 .setDescription(
"Low-level reverse breakdown ideality factor (level 2)");
245 .setDescription(
"Flicker noise coefficient");
249 .setDescription(
"Flicker noise exponent");
290 :
DeviceInstance(instance_block, configuration.getInstanceParameters(), factory_block),
295 Temp(getDeviceOptions().temp.getImmutableValue<double>()),
297 InitCondGiven(false),
327 APosEquPosNodeOffset(-1),
328 APosEquPriNodeOffset(-1),
329 ANegEquNegNodeOffset(-1),
330 ANegEquPriNodeOffset(-1),
331 APriEquPosNodeOffset(-1),
332 APriEquNegNodeOffset(-1),
333 APriEquPriNodeOffset(-1),
335 fPosEquPosNodePtr(0),
336 fPosEquPriNodePtr(0),
337 fNegEquNegNodePtr(0),
338 fNegEquPriNodePtr(0),
339 fPriEquPosNodePtr(0),
340 fPriEquNegNodePtr(0),
341 fPriEquPriNodePtr(0),
342 qPosEquPosNodePtr(0),
343 qPosEquPriNodePtr(0),
344 qNegEquNegNodePtr(0),
345 qNegEquPriNodePtr(0),
346 qPriEquPosNodePtr(0),
347 qPriEquNegNodePtr(0),
348 qPriEquPriNodePtr(0),
386 if (!
given(
"LAMBERTW"))
426 const std::vector<int> & extLIDVecRef)
431 #ifdef Xyce_DEBUG_DEVICE
435 Xyce::dout() << std::endl << section_divider << std::endl;
436 Xyce::dout() <<
"In Instance::register LIDs\n\n";
437 Xyce::dout() <<
"name = " <<
getName() << std::endl;
438 Xyce::dout() <<
"number of internal variables: " <<
numIntVars << std::endl;
439 Xyce::dout() <<
"number of external variables: " <<
numExtVars << std::endl;
461 #ifdef Xyce_DEBUG_DEVICE
464 Xyce::dout() <<
"\nSolution and RHS variables:\n";
465 Xyce::dout() <<
"\nli_Pos = ";
466 Xyce::dout().width(4);
467 Xyce::dout() <<
li_Pos << std::endl;
469 Xyce::dout() <<
"\nli_Neg = ";
470 Xyce::dout().width(4);
471 Xyce::dout() <<
li_Neg << std::endl;
473 Xyce::dout() <<
"\nli_Pri = ";
474 Xyce::dout().width(4);
475 Xyce::dout() <<
li_Pri << std::endl;
482 #ifdef Xyce_DEBUG_DEVICE
485 Xyce::dout() <<
"\nEnd of Instance::register LIDs\n";
486 Xyce::dout() << section_divider << std::endl;
507 tmpstr =
getName()+
"_internal";
541 const std::vector<int> & stoLIDVecRef )
553 #ifdef Xyce_DEBUG_DEVICE
556 Xyce::dout() <<
"li_storevd = " <<
li_storevd;
573 if( storeNameMap.empty () )
577 std::string modName(getName());
578 spiceInternalName(modName);
580 tmpstr = modName+
":vd";
581 storeNameMap[ li_storevd ] = tmpstr;
582 if( loadLeadCurrent )
584 tmpstr = modName+
":DEV_I";
585 storeNameMap[ li_store_dev_i ] = tmpstr;
619 std::vector<int> map;
620 std::vector< std::vector<int> > map2;
655 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
710 double Cd_Jdxp = 0.0;
711 Cd_Jdxp = -(
Cd ) * Vd_diff;
762 double Gd_Jdxp = 0.0;
763 Gd_Jdxp = -(
Gd ) * Vd_diff;
875 bool bsuccess =
true;
924 double VteR = NR * Vt;
954 if ((*flagSolVectorPtr)[
li_Pos] == 0 ||
955 (*flagSolVectorPtr)[
li_Neg] == 0 ||
956 (*flagSolVectorPtr)[
li_Pri] == 0)
995 double Vdtmp = -( BV +
Vd );
1012 #ifdef Xyce_DEBUG_DEVICE
1015 Xyce::dout() << Xyce::section_divider << std::endl;
1016 Xyce::dout() <<
"Instance::updateIntermediateVars " <<
getName()<<std::endl;
1030 if (
Vd >= -3.0 * Vte)
1046 Vrs = (
Id +
Icd)*RS;
1051 if (
Vd >= -3.0 * Vte)
1074 if(
Vd >= -3.0 * Vte) IRfactor = 1.0;
1075 else IRfactor =
tIRF;
1078 if (
Vd >= -3.0 * Vte)
1080 double arg1 =
Vd / Vte;
1082 double evd = exp(arg1);
1086 #ifdef Xyce_DEBUG_DEVICE
1089 Xyce::dout() <<
"Normal exponential regime." << std::endl;
1090 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1091 Xyce::dout() <<
" Vte = " << Vte << std::endl;
1092 Xyce::dout() <<
" Id = " <<
Id << std::endl;
1093 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1102 double arg = 3.0 * Vte / (
Vd *
CONSTe);
1103 arg = arg * arg * arg;
1106 #ifdef Xyce_DEBUG_DEVICE
1109 Xyce::dout() <<
"Linear reverse bias regime." << std::endl;
1110 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1111 Xyce::dout() <<
" tBrkdwnV = " <<
tBrkdwnV << std::endl;
1112 Xyce::dout() <<
" Id = " <<
Id << std::endl;
1113 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1123 double evrev = exp(arg1);
1125 #ifdef Xyce_BREAKDOWN_ORIGINAL
1132 arg2=arg2*arg2*arg2;
1133 double Isat_tBrkdwnV=Isat*(1-arg2);
1138 #ifdef Xyce_DEBUG_DEVICE
1141 Xyce::dout() <<
"Reverse breakdown regime." << std::endl;
1142 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1143 Xyce::dout() <<
" tBrkdwnV = " <<
tBrkdwnV << std::endl;
1144 Xyce::dout() <<
" Id = " << Id << std::endl;
1145 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1155 #ifdef Xyce_DEBUG_DEVICE
1158 Xyce::dout() <<
" Level 2 diode code " << std::endl;
1164 if(
Vd >= -3.0*Vte) IRfactor=1.0;
1165 else IRfactor =
tIRF;
1168 if (
Vd >= -3.0 * Vte)
1170 double arg1 =
Vd / Vte;
1172 double evd = exp(arg1);
1179 Irec = IsatR * (evd - 1.0);
1180 Gd2 = IsatR*evd/VteR;
1187 DKhi = 0.5*Khi*Gd1/(
tIKF+Inorm);
1197 Id = Inorm*Khi + Irec*Kgen;
1198 Gd = Gd1*Khi + Inorm*DKhi + Gd2*Kgen + Irec*DKgen;
1199 #ifdef Xyce_DEBUG_DEVICE
1202 Xyce::dout() <<
"L2 Normal exponential regime." << std::endl;
1203 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1204 Xyce::dout() <<
" Vte = " << Vte << std::endl;
1205 Xyce::dout() <<
" Id = " <<
Id << std::endl;
1206 Xyce::dout() <<
" Irec= " << Irec << std::endl;
1207 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1208 Xyce::dout() <<
" Gd1 = " << Gd1 << std::endl;
1209 Xyce::dout() <<
" Gd2 = " << Gd2 << std::endl;
1210 Xyce::dout() <<
" Khi = " << Khi << std::endl;
1211 Xyce::dout() <<
" Kgen=" << Kgen << std::endl;
1212 Xyce::dout() <<
"DKgen=" <<DKgen << std::endl;
1220 double arg = 3.0 * Vte / (
Vd *
CONSTe);
1221 arg = arg * arg * arg;
1224 #ifdef Xyce_DEBUG_DEVICE
1227 Xyce::dout() <<
"L2 Linear reverse bias regime." << std::endl;
1228 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1229 Xyce::dout() <<
" tBrkdwnV = " <<
tBrkdwnV << std::endl;
1230 Xyce::dout() <<
" Id = " <<
Id << std::endl;
1231 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1241 double evrev = exp(arg1);
1243 #ifdef Xyce_BREAKDOWN_ORIGINAL
1250 arg2=arg2*arg2*arg2;
1251 double Isat_tBrkdwnV=Isat*(1-arg2);
1255 #ifdef Xyce_DEBUG_DEVICE
1258 Xyce::dout() <<
"L2 Reverse breakdown regime." << std::endl;
1259 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1260 Xyce::dout() <<
" tBrkdwnV = " <<
tBrkdwnV << std::endl;
1261 Xyce::dout() <<
" Id = " << Id << std::endl;
1262 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1280 double arg1 = -M * log(arg);
1282 double sarg = exp(arg1);
1285 Qd = TT *
Id +
tJctPot * Czero * (1.0 - arg * sarg) / (1.0 - M);
1286 Cd = TT *
Gd + Czero * sarg;
1290 double Czof2 = Czero / F2;
1291 double MotJctPot = M /
tJctPot;
1295 Czof2 * (F3 * (
Vc -
tDepCap) + (0.5 * MotJctPot) *
1298 Cd = TT *
Gd + Czof2 * (F3 + MotJctPot *
Vc);
1300 #ifdef Xyce_DEBUG_DEVICE
1303 Xyce::dout() <<
"Qd = " <<
Qd << std::endl;
1304 Xyce::dout() <<
"Cd = " <<
Qd << std::endl;
1314 #ifdef Xyce_DEBUG_DEVICE
1317 Xyce::dout() << Xyce::section_divider << std::endl;
1337 double xfc = log( 1.0 -
model_.
FC );
1339 if( temp != -999.0 )
Temp = temp;
1347 double pbfact = -2.0*vt*(1.5*log(fact2)+
CONSTQ*arg);
1353 double pbfact1 = -2.0*vtnom*(1.5*log(fact1)+
CONSTQ*arg1);
1355 double pbo = (
model_.
VJ-pbfact1)/fact1;
1356 double gmaold = (
model_.
VJ-pbo)/pbo;
1363 double gmanew = (
tJctPot-pbo)/pbo;
1392 tempBV =
model_.
BV*(1 + (Temp-TNOM)*
1411 #ifdef Xyce_BREAKDOWN_ORIGINAL
1429 double reltol = 1.0e-3;
1432 double IRfactor =
tIRF;
1435 if( cbv < IRfactor*tSatCur*tempBV/vt )
1437 cbv = IRfactor*tSatCur*tempBV/vt;
1442 double tol = reltol*cbv;
1443 xbv = tempBV-vt*log(1.0+cbv/(IRfactor*tSatCur));
1444 for(
int i = 0; i < 25; ++i )
1446 xbv = tempBV-vt*log(cbv/(IRfactor*tSatCur)+1.0-xbv/vt);
1447 xcbv = IRfactor*tSatCur*(exp((tempBV-xbv)/vt)-1.0+xbv/vt);
1448 if(fabs(xcbv-cbv)<=tol)
break;
1456 double IRFactor=
tIRF;
1462 const int ITER_COUNT_MAX=8;
1465 double arg1=3.0*vte/(
CONSTe*tempBV);
1466 arg1=arg1*arg1*arg1;
1467 cthreshlow=tSatCur*IRFactor*(1-arg1);
1469 exp(-1.0*(3.0*vte-tempBV)/vte);
1471 if(cbv >= cthreshhigh)
1477 else if(cbv <= cthreshlow)
1490 for(iter_count=0; iter_count < ITER_COUNT_MAX; iter_count++)
1492 arg2=3.0*vte/(
CONSTe*xbv);
1493 arg2=arg2*arg2*arg2;
1494 xbv=tempBV-vte*log(cbv/(tSatCur*IRFactor))+vte *
1512 #ifdef Xyce_DEBUG_DEVICE
1515 Xyce::dout() << Xyce::section_divider << std::endl;
1516 Xyce::dout() <<
"Instance::UpdateTemperature" <<
getName() <<std::endl;
1517 Xyce::dout() <<
" IS = " <<
model_.
IS << std::endl;
1518 Xyce::dout() <<
" vtnom = " << vtnom << std::endl;
1519 Xyce::dout() <<
" xfc = " << xfc << std::endl;
1520 Xyce::dout() <<
" TNOM = " << TNOM << std::endl;
1521 Xyce::dout() <<
" vt = " << vt << std::endl;
1522 Xyce::dout() <<
" fact2 = " << fact2 << std::endl;
1523 Xyce::dout() <<
" egfet = " << egfet << std::endl;
1524 Xyce::dout() <<
" arg = " << arg << std::endl;
1525 Xyce::dout() <<
" pbfact = " << pbfact << std::endl;
1526 Xyce::dout() <<
" egfet1 = " << egfet1 << std::endl;
1527 Xyce::dout() <<
" arg1 = " << arg1 << std::endl;
1528 Xyce::dout() <<
" fact1 = " << fact1 << std::endl;
1529 Xyce::dout() <<
" pbfact1 = " << pbfact1 << std::endl;
1530 Xyce::dout() <<
" pbo = " << pbo << std::endl;
1531 Xyce::dout() <<
" gmaold = " << gmaold << std::endl;
1532 Xyce::dout() <<
" gmanew = " << gmanew << std::endl;
1533 Xyce::dout() <<
" tJctCap = " <<
tJctCap << std::endl;
1534 Xyce::dout() <<
" tJctPot = " <<
tJctPot << std::endl;
1535 Xyce::dout() <<
" tSatCur = " << tSatCur << std::endl;
1536 Xyce::dout() <<
" tF1 = " <<
tF1 << std::endl;
1537 Xyce::dout() <<
" tDepCap = " <<
tDepCap << std::endl;
1538 Xyce::dout() <<
" vte = " << vte << std::endl;
1539 Xyce::dout() <<
" tempBV = " << tempBV << std::endl;
1540 Xyce::dout() <<
" tVcrit = " <<
tVcrit << std::endl;
1541 Xyce::dout() <<
" tRS = " <<
tRS << std::endl;
1542 Xyce::dout() <<
" tCOND = " <<
tCOND << std::endl;
1543 Xyce::dout() <<
" tIRF = " <<
tIRF << std::endl;
1544 Xyce::dout() <<
" tBrkdwnV= " <<
tBrkdwnV << std::endl;
1613 double arg1 = (
Vd + Isat*RS)/Vte;
1615 double evd = exp(arg1);
1616 double lambWArg = Isat*RS*evd/Vte;
1622 Id = -Isat+Vte*(lambWReturn)/RS;
1623 Gd = lambWReturn / ((1 + lambWReturn)*RS);
1642 double FF2 = (1/2 - FF1)*(-2);
1643 double arg = Vte/RS;
1644 double arg1 = (Isat/arg - 3);
1645 double arg2 = FF1*arg1;
1647 double evd = exp(arg2);
1648 double lambWArg = Isat*evd/arg;
1654 #ifdef Xyce_DEBUG_DEVICE
1658 Xyce::dout() <<
"Safe LambertW return" << std::endl;
1660 Xyce::dout() <<
"LambertW argument not in domain" << std::endl;
1662 Xyce::dout() <<
"Arithmetic problems with LambertW" << std::endl;
1666 Id = -Isat*FF1 + FF2*lambWReturn*arg;
1668 double GdFF1 = 1/(-3.0*Vte +
tBrkdwnV);
1669 double GdFF2 = 2 * GdFF1;
1670 double GdW = arg*lambWReturn*GdFF1*arg1/(1 + lambWReturn);
1671 Gd = -Isat*GdFF1 + GdFF2*arg*lambWReturn + FF2*GdW;
1673 #ifdef Xyce_DEBUG_DEVICE
1676 Xyce::dout() <<
"lambWArg = " << lambWArg << std::endl;
1677 Xyce::dout() <<
"lambWError = " << lambWError << std::endl;
1678 Xyce::dout() <<
"lambWReturn= " << lambWReturn << std::endl;
1679 Xyce::dout() <<
"Id = " <<
Id << std::endl;
1680 Xyce::dout() <<
"Gd = " <<
Gd << std::endl;
1681 Xyce::dout() <<
"Using lambertwReverseBias" << std::endl;
1749 double evd = exp(arg1);
1750 double lambWArg = Isat*RS*evd/Vte;
1756 Id = -Vte*lambWReturn/RS;
1757 Gd = lambWReturn / ((1 + lambWReturn)*RS);
1775 if(
M > 0.9 )
M = 0.9;
1778 if(
EG < 0.1 )
EG = 0.1;
1781 if(
FC > 0.95 )
FC = 0.95;
1788 double xfc = log(1.0-
FC);
1789 F2 = exp((1.0+
M)*xfc);
1790 F3 = 1.0-
FC*(1.0+
M);
1806 std::vector<Instance*>::iterator iter;
1810 for (iter=first; iter!=last; ++iter)
1812 (*iter)->processParams();
1830 :
DeviceModel(MB, configuration.getModelParameters(), factory_block),
1882 std::string bad_parameters;
1885 bad_parameters +=
" ISR";
1887 bad_parameters +=
" NR";
1889 bad_parameters +=
" IKF";
1891 bad_parameters +=
" NBV";
1893 bad_parameters +=
" IBVL";
1895 bad_parameters +=
" NBVL";
1897 bad_parameters +=
" TIKF";
1899 bad_parameters +=
" TBV1";
1901 bad_parameters +=
" TBV2";
1903 bad_parameters +=
" TRS1";
1905 bad_parameters +=
" TRS2";
1906 if (!bad_parameters.empty())
1908 UserError0(*
this) <<
"Illegal parameter(s) given for level 1 diode:" << bad_parameters;
1926 std::vector<Instance*>::iterator iterI;
1931 for (iterI = firstI; iterI != lastI; ++iterI)
1948 std::vector<Instance*>::const_iterator iter;
1954 os <<
" name model name Parameters" << std::endl;
1955 for (i=0, iter=first; iter!=last; ++iter, ++i)
1957 os <<
" " << i <<
": " << (*iter)->getName() <<
" ";
1961 os <<
"AREA = " << (*iter)->Area << std::endl;
1962 os <<
" IC = " << (*iter)->InitCond << std::endl;
1963 os <<
"TEMP = " << (*iter)->Temp << std::endl;
1964 os <<
" off = " << (*iter)->off << std::endl;
1990 for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
2009 bool bsuccess =
true;
2020 bsuccess = bsuccess && btmp;
2054 double Cd_Jdxp = -( di.
Cd ) * Vd_diff;
2055 double Gd_Jdxp = -( di.
Gd ) * Vd_diff;
2059 dFdxdVp[di.
li_Neg] += Gd_Jdxp;
2060 dFdxdVp[di.
li_Pri] -= Gd_Jdxp;
2064 dQdxdVp[di.
li_Neg] += Cd_Jdxp;
2065 dQdxdVp[di.
li_Pri] -= Cd_Jdxp;
2094 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
2138 .registerDevice(
"d", 1)
2139 .registerDevice(
"d", 2)
2140 .registerModelType(
"d", 1)
2141 .registerModelType(
"d", 2);