46 #include <Xyce_config.h>
51 #if defined(HAVE_UNORDERED_MAP)
52 #include <unordered_map>
53 using std::unordered_map;
54 #elif defined(HAVE_TR1_UNORDERED_MAP)
55 #include <tr1/unordered_map>
56 using std::tr1::unordered_map;
58 #error neither unordered_map or tr1/unordered_map found
61 #if defined(HAVE_UNORDERED_SET)
62 #include <unordered_set>
63 using std::unordered_set;
64 #elif defined(HAVE_TR1_UNORDERED_SET)
65 #include <tr1/unordered_set>
66 using std::tr1::unordered_set;
68 #error neither unordered_set or tr1/unordered_set found
80 #include <N_ERH_ErrorMgr.h>
97 :
DeviceEntity(parametric_data, factory_block.solverState_, factory_block.deviceOptions_, model_block.getNetlistLocation().getFilename(), model_block.getNetlistLocation().getLineNumber()),
99 type_(model_block.getType()),
100 level_(model_block.getLevel()),
101 temperatureModel(
""),
111 return os <<
"model " <<
name_;
125 std::vector<int> m_start;
126 unordered_set<std::string> pname;
127 std::vector<std::string> ptype_expr;
130 m_start.push_back(param_index);
131 for (std::vector<Param>::const_iterator mp = params.begin(); mp != params.end(); ++mp)
134 if ((*mp).tag() ==
"INDEPENDENT;PARAM")
136 m_start.push_back(param_index);
141 std::pair<unordered_set<std::string>::iterator,
bool> ret = pname.insert((*mp).tag());
142 if (ret.second==
false)
144 UserError0(*
this) <<
"Duplicate specification of parameter " << (*mp).tag();
147 if (m_start.size() == 1)
150 if ((*mp).getType() == Util::EXPR)
152 ptype_expr.push_back( (*mp).tag() );
159 std::sort( ptype_expr.begin(), ptype_expr.end() );
160 ptype_expr.erase(std::unique(ptype_expr.begin(), ptype_expr.end() ), ptype_expr.end() );
162 if (m_start.size() == 1)
168 m_start.push_back(param_index + 1);
172 std::string tmod(
"");
173 std::string dmod(
"");
174 std::string modName(
"");
176 for (
int i = 0; i < m_start.size()-1; ++i)
178 for (
int j = m_start[i]; j < m_start[i+1]-1; ++j)
180 if (params[j].tag() ==
"TEMPMODEL" && params[j].stringValue() !=
"NONE")
184 tmod = params[j].stringValue();
188 if (tmod != params[j].stringValue())
190 UserError0(*
this) <<
"Inconsistent or missing TEMPMODEL parameter, " << params[j].stringValue() <<
" specified here, " << tmod <<
" specified perviously";
195 if (params[j].tag() ==
"DOSEMODEL" && params[j].stringValue() !=
"NONE")
199 dmod = params[j].stringValue();
203 if (dmod != params[j].stringValue())
205 UserError0(*
this) <<
"Inconsistent or missing DOSEMODEL parameter, " << params[j].stringValue() <<
" specified here, " << dmod <<
" specified perviously";
213 if (tmod ==
"" && dmod ==
"")
215 UserError0(*
this) <<
"Duplicate model specification implies parameter interpolation, TEMPMODEL or DOSEMODEL parameters must specified";
218 else if (tmod !=
"" && dmod !=
"")
220 UserError0(*
this) <<
"Only one of TEMPMODEL or DOSEMODEL parameters may be specified";
234 if (modName ==
"QUADRATIC")
237 if (m_start.size() != 4)
239 UserError0(*
this) <<
"Three model specifications required for QUADRATIC fit";
244 else if (modName ==
"PWL")
247 fit.resize(m_start.size() - 1);
251 UserError0(*
this) <<
"Only QUADRATIC or PWL interpolation method is supported";
256 unordered_map<std::string,double> basePars;
257 std::vector<double> t;
260 for (
int i = 0 ;i < m_start.size()-1; ++i)
262 for (
int j = m_start[i]; j < m_start[i+1]-1; ++j)
264 par = params[j].tag();
267 DevelFatal0(*this).in(
"DeviceModel::setModParams") <<
"Parameter " << par <<
" not found";
276 t.push_back(params[j].getImmutableValue<double>());
283 t.push_back(params[j].getImmutableValue<double>());
288 if (params[j].
getType() != Util::EXPR)
290 basePars[par] = params[j].getImmutableValue<
double>();
295 if (std::binary_search( ptype_expr.begin(), ptype_expr.end(), par))
297 UserWarning0(*
this) <<
"Non-constant expression for parameter " << par <<
", it will not interpolated";
301 if (basePars.find(par) == basePars.end())
303 UserError0(*
this) <<
"Unknown parameter " << params[j].tag() <<
" in temperature compensation .MODEL statement";
306 if (basePars[par] != params[j].getImmutableValue<double>() && params[j].
given())
312 fit[0].push_back(basePars[par]);
321 if (t.size() != m_start.size()-1)
323 UserError0(*
this) << (
iModel ==
TEMP ?
"TNOM" :
"DOSE") <<
" not specified in all .MODEL statements";
327 for (
int i = 1; i < t.size(); ++i)
329 for (
int j = 0; j < i; ++j)
333 UserError0(*
this) <<
"Identical " << (
iModel ==
TEMP ?
"TNOM" :
"DOSE") <<
" values in .MODEL statements";
342 std::vector<std::vector<double> > temp(nFit);
343 std::vector<std::vector<double> > val(nFit);
346 for (
int i = 1; i <
fit.size(); ++i)
353 std::map<std::string, int>::iterator fm =
fitMap.begin();
354 std::map<std::string, int>::iterator fm_end =
fitMap.end();
356 for ( ; fm != fm_end ; ++fm)
361 throw std::runtime_error(std::string(
"Parameter ") + par +
" not found");
382 for (
int i = 0; i < nFit; ++i)
384 temp[i].push_back(t[0]);
385 val[i].push_back(
fit[0][i]);
391 message <<
"Negative parameter value for log interpolation based parameter ";
393 for ( ; fm != fm_end ; ++fm)
395 if ((*fm).second == i)
404 val[i][0] = log(val[i][0]);
410 for (
int i = 1; i < m_start.size()-1; ++i)
412 for (
int j = m_start[i]; j < m_start[i+1]-1; ++j)
414 if (params[j].
getType() == Util::DBLE && params[j].given())
416 par = params[j].tag();
417 std::map<std::string, int>::iterator fm1 =
fitMap.find(par);
421 temp[k].push_back(t[i]);
422 double p = params[j].getImmutableValue<
double>();
428 message <<
"Negative parameter value for log interpolation based parameter ";
430 for ( ; fm != fm_end ; ++fm)
432 if ((*fm).second == k)
458 std::map<std::string, int>::iterator f;
462 if (temp[i].size() == 2)
464 fit[0][i] = val[i][0];
465 fit[1][i] = (val[i][1] - val[i][0])/(temp[i][1] - temp[i][0]);
468 else if (temp[i].size() == 3)
470 fit[0][i] = val[i][0];
472 x1 = temp[i][1] - temp[i][0];
474 x2 = temp[i][2] - temp[i][0];
476 fit[2][i] = (x2*y1-x1*y2-
fit[0][i]*(x2-x1))/(x2*x1*x1-x1*x2*x2);
477 fit[1][i] = (y1-
fit[2][i]*x1*x1-
fit[0][i])/x1;
481 DevelFatal0(*this).in(
"setModParams") <<
"Internal error in DeviceModel, illegal number of fit points for parameter " << (*f).first;
483 if ((*f).first ==
"TNOM")
492 std::map<double,int> tOrd;
493 for (
int i = 0; i < nT; ++i)
498 std::map<double,int>::iterator tOrd_i = tOrd.begin();
499 std::map<double,int>::iterator tOrd_end = tOrd.end();
500 for ( ; tOrd_i != tOrd_end; ++tOrd_i)
508 base.push_back((*tOrd_i).first);
510 (*tOrd_i).second = i++;
512 std::map<std::string, int>::iterator f;
513 std::map<std::string, int>::iterator f_end;
514 std::vector<bool> p(nT,
false);
517 for ( ; f!=f_end; ++f)
520 for (
int j = 0 ;j < nT; ++j)
524 for (
int j = 0; j < temp[i].size() ; ++j)
526 int ind = tOrd[temp[i][j]];
528 fit[ind][i] = val[i][j];
530 for (
int j = 0; j < nT ; ++j)
536 while (k_lo >= 0 && !p[k_lo])
540 while (k_hi <nT && !p[k_hi])
552 DevelFatal0(*this).in(
"DeviceModel::setModParams") <<
"DeviceModel::setModParams: Internal error forming PWL interpolation";
560 fit[j][i] =
fit[k_hi][i]*frac+
fit[k_lo][i]*(1-frac);
568 if ((*f).first ==
"TNOM")
579 std::vector<Param> remaining_params(¶ms[0], ¶ms[m_start[1] - 1]);
614 for (i=0 ; i<nFit ; ++i)
666 return (
fitMap.size() > 0);
680 int i, j, k_hi, k_lo;
693 std::map<std::string,int>::iterator fp;
694 std::map<std::string,int>::iterator fm_begin=
fitMap.begin();
695 std::map<std::string,int>::iterator fm_end=
fitMap.end();
696 for (fp=fm_begin; fp != fm_end; fp++)
699 p = (
fit[2][i]*del +
fit[1][i])*del +
fit[0][i];
705 else if (p <
min_par[i] && i>0)
719 for (j=0 ; j<
fit.size() ; ++j)
731 else if (k_hi ==
fit.size())
743 for (i=0 ; i<nFit ; ++i)
750 for (i=0 ; i<nFit ; ++i)
754 for (i=0 ; i<nFit ; ++i)
783 for (i=0 ; i<nFit ; ++i)
std::vector< double > oldParams
std::vector< double > max_par
bool given(const std::string ¶meter_name) const
Pure virtual class to augment a linear system.
std::vector< std::vector< double > > fit
const std::string & getName(const C *c)
Returns the name of the specified object.
void setParams(const std::vector< Param > ¶ms)
const ParameterMap & getParameterMap() const
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
std::vector< double > base
bool interpolateDOSE(double)
Class ParametricData manages the configuration information and the parameter binding map...
ExprAccess getExpressionAccess() const
Gets the expression access which describes the usage of the paramter.
Parameter uses temperature interpolation based on log of value.
Class Descriptor describes the parameters stored in the ParametricData parameter map.
std::vector< fitType > parType
bool interpolateTNOM(double)
virtual std::ostream & printName(std::ostream &os) const
const std::string & getType() const
bool isType() const
Tests entry data type.
std::vector< double > min_par
ModelBlock represents a .MODEL line from the netlist.
T ParameterBase::* getMemberPtr() const
Returns the parameter member variable pointer of the enrtry.
std::map< std::string, int > fitMap
std::vector< double DeviceEntity::* > fitParams
void setModParams(const std::vector< Param > ¶ms)