Xyce  6.1
N_DEV_Digital.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2015 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_Digital.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Dave Shirley, PSSI
33 //
34 // Creation Date : 01/05/06
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.120 $
40 //
41 // Revision Date : $Date: 2015/10/06 17:43:32 $
42 //
43 // Current Owner : $Author: peshola $
44 //-------------------------------------------------------------------------
45 #include <Xyce_config.h>
46 
47 // ---------- Standard Includes ----------
48 #include <N_UTL_Math.h>
49 #include <iostream>
50 #include <sstream>
51 
52 #include <N_DEV_Const.h>
53 #include <N_DEV_DeviceMaster.h>
54 #include <N_DEV_DeviceOptions.h>
55 #include <N_DEV_Digital.h>
56 #include <N_DEV_ExternData.h>
57 #include <N_DEV_MatrixLoadData.h>
58 #include <N_DEV_Message.h>
59 #include <N_DEV_SolverState.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>
65 
66 namespace Xyce {
67 namespace Device {
68 namespace Digital {
69 
70 // enables debug output for just the digital devices
71 //static const int DEBUG_DEVICE = 1;
72 
74 {
75 // Set up double precision variables:
76 
77  // Set up non-double precision variables:
78  p.addPar ("IC1", false, &Digital::Instance::ic1)
79  .setUnit(U_LOGIC)
80  .setDescription("Vector of initial values for output(s)");
81  p.addPar ("IC2", false, &Digital::Instance::ic2);
82 
83  p.makeVector ("IC", 2);
84 }
85 
87 {
88  // Set up double precision variables:
89  p.addPar ("VLO", 0., &Digital::Model::vlo)
90  .setUnit(U_VOLT)
91  .setDescription("Internal low state supply voltage");
92 
93  p.addPar ("VHI", 0., &Digital::Model::vhi)
94  .setUnit(U_VOLT)
95  .setDescription("Internal high state supply voltage");
96 
97  p.addPar ("VREF", 0., &Digital::Model::vref)
98  .setUnit(U_VOLT)
99  .setDescription("Internal reference voltage for inputs");
100 
101  p.addPar ("CLO", 1.e-6, &Digital::Model::clo)
102  .setUnit(U_FARAD)
103  .setDescription("Capacitance between output node and low reference");
104 
105  p.addPar ("CHI", 1.e-6, &Digital::Model::chi)
106  .setUnit(U_FARAD)
107  .setDescription("Capacitance between output node and high reference");
108 
109  p.addPar ("CLOAD", 1.e-6, &Digital::Model::cload)
110  .setUnit(U_FARAD)
111  .setDescription("Capacitance between input node and input reference");
112 
113  p.addPar ("RLOAD", 1000., &Digital::Model::rload)
114  .setUnit(U_OHM)
115  .setDescription("Resistance between input node and input reference");
116 
117  p.addPar ("S0RLO", 100., &Digital::Model::s0rlo)
118  .setUnit(U_OHM)
119  .setDescription("Low state resistance between output node and low reference");
120 
121  p.addPar ("S0RHI", 100., &Digital::Model::s0rhi)
122  .setUnit(U_OHM)
123  .setDescription("Low state resitance between output node and high reference");
124 
125  p.addPar ("S0TSW", 1.e-8, &Digital::Model::s0tsw)
126  .setUnit(U_SECOND)
127  .setDescription("Switching time transition to low state");
128 
129  p.addPar ("S0VLO", -1.5, &Digital::Model::s0vlo)
130  .setUnit(U_VOLT)
131  .setDescription("Minimum voltage to switch to low state");
132 
133  p.addPar ("S0VHI", 1.7, &Digital::Model::s0vhi)
134  .setUnit(U_VOLT)
135  .setDescription("Maximum voltage to switch to low state");
136 
137  p.addPar ("S1RLO", 100., &Digital::Model::s1rlo)
138  .setUnit(U_OHM)
139  .setDescription("High state resistance between output node and low reference");
140 
141  p.addPar ("S1RHI", 100., &Digital::Model::s1rhi)
142  .setUnit(U_OHM)
143  .setDescription("High state resistance between output node and high reference");
144 
145  p.addPar ("S1TSW", 1.e-8, &Digital::Model::s1tsw)
146  .setUnit(U_SECOND)
147  .setDescription("Switching time transition to high state");
148 
149  p.addPar ("S1VLO", 0.9, &Digital::Model::s1vlo)
150  .setUnit(U_VOLT)
151  .setDescription("Minimum voltage to switch to high state");
152 
153  p.addPar ("S1VHI", 7.0, &Digital::Model::s1vhi)
154  .setUnit(U_VOLT)
155  .setDescription("Maximum voltage to switch to high state");
156 
157  p.addPar ("DELAY", 1.e-8, &Digital::Model::delay)
158  .setUnit(U_SECOND)
159  .setDescription("Delay time of device");
160 }
161 
162 // Class Instance
163 //-----------------------------------------------------------------------------
164 // Function : Instance::processParams
165 // Purpose :
166 // Special Notes :
167 // Scope : public
168 // Creator : Dave Shirley, PSSI
169 // Creation Date : 01/05/06
170 //-----------------------------------------------------------------------------
172 {
173 
174  // If there are any time dependent parameters, set their values for
175  // the current time.
176 
177  return true;
178 }
179 
180 //-----------------------------------------------------------------------------
181 // Function : Instance::Instance
182 // Purpose : instance block constructor
183 // Special Notes :
184 // Scope : public
185 // Creator : Dave Shirley, PSSI
186 // Creation Date : 01/05/06
187 //-----------------------------------------------------------------------------
189  const Configuration & configuration,
190  const InstanceBlock & instance_block,
191  Model & model,
192  const FactoryBlock & factory_block)
193  : DeviceInstance(instance_block, configuration.getInstanceParameters(), factory_block),
194  model_(model),
195  li_Lo(-1),
196  li_Hi(-1),
197  li_Ref(-1),
198  row_Lo(-1),
199  row_Hi(-1),
200  row_Ref(-1),
201  breakTime(0.),
202  gateInfo_(0),
203  supportsXState_(false)
204 {
205  // added for compatibility with PSpice DIGINITSTATE
207  if ( digInitState_ < 0 || digInitState_ > 3 )
208  {
209  // If the user specifies an invalid value then use the default value.
210  digInitState_ = 3;
211  UserWarning(*this) << "Invalid DIGINITSTATE: " << getDeviceOptions().digInitState
212  << ". Setting to default DIGINITSTATE: " << digInitState_ << std::endl;
213  }
214 
215 
216  // added for debug purposes for tracking input/output state changes
217  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
218  {
220  inputStateChange_ = false;
221  }
222 
223  int dev_numInputs = 0;
224  char dev_letter = getName().getDeviceLetter();
225  numExtVars = 0;
226 
227  // Code required to support both Y-style and U-style digital devices.
228  // Y digital devices are now deprecated.
229  //dev_numInputs = getName().getNumInputs();
230  //deviceInfo_->updatePowerPinLi(li_Lo,li_Hi,li_Ref,numExtVars,
231  // model_.given("VLO"),
232  // model_.given("VHI"),
233  // model_.given("VREF"));
234  if (dev_letter == 'U') {
235  dev_numInputs = getName().getNumInputs();
236 
237  // For U devices, DPWR and DGND are always specified on the instance line.
238  // Warning message if VHI, VLO or VREF are in the model card.
239  li_Lo = 0;
240  li_Hi = 0;
241  li_Ref = 0;
242  numExtVars += 2;
243  if (model_.given("VLO"))
244  {
245  UserWarning(*this)<< "VLO model parameter ignored for U digital device";
246  }
247  if (model_.given("VHI"))
248  {
249  UserWarning(*this)<< "VHI model parameter ignored for U digital device";
250  }
251  if (model_.given("VREF"))
252  {
253  UserWarning(*this)<< "VREF model parameter ignored for U digital device";
254  }
255  }
256  else if (dev_letter == 'Y')
257  {
258  // legacy code required to support VLO, VHI and VREF variables
259  // being on the instance line rather than in model card in Y devices
260  UserWarning(*this)<< "Y-type digital device is deprecated. Consider using U-type digital device instead.";
261  if (!model_.given("VLO"))
262  {
263  li_Lo = 0;
264  ++numExtVars;
265  }
266  if (!model_.given("VHI"))
267  {
268  li_Hi = 0;
269  ++numExtVars;
270  }
271  if (!model_.given("VREF"))
272  {
273  li_Ref = 0;
274  ++numExtVars;
275  }
276  }
277  else
278  {
279  UserError0(*this) << "Digital device letter must be Y or U: " << getName();
280  return;
281  }
282 
283  // Configure number of inputs/outputs for each device
284  // Y devices are limited to 2 inputs.
285  std::string dev_type = getName().getDeviceType();
286 
287  // the need for dev_letter in this function call will go away
288  // once the Y devices are deprecated
289  if (dev_type == "NOT" || dev_type == "INV")
290  {
291  gateInfo_ = new InvData(dev_type,dev_letter,dev_numInputs);
292  }
293  else if (dev_type == "AND")
294  {
295  gateInfo_ = new AndData(dev_type,dev_letter,dev_numInputs);
296  }
297  else if (dev_type == "NAND")
298  {
299  gateInfo_ = new NandData(dev_type,dev_letter,dev_numInputs);
300  }
301  else if (dev_type == "OR")
302  {
303  gateInfo_ = new OrData(dev_type,dev_letter,dev_numInputs);
304  }
305  else if (dev_type == "NOR")
306  {
307  gateInfo_ = new NorData(dev_type,dev_letter,dev_numInputs);
308  }
309  else if (dev_type == "ADD")
310  {
311  gateInfo_ = new AddData(dev_type,dev_letter,dev_numInputs);
312  }
313  else if (dev_type == "XOR")
314  {
315  gateInfo_ = new XorData(dev_type,dev_letter,dev_numInputs);
316  }
317  else if (dev_type == "NXOR")
318  {
319  gateInfo_ = new NxorData(dev_type,dev_letter,dev_numInputs);
320  }
321  else if (dev_type == "DFF")
322  {
323  gateInfo_ = new DffData(dev_type,dev_letter,dev_numInputs);
324  }
325  else if (dev_type == "DLTCH")
326  {
327  gateInfo_ = new DltchData(dev_type,dev_letter,dev_numInputs);
328  }
329  else if (dev_type == "BUF")
330  {
331  gateInfo_ = new BufData(dev_type,dev_letter,dev_numInputs);
332  }
333  else
334  {
335  UserError0(*this) << "Unknown digital device type " << dev_type;
336  return;
337  }
338  // return the number of I/O pins to the Instance
341  gate = gateInfo_->getType();
343  icGiven_.resize(numOutput);
344 
345  int iBase = numExtVars;
346  int oBase = numExtVars + numInput;
347  numExtVars += numInput + numOutput;
348 
349  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
350  {
351  Xyce::dout() << "Digital Device " << getName() << " has iBase = " <<
352  iBase << ", oBase = " << oBase << ", numExtVars = " <<
353  numExtVars << std::endl;
354  }
355 
356  // catch cases of AND, NAND, OR or NOR gate with only one input specified
357  // or the number of nodes on the instance line does not match the
358  // (N) value specified as part of the gate type (e.g, AND(4)).
359  // Also catch case where gates with a fixed number of inputs have
360  // wrong number of inputs
361  gateInfo_->checkErrors(*this,instance_block,iBase,dev_numInputs);
362 
363  numIntVars = 0;
364  numStateVars = 4*numInput + 6*numOutput;
365 
366  li_Inp.resize(numInput);
367  li_currentStateInp.resize(numInput);
368  li_transitionTimeInp.resize(numInput);
369  li_QinpState.resize(numInput);
370  li_IinpState.resize(numInput);
371  li_Out.resize(numOutput);
372  li_currentStateOut.resize(numOutput);
373  li_transitionTimeOut.resize(numOutput);
374  li_QloState.resize(numOutput);
375  li_IloState.resize(numOutput);
376  li_QhiState.resize(numOutput);
377  li_IhiState.resize(numOutput);
378 
379  qlo.resize(numOutput);
380  ilo.resize(numOutput);
381  vcaplo.resize(numOutput);
382  qhi.resize(numOutput);
383  ihi.resize(numOutput);
384  vcaphi.resize(numOutput);
385  qref.resize(numInput);
386  iref.resize(numInput);
387  vcapref.resize(numInput);
388  rilo.resize(numOutput);
389  rihi.resize(numOutput);
390  riref.resize(numInput);
391  currentOut.resize(numOutput);
392  currentIn.resize(numInput);
393  glo.resize(numOutput);
394  ghi.resize(numOutput);
395 
396  qInp.resize(numInput);
397  iInp.resize(numInput);
398  vcapInp.resize(numInput);
399  currentInp.resize(numInput);
400 
401  inpL.resize(numInput);
402  iTime.resize(numInput);
403  outL.resize(numOutput);
404  oTime.resize(numOutput);
405 
406  // These are to store the indicies into the jacobian for the four element
407  // stamps for the capacitor/resistors connected to the input/outputs. The
408  // format is to have 6 int vectors for each stamp with format:
409  // (row 1, col 1, col 2, row 2, col 1, col 2). These will be replaced in
410  // registerJacLIDs with the indicies into the actual jacobian matrix.
411 
412  li_jac_Ref.resize(numInput);
413  li_jac_Hi.resize(numOutput);
414  li_jac_Lo.resize(numOutput);
415 
416  devConMap.resize(numExtVars);
417  for (int i=0 ; i<numExtVars ; ++i)
418  devConMap[i] = 1;
419 
420  jacStamp.resize(numExtVars);
421  int row = 0;
422  // Code required to support both Y-style and U-style digital devices.
423  // Y digital devices are now deprecated.
424  if (dev_letter == 'U')
425  {
426  // digital power and digital ground node are always on
427  // the instance line for a U device. The low reference
428  // voltage for inputs is assumed to be the same as the
429  // digital ground node.
430  row_Hi = row;
431  jacStamp[row].push_back(row);
432  for (int i=0 ; i<numOutput ; ++i)
433  {
434  li_jac_Hi[i].push_back(row);
435  li_jac_Hi[i].push_back(0);
436  li_jac_Hi[i].push_back(jacStamp[row].size());
437  li_jac_Hi[i].push_back(oBase+i);
438  li_jac_Hi[i].push_back(jacStamp[oBase+i].size());
439  jacStamp[row].push_back(oBase+i);
440  jacStamp[oBase+i].push_back(row);
441  }
442  ++row;
443 
444  row_Lo = row;
445  jacStamp[row].push_back(row);
446  for (int i=0 ; i<numOutput ; ++i)
447  {
448  li_jac_Lo[i].push_back(row);
449  li_jac_Lo[i].push_back(0);
450  li_jac_Lo[i].push_back(jacStamp[row].size());
451  li_jac_Lo[i].push_back(oBase+i);
452  li_jac_Lo[i].push_back(jacStamp[oBase+i].size());
453  jacStamp[row].push_back(oBase+i);
454  jacStamp[oBase+i].push_back(row);
455  }
456 
457  row_Ref = row;
458  for (int i=0 ; i<numInput ; ++i)
459  {
460  li_jac_Ref[i].push_back(row);
461  li_jac_Ref[i].push_back(0);
462  li_jac_Ref[i].push_back(1);
463  li_jac_Ref[i].push_back(iBase+i);
464  li_jac_Ref[i].push_back(jacStamp[iBase+i].size());
465  jacStamp[row].push_back(iBase+i);
466  jacStamp[iBase+i].push_back(row);
467  }
468  }
469  else if (dev_letter == 'Y')
470  {
471  // output low and output high reference voltages and input
472  // low reference voltage are optionally on the instance line
473  // for Y devices.
474  if (li_Lo == 0)
475  {
476  row_Lo = row;
477  jacStamp[row].push_back(row);
478  for (int i=0 ; i<numOutput ; ++i)
479  {
480  li_jac_Lo[i].push_back(row);
481  li_jac_Lo[i].push_back(0);
482  li_jac_Lo[i].push_back(jacStamp[row].size());
483  li_jac_Lo[i].push_back(oBase+i);
484  li_jac_Lo[i].push_back(jacStamp[oBase+i].size());
485  jacStamp[row].push_back(oBase+i);
486  jacStamp[oBase+i].push_back(row);
487  }
488  ++row;
489  }
490  if (li_Hi == 0)
491  {
492  row_Hi = row;
493  jacStamp[row].push_back(row);
494  for (int i=0 ; i<numOutput ; ++i)
495  {
496  li_jac_Hi[i].push_back(row);
497  li_jac_Hi[i].push_back(0);
498  li_jac_Hi[i].push_back(jacStamp[row].size());
499  li_jac_Hi[i].push_back(oBase+i);
500  li_jac_Hi[i].push_back(jacStamp[oBase+i].size());
501  jacStamp[row].push_back(oBase+i);
502  jacStamp[oBase+i].push_back(row);
503  }
504  ++row;
505  }
506  if (li_Ref == 0)
507  {
508  row_Ref = row;
509  jacStamp[row].push_back(row);
510  for (int i=0 ; i<numInput ; ++i)
511  {
512  li_jac_Ref[i].push_back(row);
513  li_jac_Ref[i].push_back(0);
514  li_jac_Ref[i].push_back(jacStamp[row].size());
515  li_jac_Ref[i].push_back(iBase+i);
516  li_jac_Ref[i].push_back(jacStamp[iBase+i].size());
517  jacStamp[row].push_back(iBase+i);
518  jacStamp[iBase+i].push_back(row);
519  }
520  ++row;
521  }
522  }
523  else
524  {
525  UserError0(*this) << "Digital device letter must be Y or U: " << getName();
526  return;
527  }
528 
529  for (int i=0 ; i<numInput ; ++i)
530  {
531  if (li_Ref == 0)
532  {
533  li_jac_Ref[i].push_back(jacStamp[iBase+i].size());
534  }
535  else
536  {
537  li_jac_Ref[i].push_back(iBase+i);
538  }
539  jacStamp[iBase+i].push_back(iBase+i);
540  }
541  for (int i=0 ; i<numOutput ; ++i)
542  {
543  if (li_Lo == 0)
544  {
545  li_jac_Lo[i].push_back(jacStamp[oBase+i].size());
546  }
547  else
548  {
549  li_jac_Lo[i].push_back(oBase+i);
550  }
551  if (li_Hi == 0)
552  {
553  li_jac_Hi[i].push_back(jacStamp[oBase+i].size());
554  }
555  else
556  {
557  li_jac_Hi[i].push_back(oBase+i);
558  }
559  jacStamp[oBase+i].push_back(oBase+i);
560  }
561 
562  // Set params to constant default values:
563  setDefaultParams ();
564 
565  // Set params according to instance line and constant defaults from metadata:
566  setParams (instance_block.params);
567 
568  // Set any non-constant parameter defaults:
569 
570  // Calculate any parameters specified as expressions:
572 
573  // calculate dependent (ie computed) params:
574  processParams ();
575 }
576 
577 //-----------------------------------------------------------------------------
578 // Function : Instance::~Instance
579 // Purpose : destructor
580 // Special Notes :
581 // Scope : public
582 // Creator : Dave Shirley, PSSI
583 // Creation Date : 01/05/06
584 //-----------------------------------------------------------------------------
586 {
587  delete gateInfo_;
588 }
589 
590 // Additional Declarations
591 
592 //-----------------------------------------------------------------------------
593 // Function : Instance::registerLIDs
594 // Purpose :
595 // Special Notes :
596 // Scope : public
597 // Creator : Dave Shirley, PSSI
598 // Creation Date : 01/05/06
599 //-----------------------------------------------------------------------------
600 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
601  const std::vector<int> & extLIDVecRef)
602 
603 {
604  std::string msg;
605 
606  // Check if the size of the ID lists corresponds to the proper number of
607  // internal and external variables.
608  int numInt = intLIDVecRef.size();
609  int numExt = extLIDVecRef.size();
610 
611  if (numInt != numIntVars)
612  {
613  msg = "Instance::registerLIDs:";
614  msg += "numInt != numIntVars";
615  N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL,msg);
616  }
617 
618  if (numExt != numExtVars)
619  {
620  msg = "Instance::registerLIDs:";
621  msg += "numExt != numExtVars";
622  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
623  }
624 
625  // Copy over the local ID lists:
626  intLIDVec = intLIDVecRef;
627  extLIDVec = extLIDVecRef;
628 
629  // Now use these lists to obtain the indices into the linear algebra
630  // entities. This assumes an order. For the matrix indices, first do the
631  // rows.
632 
633  int i=0, j;
634  // Code required to support both Y-style and U-style digital devices.
635  // Y digital devices are now deprecated
636  char dev_letter = getName().getDeviceLetter();
637  if (dev_letter == 'U')
638  {
639  // ordering on U-device instance line is dig_power_node (DPWR) then
640  // dig_ground_node (DGND). Assume that input low-reference
641  // voltage (VREF in Y devices) is equal to DGND.
642  li_Hi = extLIDVec[i++];
643  li_Lo = extLIDVec[i++];
644  li_Ref = li_Lo;
645  }
646  else if (dev_letter == 'Y')
647  {
648  // for Y devices, ordering of output high/low reference nodes (VHI/VLO)
649  // on instance line is reversed. Input low-reference voltage (VREF),
650  // VHI and VLO can either be on the instance line or in the model card.
651  if (li_Lo == 0)
652  li_Lo = extLIDVec[i++];
653  if (li_Hi == 0)
654  li_Hi = extLIDVec[i++];
655  if (li_Ref == 0)
656  li_Ref = extLIDVec[i++];
657  }
658  else
659  {
660  UserError0(*this) << "Digital device letter must be Y or U: " << getName();
661  }
662 
663  for (j=0 ; j<numInput ; ++j)
664  li_Inp[j] = extLIDVec[i++];
665  for (j=0 ; j<numOutput ; ++j)
666  li_Out[j] = extLIDVec[i++];
667 }
668 
669 //-----------------------------------------------------------------------------
670 // Function : Instance::registerStateLIDs
671 // Purpose :
672 // Special Notes :
673 // Scope : public
674 // Creator : Dave Shirley, PSSI
675 // Creation Date : 01/05/06
676 //-----------------------------------------------------------------------------
677 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef)
678 {
679  std::string msg;
680 
681  // Check if the size of the ID lists corresponds to the proper number of
682  // internal and external variables.
683  int numSta = staLIDVecRef.size();
684 
685  if (numSta != numStateVars)
686  {
687  msg = "Instance::registerStateLIDs:";
688  msg += "numSta != numStateVars";
689  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
690  }
691 
692  // Copy over the global ID lists:
693  staLIDVec = staLIDVecRef;
694 
695  int j=0;
696 
697  for (int i=0 ; i<numInput ; ++i)
698  {
699  li_currentStateInp[i] = staLIDVec[j++];
701  li_QinpState[i] = staLIDVec[j++];
702  li_IinpState[i] = staLIDVec[j++];
703  }
704 
705  for (int i=0 ; i<numOutput ; ++i)
706  {
707  li_currentStateOut[i] = staLIDVec[j++];
709  li_QloState[i] = staLIDVec[j++];
710  li_IloState[i] = staLIDVec[j++];
711  li_QhiState[i] = staLIDVec[j++];
712  li_IhiState[i] = staLIDVec[j++];
713  }
714 }
715 
716 //-----------------------------------------------------------------------------
717 // Function : Instance::loadNodeSymbols
718 // Purpose :
719 // Special Notes :
720 // Scope : public
721 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
722 // Creation Date : 05/13/05
723 //-----------------------------------------------------------------------------
724 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
725 {
726 }
727 
728 //-----------------------------------------------------------------------------
729 // Function : Instance::jacobianStamp
730 // Purpose :
731 // Special Notes :
732 // Scope : public
733 // Creator : Dave Shirley, PSSI
734 // Creation Date : 01/05/06
735 //-----------------------------------------------------------------------------
736 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
737 {
738  return jacStamp;
739 }
740 
741 //-----------------------------------------------------------------------------
742 // Function : Instance::registerJacLIDs
743 // Purpose :
744 // Special Notes :
745 // Scope : public
746 // Creator : Dave Shirley, PSSI
747 // Creation Date : 01/05/06
748 //-----------------------------------------------------------------------------
749 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
750 {
751  DeviceInstance::registerJacLIDs( jacLIDVec );
752  int iBase = numExtVars - numInput - numOutput;
753  int oBase = iBase + numInput;
754  int lo_present, hi_present;
755 
756  (row_Lo < 0) ? (lo_present = 0) : (lo_present = 1);
757  (row_Hi < 0) ? (hi_present = 0) : (hi_present = 1);
758 
759  // Code required to support both Y-style and U-style digital devices.
760  // Y digital devices are now deprecated.
761  char dev_letter = getName().getDeviceLetter();
762 
763  if (dev_letter == 'U')
764  {
765  if ( (row_Lo == -1) || (row_Hi == -1) || (row_Ref == -1) )
766  {
767  UserError0(*this) << "Internal error in Instance::registerJacLIDs() for " << getName();
768  }
769  else
770  {
771  for (int i=0 ; i<numInput ; ++i)
772  {
773  li_jac_Ref[i][1] = jacLIDVec[li_jac_Ref[i][0]][li_jac_Ref[i][1]];
774  li_jac_Ref[i][2] = jacLIDVec[li_jac_Ref[i][0]][li_jac_Ref[i][2]];
775  li_jac_Ref[i][4] = jacLIDVec[li_jac_Ref[i][3]][li_jac_Ref[i][4]];
776  li_jac_Ref[i][5] = jacLIDVec[li_jac_Ref[i][3]][li_jac_Ref[i][5]];
777  }
778 
779  for (int i=0 ; i<numOutput ; ++i)
780  {
781  li_jac_Lo[i][1] = jacLIDVec[li_jac_Lo[i][0]][li_jac_Lo[i][1]];
782  li_jac_Lo[i][2] = jacLIDVec[li_jac_Lo[i][0]][li_jac_Lo[i][2]];
783  li_jac_Lo[i][4] = jacLIDVec[li_jac_Lo[i][3]][li_jac_Lo[i][4]];
784  li_jac_Lo[i][5] = jacLIDVec[li_jac_Lo[i][3]][li_jac_Lo[i][5]];
785  }
786 
787  for (int i=0 ; i<numOutput ; ++i)
788  {
789  li_jac_Hi[i][1] = jacLIDVec[li_jac_Hi[i][0]][li_jac_Hi[i][1]];
790  li_jac_Hi[i][2] = jacLIDVec[li_jac_Hi[i][0]][li_jac_Hi[i][2]];
791  li_jac_Hi[i][4] = jacLIDVec[li_jac_Hi[i][3]][li_jac_Hi[i][4]];
792  li_jac_Hi[i][5] = jacLIDVec[li_jac_Hi[i][3]][li_jac_Hi[i][5]];
793  }
794  }
795  }
796  else if (dev_letter == 'Y')
797  {
798  // row_Ref == -1 means that VREF is in the model card
799  if (row_Ref == -1)
800  {
801  for (int i=0 ; i<numInput ; ++i)
802  {
803  li_jac_Ref[i].push_back(jacLIDVec[li_jac_Ref[i][0]][0]);
804  }
805  }
806  else
807  {
808  // this for loop is identical for both U and Y devices
809  for (int i=0 ; i<numInput ; ++i)
810  {
811  li_jac_Ref[i][1] = jacLIDVec[li_jac_Ref[i][0]][li_jac_Ref[i][1]];
812  li_jac_Ref[i][2] = jacLIDVec[li_jac_Ref[i][0]][li_jac_Ref[i][2]];
813  li_jac_Ref[i][4] = jacLIDVec[li_jac_Ref[i][3]][li_jac_Ref[i][4]];
814  li_jac_Ref[i][5] = jacLIDVec[li_jac_Ref[i][3]][li_jac_Ref[i][5]];
815  }
816  }
817 
818  // row_Lo == -1 means that VLO is in the model card
819  if (row_Lo == -1)
820  {
821  for (int i=0 ; i<numOutput ; ++i)
822  {
823  li_jac_Lo[i].push_back(jacLIDVec[li_jac_Lo[i][0]][hi_present]);
824  }
825  }
826  else
827  {
828  // this for loop is identical for both U and Y devices
829  for (int i=0 ; i<numOutput ; ++i)
830  {
831  li_jac_Lo[i][1] = jacLIDVec[li_jac_Lo[i][0]][li_jac_Lo[i][1]];
832  li_jac_Lo[i][2] = jacLIDVec[li_jac_Lo[i][0]][li_jac_Lo[i][2]];
833  li_jac_Lo[i][4] = jacLIDVec[li_jac_Lo[i][3]][li_jac_Lo[i][4]];
834  li_jac_Lo[i][5] = jacLIDVec[li_jac_Lo[i][3]][li_jac_Lo[i][5]];
835  }
836  }
837 
838  // row_Hi == -1 means that VHI is in the model card
839  if (row_Hi == -1)
840  {
841  for (int i=0 ; i<numOutput ; ++i)
842  {
843  li_jac_Hi[i].push_back(jacLIDVec[li_jac_Hi[i][0]][lo_present]);
844  }
845  }
846  else
847  {
848  // this for loop is identical for both U and Y devices
849  for (int i=0 ; i<numOutput ; ++i)
850  {
851  li_jac_Hi[i][1] = jacLIDVec[li_jac_Hi[i][0]][li_jac_Hi[i][1]];
852  li_jac_Hi[i][2] = jacLIDVec[li_jac_Hi[i][0]][li_jac_Hi[i][2]];
853  li_jac_Hi[i][4] = jacLIDVec[li_jac_Hi[i][3]][li_jac_Hi[i][4]];
854  li_jac_Hi[i][5] = jacLIDVec[li_jac_Hi[i][3]][li_jac_Hi[i][5]];
855  }
856  }
857  }
858  else
859  {
860  UserError0(*this) << "Digital device letter must be Y or U: " << getName();
861  }
862 }
863 
864 //-----------------------------------------------------------------------------
865 // Function : Instance::updatePrimaryState
866 // Purpose :
867 // Special Notes :
868 // Scope : public
869 // Creator : Dave Shirley, PSSI
870 // Creation Date : 01/05/06
871 //-----------------------------------------------------------------------------
873 {
874  //added for debug purposes, for tracking input state changes
875  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
876  {
877  inputStateChange_ = false;
878  }
879 
880  bool bsuccess = true;
881  double v_poslo, v_poshi, v_posref, v_neg;
882  double elapsed, time, frac, lastT;
883  int currentState;
884  double transitionTime;
885  bool changeState = false; //Genie 110812
886  bool clocking = false; //Genie 111212
887 
888  Linear::Vector & solVector = *(extData.nextSolVectorPtr);
889  Linear::Vector & staVector = *(extData.nextStaVectorPtr);
890  Linear::Vector & oldStaVector = *(extData.currStaVectorPtr);
891  Linear::Vector & oldSolVector = *(extData.currSolVectorPtr);
892 
893  // added so that the oldState vector can be passed into gateInfo_->evaluateTruthTable()
894  std::vector<bool> oldState;
895  oldState.resize(numOutput);
896 
897  // The convention in this device is to consider the 'positive' side of the
898  // capacitors as the Vsrc or node that supplies the voltage, or for the
899  // output, vref. The 'positive' voltages are thus the same for all
900  // input/outputs
901  (li_Lo >= 0) ? (v_poslo = solVector[li_Lo]) : (v_poslo = model_.vlo);
902 
903  // If VHI is not specified, li_Hi >=0 and v_poshi is derived from
904  // CLOAD/RLOAD by solVector. If VHI is specified, li_Hi == -1 and
905  // v_poshi is specified by the netlist model card.
906  (li_Hi >= 0) ? (v_poshi = solVector[li_Hi]) : (v_poshi = model_.vhi);
907  (li_Ref >= 0) ? (v_posref = solVector[li_Ref]) : (v_posref = model_.vref);
908 
909  lastT = 0;
910 
911  for (int i=0 ; i<numInput ; ++i)
912  {
913  //initialize
914  currentState = static_cast <int> (oldStaVector[li_currentStateInp[i]]);
915  transitionTime = oldStaVector[li_transitionTimeInp[i]];
916  changeState = false; //Genie 022013 Clear the memory of changeState.
917 
918  // obtain voltage drop accross the capacitor:
919  v_neg = solVector[li_Inp[i]];
920 
921  time = getSolverState().currTime_;
922  elapsed = time - transitionTime;
923 
924  vcapref[i] = v_posref-v_neg;
925  riref[i] = model_.gload*(vcapref[i]);
926 
927  // Obtain the "current" value for the charge stored in the capacitors.
928  qref[i] = model_.cload*vcapref[i];
929 
930  if (getSolverState().dcopFlag)
931  {
932  transitionTime = 0;
933  (-vcapref[i] < model_.s0vhi) ? (currentState = 0) : (currentState = 1);
934 
935  oldStaVector[li_currentStateInp[i]] = currentState;
936  oldStaVector[li_transitionTimeInp[i]] = transitionTime;
937  }
938 
939  iTime[i] = transitionTime;
940 
941  staVector[li_transitionTimeInp[i]] = transitionTime;
942 
943  if (currentState == 0)
944  {
945  inpL[i] = false;
946  if ((-vcapref[i] > model_.s0vhi) && (-vcapref[i] > model_.s1vlo))
947  {
948  currentState = 1;
949  changeState = true;
950  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
951  {
952  Xyce::dout() << "Device " << getName() << " changed state from 1 to 0 at time " << getSolverState().currTime_ << std::endl;
953  }
954  // This call updates the clock status if the gate has a clock pin
955  // and this line is the clock pin. clocking is a local variable within
956  // updatePrimaryState()
957  if (gateInfo_->isClockLine(i)) { clocking = true; }
958  }
959  }
960  else
961  {
962  inpL[i] = true;
963  if ((-vcapref[i] < model_.s1vlo) && (-vcapref[i] < model_.s0vhi))
964  {
965  currentState = 0;
966  changeState = true;
967  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
968  {
969  Xyce::dout() << "Device " << getName() << " changed state from 1 to 0 at time " << getSolverState().currTime_ << std::endl;
970  }
971  // This call updates the clock status if the gate has a clock pin
972  // and this line is the clock pin. clocking is a local variable within
973  // updatePrimaryState()
974  if (gateInfo_->isClockLine(i)) { clocking = true; }
975  }
976  }
977 
978  if (changeState)
979  {
980  double vOld, del;
981 
982  inpL[i] = (currentState == 1);
983  (li_Ref >= 0) ? (vOld = oldSolVector[li_Ref]) : (vOld = model_.vref);
984  vOld = oldSolVector[li_Inp[i]] - vOld;
985  if (fabs(vcapref[i]+vOld) < 1.e-12)
986  del = 0;
987  else
988  {
989  if (inpL[i])
990  {
991  del = getSolverState().currTimeStep_ * (-vcapref[i] - model_.s0vhi)/(-vcapref[i] - vOld);
992  }
993  else
994  {
995  del = getSolverState().currTimeStep_ * (vcapref[i] + model_.s1vlo)/(vcapref[i] + vOld);
996  }
997  }
998  staVector[li_transitionTimeInp[i]] = time - del;
999  iTime[i] = time;
1000  }
1001 
1002  staVector[li_currentStateInp[i]] = currentState;
1003  staVector[li_QinpState[i]] = qref[i];
1004 
1005  if (iTime[i] > lastT)
1006  lastT = iTime[i];
1007 
1008  // added for debug, for tracking input state changes
1009  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1010  {
1011  if (changeState == true && inputStateChange_ == false)
1012  {
1013  inputStateChange_ = true;
1014  }
1015  }
1016  } // end for loop numInput i
1017 
1018  // update the truth table for this iteration
1019  for (int i=0 ; i <numOutput ; ++i)
1020  {
1021  oldState[i] = oldStaVector[li_currentStateOut[i]];
1022  }
1024  getSolverState().dcopFlag,clocking, oldState);
1025 
1026  bool curr;
1027  breakTime = 0;
1028  for (int i=0 ; i<numOutput ; ++i)
1029  {
1030  time = getSolverState().currTime_;
1031  if (getSolverState().dcopFlag)
1032  {
1033  gateInfo_->setIC(*this,i);
1034 
1035  oldStaVector[li_currentStateOut[i]] = outL[i]?1:0;
1036  oldStaVector[li_transitionTimeOut[i]] = time;
1037  }
1038 
1039  //current logic state of output nodes
1040  currentState = static_cast <int> (oldStaVector[li_currentStateOut[i]]);
1041  transitionTime = oldStaVector[li_transitionTimeOut[i]];
1042 
1043  if (currentState == 1)
1044  curr = true;
1045  else
1046  curr = false;
1047 
1048  if (curr != outL[i]) // This is executed when scopFlag is false
1049  {
1050  if (oTime[i] <= time)
1051  {
1052  currentState = 1-currentState;
1053  transitionTime = oTime[i];
1054  }
1055  else
1056  {
1057  if (breakTime == 0 || (breakTime > 0 && breakTime > oTime[i]))
1058  {
1059  breakTime = oTime[i];
1060  }
1061  }
1062  }
1063 
1064  staVector[li_currentStateOut[i]] = currentState;
1065  staVector[li_transitionTimeOut[i]] = transitionTime;
1066 
1067  // obtain voltage drop accross the capacitors:
1068  v_neg = solVector[li_Out[i]];
1069 
1070  elapsed = time - transitionTime;
1071 
1072  if (currentState == 0)
1073  elapsed /= model_.s0tsw;
1074  else if (currentState == 1)
1075  elapsed /= model_.s1tsw;
1076  else
1077  {
1078  std::string msg("Instance::updateSecondaryState: unrecognized state");
1079  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
1080  }
1081 
1082  frac = exp(-elapsed); //Genie 112812. This line can be omitted.
1083  if (transitionTime == 0)
1084  frac = 0;
1085  else
1086  {
1087  if (elapsed > 1)
1088  frac = 0;
1089  else
1090  {
1091  // This is a simple linear transition. Since there is a
1092  // breakpoint at the start of the transition it is OK to
1093  // have a discontinuity there.
1094  frac = 1-elapsed;
1095  }
1096  }
1097 
1098  // DFF and DLTCH outputs are put into the "X" state at DCOP if the DIGINITSTATE option
1099  // equals 2 and an initial condition was not specified for this output.
1100  if ( digInitState_ == 2 && getSolverState().dcopFlag && supportsXState_ && !icGiven_[i])
1101  {
1102  // for the "X" state have the output both pulled-up to the high-state voltage and pulled
1103  // down to the low-state voltage
1104  glo[i] = 1/(frac*model_.s1rlo + (1-frac)*model_.s0rlo);
1105  ghi[i] = 1/(frac*model_.s0rhi + (1-frac)*model_.s1rhi);
1106  }
1107  else if (currentState == 0)
1108  {
1109  glo[i] = 1/(frac*model_.s1rlo + (1-frac)*model_.s0rlo);
1110  ghi[i] = 1/(frac*model_.s1rhi + (1-frac)*model_.s0rhi);
1111  }
1112  else
1113  {
1114  glo[i] = 1/(frac*model_.s0rlo + (1-frac)*model_.s1rlo);
1115  ghi[i] = 1/(frac*model_.s0rhi + (1-frac)*model_.s1rhi);
1116  }
1117 
1118  rilo[i] = glo[i]*(v_poslo-v_neg);
1119  rihi[i] = ghi[i]*(v_poshi-v_neg);
1120 
1121  vcaplo[i] = v_poslo-v_neg;
1122  vcaphi[i] = v_poshi-v_neg;
1123 
1124  // Obtain the "current" value for the charge stored in the capacitors.
1125  qlo[i] = model_.clo*vcaplo[i];
1126  qhi[i] = model_.chi*vcaphi[i];
1127 
1128  staVector[li_QloState[i]] = qlo[i];
1129  staVector[li_QhiState[i]] = qhi[i];
1130 
1131  }// end for loop numOutput i
1132 
1133  return bsuccess;
1134 }
1135 
1136 //-----------------------------------------------------------------------------
1137 // Function : Instance::updateSecondaryState
1138 // Purpose :
1139 // Special Notes :
1140 // Scope : public
1141 // Creator : Dave Shirley, PSSI
1142 // Creation Date : 01/05/06
1143 //-----------------------------------------------------------------------------
1145 {
1146  bool bsuccess = true;
1147 
1148  Linear::Vector * staVectorPtr = extData.nextStaVectorPtr;
1149 
1150  // Now that the state vector for time=0 is up-to-date, get the
1151  // derivative with respect to time of the charge, to obtain the
1152  // best estimate for the current in the capacitors.
1153 
1154  for (int i=0 ; i<numOutput ; ++i)
1155  {
1158 
1159  currentOut[i] = ilo[i] + ihi[i] + rilo[i] + rihi[i];
1160 
1161  (*staVectorPtr)[li_IloState[i]] = ilo[i];
1162  (*staVectorPtr)[li_IhiState[i]] = ihi[i];
1163  }
1164 
1165  for (int i=0 ; i<numInput ; ++i)
1166  {
1168 
1169  currentIn[i] = iref[i] + riref[i];
1170 
1171  (*staVectorPtr)[li_IinpState[i]] = iref[i];
1172  }
1173 
1174 
1175  return bsuccess;
1176 }
1177 
1178 //-----------------------------------------------------------------------------
1179 // Function : Instance::getInstanceBreakPoints
1180 // Purpose : Add break point for anticipated digital output transition
1181 // Special Notes :
1182 // Scope : public
1183 // Creator : Dave Shirley, PSSI
1184 // Creation Date : 02/07/06
1185 //-----------------------------------------------------------------------------
1187  std::vector<Util::BreakPoint> & breakPointTimes)
1188 {
1189  if (breakTime > getSolverState().currTime_)
1190  {
1191  breakPointTimes.push_back(breakTime);
1192  }
1193  return true;
1194 }
1195 
1196 //-----------------------------------------------------------------------------
1197 // Function : Instance::acceptStep
1198 // Purpose : This function is to be called ONLY at the point
1199 // when the time integrator has determined we've got a
1200 // converged, acceptable solution and is accepting it,
1201 // but before it's updated its times and rotated vectors.
1202 // It is used for debugging purpose
1203 //
1204 // Special Notes : In SPICE this same stuff was done in the "TRAaccept" function.
1205 //
1206 // Scope : public
1207 // Creator : Pete Sholander, SNL
1208 // Creation Date : 06/30/14
1209 //-----------------------------------------------------------------------------
1211 {
1212  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1213  {
1214  // this debugging code prints out cases where the input changes occur within the
1215  // the model delay, which may cause incorrect output states in some cases
1216  if (inputStateChange_)
1217  {
1219  if (delta <= model_.delay)
1220  {
1221  Xyce::dout() << "Device " << getName() << " changed state & accepted time step at "
1222  << getSolverState().currTime_ << ". Previous state" << std::endl
1223  << "change at Device " << getName() << " at time "
1224  << prevInputStateChangeTime_ << " was shorted-spaced. Delta= "
1225  << delta << std::endl << std::endl;
1226  }
1228  }
1229  }
1230 }
1231 
1232 //-----------------------------------------------------------------------------
1233 // Function : Instance::loadDAEQVector
1234 //
1235 // Purpose : Loads the Q-vector contributions for a single
1236 // digital instance.
1237 //
1238 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1239 // which the system of equations is represented as:
1240 //
1241 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1242 //
1243 // Scope : public
1244 // Creator : Dave Shirley, PSSI
1245 // Creation Date : 01/05/06
1246 //-----------------------------------------------------------------------------
1248 {
1249  bool bsuccess = true;
1250 
1251  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1252  {
1253  Xyce::dout() << subsection_divider << std::endl;
1254  Xyce::dout() << " Instance::loadDAEQVector" << std::endl;
1255  Xyce::dout() << " name = " << getName() <<std::endl;
1256  }
1257 
1258  for (int i=0 ; i<numOutput ; ++i)
1259  {
1260  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1261  {
1262  Xyce::dout() << " qlo[" << i << "] = " << qlo[i] << std::endl;
1263  Xyce::dout() << " qhi[" << i << "] = " << qhi[i] << std::endl;
1264  }
1265 
1266  if (li_Lo >= 0)
1267  {
1268 
1269  (*extData.daeQVectorPtr)[li_Lo] += qlo[i];
1270  }
1271  if (li_Hi >= 0)
1272  {
1273 
1274  (*extData.daeQVectorPtr)[li_Hi] += qhi[i];
1275  }
1276 
1277 
1278  (*extData.daeQVectorPtr)[li_Out[i]] -= qlo[i];
1279 
1280  (*extData.daeQVectorPtr)[li_Out[i]] -= qhi[i];
1281  }
1282 
1283  for (int i=0 ; i<numInput ; ++i)
1284  {
1285  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1286  {
1287  Xyce::dout() << " qref[" << i << "] = " << qref[i] << std::endl;
1288  }
1289 
1290  if (li_Ref >= 0)
1291  {
1292 
1293  (*extData.daeQVectorPtr)[li_Ref] += qref[i];
1294  }
1295 
1296 
1297  (*extData.daeQVectorPtr)[li_Inp[i]] -= qref[i];
1298  }
1299 
1300  return bsuccess;
1301 }
1302 
1303 //-----------------------------------------------------------------------------
1304 // Function : Instance::loadDAEFVector
1305 //
1306 // Purpose : Loads the F-vector contributions for a single
1307 // digital instance.
1308 //
1309 // Special Notes :
1310 //
1311 // Scope : public
1312 // Creator : Dave Shirley, PSSI
1313 // Creation Date : 01/05/06
1314 //-----------------------------------------------------------------------------
1316 {
1317  bool bsuccess = true;
1318  double coef = 0.0;
1319  double Vpos = 0.0;
1320  double Vneg = 0.0;
1321  double v_tmp = 0.0;
1322 
1323  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1324  {
1325  Xyce::dout() << subsection_divider << std::endl;
1326  Xyce::dout() << " Instance::loadDAEFVector" << std::endl;
1327  Xyce::dout() << " name = " << getName() <<std::endl;
1328  }
1329 
1330  for (int i=0 ; i<numOutput ; ++i)
1331  {
1332  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1333  {
1334  Xyce::dout() << " rilo[" << i << "] = " << rilo[i] << std::endl;
1335  Xyce::dout() << " rihi[" << i << "] = " << rihi[i] << std::endl;
1336  }
1337 
1338  if (li_Lo >= 0)
1339  {
1340 
1341  (*extData.daeFVectorPtr)[li_Lo] += rilo[i];
1342  }
1343  if (li_Hi >= 0)
1344  {
1345 
1346  (*extData.daeFVectorPtr)[li_Hi] += rihi[i];
1347  }
1348 
1349 
1350  (*extData.daeFVectorPtr)[li_Out[i]] -= rilo[i];
1351 
1352  (*extData.daeFVectorPtr)[li_Out[i]] -= rihi[i];
1353  }
1354 
1355  for (int i=0 ; i<numInput ; ++i)
1356  {
1357  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1358  {
1359  Xyce::dout() << " riref[" << i << "] = " << riref[i] << std::endl;
1360  }
1361 
1362  if (li_Ref >= 0)
1363  {
1364 
1365  (*extData.daeFVectorPtr)[li_Ref] += riref[i];
1366  }
1367 
1368 
1369  (*extData.daeFVectorPtr)[li_Inp[i]] -= riref[i];
1370  }
1371 
1372  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1373  {
1374  Xyce::dout() << subsection_divider << std::endl;
1375  }
1376 
1377  return bsuccess;
1378 }
1379 
1380 //-----------------------------------------------------------------------------
1381 // Function : Instance::loadDAEdQdx
1382 //
1383 // Purpose : Loads the dQdx-matrix contributions for a single
1384 // digital instance.
1385 //
1386 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1387 // which the system of equations is represented as:
1388 //
1389 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1390 //
1391 // Scope : public
1392 // Creator : Dave Shirley, PSSI
1393 // Creation Date : 01/05/06
1394 //-----------------------------------------------------------------------------
1396 {
1397  bool bsuccess = true;
1398 
1399  Linear::Matrix * dQdxMatPtr = extData.dQdxMatrixPtr;
1400 
1401  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1402  {
1403  Xyce::dout() << subsection_divider <<std::endl;
1404  Xyce::dout() << " Instance::loadDAEdQdx" << std::endl;
1405  Xyce::dout() << " name = " << getName() << std::endl;
1406  }
1407 
1408  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1409  {
1410  Xyce::dout() << "\nLoading DIGITAL dQdx matrix\n";
1411  Xyce::dout() << "Capacitance lo: " << model_.clo << std::endl;
1412  Xyce::dout() << "Capacitance hi: " << model_.chi << std::endl;
1413  Xyce::dout() << "Capacitance load: " << model_.cload << std::endl;
1414  Xyce::dout() << "DONE DIGITAL dQdx matrix LOAD\n";
1415  }
1416 
1417  for (int i=0 ; i<numInput ; ++i)
1418  {
1419  if (row_Ref >= 0)
1420  {
1421 
1422  (*dQdxMatPtr)[li_Ref][li_jac_Ref[i][1]] += model_.cload;
1423 
1424  (*dQdxMatPtr)[li_Ref][li_jac_Ref[i][2]] -= model_.cload;
1425 
1426  (*dQdxMatPtr)[li_Inp[i]][li_jac_Ref[i][4]] -= model_.cload;
1427 
1428  (*dQdxMatPtr)[li_Inp[i]][li_jac_Ref[i][5]] += model_.cload;
1429  }
1430  else
1431  {
1432 
1433  (*dQdxMatPtr)[li_Inp[i]][li_jac_Ref[i][1]] += model_.cload;
1434  }
1435  }
1436 
1437  for (int i=0 ; i<numOutput ; ++i)
1438  {
1439  if (row_Lo >= 0)
1440  {
1441 
1442  (*dQdxMatPtr)[li_Lo][li_jac_Lo[i][1]] += model_.clo;
1443 
1444  (*dQdxMatPtr)[li_Lo][li_jac_Lo[i][2]] -= model_.clo;
1445 
1446  (*dQdxMatPtr)[li_Out[i]][li_jac_Lo[i][4]] -= model_.clo;
1447 
1448  (*dQdxMatPtr)[li_Out[i]][li_jac_Lo[i][5]] += model_.clo;
1449  }
1450  else
1451  {
1452 
1453  (*dQdxMatPtr)[li_Out[i]][li_jac_Lo[i][1]] += model_.clo;
1454  }
1455  if (row_Hi >= 0)
1456  {
1457 
1458  (*dQdxMatPtr)[li_Hi][li_jac_Hi[i][1]] += model_.chi;
1459 
1460  (*dQdxMatPtr)[li_Hi][li_jac_Hi[i][2]] -= model_.chi;
1461 
1462  (*dQdxMatPtr)[li_Out[i]][li_jac_Hi[i][4]] -= model_.chi;
1463 
1464  (*dQdxMatPtr)[li_Out[i]][li_jac_Hi[i][5]] += model_.chi;
1465  }
1466  else
1467  {
1468 
1469  (*dQdxMatPtr)[li_Out[i]][li_jac_Hi[i][1]] += model_.chi;
1470  }
1471  }
1472 
1473  return bsuccess;
1474 }
1475 
1476 //-----------------------------------------------------------------------------
1477 // Function : Instance::loadDAEdFdx ()
1478 //
1479 // Purpose : Loads the F-vector contributions for a single
1480 // digital instance.
1481 //
1482 // Special Notes : See the special notes for loadDAEFVector.
1483 // For digital devices this is the contribution of the resistors
1484 //
1485 // Scope : public
1486 // Creator : Dave Shirley, PSSI
1487 // Creation Date : 01/05/06
1488 //-----------------------------------------------------------------------------
1490 {
1491  bool bsuccess = true;
1492  Linear::Matrix * dFdxMatPtr = extData.dFdxMatrixPtr;
1493 
1494  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1495  {
1496  Xyce::dout() << subsection_divider <<std::endl;
1497  Xyce::dout() << " Instance::loadDAEdFdx" << std::endl;
1498  }
1499 
1500  for (int i=0 ; i<numInput ; ++i)
1501  {
1502  if (row_Ref >= 0)
1503  {
1504 
1505  (*dFdxMatPtr)[li_Ref][li_jac_Ref[i][1]] += model_.gload;
1506 
1507  (*dFdxMatPtr)[li_Ref][li_jac_Ref[i][2]] -= model_.gload;
1508 
1509  (*dFdxMatPtr)[li_Inp[i]][li_jac_Ref[i][4]] -= model_.gload;
1510 
1511  (*dFdxMatPtr)[li_Inp[i]][li_jac_Ref[i][5]] += model_.gload;
1512  }
1513  else
1514  {
1515 
1516  (*dFdxMatPtr)[li_Inp[i]][li_jac_Ref[i][1]] += model_.gload;
1517  }
1518  }
1519 
1520  for (int i=0 ; i<numOutput ; ++i)
1521  {
1522  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1523  {
1524  Xyce::dout() << " glo[" << i << "] = " << glo[i] << std::endl;
1525  Xyce::dout() << " ghi[" << i << "] = " << ghi[i] << std::endl;
1526  }
1527 
1528  if (row_Lo >= 0)
1529  {
1530 
1531  (*dFdxMatPtr)[li_Lo][li_jac_Lo[i][1]] += glo[i];
1532 
1533  (*dFdxMatPtr)[li_Lo][li_jac_Lo[i][2]] -= glo[i];
1534 
1535  (*dFdxMatPtr)[li_Out[i]][li_jac_Lo[i][4]] -= glo[i];
1536 
1537  (*dFdxMatPtr)[li_Out[i]][li_jac_Lo[i][5]] += glo[i];
1538  }
1539  else
1540  {
1541 
1542  (*dFdxMatPtr)[li_Out[i]][li_jac_Lo[i][1]] += glo[i];
1543  }
1544  if (row_Hi >= 0)
1545  {
1546 
1547  (*dFdxMatPtr)[li_Hi][li_jac_Hi[i][1]] += ghi[i];
1548 
1549  (*dFdxMatPtr)[li_Hi][li_jac_Hi[i][2]] -= ghi[i];
1550 
1551  (*dFdxMatPtr)[li_Out[i]][li_jac_Hi[i][4]] -= ghi[i];
1552 
1553  (*dFdxMatPtr)[li_Out[i]][li_jac_Hi[i][5]] += ghi[i];
1554  }
1555  else
1556  {
1557 
1558  (*dFdxMatPtr)[li_Out[i]][li_jac_Hi[i][1]] += ghi[i];
1559  }
1560  }
1561 
1562  return bsuccess;
1563 }
1564 
1565 // Class Model
1566 //-----------------------------------------------------------------------------
1567 // Function : Model::processParams
1568 // Purpose :
1569 // Special Notes :
1570 // Scope : public
1571 // Creator : Dave Shirley, PSSI
1572 // Creation Date : 01/05/06
1573 //-----------------------------------------------------------------------------
1575 {
1576 
1577  // If there are any time dependent parameters, set their values for
1578  // the current time.
1579 
1580  return true;
1581 }
1582 
1583 
1584 
1585 //----------------------------------------------------------------------------
1586 // Function : Model::processInstanceParams
1587 // Purpose :
1588 // Special Notes :
1589 // Scope : public
1590 // Creator : Dave Shirely, PSSI
1591 // Creation Date : 03/23/06
1592 //----------------------------------------------------------------------------
1594 {
1595 
1596  std::vector<Instance*>::iterator iter;
1597  std::vector<Instance*>::iterator first = instanceContainer.begin();
1598  std::vector<Instance*>::iterator last = instanceContainer.end();
1599 
1600  for (iter=first; iter!=last; ++iter)
1601  {
1602  (*iter)->processParams();
1603  }
1604 
1605  return true;
1606 }
1607 
1608 //-----------------------------------------------------------------------------
1609 // Function : Model::Model
1610 // Purpose : block constructor
1611 // Special Notes :
1612 // Scope : public
1613 // Creator : Dave Shirley, PSSI
1614 // Creation Date : 01/05/06
1615 //-----------------------------------------------------------------------------
1616 
1618  const Configuration & configuration,
1619  const ModelBlock & MB,
1620  const FactoryBlock & factory_block)
1621  : DeviceModel(MB, configuration.getModelParameters(), factory_block)
1622 
1623 {
1624 
1625  // Set params to constant default values:
1626  setDefaultParams ();
1627 
1628  // Set params according to .model line and constant defaults from metadata:
1629  setModParams (MB.params);
1630 
1631  // Set any non-constant parameter defaults:
1632 
1633  // Calculate any parameters specified as expressions:
1635 
1636  // calculate dependent (ie computed) params and check for errors:
1637  if (rload == 0)
1638  {
1639  UserError0(*this) << "Zero load resistance in inputs";
1640  }
1641  gload = 1/rload;
1642 
1643  processParams ();
1644 }
1645 
1646 //-----------------------------------------------------------------------------
1647 // Function : Model::Model
1648 // Purpose : destructor
1649 // Special Notes :
1650 // Scope : public
1651 // Creator : Dave Shirley, PSSI
1652 // Creation Date : 01/05/06
1653 //-----------------------------------------------------------------------------
1654 
1656 {
1657  std::vector<Instance*>::iterator iter;
1658  std::vector<Instance*>::iterator first = instanceContainer.begin();
1659  std::vector<Instance*>::iterator last = instanceContainer.end();
1660 
1661  for (iter=first; iter!=last; ++iter)
1662  {
1663  delete (*iter);
1664  }
1665 
1666 }
1667 
1668 //-----------------------------------------------------------------------------
1669 // Function : Model::printOutInstances
1670 // Purpose : debugging tool.
1671 // Special Notes :
1672 // Scope : public
1673 // Creator : Dave Shirley, PSSI
1674 // Creation Date : 01/05/06
1675 //-----------------------------------------------------------------------------
1676 
1677 std::ostream &Model::printOutInstances(std::ostream &os) const
1678 {
1679  std::vector<Instance*>::const_iterator iter;
1680  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
1681  std::vector<Instance*>::const_iterator last = instanceContainer.end();
1682 
1683  int i,isize;
1684 
1685  isize = instanceContainer.size();
1686  os << std::endl;
1687  os << "Number of digital instances: " << isize << std::endl;
1688  os << " name\t\tmodelName\tParameters" << std::endl;
1689 
1690  for (i = 0, iter = first; iter != last; ++iter, ++i)
1691  {
1692  os << " " << i << ": " << (*iter)->getName() << "\t";
1693  os << getName();
1694  os << std::endl;
1695  }
1696 
1697  os << std::endl;
1698 
1699  return os;
1700 }
1701 
1702 
1703 //-----------------------------------------------------------------------------
1704 // Function : Model::forEachInstance
1705 // Purpose :
1706 // Special Notes :
1707 // Scope : public
1708 // Creator : David Baur
1709 // Creation Date : 2/4/2014
1710 //-----------------------------------------------------------------------------
1711 /// Apply a device instance "op" to all instances associated with this
1712 /// model
1713 ///
1714 /// @param[in] op Operator to apply to all instances.
1715 ///
1716 ///
1717 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
1718 {
1719  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1720  op(*it);
1721 }
1722 
1723 
1724 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
1725 {
1726 
1727  return new DeviceMaster<Traits>(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
1728 }
1729 
1731 {
1732  // NOT device is deprecated now
1734  .registerDevice("inv", 1)
1735  .registerDevice("not",1)
1736  .registerDevice("and", 1)
1737  .registerDevice("nand", 1)
1738  .registerDevice("or", 1)
1739  .registerDevice("nor", 1)
1740  .registerDevice("add", 1)
1741  .registerDevice("xor", 1)
1742  .registerDevice("nxor", 1)
1743  .registerDevice("dff", 1)
1744  .registerDevice("buf", 1)
1745  .registerDevice("dltch", 1)
1746  .registerModelType("dig", 1);
1747 }
1748 
1749 //-----------------------------------------------------------------------------
1750 // Function : DeviceData::DeviceData
1751 // Purpose : Constructor for the DeviceData Class
1752 // Special Notes :
1753 // Scope : public
1754 // Creator : Pete Sholander
1755 // Creation Date : 8/7/2015
1756 //-----------------------------------------------------------------------------
1757 DeviceData::DeviceData(const char devLetter_):
1758  devLetter_('U')
1759 {
1760  //no op
1761 }
1762 
1763 //-----------------------------------------------------------------------------
1764 // Function : DeviceData::DeviceData
1765 // Purpose : destructor for the DeviceData class
1766 // Special Notes :
1767 // Scope : public
1768 // Creator : Pete Sholander
1769 // Creation Date : 8/7/2015
1770 //-----------------------------------------------------------------------------
1772 {}
1773 
1774 //-----------------------------------------------------------------------------
1775 // Function : DeviceData::updatePowerPinLi
1776 // Purpose : updates li_Lo, li_Hi, li_Ref and numExtVars
1777 // Special Notes :
1778 // Scope : public
1779 // Creator : Pete Sholander
1780 // Creation Date : 8/7/2015
1781 //-----------------------------------------------------------------------------
1782 void DeviceData::updatePowerPinLi(int& li_Lo, int& li_Hi, int& li_Ref,
1783  int& numExtVars, const bool vlo_given, const bool vhi_given,
1784  const bool vref_given)
1785 {
1786  // no op
1787 }
1788 
1789 //-----------------------------------------------------------------------------
1790 // Function : UDeviceData::UDeviceData
1791 // Purpose : Constructor for the UDeviceData Class
1792 // Special Notes :
1793 // Scope : public
1794 // Creator : Pete Sholander
1795 // Creation Date : 8/7/2015
1796 //-----------------------------------------------------------------------------
1797 UDeviceData::UDeviceData(const char devLetter_):
1798  DeviceData('U')
1799 {
1800  //Xyce::dout() << "Here in UDeviceData constructor\n";
1801 }
1802 
1803 //-----------------------------------------------------------------------------
1804 // Function : UDeviceData::UDeviceData
1805 // Purpose : destructor for the UDeviceData class
1806 // Special Notes :
1807 // Scope : public
1808 // Creator : Pete Sholander
1809 // Creation Date : 8/7/2015
1810 //-----------------------------------------------------------------------------
1812 {}
1813 
1814 //-----------------------------------------------------------------------------
1815 // Function : UDeviceData::updatePowerPinLi
1816 // Purpose : updates li_Lo, li_Hi, li_Ref and numExtVars for the U Device
1817 // Special Notes :
1818 // Scope : public
1819 // Creator : Pete Sholander
1820 // Creation Date : 8/7/2015
1821 //-----------------------------------------------------------------------------
1822 void UDeviceData::updatePowerPinLi(int& li_Lo, int& li_Hi, int& li_Ref,
1823  int& numExtVars, const bool vlo_given, const bool vhi_given,
1824  const bool vref_given)
1825 {
1826  // For U devices, DPWR and DGND are always specified on the instance line.
1827  // Warning message if VHI, VLO or VREF are in the model card.
1828  li_Lo = 0;
1829  li_Hi = 0;
1830  li_Ref = 0;
1831  numExtVars += 2;
1832  //if (model_.given("VLO"))
1833  //{
1834  // UserWarning(*this)<< "VLO model parameter ignored for U digital device";
1835  //}
1836  //if (model_.given("VHI"))
1837  //{
1838  // UserWarning(*this)<< "VHI model parameter ignored for U digital device";
1839  //}
1840  //if (model_.given("VREF"))
1841  //{
1842  // UserWarning(*this)<< "VREF model parameter ignored for U digital device";
1843  //}
1844 }
1845 
1846 //-----------------------------------------------------------------------------
1847 // Function : YDeviceData::YDeviceData
1848 // Purpose : Constructor for the DeviceData Class
1849 // Special Notes :
1850 // Scope : public
1851 // Creator : Pete Sholander
1852 // Creation Date : 8/7/2015
1853 //-----------------------------------------------------------------------------
1854 YDeviceData::YDeviceData(const char devLetter_):
1855  DeviceData('Y')
1856 {
1857  //no op
1858 }
1859 
1860 //-----------------------------------------------------------------------------
1861 // Function : YDeviceData::~YDeviceData
1862 // Purpose : destructor for the YDeviceData class
1863 // Special Notes :
1864 // Scope : public
1865 // Creator : Pete Sholander
1866 // Creation Date : 8/7/2015
1867 //-----------------------------------------------------------------------------
1869 {}
1870 
1871 //-----------------------------------------------------------------------------
1872 // Function : YDeviceData::updatePowerPinLi
1873 // Purpose : updates li_Lo, li_Hi, li_Ref and numExtVars for the Y Device
1874 // Special Notes :
1875 // Scope : public
1876 // Creator : Pete Sholander
1877 // Creation Date : 8/7/2015
1878 //-----------------------------------------------------------------------------
1879 void YDeviceData::updatePowerPinLi(int& li_Lo, int& li_Hi, int& li_Ref,
1880  int& numExtVars, const bool vlo_given, const bool vhi_given,
1881  const bool vref_given)
1882 {
1883  // legacy code required to support VLO, VHI and VREF variables
1884  // being on the instance line rather than in model card in Y devices
1885  if (!vlo_given) //!model_.given("VLO"))
1886  {
1887  li_Lo = 0;
1888  ++numExtVars;
1889  }
1890  if (!vhi_given) //(!model_.given("VHI"))
1891  {
1892  li_Hi = 0;
1893  ++numExtVars;
1894  }
1895  if (!vref_given) //(!model_.given("VREF"))
1896  {
1897  li_Ref = 0;
1898  ++numExtVars;
1899  }
1900 }
1901 
1902 //-----------------------------------------------------------------------------
1903 // Function : GateData::GateData
1904 // Purpose : Constructor for the GateData Class
1905 // Special Notes :
1906 // Scope : public
1907 // Creator : Pete Sholander
1908 // Creation Date : 8/6/2015
1909 //-----------------------------------------------------------------------------
1910 GateData::GateData(const std::string gateType_,const char devLetter_, const int ilNumInput_):
1911  gateType_(""),
1912  devLetter_('U'),
1913  ilNumInput_(0)
1914 {
1915  //no op
1916 }
1917 
1918 //-----------------------------------------------------------------------------
1919 // Function : GateData::~GateData
1920 // Purpose : destructor for the GateData class
1921 // Special Notes :
1922 // Scope : public
1923 // Creator : Pete Sholander
1924 // Creation Date : 8/6/2015
1925 //-----------------------------------------------------------------------------
1927 {}
1928 
1929 //-----------------------------------------------------------------------------
1930 // Function : GateData::evalTruthTable
1931 // Purpose : eval truth table and update output time for generic gate type.
1932 // This function will be virtualized once the rest are done.
1933 // Special Notes :
1934 // Scope : public
1935 // Creator : Pete Sholander
1936 // Creation Date : 8/6/2015
1937 //-----------------------------------------------------------------------------
1938 void GateData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
1939  std::vector<double>& oTime, const double lastT, const double delay,
1940  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldState)
1941 {
1942  // no op
1943 }
1944 
1945 //-----------------------------------------------------------------------------
1946 // Function : GateData::checkErrors
1947 // Purpose : check for instance line errors
1948 // Special Notes :
1949 // Scope : public
1950 // Creator : Pete Sholander
1951 // Creation Date : 8/6/2015
1952 //-----------------------------------------------------------------------------
1953 void GateData::checkErrors(const Instance& instance, const InstanceBlock& instance_block,
1954  const int& iBase, const int& dev_numInputs)
1955 {
1956  if (instance.numExtVars != instance_block.numExtVars)
1957  {
1958  UserError0(instance) << "Incorrect number of nodes in digital device."
1959  << " Found " << instance_block.numExtVars << ", should be " << instance.numExtVars;
1960  }
1961 }
1962 
1963 //-----------------------------------------------------------------------------
1964 // Function : GateData::isClockLine
1965 // Purpose : returns true if inputPin is the clock line
1966 // Special Notes :
1967 // Scope : public
1968 // Creator : Pete Sholander
1969 // Creation Date : 8/12/2015
1970 //-----------------------------------------------------------------------------
1971 bool GateData::isClockLine(const int inputPin)
1972 {
1973  return false;
1974 }
1975 
1976 //-----------------------------------------------------------------------------
1977 // Function : GateData::setIC
1978 // Purpose : set the initial conditions at a gate
1979 // Special Notes :
1980 // Scope : public
1981 // Creator : Pete Sholander
1982 // Creation Date : 8/6/2015
1983 //-----------------------------------------------------------------------------
1984 void GateData::setIC(Instance& instance, const int pinNum)
1985 {
1986  if (pinNum == 0)
1987  {
1988  if (instance.given("IC1"))
1989  {
1990  instance.outL[pinNum] = instance.ic1;
1991  instance.icGiven_[0] = true;
1992  }
1993  else
1994  {
1995  instance.icGiven_[0] = false;
1996  }
1997  }
1998  else if (pinNum == 1)
1999  {
2000  if (instance.given("IC2"))
2001  {
2002  instance.outL[pinNum] = instance.ic2;
2003  instance.icGiven_[1] = true;
2004  }
2005  else
2006  {
2007  instance.icGiven_[1] = false;
2008  }
2009  }
2010  else
2011  {
2012  std::string msg("Insufficient initial conditions supported in digital device");
2013  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2014  }
2015 }
2016 
2017 //-----------------------------------------------------------------------------
2018 // Function : GateData::getNumIO
2019 // Purpose : access the numInput and numOutput variables
2020 // Special Notes :
2021 // Scope : public
2022 // Creator : Pete Sholander
2023 // Creation Date : 8/6/2015
2024 //-----------------------------------------------------------------------------
2025 void GateData::getNumIO(int& input, int& output)
2026 {
2027  input = numInput_;
2028  output = numOutput_;
2029 }
2030 
2031 //-----------------------------------------------------------------------------
2032 // Function : InvData::InvData
2033 // Purpose : Constructor for the INV and NOT gate types
2034 // Special Notes :
2035 // Scope : public
2036 // Creator : Pete Sholander
2037 // Creation Date : 8/3/2015
2038 //-----------------------------------------------------------------------------
2039 InvData::InvData(const std::string gateType_, const char devLetter_, const int ilNumInput_):
2040  GateData(gateType_,devLetter_,ilNumInput_)
2041 {
2042  numInput_ = 1;
2043  numOutput_ = 1;
2044  type_ = INV;
2045  supportsXState_ = false;
2046 }
2047 
2048 //-----------------------------------------------------------------------------
2049 // Function : InvData::~InvData
2050 // Purpose : destructor for the InvData class
2051 // Special Notes :
2052 // Scope : public
2053 // Creator : Pete Sholander
2054 // Creation Date : 8/6/2015
2055 //-----------------------------------------------------------------------------
2057 {}
2058 
2059 //-----------------------------------------------------------------------------
2060 // Function : InvData::evalTruthTable
2061 // Purpose : eval truth table and update output time for INV and NOT gate types
2062 // Special Notes :
2063 // Scope : public
2064 // Creator : Pete Sholander
2065 // Creation Date : 8/6/2015
2066 //-----------------------------------------------------------------------------
2067 void InvData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2068  std::vector<double>& oTime, const double lastT, const double delay,
2069  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldState)
2070 {
2071  outL[0] = !inpL[0];
2072  oTime[0] = lastT + delay; // delay is model_.delay
2073 }
2074 
2075 //-----------------------------------------------------------------------------
2076 // Function : InvData::checkErrors
2077 // Purpose : check for instance line warnings for INV and NOT gate types
2078 // Special Notes :
2079 // Scope : public
2080 // Creator : Pete Sholander
2081 // Creation Date : 8/10/2015
2082 //-----------------------------------------------------------------------------
2083 void InvData::checkErrors(const Instance& instance, const InstanceBlock& instance_block,
2084  const int& iBase, const int& dev_numInputs)
2085 {
2086  if (gateType_ == "NOT")
2087  {
2088  UserWarning(instance)<< "NOT gate type (" << instance.getName() << ") is deprecated. Consider using INV instead.";
2089  }
2090  GateData::checkErrors(instance, instance_block, iBase, dev_numInputs);
2091 }
2092 
2093 //-----------------------------------------------------------------------------
2094 // Function : AndData::AndData
2095 // Purpose : Constructor for the AND gate type
2096 // Special Notes :
2097 // Scope : public
2098 // Creator : Pete Sholander
2099 // Creation Date : 8/3/2015
2100 //-----------------------------------------------------------------------------
2101 AndData::AndData(const std::string gateType_, const char devLetter_, const int ilNumInput_):
2102  GateData(gateType_,devLetter_,ilNumInput_)
2103 {
2104  numInput_ = (devLetter_ == 'Y') ? 2 : ilNumInput_;
2105  numOutput_ = 1;
2106  type_ = AND;
2107  supportsXState_ = false;
2108 }
2109 
2110 //-----------------------------------------------------------------------------
2111 // Function : AndData::~AndData
2112 // Purpose : destructor for the AndData class
2113 // Special Notes :
2114 // Scope : public
2115 // Creator : Pete Sholander
2116 // Creation Date : 8/6/2015
2117 //-----------------------------------------------------------------------------
2119 {}
2120 
2121 //-----------------------------------------------------------------------------
2122 // Function : AndData::evalTruthTable
2123 // Purpose : eval truth table and update output time for AND gate type
2124 // Special Notes :
2125 // Scope : public
2126 // Creator : Pete Sholander
2127 // Creation Date : 8/6/2015
2128 //-----------------------------------------------------------------------------
2129 void AndData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2130  std::vector<double>& oTime, const double lastT, const double delay,
2131  const bool dcopFlag, const bool clocking,const std::vector<bool>& oldState)
2132 {
2133  outL[0] = !(count(inpL.begin(),inpL.end(),false) > 0);
2134  oTime[0] = lastT + delay; // delay is model_.delay
2135 }
2136 
2137 //-----------------------------------------------------------------------------
2138 // Function : AndData::checkErrors
2139 // Purpose : check for instance line errors for AND gate type
2140 // Special Notes :
2141 // Scope : public
2142 // Creator : Pete Sholander
2143 // Creation Date : 8/10/2015
2144 //-----------------------------------------------------------------------------
2145 void AndData::checkErrors(const Instance& instance, const InstanceBlock& instance_block,
2146  const int& iBase, const int& dev_numInputs)
2147 {
2148  if (instance.numInput == 1)
2149  {
2150  UserError0(instance) << "this device must have more than one input.";
2151  }
2152  if ( (dev_numInputs != 0) && (instance_block.numExtVars - iBase - instance.numOutput != dev_numInputs) )
2153  {
2154  UserError0(instance) << "too few I/O nodes on instance line.";
2155  }
2156  GateData::checkErrors(instance, instance_block, iBase, dev_numInputs);
2157 }
2158 
2159 //-----------------------------------------------------------------------------
2160 // Function : NandData::NandData
2161 // Purpose : Constructor for the NAND gate type
2162 // Special Notes :
2163 // Scope : public
2164 // Creator : Pete Sholander
2165 // Creation Date : 8/3/2015
2166 //-----------------------------------------------------------------------------
2167 NandData::NandData(const std::string gateType_, const char devLetter_, const int ilNumInput_):
2168  GateData(gateType_,devLetter_,ilNumInput_)
2169 {
2170  numInput_ = (devLetter_ == 'Y') ? 2 : ilNumInput_;
2171  numOutput_ = 1;
2172  type_ = NAND;
2173  supportsXState_ = false;
2174 }
2175 
2176 //-----------------------------------------------------------------------------
2177 // Function : NandData::~NandData
2178 // Purpose : destructor for the AndData class
2179 // Special Notes :
2180 // Scope : public
2181 // Creator : Pete Sholander
2182 // Creation Date : 8/6/2015
2183 //-----------------------------------------------------------------------------
2185 {}
2186 
2187 //-----------------------------------------------------------------------------
2188 // Function : NandData::evalTruthTable
2189 // Purpose : eval truth table and update output time for NAND gate type
2190 // Special Notes :
2191 // Scope : public
2192 // Creator : Pete Sholander
2193 // Creation Date : 8/6/2015
2194 //-----------------------------------------------------------------------------
2195 void NandData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2196  std::vector<double>& oTime, const double lastT, const double delay,
2197  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldState)
2198 {
2199  outL[0] = (count(inpL.begin(),inpL.end(),false) > 0);
2200  oTime[0] = lastT + delay; // delay is model_.delay
2201 }
2202 
2203 //-----------------------------------------------------------------------------
2204 // Function : NandData::checkErrors
2205 // Purpose : check for instance line errors for NAND gate type
2206 // Special Notes :
2207 // Scope : public
2208 // Creator : Pete Sholander
2209 // Creation Date : 8/10/2015
2210 //-----------------------------------------------------------------------------
2211 void NandData::checkErrors(const Instance& instance, const InstanceBlock& instance_block,
2212  const int& iBase, const int& dev_numInputs)
2213 {
2214  if (instance.numInput == 1)
2215  {
2216  UserError0(instance) << "this device must have more than one input.";
2217  }
2218  if ( (dev_numInputs != 0) && (instance_block.numExtVars - iBase - instance.numOutput != dev_numInputs) )
2219  {
2220  UserError0(instance) << "too few I/O nodes on instance line.";
2221  }
2222  GateData::checkErrors(instance, instance_block, iBase, dev_numInputs);
2223 }
2224 
2225 //-----------------------------------------------------------------------------
2226 // Function : OrData::OrData
2227 // Purpose : Constructor for the OR gate type
2228 // Special Notes :
2229 // Scope : public
2230 // Creator : Pete Sholander
2231 // Creation Date : 8/3/2015
2232 //-----------------------------------------------------------------------------
2233 OrData::OrData(const std::string gateType_, const char devLetter_, const int ilNumInput_):
2234  GateData(gateType_,devLetter_,ilNumInput_)
2235 {
2236  numInput_ = (devLetter_ == 'Y') ? 2 : ilNumInput_;
2237  numOutput_ = 1;
2238  type_ = OR;
2239  supportsXState_ = false;
2240 }
2241 
2242 //-----------------------------------------------------------------------------
2243 // Function : OrData::~OrData
2244 // Purpose : destructor for the OrData class
2245 // Special Notes :
2246 // Scope : public
2247 // Creator : Pete Sholander
2248 // Creation Date : 8/6/2015
2249 //-----------------------------------------------------------------------------
2251 {}
2252 
2253 //-----------------------------------------------------------------------------
2254 // Function : OrData::evalTruthTable
2255 // Purpose : eval truth table and update output time for OR gate type
2256 // Special Notes :
2257 // Scope : public
2258 // Creator : Pete Sholander
2259 // Creation Date : 8/6/2015
2260 //-----------------------------------------------------------------------------
2261 void OrData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2262  std::vector<double>& oTime, const double lastT, const double delay,
2263  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldState)
2264 {
2265  outL[0] = outL[0] = (count(inpL.begin(),inpL.end(),true) > 0);
2266  oTime[0] = lastT + delay; // delay is model_.delay
2267 }
2268 
2269 //-----------------------------------------------------------------------------
2270 // Function : OrData::checkErrors
2271 // Purpose : check for instance line errors for OR gate type
2272 // Special Notes :
2273 // Scope : public
2274 // Creator : Pete Sholander
2275 // Creation Date : 8/10/2015
2276 //-----------------------------------------------------------------------------
2277 void OrData::checkErrors(const Instance& instance, const InstanceBlock& instance_block,
2278  const int& iBase, const int& dev_numInputs)
2279 {
2280  if (instance.numInput == 1)
2281  {
2282  UserError0(instance) << "this device must have more than one input.";
2283  }
2284  if ( (dev_numInputs != 0) && (instance_block.numExtVars - iBase - instance.numOutput != dev_numInputs) )
2285  {
2286  UserError0(instance) << "too few I/O nodes on instance line.";
2287  }
2288  GateData::checkErrors(instance, instance_block, iBase, dev_numInputs);
2289 }
2290 
2291 //-----------------------------------------------------------------------------
2292 // Function : NorData::NorData
2293 // Purpose : Constructor for the NOR gate type
2294 // Special Notes :
2295 // Scope : public
2296 // Creator : Pete Sholander
2297 // Creation Date : 8/3/2015
2298 //-----------------------------------------------------------------------------
2299 NorData::NorData(const std::string gateType_,const char devLetter_, const int ilNumInput_):
2300  GateData(gateType_,devLetter_,ilNumInput_)
2301 {
2302  numInput_ = (devLetter_ == 'Y') ? 2 : ilNumInput_;
2303  numOutput_ = 1;
2304  type_ = NOR;
2305  supportsXState_ = false;
2306 }
2307 
2308 //-----------------------------------------------------------------------------
2309 // Function : NorData::~NorData
2310 // Purpose : destructor for the NorData class
2311 // Special Notes :
2312 // Scope : public
2313 // Creator : Pete Sholander
2314 // Creation Date : 8/6/2015
2315 //-----------------------------------------------------------------------------
2317 {}
2318 
2319 //-----------------------------------------------------------------------------
2320 // Function : NorData::evalTruthTable
2321 // Purpose : eval truth table and update output time for NOR gate type
2322 // Special Notes :
2323 // Scope : public
2324 // Creator : Pete Sholander
2325 // Creation Date : 8/6/2015
2326 //-----------------------------------------------------------------------------
2327 void NorData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2328  std::vector<double>& oTime, const double lastT, const double delay,
2329  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldState)
2330 {
2331  outL[0] = !(count(inpL.begin(),inpL.end(),true) > 0);
2332  oTime[0] = lastT + delay; // delay is model_.delay
2333 }
2334 
2335 //-----------------------------------------------------------------------------
2336 // Function : NorData::checkErrors
2337 // Purpose : check for instance line errors for NOR gate type
2338 // Special Notes :
2339 // Scope : public
2340 // Creator : Pete Sholander
2341 // Creation Date : 8/10/2015
2342 //-----------------------------------------------------------------------------
2343 void NorData::checkErrors(const Instance& instance, const InstanceBlock& instance_block,
2344  const int& iBase, const int& dev_numInputs)
2345 {
2346  if (instance.numInput == 1)
2347  {
2348  UserError0(instance) << "this device must have more than one input.";
2349  }
2350  if ( (dev_numInputs != 0) && (instance_block.numExtVars - iBase - instance.numOutput != dev_numInputs) )
2351  {
2352  UserError0(instance) << "too few I/O nodes on instance line.";
2353  }
2354  GateData::checkErrors(instance, instance_block, iBase, dev_numInputs);
2355 }
2356 
2357 //-----------------------------------------------------------------------------
2358 // Function : AddData::AddData
2359 // Purpose : Constructor for the ADD gate type
2360 // Special Notes :
2361 // Scope : public
2362 // Creator : Pete Sholander
2363 // Creation Date : 8/3/2015
2364 //-----------------------------------------------------------------------------
2365 AddData::AddData(const std::string gateType_,const char devLetter_, const int ilNumInput_):
2366  GateData(gateType_,devLetter_,ilNumInput_)
2367 {
2368  numInput_ = 3;
2369  numOutput_ = 2;
2370  type_ = ADD;
2371  supportsXState_ = false;
2372 }
2373 
2374 //-----------------------------------------------------------------------------
2375 // Function : AddData::~AddData
2376 // Purpose : destructor for the AddData class
2377 // Special Notes :
2378 // Scope : public
2379 // Creator : Pete Sholander
2380 // Creation Date : 8/6/2015
2381 //-----------------------------------------------------------------------------
2383 {}
2384 
2385 //-----------------------------------------------------------------------------
2386 // Function : AddData::evalTruthTable
2387 // Purpose : eval truth table and update output time for ADD gate type
2388 // Special Notes :
2389 // Scope : public
2390 // Creator : Pete Sholander
2391 // Creation Date : 8/6/2015
2392 //-----------------------------------------------------------------------------
2393 void AddData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2394  std::vector<double>& oTime, const double lastT, const double delay,
2395  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldState)
2396 {
2397  outL[0] = inpL[0] ^ inpL[1] ^ inpL[2];
2398  // carry-out sum
2399  outL[1] = (inpL[0] & inpL[1]) | (inpL[1] & inpL[2]) | (inpL[0] & inpL[2]);
2400 
2401  oTime[0] = lastT+delay;
2402  oTime[1] = lastT+delay;
2403 }
2404 
2405 //-----------------------------------------------------------------------------
2406 // Function : XorData::XorData
2407 // Purpose : Constructor for the XOR gate type
2408 // Special Notes :
2409 // Scope : public
2410 // Creator : Pete Sholander
2411 // Creation Date : 8/3/2015
2412 //-----------------------------------------------------------------------------
2413 XorData::XorData(const std::string gateType_,const char devLetter_, const int ilNumInput_):
2414  GateData(gateType_,devLetter_,ilNumInput_)
2415 {
2416  numInput_ = 2;
2417  numOutput_ = 1;
2418  type_ = XOR;
2419  supportsXState_ = false;
2420 }
2421 
2422 //-----------------------------------------------------------------------------
2423 // Function : XorData::~XorData
2424 // Purpose : destructor for the XorData class
2425 // Special Notes :
2426 // Scope : public
2427 // Creator : Pete Sholander
2428 // Creation Date : 8/6/2015
2429 //-----------------------------------------------------------------------------
2431 {}
2432 
2433 //-----------------------------------------------------------------------------
2434 // Function : XorData::evalTruthTable
2435 // Purpose : eval truth table and update output time for XOR gate type
2436 // Special Notes :
2437 // Scope : public
2438 // Creator : Pete Sholander
2439 // Creation Date : 8/6/2015
2440 //-----------------------------------------------------------------------------
2441 void XorData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2442  std::vector<double>& oTime, const double lastT, const double delay,
2443  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldState)
2444 {
2445  outL[0] = inpL[0] ^ inpL[1];
2446  oTime[0] = lastT + delay; // delay is model_.delay
2447 }
2448 
2449 //-----------------------------------------------------------------------------
2450 // Function : NxorData::NxorData
2451 // Purpose : Constructor for the NXOR gate type
2452 // Special Notes :
2453 // Scope : public
2454 // Creator : Pete Sholander
2455 // Creation Date : 8/3/2015
2456 //-----------------------------------------------------------------------------
2457 NxorData::NxorData(const std::string gateType_,const char devLetter_, const int ilNumInput_):
2458  GateData(gateType_,devLetter_,ilNumInput_)
2459 {
2460  numInput_ = 2;
2461  numOutput_ = 1;
2462  type_ = NXOR;
2463  supportsXState_ = false;
2464 }
2465 
2466 //-----------------------------------------------------------------------------
2467 // Function : NxorData::~NxorData
2468 // Purpose : destructor for the NxorData class
2469 // Special Notes :
2470 // Scope : public
2471 // Creator : Pete Sholander
2472 // Creation Date : 8/6/2015
2473 //-----------------------------------------------------------------------------
2475 {}
2476 
2477 //-----------------------------------------------------------------------------
2478 // Function : NxorData::evalTruthTable
2479 // Purpose : eval truth table and update output time for NXOR gate type
2480 // Special Notes :
2481 // Scope : public
2482 // Creator : Pete Sholander
2483 // Creation Date : 8/6/2015
2484 //-----------------------------------------------------------------------------
2485 void NxorData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2486  std::vector<double>& oTime, const double lastT, const double delay,
2487  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldStaVector)
2488 {
2489  outL[0] = !(inpL[0] ^ inpL[1]);
2490  oTime[0] = lastT + delay; // delay is model_.delay
2491 }
2492 
2493 //-----------------------------------------------------------------------------
2494 // Function : DffData::DffData
2495 // Purpose : Constructor for the DFF gate type
2496 // Special Notes :
2497 // Scope : public
2498 // Creator : Pete Sholander
2499 // Creation Date : 8/3/2015
2500 //-----------------------------------------------------------------------------
2501 DffData::DffData(const std::string gateType_,const char devLetter_, const int ilNumInput_):
2502  GateData(gateType_,devLetter_,ilNumInput_)
2503 {
2504  numInput_ = 4; //PREB, CLRB, clock, data
2505  numOutput_ = 2; // Q, Q_bar
2506  clockPin_ = 2;
2507  type_ = DFF;
2508  supportsXState_ = true;
2509 }
2510 
2511 //-----------------------------------------------------------------------------
2512 // Function : DffData::~DffData
2513 // Purpose : destructor for the DffData class
2514 // Special Notes :
2515 // Scope : public
2516 // Creator : Pete Sholander
2517 // Creation Date : 8/6/2015
2518 //-----------------------------------------------------------------------------
2520 {}
2521 
2522 //-----------------------------------------------------------------------------
2523 // Function : Dff::evalTruthTable
2524 // Purpose : eval truth table and update output time for DFF gate type
2525 // Special Notes :
2526 // Scope : public
2527 // Creator : Pete Sholander
2528 // Creation Date : 8/6/2015
2529 //-----------------------------------------------------------------------------
2530 void DffData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2531  std::vector<double>& oTime, const double lastT, const double delay,
2532  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldState)
2533 {
2534  // DFF: in0: PREB, in1: CLRB, in2: clock, in3: data
2535  // DFF: out0: Q, out1: Q_bar
2536  // CD4013B: set = !PREB, reset = !CLRB
2537  // CD4013B: in0: set, in1: reset, in2: clock, in3: data
2538  // CD4013B: out0: Q, out1: Q_bar
2539  if (clocking && inpL[2] ==1) //clock rising edge 0->1
2540  {
2541  if (inpL[0] == 1 && inpL[1] == 1) //PREB = CLRB = 1
2542  {
2543  outL[0] = inpL[3]; //Q = D
2544  outL[1] = !(inpL[3]); //Q_bar = !D
2545  }
2546  }
2547  else if (clocking && inpL[2] ==0) //clock falling edge 1->0
2548  {
2549  if (inpL[0] == 1 && inpL[1] == 1) //PREB = CLRB = 1
2550  {
2551  //oldState0 = oldStaVector[li_currentStateOut[0]]
2552  //oldState1 = oldStaVector[li_currentStateOut[1]]
2553  outL[0] = oldState[0];
2554  outL[1] = oldState[1];
2555  }
2556  }
2557  else // no clock change
2558  {
2559  if (inpL[0] == 1 && inpL[1] == 0) //PREB=1, CLRB = 0
2560  {
2561  outL[0] = 0;
2562  outL[1] = 1;
2563  }
2564  else if (inpL[0] == 0 && inpL[1] == 1) //PREB = 0, CLRB = 1
2565  {
2566  outL[0] = 1;
2567  outL[1] = 0;
2568  }
2569  else if (inpL[0] == 0 && inpL[1] == 0) //PREB = CLRB = 0
2570  {
2571  outL[0] = 1;
2572  outL[1] = 1;
2573  }
2574  else if (dcopFlag) // getSolverState().dcopFlag
2575  { // Handle dcop calculation when enable is low. This forces Q and Qbar to be
2576  // different at DCOP. This behavior differs from PSpice, where Q and Qbar
2577  // would be in an indeterminate state that is about halfway between V_LO and V_HI.
2578  outL[0] = inpL[3];
2579  outL[1] = !inpL[3];
2580  }
2581  else if (outL[1] == outL[0])
2582  { // handles unstable state after PREB/CLRB = 0 state
2583  outL[1] = !outL[0];
2584  }
2585  else
2586  {
2587  // no op. Keep outputs in current state
2588  }
2589  }
2590 
2591  //Xyce::dout() << "Clocking, dcop and I/O are " << clocking << "," << dcopFlag
2592  // << " and (" << inpL[0] << "," << inpL[1]
2593  // << "," << inpL[2] << "," << inpL[3] << ") and ("
2594  // << outL[0] << "," << outL[1] << ")" << std::endl;
2595 
2596  oTime[0] = lastT+delay; // delay = model_.delay
2597  oTime[1] = lastT+delay;
2598 }
2599 
2600 //-----------------------------------------------------------------------------
2601 // Function : DffData::isClockLine
2602 // Purpose : returns true if inputPin is the clock line
2603 // Special Notes :
2604 // Scope : public
2605 // Creator : Pete Sholander
2606 // Creation Date : 8/12/2015
2607 //-----------------------------------------------------------------------------
2608 bool DffData::isClockLine(const int inputPin)
2609 {
2610  // Pin 2 is the clk pin in DFF. This is defined in the class definition in the
2611  // header file.
2612  return inputPin == clockPin_ ? true : false;
2613 }
2614 
2615 //-----------------------------------------------------------------------------
2616 // Function : DffData::setIC
2617 // Purpose : set the initial conditions at a DFF gate
2618 // Special Notes :
2619 // Scope : public
2620 // Creator : Pete Sholander
2621 // Creation Date : 8/14/2015
2622 //-----------------------------------------------------------------------------
2623 void DffData::setIC(Instance& instance, const int pinNum)
2624 {
2625  if (pinNum == 0)
2626  {
2627  if (instance.given("IC1"))
2628  {
2629  instance.outL[pinNum] = instance.ic1;
2630  instance.icGiven_[0] = true;
2631  }
2632  else if (instance.digInitState_ == 0)
2633  {
2634  instance.outL[pinNum] = 0;
2635  instance.icGiven_[0] = false;
2636  }
2637  else if (instance.digInitState_ == 1)
2638  {
2639  instance.outL[pinNum] = 1;
2640  instance.icGiven_[0] = false;
2641  }
2642  else // covers digInitState_ == 2 || 3
2643  {
2644  instance.icGiven_[0] = false;
2645  }
2646  }
2647  else if (pinNum == 1)
2648  {
2649  if (instance.given("IC2"))
2650  {
2651  instance.outL[pinNum] = instance.ic2;
2652  instance.icGiven_[1] = true;
2653  }
2654  else if (instance.digInitState_ == 0)
2655  {
2656  instance.outL[pinNum] = 1;
2657  instance.icGiven_[1] = false;
2658  }
2659  else if (instance.digInitState_ == 1)
2660  {
2661  instance.outL[pinNum] = 0;
2662  instance.icGiven_[1] = false;
2663  }
2664  else // covers digInitState_ == 2 || 3
2665  {
2666  instance.icGiven_[1] = false;
2667  }
2668  }
2669  else
2670  {
2671  std::string msg("Insufficient initial conditions supported in digital device");
2672  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2673  }
2674 }
2675 
2676 //-----------------------------------------------------------------------------
2677 // Function : DltchData::DltchData
2678 // Purpose : Constructor for the DLTCH gate type
2679 // Special Notes :
2680 // Scope : public
2681 // Creator : Pete Sholander
2682 // Creation Date : 8/3/2015
2683 //-----------------------------------------------------------------------------
2684 DltchData::DltchData(const std::string gateType_,const char devLetter_, const int ilNumInput_):
2685  GateData(gateType_,devLetter_,ilNumInput_)
2686 {
2687  numInput_ = 4; //PREB, CLRB, enable, data
2688  numOutput_ = 2; // Q, Q_bar
2689  type_ = DLTCH;
2690  supportsXState_ = true;
2691 }
2692 
2693 //-----------------------------------------------------------------------------
2694 // Function : DltchData::~DltchData
2695 // Purpose : destructor for the DltchData class
2696 // Special Notes :
2697 // Scope : public
2698 // Creator : Pete Sholander
2699 // Creation Date : 8/6/2015
2700 //-----------------------------------------------------------------------------
2702 {}
2703 
2704 //-----------------------------------------------------------------------------
2705 // Function : DltchData::evalTruthTable
2706 // Purpose : eval truth table and update output time for DLTCH gate type
2707 // Special Notes :
2708 // Scope : public
2709 // Creator : Pete Sholander
2710 // Creation Date : 8/6/2015
2711 //-----------------------------------------------------------------------------
2712 void DltchData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2713  std::vector<double>& oTime, const double lastT, const double delay,
2714  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldState)
2715 {
2716  // DLTCH: in0: PREB, in1: CLRB, in2: enable, in3: data
2717  // DLTCH: out0: Q, out1: Q_bar
2718  if ((inpL[0] == 1) && (inpL[1] == 0))
2719  {
2720  outL[0] = 0;
2721  outL[1] = 1;
2722  oTime[0] = lastT+delay; // delay = model_.delay
2723  oTime[1] = lastT+delay;
2724  }
2725  else if ((inpL[0] == 0) && (inpL[1] == 1))
2726  {
2727  outL[0] = 1;
2728  outL[1] = 0;
2729  oTime[0] = lastT+delay;
2730  oTime[1] = lastT+delay;
2731  }
2732  else if ((inpL[0] == 0) && (inpL[1] == 0))
2733  { // this state is unstable. The transition out of this state is handled by the
2734  // else if (outL[1] == outL[0]) block below
2735  outL[0] = 1;
2736  outL[1] = 1;
2737  oTime[0] = lastT+delay;
2738  oTime[1] = lastT+delay;
2739  }
2740  else if (inpL[2] == 1)
2741  { // enable line, PREB and CLRB are TRUE
2742  outL[0] = inpL[3];
2743  outL[1] = !inpL[3];
2744  oTime[0] = lastT+delay;
2745  oTime[1] = lastT+delay;
2746  }
2747  else if (dcopFlag) // getSolverState().dcopFlag
2748  { // Handle dcop calculation when enable is low. This forces Q and Qbar to be
2749  // different at DCOP. This behavior differs from PSpice, where Q and Qbar
2750  // would be in an indeterminate state that is about halfway between V_LO and V_HI.
2751  outL[0] = inpL[3];
2752  outL[1] = !inpL[3];
2753  }
2754  else if (outL[1] == outL[0])
2755  { // handles unstable state after PREB/CLRB = 0 state
2756  outL[1] = !outL[0];
2757  oTime[1] = lastT+delay;
2758  }
2759  else
2760  {
2761  // no op. Keep outputs latched in current state
2762  }
2763 }
2764 
2765 //-----------------------------------------------------------------------------
2766 // Function : DltchData::setIC
2767 // Purpose : set the initial conditions at a DLTCH gate
2768 // Special Notes :
2769 // Scope : public
2770 // Creator : Pete Sholander
2771 // Creation Date : 8/14/2015
2772 //-----------------------------------------------------------------------------
2773 void DltchData::setIC(Instance& instance, const int pinNum)
2774 {
2775  if (pinNum == 0)
2776  {
2777  if (instance.given("IC1"))
2778  {
2779  instance.outL[pinNum] = instance.ic1;
2780  instance.icGiven_[0] = true;
2781  }
2782  else if (instance.digInitState_ == 0)
2783  {
2784  instance.outL[pinNum] = 0;
2785  instance.icGiven_[0] = false;
2786  }
2787  else if (instance.digInitState_ == 1)
2788  {
2789  instance.outL[pinNum] = 1;
2790  instance.icGiven_[0] = false;
2791  }
2792  else // covers digInitState_ == 2 || 3
2793  {
2794  instance.icGiven_[0] = false;
2795  }
2796  }
2797  else if (pinNum == 1)
2798  {
2799  if (instance.given("IC2"))
2800  {
2801  instance.outL[pinNum] = instance.ic2;
2802  instance.icGiven_[1] = true;
2803  }
2804  else if (instance.digInitState_ == 0)
2805  {
2806  instance.outL[pinNum] = 1;
2807  instance.icGiven_[1] = false;
2808  }
2809  else if (instance.digInitState_ == 1)
2810  {
2811  instance.outL[pinNum] = 0;
2812  instance.icGiven_[1] = false;
2813  }
2814  else // covers digInitState_ == 2 || 3
2815  {
2816  instance.icGiven_[1] = false;
2817  }
2818  }
2819  else
2820  {
2821  std::string msg("Insufficient initial conditions supported in digital device");
2822  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2823  }
2824 }
2825 
2826 //-----------------------------------------------------------------------------
2827 // Function : BufData::BufData
2828 // Purpose : Constructor for the Buf gate type
2829 // Special Notes :
2830 // Scope : public
2831 // Creator : Pete Sholander
2832 // Creation Date : 8/3/2015
2833 //-----------------------------------------------------------------------------
2834 BufData::BufData(const std::string gateType_,const char devLetter_, const int ilNumInput_):
2835  GateData(gateType_,devLetter_,ilNumInput_)
2836 {
2837  numInput_ = 1;
2838  numOutput_ = 1;
2839  type_= BUF;
2840  supportsXState_ = false;
2841 }
2842 
2843 //-----------------------------------------------------------------------------
2844 // Function : BufData::~BufData
2845 // Purpose : destructor for the BufData class
2846 // Special Notes :
2847 // Scope : public
2848 // Creator : Pete Sholander
2849 // Creation Date : 8/6/2015
2850 //-----------------------------------------------------------------------------
2852 {}
2853 
2854 //-----------------------------------------------------------------------------
2855 // Function : BufData::evalTruthTable
2856 // Purpose : eval truth table and update output time for BUF gate type
2857 // Special Notes :
2858 // Scope : public
2859 // Creator : Pete Sholander
2860 // Creation Date : 8/6/2015
2861 //-----------------------------------------------------------------------------
2862 void BufData::evalTruthTable(const std::vector<bool> inpL, std::vector<bool>& outL,
2863  std::vector<double>& oTime, const double lastT, const double delay,
2864  const bool dcopFlag, const bool clocking, const std::vector<bool>& oldState)
2865 {
2866  outL[0] = inpL[0];
2867  oTime[0] = lastT + delay; // delay is model_.delay
2868 }
2869 
2870 } // namespace Digital
2871 } // namespace Device
2872 } // namespace Xyce
const InstanceName & getName() const
std::vector< int > li_QinpState
std::vector< double > vcaplo
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
std::vector< double > iref
std::vector< double > rihi
std::vector< double > currentInp
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
const SolverState & solverState_
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
Descriptor & addPar(const char *parName, T default_value, T U::*varPtr)
Adds the parameter description to the parameter map.
Definition: N_DEV_Pars.h:1429
std::vector< int > li_IhiState
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
Linear::Vector * currSolVectorPtr
double currTimeStep_
Region, BJT, Digital, ThermalResistor, ROM, Charon, Others.
Linear::Vector * nextSolVectorPtr
std::vector< Instance * > instanceContainer
std::vector< int > li_QloState
bool given(const std::string &parameter_name) const
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
Linear::Vector * daeQVectorPtr
Pure virtual class to augment a linear system.
AndData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
void makeVector(const std::string &cname, int len)
Allows the parameter to be specified as a vector.
Definition: N_DEV_Pars.h:1597
std::vector< std::vector< int > > jacStamp
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
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
std::vector< int > li_IloState
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
std::vector< Param > params
Parameters from the line.
DffData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
std::vector< int > li_IinpState
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
virtual bool isClockLine(const int)
virtual void setIC(Instance &, const int)
std::vector< bool > icGiven_
void setParams(const std::vector< Param > &params)
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)
Definition: N_DEV_Digital.C:86
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
std::vector< double > iInp
std::vector< double > oTime
void checkErrors(const Instance &, const InstanceBlock &, const int &, const int &)
const DeviceOptions & getDeviceOptions() const
std::vector< double > vcapInp
InvData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
void setIC(Instance &, const int)
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.
Definition: N_DEV_Device.h:101
void updatePowerPinLi(int &, int &, int &, int &, const bool, const bool, const bool)
void updatePowerPinLi(int &, int &, int &, int &, const bool, const bool, const bool)
std::vector< double > glo
virtual void updatePowerPinLi(int &, int &, int &, int &, const bool, const bool, const bool)
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
void checkErrors(const Instance &, const InstanceBlock &, const int &, const int &)
char getDeviceLetter() const
Return the first letter of the device specification after the subcircuit.
NandData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
void checkErrors(const Instance &, const InstanceBlock &, const int &, const int &)
Class Configuration contains device configuration data.
virtual void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
std::vector< double > iTime
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
int digInitState
used to initialize all of the digital gates in a circuit
std::vector< std::vector< int > > li_jac_Ref
void checkErrors(const Instance &, const InstanceBlock &, const int &, const int &)
NorData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
DltchData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
std::vector< double > ghi
BufData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
YDeviceData(const char devLetter_)
bool processParams()
processParams
const SolverState & getSolverState() const
NxorData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
Definition: N_DEV_Digital.C:73
GateData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
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
AddData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
std::vector< int > li_currentStateInp
ModelBlock represents a .MODEL line from the netlist.
UDeviceData(const char devLetter_)
Manages parameter binding for class C.
Definition: N_DEV_Pars.h:214
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
InstanceBlock represent a device instance line from the netlist.
double currTime_
DeviceEntity for expression time, breakpoints DeviceMgr for dependent parameters, breakpoints...
virtual void checkErrors(const Instance &, const InstanceBlock &, const int &, const int &)
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
DeviceData(const char devLetter_)
std::vector< int > li_currentStateOut
void checkErrors(const Instance &, const InstanceBlock &, const int &, const int &)
std::vector< double > currentIn
void evalTruthTable(const std::vector< bool >, std::vector< bool > &, std::vector< double > &, const double, const double, const bool, const bool, const std::vector< bool > &)
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 > &params)
XorData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
void setIC(Instance &, const int)
bool processInstanceParams()
processInstanceParams
OrData(const std::string gateType_, const char devLetter_, const int ilNumInput_)
std::vector< std::vector< int > > li_jac_Lo