46 #include <Xyce_config.h>
60 #include <N_ERH_ErrorMgr.h>
77 :
DeviceEntity(parametric_data, factory_block.solverState_, factory_block.deviceOptions_, model_block.getNetlistLocation().getPath(), model_block.getNetlistLocation().getLineNumber()),
79 type_(model_block.getType()),
80 level_(model_block.getLevel()),
91 return os <<
"model " <<
name_;
105 std::vector<int> m_start;
106 std::set<std::string> pname;
107 std::map<std::string, int> ptype;
110 m_start.push_back(param_index);
111 for (std::vector<Param>::const_iterator mp = params.begin(); mp != params.end(); ++mp)
114 if ((*mp).tag() ==
"INDEPENDENT;PARAM")
116 m_start.push_back(param_index);
121 if (pname.find((*mp).tag()) != pname.end())
123 UserError0(*
this) <<
"Duplicate specification of parameter " << (*mp).tag();
126 pname.insert((*mp).tag());
127 if (m_start.size() == 1)
129 ptype[(*mp).tag()] = (*mp).getType();
133 if (m_start.size() == 1)
139 m_start.push_back(param_index + 1);
143 std::string tmod(
"");
144 std::string dmod(
"");
145 std::string modName(
"");
147 for (
int i = 0; i < m_start.size()-1; ++i)
149 for (
int j = m_start[i]; j < m_start[i+1]-1; ++j)
151 if (params[j].tag() ==
"TEMPMODEL" && params[j].stringValue() !=
"NONE")
155 tmod = params[j].stringValue();
159 if (tmod != params[j].stringValue())
161 UserError0(*
this) <<
"Inconsistent or missing TEMPMODEL parameter, " << params[j].stringValue() <<
" specified here, " << tmod <<
" specified perviously";
166 if (params[j].tag() ==
"DOSEMODEL" && params[j].stringValue() !=
"NONE")
170 dmod = params[j].stringValue();
174 if (dmod != params[j].stringValue())
176 UserError0(*
this) <<
"Inconsistent or missing DOSEMODEL parameter, " << params[j].stringValue() <<
" specified here, " << dmod <<
" specified perviously";
184 if (tmod ==
"" && dmod ==
"")
186 UserError0(*
this) <<
"Duplicate model specification implies parameter interpolation, TEMPMODEL or DOSEMODEL parameters must specified";
189 else if (tmod !=
"" && dmod !=
"")
191 UserError0(*
this) <<
"Only one of TEMPMODEL or DOSEMODEL parameters may be specified";
205 if (modName ==
"QUADRATIC")
208 if (m_start.size() != 4)
210 UserError0(*
this) <<
"Three model specifications required for QUADRATIC fit";
215 else if (modName ==
"PWL")
218 fit.resize(m_start.size() - 1);
222 UserError0(*
this) <<
"Only QUADRATIC or PWL interpolation method is supported";
227 std::map<std::string,double> basePars;
228 std::vector<double> t;
231 for (
int i = 0 ;i < m_start.size()-1; ++i)
233 for (
int j = m_start[i]; j < m_start[i+1]-1; ++j)
235 par = params[j].tag();
238 DevelFatal0(*this).in(
"DeviceModel::setModParams") <<
"Parameter " << par <<
" not found";
247 t.push_back(params[j].getImmutableValue<double>());
254 t.push_back(params[j].getImmutableValue<double>());
259 if (params[j].
getType() != Util::EXPR)
261 basePars[par] = params[j].getImmutableValue<
double>();
266 if (ptype[par] == Util::EXPR)
268 UserWarning0(*
this) <<
"Non-constant expression for parameter " << par <<
", it will not interpolated";
272 if (basePars.find(par) == basePars.end())
274 UserError0(*
this) <<
"Unknown parameter " << params[j].tag() <<
" in temperature compensation .MODEL statement";
277 if (basePars[par] != params[j].getImmutableValue<double>() && params[j].
given())
283 fit[0].push_back(basePars[par]);
292 if (t.size() != m_start.size()-1)
294 UserError0(*
this) << (
iModel ==
TEMP ?
"TNOM" :
"DOSE") <<
" not specified in all .MODEL statements";
298 for (
int i = 1; i < t.size(); ++i)
300 for (
int j = 0; j < i; ++j)
304 UserError0(*
this) <<
"Identical " << (
iModel ==
TEMP ?
"TNOM" :
"DOSE") <<
" values in .MODEL statements";
313 std::vector<std::vector<double> > temp(nFit);
314 std::vector<std::vector<double> > val(nFit);
317 for (
int i = 1; i <
fit.size(); ++i)
324 std::map<std::string, int>::iterator fm =
fitMap.begin();
325 std::map<std::string, int>::iterator fm_end =
fitMap.end();
327 for ( ; fm != fm_end ; ++fm)
332 throw std::runtime_error(std::string(
"Parameter ") + par +
" not found");
353 for (
int i = 0; i < nFit; ++i)
355 temp[i].push_back(t[0]);
356 val[i].push_back(
fit[0][i]);
362 message <<
"Negative parameter value for log interpolation based parameter ";
364 for ( ; fm != fm_end ; ++fm)
366 if ((*fm).second == i)
375 val[i][0] = log(val[i][0]);
381 for (
int i = 1; i < m_start.size()-1; ++i)
383 for (
int j = m_start[i]; j < m_start[i+1]-1; ++j)
385 if (params[j].
getType() == Util::DBLE && params[j].given())
387 par = params[j].tag();
388 std::map<std::string, int>::iterator fm1 =
fitMap.find(par);
392 temp[k].push_back(t[i]);
393 double p = params[j].getImmutableValue<
double>();
399 message <<
"Negative parameter value for log interpolation based parameter ";
401 for ( ; fm != fm_end ; ++fm)
403 if ((*fm).second == k)
429 std::map<std::string, int>::iterator f;
433 if (temp[i].size() == 2)
435 fit[0][i] = val[i][0];
436 fit[1][i] = (val[i][1] - val[i][0])/(temp[i][1] - temp[i][0]);
439 else if (temp[i].size() == 3)
441 fit[0][i] = val[i][0];
443 x1 = temp[i][1] - temp[i][0];
445 x2 = temp[i][2] - temp[i][0];
447 fit[2][i] = (x2*y1-x1*y2-
fit[0][i]*(x2-x1))/(x2*x1*x1-x1*x2*x2);
448 fit[1][i] = (y1-
fit[2][i]*x1*x1-
fit[0][i])/x1;
452 DevelFatal0(*this).in(
"setModParams") <<
"Internal error in DeviceModel, illegal number of fit points for parameter " << (*f).first;
454 if ((*f).first ==
"TNOM")
463 std::map<double,int> tOrd;
464 for (
int i = 0; i < nT; ++i)
469 std::map<double,int>::iterator tOrd_i = tOrd.begin();
470 std::map<double,int>::iterator tOrd_end = tOrd.end();
471 for ( ; tOrd_i != tOrd_end; ++tOrd_i)
479 base.push_back((*tOrd_i).first);
481 (*tOrd_i).second = i++;
483 std::map<std::string, int>::iterator f;
484 std::map<std::string, int>::iterator f_end;
485 std::vector<bool> p(nT,
false);
488 for ( ; f!=f_end; ++f)
491 for (
int j = 0 ;j < nT; ++j)
495 for (
int j = 0; j < temp[i].size() ; ++j)
497 int ind = tOrd[temp[i][j]];
499 fit[ind][i] = val[i][j];
501 for (
int j = 0; j < nT ; ++j)
507 while (k_lo >= 0 && !p[k_lo])
511 while (k_hi <nT && !p[k_hi])
523 DevelFatal0(*this).in(
"DeviceModel::setModParams") <<
"DeviceModel::setModParams: Internal error forming PWL interpolation";
531 fit[j][i] =
fit[k_hi][i]*frac+
fit[k_lo][i]*(1-frac);
539 if ((*f).first ==
"TNOM")
550 std::vector<Param> remaining_params(¶ms[0], ¶ms[m_start[1] - 1]);
585 for (i=0 ; i<nFit ; ++i)
637 return (
fitMap.size() > 0);
651 int i, j, k_hi, k_lo;
664 std::map<std::string,int>::iterator fp;
665 std::map<std::string,int>::iterator fm_begin=
fitMap.begin();
666 std::map<std::string,int>::iterator fm_end=
fitMap.end();
667 for (fp=fm_begin; fp != fm_end; fp++)
670 p = (
fit[2][i]*del +
fit[1][i])*del +
fit[0][i];
676 else if (p <
min_par[i] && i>0)
690 for (j=0 ; j<
fit.size() ; ++j)
702 else if (k_hi ==
fit.size())
714 for (i=0 ; i<nFit ; ++i)
721 for (i=0 ; i<nFit ; ++i)
725 for (i=0 ; i<nFit ; ++i)
754 for (i=0 ; i<nFit ; ++i)