45 #include <Xyce_config.h>
48 #include <N_UTL_Math.h>
60 #include <N_ERH_ErrorMgr.h>
61 #include <N_LAS_Matrix.h>
62 #include <N_LAS_Vector.h>
63 #include <N_UTL_BreakPoint.h>
64 #include <N_UTL_FeatureTest.h>
80 .setDescription(
"Vector of initial values for output(s)");
91 .setDescription(
"Internal low state supply voltage");
95 .setDescription(
"Internal high state supply voltage");
99 .setDescription(
"Internal reference voltage for inputs");
103 .setDescription(
"Capacitance between output node and low reference");
107 .setDescription(
"Capacitance between output node and high reference");
111 .setDescription(
"Capacitance between input node and input reference");
115 .setDescription(
"Resistance between input node and input reference");
119 .setDescription(
"Low state resistance between output node and low reference");
123 .setDescription(
"Low state resitance between output node and high reference");
127 .setDescription(
"Switching time transition to low state");
131 .setDescription(
"Minimum voltage to switch to low state");
135 .setDescription(
"Maximum voltage to switch to low state");
139 .setDescription(
"High state resistance between output node and low reference");
143 .setDescription(
"High state resistance between output node and high reference");
147 .setDescription(
"Switching time transition to high state");
151 .setDescription(
"Minimum voltage to switch to high state");
155 .setDescription(
"Maximum voltage to switch to high state");
159 .setDescription(
"Delay time of device");
193 :
DeviceInstance(instance_block, configuration.getInstanceParameters(), factory_block),
204 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
210 int dev_numInputs = 0;
217 if (dev_letter ==
'U') {
228 UserWarning(*
this)<<
"VLO model parameter ignored for U digital device";
232 UserWarning(*
this)<<
"VHI model parameter ignored for U digital device";
236 UserWarning(*
this)<<
"VREF model parameter ignored for U digital device";
239 else if (dev_letter ==
'Y')
243 UserWarning(*
this)<<
"Y digital device (" <<
getName() <<
") is deprecated. Consider using U device instead.";
270 if (dev_type ==
"NOT" || dev_type ==
"INV")
272 if (dev_type ==
"NOT")
274 UserWarning(*
this)<<
"NOT gate type (" <<
getName() <<
") is deprecated. Consider using INV instead.";
280 else if (dev_type ==
"AND")
282 numInput = (dev_letter ==
'Y') ? 2 : dev_numInputs;
286 else if (dev_type ==
"NAND")
288 numInput = (dev_letter ==
'Y') ? 2 : dev_numInputs;
292 else if (dev_type ==
"OR")
294 numInput = (dev_letter ==
'Y') ? 2 : dev_numInputs;
298 else if (dev_type ==
"NOR")
300 numInput = (dev_letter ==
'Y') ? 2 : dev_numInputs;
304 else if (dev_type ==
"ADD")
310 else if (dev_type ==
"XOR")
316 else if (dev_type ==
"NXOR")
322 else if (dev_type ==
"DFF")
328 else if (dev_type ==
"DLTCH")
334 else if (dev_type ==
"BUF")
342 UserError0(*
this) <<
"Unknown digital device type " << dev_type;
350 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
352 Xyce::dout() <<
"Digital Device " <<
getName() <<
" has iBase = " <<
353 iBase <<
", oBase = " << oBase <<
", numExtVars = " <<
364 UserError0(*
this) <<
"this device must have more than one input.";
366 if ( (dev_numInputs != 0) && (instance_block.
numExtVars - iBase - numOutput != dev_numInputs) )
368 std::cout << instance_block.
numExtVars <<
" " << dev_numInputs <<
" " <<
numExtVars << std::endl;
369 UserError0(*
this) <<
"too few I/O nodes on instance line.";
376 UserError0(*
this) <<
"Incorrect number of nodes in digital device "
396 qlo.resize(numOutput);
397 ilo.resize(numOutput);
399 qhi.resize(numOutput);
400 ihi.resize(numOutput);
402 qref.resize(numInput);
403 iref.resize(numInput);
405 rilo.resize(numOutput);
406 rihi.resize(numOutput);
407 riref.resize(numInput);
410 glo.resize(numOutput);
411 ghi.resize(numOutput);
413 qInp.resize(numInput);
414 iInp.resize(numInput);
418 inpL.resize(numInput);
419 iTime.resize(numInput);
420 outL.resize(numOutput);
421 oTime.resize(numOutput);
441 if (dev_letter ==
'U')
486 else if (dev_letter ==
'Y')
556 jacStamp[iBase+i].push_back(iBase+i);
576 jacStamp[oBase+i].push_back(oBase+i);
616 const std::vector<int> & extLIDVecRef)
623 int numInt = intLIDVecRef.size();
624 int numExt = extLIDVecRef.size();
628 msg =
"Instance::registerLIDs:";
629 msg +=
"numInt != numIntVars";
630 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL,msg);
635 msg =
"Instance::registerLIDs:";
636 msg +=
"numExt != numExtVars";
637 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
652 if (dev_letter ==
'U')
661 else if (dev_letter ==
'Y')
698 int numSta = staLIDVecRef.size();
702 msg =
"Instance::registerStateLIDs:";
703 msg +=
"numSta != numStateVars";
704 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
769 int lo_present, hi_present;
771 (
row_Lo < 0) ? (lo_present = 0) : (lo_present = 1);
772 (
row_Hi < 0) ? (hi_present = 0) : (hi_present = 1);
778 if (dev_letter ==
'U')
782 UserError0(*
this) <<
"Internal error in Instance::registerJacLIDs() for " <<
getName();
789 li_jac_Ref[i][2] = jacLIDVec[li_jac_Ref[i][0]][li_jac_Ref[i][2]];
790 li_jac_Ref[i][4] = jacLIDVec[li_jac_Ref[i][3]][li_jac_Ref[i][4]];
791 li_jac_Ref[i][5] = jacLIDVec[li_jac_Ref[i][3]][li_jac_Ref[i][5]];
797 li_jac_Lo[i][2] = jacLIDVec[li_jac_Lo[i][0]][li_jac_Lo[i][2]];
798 li_jac_Lo[i][4] = jacLIDVec[li_jac_Lo[i][3]][li_jac_Lo[i][4]];
799 li_jac_Lo[i][5] = jacLIDVec[li_jac_Lo[i][3]][li_jac_Lo[i][5]];
805 li_jac_Hi[i][2] = jacLIDVec[li_jac_Hi[i][0]][li_jac_Hi[i][2]];
806 li_jac_Hi[i][4] = jacLIDVec[li_jac_Hi[i][3]][li_jac_Hi[i][4]];
807 li_jac_Hi[i][5] = jacLIDVec[li_jac_Hi[i][3]][li_jac_Hi[i][5]];
811 else if (dev_letter ==
'Y')
827 li_jac_Ref[i][2] = jacLIDVec[li_jac_Ref[i][0]][li_jac_Ref[i][2]];
828 li_jac_Ref[i][4] = jacLIDVec[li_jac_Ref[i][3]][li_jac_Ref[i][4]];
829 li_jac_Ref[i][5] = jacLIDVec[li_jac_Ref[i][3]][li_jac_Ref[i][5]];
847 li_jac_Lo[i][2] = jacLIDVec[li_jac_Lo[i][0]][li_jac_Lo[i][2]];
848 li_jac_Lo[i][4] = jacLIDVec[li_jac_Lo[i][3]][li_jac_Lo[i][4]];
849 li_jac_Lo[i][5] = jacLIDVec[li_jac_Lo[i][3]][li_jac_Lo[i][5]];
867 li_jac_Hi[i][2] = jacLIDVec[li_jac_Hi[i][0]][li_jac_Hi[i][2]];
868 li_jac_Hi[i][4] = jacLIDVec[li_jac_Hi[i][3]][li_jac_Hi[i][4]];
869 li_jac_Hi[i][5] = jacLIDVec[li_jac_Hi[i][3]][li_jac_Hi[i][5]];
890 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
895 bool bsuccess =
true;
896 double v_poslo, v_poshi, v_posref, v_neg;
897 double elapsed, time, frac, lastT;
899 double transitionTime;
900 bool changeState =
false;
901 bool clocking =
false;
903 bool toPrint =
false;
932 v_neg = solVector[
li_Inp[i]];
935 elapsed = time - transitionTime;
949 oldStaVector[li_transitionTimeInp[i]] = transitionTime;
952 iTime[i] = transitionTime;
954 staVector[li_transitionTimeInp[i]] = transitionTime;
956 if (currentState == 0)
963 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
980 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
996 inpL[i] = (currentState == 1);
997 (li_Ref >= 0) ? (vOld = oldSolVector[li_Ref]) : (vOld =
model_.
vref);
998 vOld = oldSolVector[li_Inp[i]] - vOld;
999 if (fabs(
vcapref[i]+vOld) < 1.e-12)
1012 staVector[li_transitionTimeInp[i]] = time - del;
1019 if (
iTime[i] > lastT)
1023 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1061 outL[1] = (inpL[0] & inpL[1]) | (inpL[1] & inpL[2]) | (inpL[0] & inpL[2]);
1084 if ((
inpL[0] == 1) && (
inpL[1] == 0))
1091 else if ((
inpL[0] == 0) && (
inpL[1] == 1))
1098 else if ((
inpL[0] == 0) && (
inpL[1] == 0))
1106 else if (
inpL[2] == 1)
1136 if (clocking &&
inpL[2] ==1)
1144 else if (clocking &&
inpL[2] ==0)
1149 outL[1] = oldStaVector[li_currentStateOut[1]];
1159 else if (
inpL[0] == 0 &&
inpL[1] == 1)
1164 else if (
inpL[0] == 0 &&
inpL[1] == 0)
1193 std::string msg(
"Insufficient initial conditions supported in digital device");
1194 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
1205 if (currentState == 1)
1210 if (curr !=
outL[i])
1212 if (
oTime[i] <= time)
1214 currentState = 1-currentState;
1215 transitionTime =
oTime[i];
1227 staVector[li_transitionTimeOut[i]] = transitionTime;
1230 v_neg = solVector[
li_Out[i]];
1232 elapsed = time - transitionTime;
1234 if (currentState == 0)
1236 else if (currentState == 1)
1240 std::string msg(
"Instance::updateSecondaryState: unrecognized state");
1241 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
1244 frac = exp(-elapsed);
1245 if (transitionTime == 0)
1260 if (currentState == 0)
1271 rilo[i] =
glo[i]*(v_poslo-v_neg);
1272 rihi[i] =
ghi[i]*(v_poshi-v_neg);
1274 vcaplo[i] = v_poslo-v_neg;
1275 vcaphi[i] = v_poshi-v_neg;
1299 bool bsuccess =
true;
1340 std::vector<Util::BreakPoint> & breakPointTimes)
1365 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1374 Xyce::dout() <<
"Device " <<
getName() <<
" changed state & accepted time step at "
1376 <<
"change at Device " <<
getName() <<
" at time "
1378 << delta << std::endl << std::endl;
1402 bool bsuccess =
true;
1404 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1406 Xyce::dout() << subsection_divider << std::endl;
1407 Xyce::dout() <<
" Instance::loadDAEQVector" << std::endl;
1408 Xyce::dout() <<
" name = " <<
getName() <<std::endl;
1413 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1415 Xyce::dout() <<
" qlo[" << i <<
"] = " <<
qlo[i] << std::endl;
1416 Xyce::dout() <<
" qhi[" << i <<
"] = " <<
qhi[i] << std::endl;
1440 Xyce::dout() <<
" qref[" << i <<
"] = " <<
qref[i] << std::endl;
1470 bool bsuccess =
true;
1476 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1478 Xyce::dout() << subsection_divider << std::endl;
1479 Xyce::dout() <<
" Instance::loadDAEFVector" << std::endl;
1480 Xyce::dout() <<
" name = " <<
getName() <<std::endl;
1485 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1487 Xyce::dout() <<
" rilo[" << i <<
"] = " <<
rilo[i] << std::endl;
1488 Xyce::dout() <<
" rihi[" << i <<
"] = " <<
rihi[i] << std::endl;
1512 Xyce::dout() <<
" riref[" << i <<
"] = " <<
riref[i] << std::endl;
1527 Xyce::dout() << subsection_divider << std::endl;
1550 bool bsuccess =
true;
1554 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1556 Xyce::dout() << subsection_divider <<std::endl;
1557 Xyce::dout() <<
" Instance::loadDAEdQdx" << std::endl;
1558 Xyce::dout() <<
" name = " <<
getName() << std::endl;
1561 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1563 Xyce::dout() <<
"\nLoading DIGITAL dQdx matrix\n";
1564 Xyce::dout() <<
"Capacitance lo: " <<
model_.
clo << std::endl;
1565 Xyce::dout() <<
"Capacitance hi: " <<
model_.
chi << std::endl;
1566 Xyce::dout() <<
"Capacitance load: " <<
model_.
cload << std::endl;
1567 Xyce::dout() <<
"DONE DIGITAL dQdx matrix LOAD\n";
1644 bool bsuccess =
true;
1647 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1649 Xyce::dout() << subsection_divider <<std::endl;
1650 Xyce::dout() <<
" Instance::loadDAEdFdx" << std::endl;
1675 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1677 Xyce::dout() <<
" glo[" << i <<
"] = " <<
glo[i] << std::endl;
1678 Xyce::dout() <<
" ghi[" << i <<
"] = " <<
ghi[i] << std::endl;
1686 (*dFdxMatPtr)[
li_Lo][li_jac_Lo[i][2]] -=
glo[i];
1688 (*dFdxMatPtr)[
li_Out[i]][li_jac_Lo[i][4]] -=
glo[i];
1690 (*dFdxMatPtr)[
li_Out[i]][li_jac_Lo[i][5]] +=
glo[i];
1702 (*dFdxMatPtr)[
li_Hi][li_jac_Hi[i][2]] -=
ghi[i];
1704 (*dFdxMatPtr)[
li_Out[i]][li_jac_Hi[i][4]] -=
ghi[i];
1706 (*dFdxMatPtr)[
li_Out[i]][li_jac_Hi[i][5]] +=
ghi[i];
1747 std::vector<Instance*>::iterator iter;
1751 for (iter=first; iter!=last; ++iter)
1753 (*iter)->processParams();
1772 :
DeviceModel(MB, configuration.getModelParameters(), factory_block)
1790 UserError0(*
this) <<
"Zero load resistance in inputs";
1808 std::vector<Instance*>::iterator iter;
1812 for (iter=first; iter!=last; ++iter)
1830 std::vector<Instance*>::const_iterator iter;
1838 os <<
"Number of digital instances: " << isize << std::endl;
1839 os <<
" name\t\tmodelName\tParameters" << std::endl;
1841 for (i = 0, iter = first; iter != last; ++iter, ++i)
1843 os <<
" " << i <<
": " << (*iter)->getName() <<
"\t";
1869 for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1884 .registerDevice(
"inv", 1)
1885 .registerDevice(
"not",1)
1886 .registerDevice(
"and", 1)
1887 .registerDevice(
"nand", 1)
1888 .registerDevice(
"or", 1)
1889 .registerDevice(
"nor", 1)
1890 .registerDevice(
"add", 1)
1891 .registerDevice(
"xor", 1)
1892 .registerDevice(
"nxor", 1)
1893 .registerDevice(
"dff", 1)
1894 .registerDevice(
"buf", 1)
1895 .registerDevice(
"dltch", 1)
1896 .registerModelType(
"dig", 1);
const InstanceName & getName() const
std::vector< int > li_QinpState
std::vector< double > vcaplo
bool updateDependentParameters()
std::vector< double > iref
std::vector< double > rihi
std::vector< double > currentInp
const SolverState & solverState_
Descriptor & addPar(const char *parName, T default_value, T U::*varPtr)
Adds the parameter description to the parameter map.
std::vector< int > li_IhiState
Linear::Vector * currSolVectorPtr
Linear::Vector * nextSolVectorPtr
std::vector< Instance * > instanceContainer
std::vector< int > li_QloState
std::vector< int > devConMap
bool given(const std::string ¶meter_name) const
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
Linear::Vector * daeQVectorPtr
Pure virtual class to augment a linear system.
void makeVector(const std::string &cname, int len)
Allows the parameter to be specified as a vector.
std::vector< std::vector< int > > jacStamp
bool updateSecondaryState()
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
std::vector< double > vcaphi
std::vector< double > qlo
const std::vector< std::vector< int > > & jacobianStamp() const
std::vector< double > qInp
std::vector< double > ihi
std::vector< int > li_IloState
std::vector< Param > params
Parameters from the line.
std::vector< int > li_IinpState
void setParams(const std::vector< Param > ¶ms)
std::vector< double > qref
const std::string & getName() const
bool getInstanceBreakPoints(std::vector< Util::BreakPoint > &)
virtual std::ostream & printOutInstances(std::ostream &os) const
static void loadModelParameters(ParametricData< Model > &model_parameters)
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
std::vector< double > iInp
std::vector< double > oTime
std::vector< int > li_Inp
std::vector< double > vcapInp
std::vector< int > li_transitionTimeOut
const DeviceOptions & deviceOptions_
std::vector< double > currentOut
std::vector< double > ilo
Linear::Vector * nextStaVectorPtr
std::vector< double > riref
Instance(const Configuration &configuration, const InstanceBlock &instance_block, Model &model, const FactoryBlock &factory_block)
std::vector< double > qhi
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
std::vector< double > rilo
Linear::Matrix * dFdxMatrixPtr
The Device class is an interface for device implementations.
std::vector< double > glo
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
char getDeviceLetter() const
Return the first letter of the device specification after the subcircuit.
double prevInputStateChangeTime_
Class Configuration contains device configuration data.
std::vector< double > iTime
bool updatePrimaryState()
std::vector< std::vector< int > > li_jac_Ref
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
std::vector< double > ghi
bool processParams()
processParams
std::vector< int > li_Out
const SolverState & getSolverState() const
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
Linear::Vector * currStaVectorPtr
std::vector< int > li_QhiState
Linear::Vector * daeFVectorPtr
std::vector< double > vcapref
std::vector< std::vector< int > > li_jac_Hi
std::vector< int > li_currentStateInp
const ExternData & extData
ModelBlock represents a .MODEL line from the netlist.
Manages parameter binding for class C.
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
InstanceBlock represent a device instance line from the netlist.
std::vector< Param > params
int getNumInputs() const
For the U device, return the number of inputs which have been encoded into the device name...
const std::string & getDeviceType() const
Decodes the device type.
Linear::Matrix * dQdxMatrixPtr
std::vector< int > li_currentStateOut
std::vector< double > currentIn
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
std::vector< int > li_transitionTimeInp
Linear::Vector * nextStaDerivVectorPtr
void setModParams(const std::vector< Param > ¶ms)
bool processInstanceParams()
processInstanceParams
std::vector< std::vector< int > > li_jac_Lo