HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
wave_data.cpp
Go to the documentation of this file.
6 #include "hal_core/netlist/net.h"
7 #include <math.h>
8 #include <vector>
9 #include <QString>
10 #include <QVector>
11 #include <QMap>
12 #include <QDir>
13 #include <stdio.h>
14 
15 namespace hal {
16 
18  : WaveData(n, WaveData::ClockNet), mClock(clk), mMaxTime(tmax)
19  {
20  dataFactory();
21  }
22 
23  WaveDataClock::WaveDataClock(const Net* n, int start, u64 period, u64 tmax)
24  : WaveData(n, WaveData::ClockNet), mMaxTime(tmax)
25  {
26  mClock.clock_net = n;
27  mClock.switch_time = period / 2;
28  mClock.start_at_zero = (start==0);
29  }
30 
32  {
33  mMaxTime = tmax;
34  resetWave();
35  dataFactory();
36  }
37 
38  void WaveDataClock::dataFactory()
39  {
40  int val = mClock.start_at_zero ? 0 : 1;
41  for (u64 t=0; t<=mMaxTime; t+=mClock.switch_time)
42  {
43  mData.insert(t,val);
44  val = val ? 0 : 1;
45  }
46  }
47 
49  : mId(other.mId), mFileIndex(other.mFileIndex), mFileSize(other.mFileSize), mTimeframeSize(other.mTimeframeSize),
50  mName(other.mName), mNetType(other.mNetType), mBits(other.mBits), mValueBase(other.mValueBase),
51  mData(other.mData), mDirty(true)
52  {;}
53 
54  WaveData::WaveData(u32 id_, const QString& nam, NetType tp, const QMap<u64,int> &dat)
55  : mId(id_), mFileIndex(-1), mFileSize(0), mTimeframeSize(0), mName(nam), mNetType(tp), mBits(1), mValueBase(16), mData(dat), mDirty(true)
56  {;}
57 
59  : mId(n->get_id()), mFileIndex(-1), mFileSize(0), mTimeframeSize(0),
60  mName(QString::fromStdString(n->get_name())),
61  mNetType(tp), mBits(1), mValueBase(16), mDirty(true)
62  {;}
63 
65  {
66  mData.clear();
67  }
68 
70  {
71  mFileSize = siz;
72  mTimeframeSize = siz;
73  }
74 
76  {
78  if (mFileSize < maxSizeLoadable) return LoadAllData;
79  if (mTimeframeSize && mTimeframeSize < maxSizeLoadable) return LoadTimeframe;
80  return TooBigToLoad;
81  }
82 
83  void WaveData::setId(u32 id_)
84  {
85  mId = id_;
86  mDirty = true;
87  }
88 
89  bool WaveData::rename(const QString& nam)
90  {
91  if (mName == nam) return false;
92  mName = nam;
93  mDirty = true;
94  return true;
95  }
96 
97  void WaveData::setBits(int bts)
98  {
99  mBits = bts;
100  mDirty = true;
101  }
102 
104  {
105  int val = (int) bval;
106  if (!mData.isEmpty())
107  {
108  auto it = mData.upperBound(t);
109  if (it != mData.constBegin())
110  {
111  --it;
112  if (it.value() == bval) return; // Nothing to do, previous value matches
113  }
114  }
115  mData.insert(t,val);
116  mDirty = true;
117  }
118 
120  {
121  mData = dat;
122  mDirty = true;
123  }
124 
126  {
127  if (loadPolicy()==LoadAllData)
129  return intValue(t);
130  }
131 
133  {
134  switch (mNetType)
135  {
139  default: break;
140  }
142  }
143 
144  bool WaveData::isEqual(const WaveData& other, int tolerance) const
145  {
146  if (mFileSize != other.mFileSize) return false;
147  if (loadPolicy() == LoadAllData)
148  {
149  if (mData.size() != other.mData.size()) return false;
150  auto jt = other.mData.constBegin();
151  for (auto it = mData.begin(); it != mData.end(); ++it)
152  {
153  if (it.value() != jt.value()) return false;
154  if (abs((int64_t)it.key()-(int64_t)jt.key()) > tolerance) return false;
155  ++jt;
156  }
157  return true;
158  }
159  u64 t0 = 0;
160  for (;;)
161  {
162  std::vector<std::pair<u64,int>> evtsThis = get_events(t0);
163  std::vector<std::pair<u64,int>> evtsOther = other.get_events(t0);
164  if (evtsThis.empty()&&evtsOther.empty()) return true; // all tested
165  if (evtsThis.size()!=evtsOther.size()) return false;
166  auto jt = evtsOther.begin();
167  for (auto it = evtsThis.begin(); it != evtsThis.end(); ++it)
168  {
169  if (it->second != jt->second) return false;
170  if (abs((int64_t)it->first-(int64_t)jt->first)> tolerance) return false;
171  ++jt;
172  t0 = it->first;
173  }
174  t0++;
175  }
176  }
177 
179  {
180  return mWaveDataList->waveIndexByNetId(mId);
181  }
182 
183  std::vector<std::pair<u64,int>> WaveData::get_triggered_events(const WaveDataTrigger* wdTrig, u64 t0)
184  {
185  std::vector<std::pair<u64,int>> retval = wdTrig->get_events(t0);
186  for (auto it=retval.begin(); it!=retval.end(); ++it)
187  {
188  u64 t = it->first;
189  it->second = intValue(t);
190  }
191  return retval;
192  }
193 
194  std::vector<std::pair<u64,int>> WaveData::get_events(u64 t0) const
195  {
196  std::vector<std::pair<u64,int>> retval;
197  if (loadPolicy() == LoadAllData)
198  {
199  for (auto it = mData.lowerBound(t0); it != mData.constEnd(); ++it)
200  retval.push_back(std::make_pair(it.key(),it.value()));
201  }
202  else
203  {
204  WaveDataProvider* wdp = nullptr;
205  std::string saleaeDirectory = mWaveDataList->saleaeDirectory().get_filename();
206  switch (mNetType)
207  {
208  case WaveData::NetGroup:
209  {
210  const WaveDataGroup* wdGrp = static_cast<const WaveDataGroup*>(this);
211  wdp = new WaveDataProviderGroup(saleaeDirectory, wdGrp->children());
212  break;
213  }
215  {
216  const WaveDataBoolean* wdBool = static_cast<const WaveDataBoolean*>(this);
217  wdp = new WaveDataProviderBoolean(saleaeDirectory, wdBool->children(), wdBool->truthTable());
218  break;
219  }
221  {
222  const WaveDataTrigger* wdTrig = static_cast<const WaveDataTrigger*>(this);
223  wdp = new WaveDataProviderTrigger(saleaeDirectory, wdTrig->children(), wdTrig->toValueList(), wdTrig->get_filter_wave());
224  break;
225  }
226  default:
227  break;
228  }
229 
230  if (wdp)
231  {
232  SaleaeDataTuple sdt = wdp->startValue(t0);
233  while (sdt.mValue != SaleaeDataTuple::sReadError)
234  {
235  retval.push_back(std::make_pair(sdt.mTime,sdt.mValue));
236  sdt = wdp->nextPoint();
237  }
238  return retval;
239  }
240  if (mWaveDataList && mFileIndex>=0)
241  {
242  std::filesystem::path path = mWaveDataList->saleaeDirectory().get_datafile_path(mFileIndex);
243  if (!path.empty())
244  {
245  SaleaeInputFile sif(path);
246  if (t0)
247  {
248  if (sif.get_file_position(t0,true) < 0)
249  return retval;
250  }
252  if (sdb)
253  {
254  for (u64 i=0; i<sdb->mCount; i++)
255  retval.push_back(std::make_pair(sdb->mTimeArray[i],sdb->mValueArray[i]));
256  delete sdb;
257  }
258  }
259  }
260  }
261  return retval;
262  }
263 
265  {
266  if ((u64)mData.size() >= mFileSize) return;
267  loadSaleae();
268  }
269 
271  {
272  resetWave();
273  if (!mWaveDataList || mFileIndex<0) return false;
274  std::filesystem::path path = mWaveDataList->saleaeDirectory().get_datafile_path(mFileIndex);
275  if (path.empty()) return false;
276  SaleaeInputFile sif(path);
277  if (!sif.good()) return false;
278  u64 t0 = tframe.hasUserTimeframe() ? tframe.sceneMinTime() : 0;
279  u64 t1 = tframe.hasUserTimeframe() ? tframe.sceneMaxTime() : 0;
280  Q_ASSERT(t0 <= t1);
281 
282  int lastVal = BooleanFunction::X;
283  bool valuePending = false;
284  while (sif.good())
285  {
287  if (!sdb) break;
288  for (u64 i=0; i<sdb->mCount; i++)
289  {
290  u64 t = sdb->mTimeArray[i];
291  if (t < t0)
292  {
293  lastVal = sdb->mValueArray[i];
294  valuePending = true;
295  }
296  else if (t == t0)
297  {
298  mData.insert(t,sdb->mValueArray[i]);
299  valuePending = false;
300  }
301  else if (!t1 || t <= t1)
302  {
303  if (valuePending) mData.insert(t0,lastVal);
304  mData.insert(t,sdb->mValueArray[i]);
305  valuePending = false;
306  }
307  else
308  {
309  if (valuePending) mData.insert(t0,lastVal);
310  valuePending = false;
311  break;
312  }
313  }
314  delete sdb;
315  }
316  mDirty = true;
317  return true;
318  }
319 
321  {
322  if (!mWaveDataList) return;
325  std::string nam = mName.toStdString();
326  mFileIndex = sd.get_datafile_index(nam,mId);
327  if (mFileIndex < 0)
328  {
329  mFileIndex = sd.get_next_available_index();
330  QDir saleaeDir(QString::fromStdString(sd.get_directory()));
331  if (!saleaeDir.exists()) saleaeDir.mkpath(saleaeDir.absolutePath());
332  }
333 
334  SaleaeDirectoryNetEntry sdne(nam,mId);
335  sdne.addIndex(SaleaeDirectoryFileIndex(mFileIndex,0,maxTime(),mData.size()));
336  sd.add_or_replace_net(sdne);
337 
338  mFileSize = mData.size();
339 
340  SaleaeDataBuffer sdb(mFileSize);
341  int j = 0;
342  for (auto it = mData.constBegin(); it != mData.constEnd(); ++it)
343  {
344  sdb.mTimeArray[j] = it.key();
345  sdb.mValueArray[j] = it.value();
346  ++j;
347  }
348  SaleaeOutputFile sof(sd.get_datafile_path(mFileIndex),mFileIndex);
349  sof.put_data(&sdb);
350  }
351 
353  {
354  if (t<0) return mData.constEnd();
356  if (retval != mData.constBegin()) --retval;
357  return retval;
358  }
359 
360  u64 WaveData::neighborTransition(double t, bool next) const
361  {
362  u64 notFound = (u64) floor(t);
363  LoadPolicy lpol = loadPolicy();
364  if (lpol ==LoadAllData ||
365  (lpol == LoadTimeframe && !mData.isEmpty() && t>=mData.firstKey() && t < mData.lastKey() ))
366  {
367  if (next)
368  {
370  if (it == mData.end()) return notFound;
371  return it.key();
372  }
373  else
374  {
376  if (it == mData.begin()) return notFound;
377  --it;
378  return it.key();
379  }
380  }
381 
382  QList<WaveData*> childList;
383  switch (mNetType)
384  {
385  case NetGroup:
386  {
387  const WaveDataGroup* wdGrp = static_cast<const WaveDataGroup*>(this);
388  childList = wdGrp->children();
389  break;
390  }
391  case BooleanNet:
392  {
393  const WaveDataBoolean* wdBool = static_cast<const WaveDataBoolean*>(this);
394  childList = wdBool->children();
395  break;
396  }
397  // case TriggerNet: overwrite
398  default:
399  break;
400  }
401 
402  if (!childList.isEmpty())
403  {
404  bool first = true;
405  u64 retval = notFound;
406  for (const WaveData* wd : childList)
407  {
408  double tChild = wd->neighborTransition(t,next);
409  if (tChild == notFound) continue;
410  if (first)
411  {
412  retval = tChild;
413  first = false;
414  }
415  else if (next)
416  {
417  if (tChild < retval) retval = tChild;
418  }
419  else
420  {
421  if (tChild > retval) retval = tChild;
422  }
423  }
424  return retval;
425  }
426 
427 
428  if (!mWaveDataList) return notFound;
430  if (!sif.good()) return notFound;
431 
432  int64_t pos = sif.get_file_position(t,next);
433 
434  while (pos >= 0 && pos <= (int64_t) sif.header()->numTransitions())
435  {
436  SaleaeDataTuple sdt = sif.get_next_value();
437  if (sdt.readError()) return notFound;
438  if (next)
439  {
440  if (sdt.mTime > t) return sdt.mTime;
441  ++pos;
442  }
443  else
444  {
445  if (sdt.mTime < t) return sdt.mTime;
446  --pos;
447  }
448  sif.set_file_position(pos);
449  }
450 
451  return notFound;
452  }
453 
454  int WaveData::intValue(double t) const
455  {
456  LoadPolicy lpol = loadPolicy();
457  if (lpol == LoadAllData ||
458  (lpol == LoadTimeframe && !mData.isEmpty() && t>=mData.firstKey() && t < mData.lastKey() ))
459  {
460  if (mData.isEmpty()) return -1;
462  return it.value();
463  }
464 
465  if (!mWaveDataList) return -1;
467  if (!sif.good()) return -1;
468  return sif.get_int_value(t);
469  }
470 
471  QString WaveData::strValue(double t) const
472  {
473  if (mData.isEmpty()) return "x";
475  return strValue(it);
476  }
477 
479  {
480  if (it == mData.constEnd()) return QString();
481  return strValue(it.value());
482  }
483 
485  {
486  return stringValue(val,bits(),mValueBase);
487  }
488 
489  QString WaveData::stringValue(int val, int bits, int base)
490  {
491  switch (val) {
492  case -2 : return "z";
493  case -1 : return "x";
494  }
495  if (bits <= 1 || !val)
496  return QString::number(val);
497  if (base<0)
498  {
499  int mask = 1 << (bits-1);
500  if (val&mask)
501  return QString("-%1").arg((1 << bits) - val);
502  else
503  return QString::number(val);
504  }
505  int nDigits = 0;
506  switch (base)
507  {
508  case 2:
509  nDigits = bits;
510  return QString("0b%1").arg((uint)val,nDigits,2,QLatin1Char('0'));
511  case 16:
512  nDigits = bits / 4;
513  return QString("0x%1").arg((uint)val,nDigits,16,QLatin1Char('0'));
514  default: break;
515  }
516  return QString::number(val,base);
517  }
518 
519  std::string WaveData::fileName() const
520  {
521  if (!mWaveDataList || mFileIndex < 0) return std::string();
522  return mWaveDataList->saleaeDirectory().get_datafile_path(mFileIndex);
523  }
524 
526  {
527  if (mData.isEmpty()) return 0;
528  return mData.lastKey();
529  }
530 
531 //--------------------------------------------
533  {
534  if (!wd->id()) mCode = 0;
535  else
536  {
537  const WaveDataGroup* grp = dynamic_cast<const WaveDataGroup*>(wd);
538  if (grp) construct (grp->id(), false);
539  else construct (wd->id(), true);
540  }
541  }
542 
543  void WaveDataGroupIndex::construct(u32 id, bool isNet)
544  {
545  if (!id) mCode = 0;
546  else
547  mCode = (id << 1) | (isNet?0:1);
548  }
549 
550  uint qHash(const WaveDataGroupIndex& wdgi) { return wdgi.mCode; }
551 
552  //--------------------------------------------
553  WaveDataBoolean::WaveDataBoolean(WaveDataList* wdList, const QList<WaveData*>& boolInput, const QList<int>& acceptMask)
554  : WaveData(wdList->nextBooleanId(),"",WaveData::BooleanNet), mInputCount(boolInput.size()),
555  mInputWaves(nullptr), mTruthTable(nullptr)
556  {
557  mWaveDataList = wdList;
558  if (!mInputCount) return;
559  if (mInputCount > 16)
560  {
561  mInputCount = 0;
562  return;
563  }
564 
565  mInputWaves = new WaveData*[mInputCount];
566  for (int i = 0; i<mInputCount; i++)
567  mInputWaves[i] = boolInput.at(i);
568  rename(QString("boolean_%1").arg(id()));
569 
570 
571  int truthTableLen = (1 << mInputCount);
572  int nByte = (truthTableLen+7) / 8;
573  mTruthTable = new char[nByte];
574  memset (mTruthTable, 0, nByte);
575 
576  for (int accept : acceptMask)
577  {
578  int j = accept/8;
579  int k = accept%8;
580  mTruthTable[j] |= (1<<k);
581  }
582  mWaveDataList->registerBoolean(this);
583  }
584 
586  : WaveData(wdList->nextBooleanId(),boolFunc,WaveData::BooleanNet),
587  mInputCount(0), mInputWaves(nullptr), mTruthTable(nullptr)
588  {
589  mWaveDataList = wdList;
590  auto bf = BooleanFunction::from_string(boolFunc.toStdString());
591  if (bf.is_error()) return;
592  std::vector<std::string> netNames;
593  for (std::string netName : bf.get().get_variable_names())
594  netNames.push_back(netName);
595  if ((mInputCount = netNames.size()) <= 0) return;
596  if (mInputCount > 16)
597  {
598  mInputCount = 0;
599  return;
600  }
601  mInputWaves = new WaveData*[mInputCount];
602 
603  bool failed = false;
604  for (int i = 0; i<mInputCount; i++)
605  {
606  const std::string& netName = netNames.at(i);
607  WaveData* wd = mWaveDataList->waveDataByName(netName);
608  if (!wd)
609  {
610  failed = true;
611  break;
612  }
613  mInputWaves[i] = wd;
614  }
615 
616  if (!failed)
617  {
618  auto tt = bf.get().compute_truth_table(netNames);
619  if (tt.is_error())
620  failed = true;
621  else
622  {
623  /* dump truth table
624  std::cerr << "----" << std::endl;
625  for (const std::string& nam : bf.get().get_variable_names())
626  {
627  std::cerr << " " << nam;
628  }
629  std::cerr << std::endl;
630  for (std::vector<BooleanFunction::Value> row : tt.get())
631  {
632  for (BooleanFunction::Value val : row)
633  std::cerr << " " << BooleanFunction::to_string(val);
634  std::cerr << std::endl;
635  }
636  std::cerr << "----" << std::endl;
637  */
638 
639  int truthTableLen = (1 << mInputCount);
640  int nByte = (truthTableLen+7) / 8;
641  mTruthTable = new char[nByte];
642  memset (mTruthTable, 0, nByte);
643  for (int i=0; i<truthTableLen; i++)
644  {
645  switch (tt.get().at(0).at(i))
646  {
647  case BooleanFunction::Z:
648  case BooleanFunction::X:
649  failed = true;
650  break;
652  break;
654  int j = i/8;
655  int k = i%8;
656  mTruthTable[j] |= (1<<k);
657  break;
658  }
659  if (failed) break;
660  }
661  }
662  }
663 
664  if (failed)
665  {
666  delete [] mInputWaves;
667  mInputWaves = 0;
668  mInputCount = 0;
669  return;
670  }
671  else
672  mWaveDataList->registerBoolean(this);
673  }
674 
676  {
677  if (mInputWaves) delete [] mInputWaves;
678  if (mTruthTable) delete [] mTruthTable;
679  }
680 
682  {
683  mData.clear();
684  switch (loadPolicy())
685  {
687  return;
689  for (int i=0; i<mInputCount; i++)
690  if (mInputWaves[i]->data().isEmpty())
691  return;
692  break;
693  default:
694  break;
695  }
696 
697  QMap<u64,int> transitionTime;
698  // TODO : not loadable
699  for (int i=0; i<mInputCount; i++)
700  {
701  mInputWaves[i]->loadDataUnlessAlreadyLoaded();
702  for (u64 t : mInputWaves[i]->data().keys())
703  ++transitionTime[t];
704  }
705 
706  int lastval = SaleaeDataTuple::sReadError;
707  for (u64 t : transitionTime.keys())
708  {
709  int ttInx = 0;
710  for (int i=0; i<mInputCount; i++)
711  {
712  int val = mInputWaves[i]->get_value_at(t);
713  if (val < 0 || val > 1)
714  {
715  ttInx = 1;
716  break;
717  }
718  if (val == 1)
719  ttInx |= (1<<i);
720  }
721  int nextval = SaleaeDataTuple::sReadError;
722  if (ttInx < 0)
723  nextval = -1;
724  else
725  {
726  int j = ttInx / 8;
727  int k = ttInx % 8;
728  nextval = (mTruthTable[j] & (1<<k)) ? 1 : 0;
729  }
730  if (nextval != lastval)
731  {
732  mData.insert(t,nextval);
733  lastval = nextval;
734  }
735  }
736  }
737 
739  {
740  QList<WaveData*> retval;
741  for (int i=0; i<mInputCount; i++)
742  retval.append(mInputWaves[i]);
743  return retval;
744  }
745 
747  {
748  LoadPolicy retval = LoadAllData;
749  for (int i=0; i<mInputCount; i++)
750  {
751  const WaveData* wd = mInputWaves[i];
752  switch (wd->loadPolicy())
753  {
754  case TooBigToLoad:
755  return TooBigToLoad;
756  case LoadTimeframe:
757  retval = LoadTimeframe;
758  break;
759  default:
760  break;
761  }
762  }
763  return retval;
764  }
765 
766  int WaveDataBoolean::intValue(double t) const
767  {
768  u32 mask = 1;
769  int val = 0;
770  for (int i=0; i<mInputCount; i++)
771  {
772  int childVal = mInputWaves[i]->intValue(t);
773  if (childVal < 0) return childVal;
774  if (childVal) val |= mask;
775  mask <<= 1;
776  }
777  return (mTruthTable[val/8] & (1<<val%8)) ? 1 : 0;
778  }
779 
780 //--------------------------------------------
782  : WaveData(wdList->nextTriggerId(),"",TriggerTime),
783  mTriggerCount(wdTrigger.size()), mTriggerWaves(nullptr), mFilterWave(nullptr), mToValue(nullptr)
784  {
785  mWaveDataList = wdList;
786  rename(QString("trigger%1").arg(id()));
787  if (!mTriggerCount) return;
788  mTriggerWaves = new WaveData*[mTriggerCount];
789  mToValue = new int[mTriggerCount];
790  int nVal = toVal.size();
791  for (int i=0; i<mTriggerCount; i++)
792  {
793  mTriggerWaves[i] = wdTrigger.at(i);
794  mToValue[i] = i < nVal ? toVal[i] : -1;
795  }
796  wdList->registerTrigger(this);
797  }
798 
800  {
801  if (mTriggerWaves) delete [] mTriggerWaves;
802  if (mToValue) delete [] mToValue;
803  }
804 
806  {
807  if (wd && (wd->netType() == WaveData::NetGroup || wd->netType() == WaveData::TriggerTime)) return;
808  mFilterWave = wd;
809  recalcData();
811  if (!sdce.isNull())
812  {
814  SaleaeDirectoryNetEntry trigEntry(wd->name().toStdString(),wd->id(),wd->composedType());
815  sdce.set_filter_entry(trigEntry.uniqueKey());
817  }
818  }
819 
820  int WaveDataTrigger::intValue(double t) const
821  {
822  if (loadPolicy() == LoadAllData)
823  {
824  for (int i=0; i<mTriggerCount; i++)
825  {
826  mTriggerWaves[i]->loadDataUnlessAlreadyLoaded();
827  auto it = mTriggerWaves[i]->data().find(floor(t+0.5));
828  if (it != mTriggerWaves[i]->data().constEnd())
829  {
830  if (mToValue[i] < 0 || mToValue[i] == it.value()) return 1;
831  }
832  }
833  return 0;
834  }
835  // TODO : check disk file
836  return 0;
837  }
838 
840  {
841  mData.clear();
842  switch (loadPolicy())
843  {
844  case TooBigToLoad:
845  return;
846  case LoadTimeframe:
847  for (int i=0; i<mTriggerCount; i++)
848  if (mTriggerWaves[i]->data().isEmpty())
849  return;
850  break;
851  default:
852  for (int i=0; i<mTriggerCount; i++)
853  mTriggerWaves[i]->loadDataUnlessAlreadyLoaded();
854  break;
855  }
856 
857  for (int i=0; i<mTriggerCount; i++)
858  for (auto it = mTriggerWaves[i]->data().constBegin(); it != mTriggerWaves[i]->data().constEnd(); ++it)
859  if (mToValue[i] < 0 || mToValue[i] == it.value())
860  if (!mFilterWave || mFilterWave->intValue(it.key())==1)
861  mData.insert(it.key(),1);
862  }
863 
865  {
867  for (int i=0; i<=mTriggerCount; i++)
868  {
869  const WaveData* wd = nullptr;
870  if (i<mTriggerCount)
871  wd = mTriggerWaves[i];
872  else
873  wd = mFilterWave;
874  if (!wd) continue;
875  switch (wd->loadPolicy())
876  {
877  case TooBigToLoad:
878  return TooBigToLoad;
879  case LoadTimeframe:
880  retval = LoadTimeframe;
881  break;
882  default:
883  break;
884  }
885  }
886  return retval;
887  }
888 
890  {
891  QList<WaveData*> retval;
892  for (int i=0; i<mTriggerCount; i++)
893  retval.append(mTriggerWaves[i]);
894  return retval;
895  }
896 
897  u64 WaveDataTrigger::neighborTransition(double t, bool next) const
898  {
899  if (!mData.empty() && loadPolicy() != TooBigToLoad)
900  {
901  if (next)
902  {
903  auto it = mData.upperBound(t);
904  if (it != mData.constEnd()) return it.key();
905  return t;
906  }
907  auto it = mData.lowerBound(t);
908  if (it == mData.constEnd()) --it;
909  while (it != mData.constBegin() && it.key()>=t) --it;
910  return it.key()>=t ? t : it.key();
911  }
912  //TODO : from file
913  return t;
914  }
915 
917  {
918  QList<int> retval;
919  for (int i=0; i<mTriggerCount; i++)
920  retval.append(mToValue[i]);
921  return retval;
922  }
923 
924 //--------------------------------------------
925  WaveDataGroup::WaveDataGroup(WaveDataList *wdList, int grpId, const QString& nam)
926  : WaveData(grpId,nam,WaveData::NetGroup)
927  {
928  mWaveDataList = wdList;
929  mWaveDataList->registerGroup(this);
930  }
931 
933  : WaveData(wdList->nextGroupId(),nam,WaveData::NetGroup)
934  {
935  mWaveDataList = wdList;
936  if (nam.isEmpty()) rename(QString("group_%1").arg(id()));
937  mWaveDataList->registerGroup(this);
938  }
939 
941  : WaveData(wdList->nextGroupId(),wdGrp->name(),WaveData::NetGroup)
942  {
943  mWaveDataList = wdList;
944  int n = wdGrp->bits();
945  if (!n) return;
946 
947  QMap<u64,int>** bitValue = new QMap<u64,int>*[n];
948  for (int i=0; i<n; i++) bitValue[i] = new QMap<u64,int>();
949 
950  bool first = true;
951  int lastV = 0;
952  for (auto it = wdGrp->data().constBegin(); it != wdGrp->data().constEnd(); ++it)
953  {
954  u64 t = it.key();
955  int v = it.value();
956  for (int i=0; i<n ; i++)
957  {
958  int mask = 1 << i;
959  if ( (v&mask) != (lastV&mask) || first )
960  bitValue[i]->insert(t, (v&mask) ? 1 : 0);
961  }
962  first = false;
963  lastV = v;
964  }
965  for (int i=0; i<n; i++)
966  {
967  // Create Fake Wave Entries
968  WaveData* wd = new WaveData(id()*10000+i, QString("%1_bit%2").arg(name()).arg(i), WaveData::RegularNet, *bitValue[i]);
969  wd->setBits(1);
970  mGroupList.append(wd);
971  mIndex.insert(WaveDataGroupIndex(wd),i);
972  mWaveDataList->add(wd,false);
973  delete bitValue[i];
974  }
975  delete [] bitValue;
976  mWaveDataList->registerGroup(this);
977  }
978 
980  {
981  auto it = mWaveDataList->mDataGroups.find(id());
982  if (it != mWaveDataList->mDataGroups.end())
983  mWaveDataList->mDataGroups.erase(it);
984  }
985 
987  {
988  QVector<WaveData*> wds;
989  wds.append(wd);
990  mWaveDataList->addWavesToGroup(id(),wds);
991  }
992 
994  {
995  int irow = mIndex.value(WaveDataGroupIndex(wd),-1);
996  if (irow < 0) return;
997  removeAt(irow);
998  restoreIndex();
999  recalcData();
1000  int iwave = mWaveDataList->waveIndexByNetId(wd->id());
1001  if (iwave >= 0) mWaveDataList->emitWaveRemovedFromGroup(iwave,id());
1002  }
1003 
1004  std::vector<WaveData*> WaveDataGroup::get_waveforms() const
1005  {
1006  std::vector<WaveData*> retval;
1007  for (WaveData* wd : mGroupList) retval.push_back(wd);
1008  return retval;
1009  }
1010 
1012  {
1013  int inx = childIndex(wd);
1014  if (inx<0) return;
1015  mGroupList[inx] = wd;
1016  recalcData();
1017  }
1018 
1020  {
1023  mIndex.clear();
1024  int inx = 0;
1025  for (const WaveData* wd : mGroupList)
1026  {
1027  sdce.add_child(wd->id());
1028  mIndex[WaveDataGroupIndex(wd)] = inx++;
1029  }
1031  }
1032 
1034  {
1035  if (bits() >= 30) return;
1036  u32 netId = n->get_id();
1037  WaveData* wd = nullptr;
1038  if (!mWaveDataList->hasNet(netId))
1039  mWaveDataList->add((wd = new WaveData(n)),false);
1040  else
1041  wd = mWaveDataList->waveDataByNet(n);
1042  int inx = mGroupList.size();
1043  mGroupList.append(wd);
1044  mIndex.insert(WaveDataGroupIndex(wd),inx);
1045  }
1046 
1048  {
1049  return mGroupList;
1050  }
1051 
1053  {
1054  QList<int> retval;
1055  for (const WaveData* wd : mGroupList)
1056  {
1057  retval.append(mWaveDataList->waveIndexByNetId(wd->id()));
1058  }
1059  return retval;
1060  }
1061 
1063  {
1064  if (inx >= mGroupList.size()) return nullptr;
1065  return mGroupList.at(inx);
1066  }
1067 
1069  {
1070  return mIndex.value(WaveDataGroupIndex(wd),-1);
1071  }
1072 
1074  {
1075  return mIndex.value(WaveDataGroupIndex(id,true),-1);
1076  }
1077 
1079  {
1080  return mIndex.contains(WaveDataGroupIndex(id,true));
1081  }
1082 
1084  {
1085  int n = mGroupList.size();
1086  if (n < 1) n=1;
1087  return n;
1088  }
1089 
1091  {
1092  if (inx >= mGroupList.size()) return nullptr;
1093  WaveData* wd = mGroupList.at(inx);
1094  mGroupList.removeAt(inx);
1095  restoreIndex();
1096  recalcData();
1097  return wd;
1098  }
1099 
1100  void WaveDataGroup::insert(int inx, WaveData* wd)
1101  {
1102  if (inx >= mGroupList.size())
1103  mGroupList.append(wd);
1104  else
1105  mGroupList.insert(inx,wd);
1106  restoreIndex();
1107  recalcData();
1108  }
1109 
1111  {
1112  mGroupList.append(wds.toList());
1113  restoreIndex();
1114  recalcData();
1115  }
1116 
1118  {
1119  int inx = childIndex(wd);
1120  if (inx < 0) return;
1121  mGroupList[inx] = wd;
1122  recalcData();
1123  }
1124 
1126  {
1128  for (const WaveData* wd : mGroupList)
1129  {
1130  switch (wd->loadPolicy())
1131  {
1133  return WaveData::TooBigToLoad;
1135  retval = WaveData::LoadTimeframe;
1136  break;
1137  default:
1138  break;
1139  }
1140  }
1141  return retval;
1142  }
1143 
1145  {
1146  mData.clear();
1147  QMultiMap<u64,int> tIndex;
1148  u32 value = 0;
1149  u32 undef = 0;
1150  int nChildren = mGroupList.size();
1151  WaveData** wdArray = new WaveData*[nChildren];
1152  if (mGroupList.isEmpty())
1153  {
1154  mData[0] = -1;
1155  mDirty = true;
1156  return;
1157  }
1158  for (int ibit = 0; ibit < nChildren; ibit++)
1159  {
1160  undef |= (1 << ibit);
1161  WaveData* wd = mGroupList.at(ibit);
1163  {
1164  // Would block, must determine group values in background thread
1165  return;
1166  }
1167  else if (wd->data().size() < (int) wd->fileSize())
1168  {
1169  // Loadable but nut loaded yet
1171  }
1172  wdArray[ibit] = wd;
1173  if (!wd) continue;
1174  for (u64 t : wd->data().keys())
1175  tIndex.insert(t,ibit);
1176  }
1177  u64 t0 = 0;
1178  for (auto it = tIndex.constBegin(); it != tIndex.constEnd(); ++it)
1179  {
1180  if (it.key() != t0)
1181  {
1182  mData.insert(t0, undef ? -1 : value);
1183  t0 = it.key();
1184  }
1185  int ibit = it.value();
1186  int v = wdArray[ibit]->data().value(t0);
1187  int mask = (1 << (nChildren - ibit - 1));
1188  if (v<0)
1189  undef |= mask;
1190  else
1191  {
1192  undef &= ( ~mask );
1193  if (v)
1194  value |= mask;
1195  else
1196  value &= ( ~mask );
1197  }
1198  }
1199  mData.insert(t0, undef ? -1 : value);
1200  delete [] wdArray;
1201  mDirty = true;
1203  }
1204 
1205  int WaveDataGroup::intValue(double t) const
1206  {
1207  u32 mask = 1 << (mGroupList.size()-1);
1208  int retval = 0;
1209  for (const WaveData* wd : mGroupList)
1210  {
1211  int childVal = wd->intValue(t);
1212  if (childVal < 0) return childVal;
1213  if (childVal) retval |= mask;
1214  mask >>= 1;
1215  }
1216  return retval;
1217  }
1218 
1219 //--------------------------------------------
1221  : mSceneMaxTime(sMinSceneWidth), mSimulateMaxTime(0), mUserdefMaxTime(0), mUserdefMinTime(0) {;}
1222 
1224  {
1225  return mSimulateMaxTime;
1226  }
1227 
1229  {
1230  if (hasUserTimeframe()) return mUserdefMaxTime;
1231  return mSceneMaxTime;
1232  }
1233 
1235  {
1236  if (t < sMinSceneWidth)
1237  mSceneMaxTime = sMinSceneWidth;
1238  else
1239  mSceneMaxTime = t;
1240  }
1241 
1243  {
1244  if (hasUserTimeframe()) return mUserdefMinTime;
1245  return 0;
1246  }
1247 
1249  {
1250  u64 x0 = sceneMinTime();
1251  u64 x1 = sceneMaxTime();
1252  if (x1 <= x0) return 1;
1253  return (x1-x0);
1254  }
1255 
1257  {
1258  return mUserdefMaxTime > 0;
1259  }
1260 
1262  {
1263  mUserdefMinTime = t0;
1264  mUserdefMaxTime = t1;
1265  }
1266 
1267 //--------------------------------------------
1268  WaveDataList::WaveDataList(const QString& sdFilename, QObject* parent)
1269  : QObject(parent),
1270  mSaleaeDirectory(sdFilename.toStdString()), mMaxGroupId(0), mMaxBooleanId(0), mMaxTriggerid(0)
1271  {;}
1272 
1274  {
1275  clearAll();
1276  }
1277 
1278  void WaveDataList::setMaxTime(u64 tmax)
1279  {
1280  if (mTimeframe.mSceneMaxTime == tmax) return;
1281 
1282  // adjust clock settings
1283  bool mustUpdateClocks = (tmax > mTimeframe.mSceneMaxTime);
1284 
1285  mTimeframe.setSceneMaxTime(tmax);
1286  if (mustUpdateClocks) updateClocks();
1287  Q_EMIT timeframeChanged(&mTimeframe);
1288  }
1289 
1291  {
1292  Q_EMIT timeframeChanged(&mTimeframe);
1293  }
1294 
1296  {
1297  mTimeframe.mSimulateMaxTime += deltaT;
1298  if (mTimeframe.mSimulateMaxTime > mTimeframe.mSceneMaxTime)
1299  setMaxTime(mTimeframe.mSimulateMaxTime);
1300  }
1301 
1303  {
1304  if (t0 == mTimeframe.mUserdefMinTime && t1 == mTimeframe.mUserdefMaxTime) return;
1305  mTimeframe.setUserTimeframe(t0,t1);
1306  for (auto it=begin(); it!=end(); ++it)
1307  {
1308  WaveData* wd = *it;
1309  // invalidate memory data
1311  {
1312 
1313  wd->setTimeframeSize(0);
1314  wd->clear();
1315  }
1316  }
1317  Q_EMIT timeframeChanged(&mTimeframe);
1318  }
1319 
1321  {
1322  bool notEmpty = ! isEmpty();
1323  mIds.clear();
1324  if (notEmpty)
1325  Q_EMIT waveRemoved(-1);
1326  setMaxTime(0);
1327  for (auto it=begin(); it!=end(); ++it)
1328  mTrashCan.append(*it);
1329  clear();
1330  emptyTrash();
1331  }
1332 
1333  void WaveDataList::dump() const
1334  {
1335  fprintf(stderr, "WaveDataList:_________%8u______________\n", (unsigned int) mTimeframe.mSimulateMaxTime);
1336  for (auto it = constBegin(); it!= constEnd(); ++it)
1337  {
1338  fprintf(stderr, " %4d <%s>:", (*it)->id(), (*it)->name().toStdString().c_str());
1339  for (auto jt = (*it)->data().begin(); jt != (*it)->data().end(); ++jt)
1340  fprintf(stderr, " <%u,%d>", (unsigned int) jt.key(), jt.value());
1341  fprintf(stderr, "\n");
1342  }
1343  fflush(stderr);
1344 
1345  }
1346 
1347  void WaveDataList::updateWaveName(int iwave, const QString& nam)
1348  {
1349  if (at(iwave)->rename(nam))
1350  {
1351  SaleaeDirectoryStoreRequest save(&mSaleaeDirectory);
1352  Q_EMIT waveRenamed(iwave);
1353  mSaleaeDirectory.rename_net(at(iwave)->id(),nam.toStdString());
1354  }
1355  }
1356 
1358  {
1359  WaveDataGroup* grp = mDataGroups.value(grpId);
1360  if (grp && grp->rename(nam))
1361  {
1362  SaleaeDirectoryStoreRequest save(&mSaleaeDirectory);
1363  Q_EMIT groupRenamed(grpId);
1364  }
1365  }
1366 
1367  void WaveDataList::emitWaveRemovedFromGroup(int iwave, int grpId)
1368  {
1369  Q_EMIT waveRemovedFromGroup(iwave, grpId);
1370  }
1371 
1373  {
1374  Q_EMIT waveAdded(inx);
1375  }
1376 
1378  {
1379  u32 netId = at(inx)->id();
1380  for (auto it = mDataGroups.begin(); it != mDataGroups.end(); ++it)
1381  if (it.value()->hasNetId(netId))
1382  {
1383  Q_EMIT waveUpdated(inx,it.value()->id());
1384  }
1385  Q_EMIT waveUpdated(inx,0);
1386  }
1387 
1389  {
1390  Q_EMIT groupUpdated(grpId);
1391  }
1392 
1394  {
1395  auto it = mTrashCan.begin();
1396  while (it != mTrashCan.end())
1397  {
1398  if ((*it)->hasSubscriber())
1399  ++it;
1400  else
1401  {
1402  delete (*it);
1403  it = mTrashCan.erase(it);
1404  }
1405  }
1406  }
1407 
1409  {
1410  WaveData* wd = at(inx);
1411  wd->saveSaleae();
1412  u32 netId = wd->id();
1413  for (auto it = mDataGroups.begin(); it != mDataGroups.end(); ++it)
1414  if (it.value()->hasNetId(netId))
1415  {
1416  it.value()->recalcData();
1417  Q_EMIT waveUpdated(inx,it.value()->id());
1418  }
1419  Q_EMIT waveUpdated(inx,0);
1420  }
1421 
1423  {
1424  for (auto it=begin(); it!=end(); ++it)
1425  if ((*it)->netType() == WaveData::ClockNet)
1426  {
1427  WaveDataClock* wdc = static_cast<WaveDataClock*>(*it);
1428  wdc->setMaxTime(mTimeframe.mSceneMaxTime);
1429  }
1430  }
1431 
1432  void WaveDataList::updateMaxTime()
1433  {
1434  u64 tmax = 0;
1435  for (auto it = constBegin(); it!= constEnd(); ++it)
1436  {
1437  u64 tmaxWave = (*it)->maxTime();
1438  if (tmaxWave > tmax) tmax = tmaxWave;
1439  }
1440  if (tmax>mTimeframe.mSceneMaxTime)
1441  setMaxTime(tmax);
1442  }
1443 
1444  void WaveDataList::add(WaveData* wd, bool updateSaleae)
1445  {
1446  int n = size();
1447 
1448  mIds[wd->id()] = n;
1449  append(wd);
1450  wd->setWaveDataList(this);
1451  updateMaxTime();
1452  if (updateSaleae) wd->saveSaleae();
1453 // if (!silent) Q_EMIT waveAdded(n);
1454  testDoubleCount();
1455  }
1456 
1458  {
1459  int iwave = waveIndexByNetId(id);
1460  if (iwave<0) return;
1461  // ugly but save. While emit is not const because of Q_SIGNAL syntax it will not modify object
1462  const_cast<WaveDataList*>(this)->emitWaveAdded(iwave);
1463  }
1464 
1465  void WaveDataList::registerTrigger(WaveDataTrigger *wdTrig)
1466  {
1467  u32 trigId = wdTrig->id();
1468  Q_ASSERT(!mDataTrigger.contains(trigId));
1469  mDataTrigger.insert(trigId,wdTrig);
1471  for (WaveData* wd : wdTrig->children())
1472  {
1473  sdce.add_child(wd->id());
1474  }
1475  std::vector<int> toValue;
1476  for (int tval : wdTrig->toValueList())
1477  toValue.push_back(tval);
1478  sdce.set_data(toValue);
1479 
1480  WaveData* wdFilt = wdTrig->get_filter_wave();
1481  if (wdFilt)
1482  {
1483  SaleaeDirectoryNetEntry filterEntry(wdFilt->name().toStdString(),wdFilt->id(),wdFilt->composedType());
1484  sdce.set_filter_entry(filterEntry.uniqueKey());
1485  }
1486  mSaleaeDirectory.add_or_replace_composed(sdce);
1487  Q_EMIT triggerAdded(trigId);
1488  }
1489 
1490  void WaveDataList::registerBoolean(WaveDataBoolean *wdBool)
1491  {
1492  u32 boolId = wdBool->id();
1493  Q_ASSERT(!mDataBooleans.contains(boolId));
1494  mDataBooleans.insert(boolId,wdBool);
1495  SaleaeDirectoryComposedEntry sdce(wdBool->name().toStdString(),boolId,SaleaeDirectoryNetEntry::Boolean);
1496  int n = 1;
1497  for (WaveData* wd : wdBool->children())
1498  {
1499  n <<= 1;
1500  sdce.add_child(wd->id());
1501  }
1502  std::vector<int> acceptVal;
1503  const char* ttable = wdBool->truthTable();
1504  for (int i=0; i<n; i++)
1505  {
1506  int j = i/8;
1507  int k = i%8;
1508  if (ttable[j] & (1<<k)) acceptVal.push_back(i);
1509  }
1510  sdce.set_data(acceptVal);
1511  mSaleaeDirectory.add_or_replace_composed(sdce);
1512  Q_EMIT booleanAdded(boolId);
1513  }
1514 
1515  void WaveDataList::registerGroup(WaveDataGroup *grp)
1516  {
1517  u32 grpId = grp->id();
1518  if (!grpId) return;
1519  Q_ASSERT(!mDataGroups.contains(grpId));
1520  mDataGroups.insert(grpId,grp);
1521  if (grpId)
1522  {
1523  mSaleaeDirectory.add_or_replace_composed(SaleaeDirectoryComposedEntry(grp->name().toStdString(),grpId,SaleaeDirectoryNetEntry::Group));
1524  updateMaxTime();
1525  Q_EMIT groupAdded(grpId);
1526  }
1527  }
1528 
1530  {
1531  SaleaeDirectoryStoreRequest save(&mSaleaeDirectory);
1532  WaveDataGroup* grp = mDataGroups.value(grpId);
1533  QVector<u32> netIds;
1534  netIds.reserve(wds.size());
1535  if (!grp) return;
1536  int inx = grp->size();
1537  for (WaveData* wd : wds)
1538  {
1539  netIds.append(wd->id());
1540  grp->insert(inx++,wd);
1541  }
1542  grp->restoreIndex();
1543  grp->recalcData();
1544  Q_EMIT waveAddedToGroup(netIds,grpId);
1545  }
1546 
1548  {
1549  wd->insertBooleanValueWithoutSync(t, bval);
1550  wd->saveSaleae();
1551  }
1552 
1554  {
1555  WaveDataGroup* grp = mDataGroups.value(grpId);
1556  if (!grp) return;
1558  mSaleaeDirectory.remove_composed(grpId,SaleaeDirectoryNetEntry::Group);
1559  mTrashCan.append(grp);
1560  }
1561 
1562  void WaveDataList::replaceWaveData(int inx, WaveData* wdNew)
1563  {
1564  // replace existing
1566  WaveData* wdOld = at(inx);
1567  Q_ASSERT(wdOld);
1568  Q_ASSERT(wdOld != wdNew);
1569  wdNew->rename(wdOld->name());
1570  operator[](inx) = wdNew;
1571  wdNew->setWaveDataList(this);
1572  for (WaveDataGroup* grp : mDataGroups.values())
1573  if (grp->hasNetId(wdNew->id()))
1574  grp->replaceChild(wdNew);
1575  if (wdNew->maxTime() > mTimeframe.mSceneMaxTime)
1576  updateMaxTime();
1577 
1578  wdNew->saveSaleae();
1579 
1580 
1581  emitWaveUpdated(inx);
1582  mTrashCan.append(wdOld);
1584  }
1585 
1587  {
1588  mSaleaeDirectory.parse_json();
1589  u64 sdMaxTime = mSaleaeDirectory.get_max_time();
1590  if (sdMaxTime > mTimeframe.mSimulateMaxTime) incrementSimulTime(sdMaxTime-mTimeframe.mSimulateMaxTime);
1591 
1592  // create empty WaveData instances for all SALEAE waves ...
1593  QMap<QString, WaveData*> saleaeWaves;
1594  for (const SaleaeDirectory::ListEntry& sdle : mSaleaeDirectory.get_net_list())
1595  {
1596  QString name = QString::fromStdString(sdle.name);
1597  WaveData* wd = new WaveData(sdle.id, name);
1598  wd->setFileIndex(sdle.fileIndex);
1599  wd->setFileSize(sdle.size);
1600  saleaeWaves.insert(name,wd);
1601  }
1602 
1603  // ... but delete waves if already existing in container
1604  for (int i=0; i<size(); i++)
1605  {
1606  WaveData* wd = at(i);
1607  auto it = saleaeWaves.find(wd->name());
1608  if (it == saleaeWaves.end()) continue;
1609  wd->setFileSize(it.value()->fileSize());
1610  wd->setFileIndex(it.value()->fileIndex());
1611  if (wd->loadPolicy() == WaveData::LoadAllData)
1612  wd->loadSaleae(mTimeframe);
1613  emitWaveUpdated(i);
1614  mTrashCan.append(it.value());
1615  saleaeWaves.erase(it);
1616  }
1617 
1618  for (auto it=saleaeWaves.begin(); it!=saleaeWaves.end(); ++it)
1619  {
1620  add(it.value(),false);
1621  }
1622  setMaxTime(mSaleaeDirectory.get_max_time());
1623 
1624  for (auto it = mDataGroups.begin(); it != mDataGroups.end(); ++it)
1625  {
1626  (*it)->recalcData();
1627  }
1628  }
1629 
1631  {
1632  Q_ASSERT(wd);
1633  int inx = mIds.value(wd->id(),-1);
1634  if (inx >= 0)
1635  replaceWaveData(inx, wd);
1636  else
1637  add(wd,true);
1638  }
1639 
1641  {
1642  if (!n) return nullptr;
1643  int inx = mIds.value(n->get_id(),-1);
1644  if (inx >= 0)
1645  {
1646  WaveData* wd = at(inx);
1647  if (wd->loadPolicy()==WaveData::LoadAllData)
1649  return wd;
1650  }
1651  WaveData* wd = new WaveData(n);
1652  if (wd->loadSaleae(mTimeframe))
1653  {
1654  add(wd,false);
1655  return wd;
1656  }
1657  delete wd;
1658  return nullptr;
1659  }
1660 
1661  WaveData* WaveDataList::waveDataByName(const std::string& nam) const
1662  {
1663  QString needle = QString::fromStdString(nam);
1664  for (WaveData* wd : *this)
1665  if (wd->name()==needle)
1666  return wd;
1667  for (WaveDataBoolean* wdb : mDataBooleans.values())
1668  if (wdb->name()==needle)
1669  return wdb;
1670  return nullptr;
1671  }
1672 
1674  {
1675  for (WaveData* wd : *this)
1676  if (wd->id() == id)
1677  return wd;
1678  for (WaveDataBoolean* wdb : mDataBooleans.values())
1679  if (wdb->id() == id)
1680  return wdb;
1681  return nullptr;
1682  }
1683 
1684  void WaveDataList::testDoubleCount()
1685  {
1686  QMap<u32,int> doubleCount;
1687  QSet<QString> notInNetlist;
1688  for (const WaveData* wd : *this)
1689  {
1690  if (!wd->id())
1691  {
1692  if (!mNotInNetlist.contains(wd->name()))
1693  notInNetlist.insert(wd->name());
1694  }
1695  else
1696  ++doubleCount[wd->id()];
1697  }
1698  for (auto it=doubleCount.constBegin(); it!=doubleCount.constEnd(); ++it)
1699  {
1700  if (it.value() > 1)
1701  {
1702  log_warning("simulation_plugin", "Duplicate waveform ({}x) found : '{}'", it.value(), at(mIds.value(it.key()))->name().toStdString());
1703  }
1704  }
1705  if (!notInNetlist.isEmpty())
1706  {
1707  for (const QString& name : notInNetlist)
1708  {
1709  log_warning("simulation_plugin", "Waveform not in (partial) netlist : '{}'", name.toStdString());
1710  }
1711  mNotInNetlist += notInNetlist;
1712  }
1713  }
1714 
1715  void WaveDataList::restoreIndex()
1716  {
1717  mIds.clear();
1718  int inx = 0;
1719 
1720  for (const WaveData* wd : *this)
1721  mIds[wd->id()] = inx++;
1722  testDoubleCount();
1723  }
1724 
1726  {
1727  QList<u32> keyList = mIds.keys();
1728  return keyList.toSet();
1729  // return QSet<u32>(keyList.begin(),keyList.end());
1730  }
1731 
1733  {
1734  auto it = mIds.find(id);
1735  if (it == mIds.end()) return;
1736  int inx = it.value();
1737  WaveData* toDelete = at(inx);
1738  removeAt(inx);
1739  restoreIndex();
1740  Q_EMIT waveRemoved(inx);
1741  mTrashCan.append(toDelete);
1742  }
1743 
1745  {
1746  int inx = 0;
1747 
1748  for (auto it = constBegin(); it!= constEnd(); ++it)
1749  {
1750  if ((*it)->data().isEmpty())
1751  {
1752  (*it)->insert(0,val);
1753  emitWaveUpdated(inx);
1754  }
1755  ++inx;
1756  }
1757  }
1758 
1759 }
u32 size
static Result< BooleanFunction > from_string(const std::string &expression)
Value
represents the type of the node
Definition: net.h:58
u32 get_id() const
Definition: net.cpp:88
uint64_t mCount
Number of elements in buffer.
Definition: saleae_file.h:137
uint64_t * mTimeArray
Buffer for mCount transition time values.
Definition: saleae_file.h:140
int * mValueArray
Buffer for mCount data values.
Definition: saleae_file.h:143
int mValue
Data value.
Definition: saleae_file.h:171
static const int sReadError
Fake data value to indicate all kind of errors.
Definition: saleae_file.h:165
uint64_t mTime
Transition time.
Definition: saleae_file.h:168
bool readError() const
Indicates that there was an error and no data was returned.
Definition: saleae_file.h:174
The SaleaeDirectoryComposedEntry class represents a composed waveform. There are currently three type...
void add_child(int key)
Add an additional child key to composed.
void set_filter_entry(int filt)
Setter for filter pointer described above.
bool isNull() const
Test for null.
The SaleaeDirectoryFileIndex class represents a single SALEAE data file. The class comprises the inde...
The SaleaeDirectory class provides the API for the SALEAE directory file. The SALEAE directory file w...
void rename_net(uint32_t id, const std::string &nam)
Change waveform name entry for net identified by id.
int get_datafile_index(const std::string &nam, uint32_t id) const
Get waveform datafile index for net identified by name and id.
void add_or_replace_net(SaleaeDirectoryNetEntry &sdne)
Add net entry if not yet existing, replace existing entry otherwise.
bool parse_json()
Parse .json file into class instance.
std::string get_directory() const
Get path to SALEAE directory without filename.
void add_or_replace_composed(SaleaeDirectoryComposedEntry sdce)
Add composed waveform entry (Group, Boolean, Trigger)
int get_next_available_index() const
Getter for next available file index ('digital_XXX.bin' with lowest number XXX not in use)
void remove_composed(uint32_t id, SaleaeDirectoryNetEntry::Type tp)
Remove composed waveform entry identified by id an type.
SaleaeDirectoryComposedEntry get_composed(uint32_t id, SaleaeDirectoryNetEntry::Type tp) const
Getter for pointer to composed waveform entry allowing modifications.
std::vector< ListEntry > get_net_list() const
Getter for all net entries.
std::string get_datafile_path(int index) const
Get full path to waveform data file.
std::string get_filename() const
Get full path to saleae directory file including filename (/.../saleae.json)
uint64_t get_max_time() const
Getter for maximum time.
The SaleaeDirectoryNetEntry class represents a regular waveform for a single simulated net....
Type
@ Boolean
@ Trigger
@ None
@ Group
int uniqueKey() const
Unique key as reference (used e.g. in mComposedEntryMap)
void addIndex(const SaleaeDirectoryFileIndex &sdfe)
Add index for binary file to net entry instance.
The SaleaeDirectoryStoreRequest class is useful to bundle requests for updating SALEAE directory....
uint64_t numTransitions() const
Getter for number of transitions stored in file. Remember that the total number of events is numTrans...
Definition: saleae_file.h:115
int64_t get_file_position(double t, bool successor=false)
SaleaeDataTuple get_next_value()
Getter for next (time,value) tuple in sequential read.
SaleaeDataBuffer * get_buffered_data(uint64_t nread)
Returns pointer to data buffer reading from current file position up to nread events....
const SaleaeHeader * header() const
Getter for header information.
Definition: saleae_file.h:214
int get_int_value(double t)
Get waveform value for time t.
void set_file_position(int64_t pos)
Goto position for next read access. Pos=0 is start value from header.
void put_data(SaleaeDataBuffer *buf)
Write buffered data.
WaveDataBoolean(WaveDataList *wdList, QString boolFunc)
Definition: wave_data.cpp:585
QList< WaveData * > children() const
Definition: wave_data.cpp:738
const char * truthTable() const
Definition: wave_data.h:296
virtual int intValue(double t) const override
Definition: wave_data.cpp:766
virtual LoadPolicy loadPolicy() const override
Definition: wave_data.cpp:746
WaveDataClock(const Net *n, const SimulationInput::Clock &clk, u64 tmax)
Definition: wave_data.cpp:17
void setMaxTime(u64 tmax)
Definition: wave_data.cpp:31
virtual void replaceChild(WaveData *wd)
Definition: wave_data.cpp:1011
QList< int > childrenWaveIndex() const
Definition: wave_data.cpp:1052
virtual void updateWaveData(WaveData *wd)
Definition: wave_data.cpp:1117
virtual void recalcData()
Definition: wave_data.cpp:1144
virtual WaveData * childAt(int inx) const
Definition: wave_data.cpp:1062
std::vector< WaveData * > get_waveforms() const
Definition: wave_data.cpp:1004
virtual int bits() const override
Definition: wave_data.cpp:1083
void remove_waveform(WaveData *wd)
Definition: wave_data.cpp:993
void addNet(const Net *n)
Definition: wave_data.cpp:1033
virtual LoadPolicy loadPolicy() const override
Definition: wave_data.cpp:1125
virtual void addWaves(const QVector< WaveData * > &wds)
Definition: wave_data.cpp:1110
virtual QList< WaveData * > children() const
Definition: wave_data.cpp:1047
virtual int intValue(double t) const override
Definition: wave_data.cpp:1205
virtual int size() const
Definition: wave_data.h:339
virtual void insert(int inx, WaveData *wd)
Definition: wave_data.cpp:1100
virtual ~WaveDataGroup()
Definition: wave_data.cpp:979
virtual int childIndex(WaveData *wd) const
Definition: wave_data.cpp:1068
WaveDataGroup(WaveDataList *wdList, int grpId, const QString &nam)
Definition: wave_data.cpp:925
void add_waveform(WaveData *wd)
Definition: wave_data.cpp:986
virtual WaveData * removeAt(int inx)
Definition: wave_data.cpp:1090
QList< WaveData * > mGroupList
Definition: wave_data.h:330
virtual int netIndex(u32 id) const
Definition: wave_data.cpp:1073
QHash< WaveDataGroupIndex, int > mIndex
Definition: wave_data.h:332
virtual bool hasNetId(u32 id) const
Definition: wave_data.cpp:1078
WaveDataGroupIndex(const WaveData *wd)
Definition: wave_data.cpp:532
void setData(const QMap< u64, int > &dat)
Definition: wave_data.cpp:119
void clear()
Definition: wave_data.h:136
int get_value_at(u64 t)
Definition: wave_data.cpp:125
SaleaeDirectoryNetEntry::Type composedType() const
Definition: wave_data.cpp:132
virtual u64 neighborTransition(double t, bool next) const
Definition: wave_data.cpp:360
bool loadSaleae(const WaveDataTimeframe &tframe=WaveDataTimeframe())
Definition: wave_data.cpp:270
bool isEqual(const WaveData &other, int tolerance=0) const
Definition: wave_data.cpp:144
std::string get_name() const
Definition: wave_data.h:132
std::vector< std::pair< u64, int > > get_events(u64 t0=0) const
Definition: wave_data.cpp:194
void resetWave()
Definition: wave_data.cpp:64
void setFileSize(u64 siz)
Definition: wave_data.cpp:69
static QString stringValue(int val, int bits, int base)
Definition: wave_data.cpp:489
bool rename(const QString &nam)
Definition: wave_data.cpp:89
virtual int intValue(double t) const
Definition: wave_data.cpp:454
void setBits(int bts)
Definition: wave_data.cpp:97
std::vector< std::pair< u64, int > > get_triggered_events(const WaveDataTrigger *wdTrig, u64 t0=0)
Definition: wave_data.cpp:183
void saveSaleae()
Definition: wave_data.cpp:320
virtual LoadPolicy loadPolicy() const
Definition: wave_data.cpp:75
WaveData(const WaveData &other)
Definition: wave_data.cpp:48
QMap< u64, int > mData
Definition: wave_data.h:91
u64 fileSize() const
Definition: wave_data.h:110
void setWaveDataList(WaveDataList *wdList)
Definition: wave_data.h:121
void loadDataUnlessAlreadyLoaded()
Definition: wave_data.cpp:264
void setId(u32 id_)
Definition: wave_data.cpp:83
const QMap< u64, int > & data() const
Definition: wave_data.h:108
QMap< u64, int >::const_iterator timeIterator(double t) const
Definition: wave_data.cpp:352
int mValueBase
Definition: wave_data.h:90
NetType netType() const
Definition: wave_data.h:105
int dataIndex() const
Definition: wave_data.cpp:178
void setTimeframeSize(u64 siz)
Definition: wave_data.h:120
WaveDataList * mWaveDataList
Definition: wave_data.h:93
std::string fileName() const
Definition: wave_data.cpp:519
QString name() const
Definition: wave_data.h:104
void insertBooleanValueWithoutSync(u64 t, BooleanFunction::Value bval)
Definition: wave_data.cpp:103
virtual int bits() const
Definition: wave_data.h:106
void setFileIndex(int saleaIndex)
Definition: wave_data.h:118
QString strValue(int val) const
Definition: wave_data.cpp:484
u32 id() const
Definition: wave_data.h:103
u64 maxTime() const
Definition: wave_data.cpp:525
void updateWaveName(int iwave, const QString &nam)
Definition: wave_data.cpp:1347
QMap< u32, WaveDataGroup * > mDataGroups
Definition: wave_data.h:203
void waveUpdated(int inx, int grpId)
WaveData * waveDataByName(const std::string &nam) const
Definition: wave_data.cpp:1661
void emitWaveRemovedFromGroup(int iwave, int grpId)
Definition: wave_data.cpp:1367
void booleanAdded(int boolId)
void addWavesToGroup(u32 grpId, const QVector< WaveData * > &wds)
Definition: wave_data.cpp:1529
void waveRemovedFromGroup(int iwave, int grpId)
QMap< u32, WaveDataBoolean * > mDataBooleans
Definition: wave_data.h:204
void emitWaveUpdated(int inx)
Definition: wave_data.cpp:1377
void add(WaveData *wd, bool updateSaleae)
Definition: wave_data.cpp:1444
void updateGroupName(u32 grpId, const QString &nam)
Definition: wave_data.cpp:1357
void triggerEndResetModel()
int waveIndexByNetId(u32 id) const
Definition: wave_data.h:227
bool hasNet(u32 id) const
Definition: wave_data.h:229
SaleaeDirectory & saleaeDirectory()
Definition: wave_data.h:242
void addOrReplace(WaveData *wd)
Definition: wave_data.cpp:1630
void groupAdded(int grpId)
void waveRemoved(int inx)
void waveRenamed(int iwave)
void setValueForEmpty(int val)
Definition: wave_data.cpp:1744
WaveData * waveDataById(const int id)
Definition: wave_data.cpp:1673
void dump() const
Definition: wave_data.cpp:1333
void timeframeChanged(const hal::WaveDataTimeframe *tframe)
void remove(u32 id)
Definition: wave_data.cpp:1732
void waveAdded(int inx)
const WaveDataTimeframe & timeFrame() const
Definition: wave_data.h:233
void emitTimeframeChanged()
Definition: wave_data.cpp:1290
WaveData * waveDataByNet(const Net *n)
Definition: wave_data.cpp:1640
void incrementSimulTime(u64 deltaT)
Definition: wave_data.cpp:1295
void setUserTimeframe(u64 t0=0, u64 t1=0)
Definition: wave_data.cpp:1302
void triggerAdded(int trigId)
void groupRenamed(int grpId)
WaveDataList(const QString &sdFilename, QObject *parent=nullptr)
Definition: wave_data.cpp:1268
QSet< u32 > toSet() const
Definition: wave_data.cpp:1725
void triggerAddToView(u32 id) const
Definition: wave_data.cpp:1457
void removeGroup(u32 grpId)
Definition: wave_data.cpp:1553
void emitWaveAdded(int inx)
Definition: wave_data.cpp:1372
void emitGroupUpdated(int grpId)
Definition: wave_data.cpp:1388
void groupAboutToBeRemoved(hal::WaveDataGroup *grp)
void insertBooleanValue(WaveData *wd, u64 t, BooleanFunction::Value bval)
Definition: wave_data.cpp:1547
void triggerBeginResetModel()
void groupUpdated(int grpId)
void waveAddedToGroup(const QVector< u32 > &netIds, int grpId)
void updateWaveData(int inx)
Definition: wave_data.cpp:1408
QMap< u32, WaveDataTrigger * > mDataTrigger
Definition: wave_data.h:205
virtual SaleaeDataTuple nextPoint()=0
virtual SaleaeDataTuple startValue(u64 t)=0
u64 sceneMaxTime() const
Definition: wave_data.cpp:1228
bool hasUserTimeframe() const
Definition: wave_data.cpp:1256
u64 sceneMinTime() const
Definition: wave_data.cpp:1242
void setSceneMaxTime(u64 t)
Definition: wave_data.cpp:1234
u64 simulateMaxTime() const
Definition: wave_data.cpp:1223
void setUserTimeframe(u64 t0=0, u64 t1=0)
Definition: wave_data.cpp:1261
virtual u64 neighborTransition(double t, bool next) const override
Definition: wave_data.cpp:897
void set_filter_wave(WaveData *wd)
Definition: wave_data.cpp:805
virtual int intValue(double t) const override
Definition: wave_data.cpp:820
QList< int > toValueList() const
Definition: wave_data.cpp:916
QList< WaveData * > children() const
Definition: wave_data.cpp:889
WaveData * get_filter_wave() const
Definition: wave_data.h:320
virtual LoadPolicy loadPolicy() const override
Definition: wave_data.cpp:864
WaveDataTrigger(WaveDataList *wdList, const QList< WaveData * > &wdTrigger, const QList< int > &toVal=QList< int >())
Definition: wave_data.cpp:781
uint64_t u64
Definition: defines.h:42
uint32_t u32
Definition: defines.h:41
#define log_warning(channel,...)
Definition: log.h:76
bool save(std::filesystem::path file_path, GateLibrary *gate_lib, bool overwrite=false)
Definition: defines.h:45
uint qHash(const LaneIndex &ri)
std::string name
QString absolutePath() const const
bool exists() const const
bool mkpath(const QString &dirPath) const const
void append(const T &value)
const T & at(int i) const const
QList::iterator begin()
QList::const_iterator constBegin() const const
QList::const_iterator constEnd() const const
QList::iterator end()
QList::iterator erase(QList::iterator pos)
void insert(int i, const T &value)
bool isEmpty() const const
const T & operator[](int i) const const
void removeAt(int i)
int size() const const
QSet< T > toSet() const const
const Key & key() const const
const Key & key() const const
T & value() const const
QMap::iterator begin()
void clear()
QMap::const_iterator constBegin() const const
QMap::const_iterator constEnd() const const
bool empty() const const
QMap::iterator end()
QMap::iterator erase(QMap::iterator pos)
QMap::iterator find(const Key &key)
const Key & firstKey() const const
QMap::iterator insert(const Key &key, const T &value)
bool isEmpty() const const
const Key key(const T &value, const Key &defaultKey) const const
QList< Key > keys() const const
const Key & lastKey() const const
QMap::iterator lowerBound(const Key &key)
int size() const const
QMap::iterator upperBound(const Key &key)
const T value(const Key &key, const T &defaultValue) const const
typename QMap< Key, T >::iterator insert(const Key &key, const T &value)
Q_EMITQ_EMIT
bool contains(const T &value) const const
QSet::iterator insert(const T &value)
bool isEmpty() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
QString number(int n, int base)
std::string toStdString() const const
void append(const T &value)
void reserve(int size)
int size() const const
QList< T > toList() const const