HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
wave_widget.cpp
Go to the documentation of this file.
11 #include "math.h"
12 
13 #include <QResizeEvent>
14 #include <QWheelEvent>
15 #include <QScrollBar>
16 #include <QHeaderView>
17 #include <QDebug>
18 #include <QApplication>
19 
24 #include "hal_core/utilities/log.h"
30 #include "gui/gui_globals.h"
31 
32 namespace hal {
33 
35  : QSplitter(parent), mController(ctrl), mControllerOwner(nullptr),
36  mControllerId(ctrl->get_id()), mControllerName(ctrl->get_name()),
37  mOngoingYscroll(false), mVisualizeNetState(false), mAutoAddWaves(true)
38  {
39  mWaveItemHash = new WaveItemHash;
40  mWaveDataList = ctrl->get_waves();
41  mTreeView = new WaveTreeView(mWaveDataList, mWaveItemHash, this);
42  mGraphicsCanvas = new WaveGraphicsCanvas(mWaveDataList, mWaveItemHash, this);
43  mTreeModel = new WaveTreeModel(mWaveDataList, mWaveItemHash, mGraphicsCanvas, this);
44  mTreeView->setModel(mTreeModel);
45  mTreeView->expandAll();
46  mTreeView->setColumnWidth(0,200);
47  mTreeView->setColumnWidth(1,40);
48  mTreeView->setColumnWidth(2,60);
49  mTreeView->header()->setStretchLastSection(true);
50  addWidget(mTreeView);
51 
52  addWidget(mGraphicsCanvas);
53 
67  connect(mTreeModel,&WaveTreeModel::numberEntriesChanged,this,&WaveWidget::handleNumberWaveformChanged,Qt::QueuedConnection);
73 
74 
75  if (parent && parent->parent()) // WaveformViewer -> QTabWidget -> WaveWidget
76  {
77  WaveformViewer* vv = static_cast<WaveformViewer*>(parent->parent());
78  if (vv)
79  {
83  }
84  }
85 
86  connect(gContentManager->getSelectionDetailsWidget(),&SelectionDetailsWidget::triggerHighlight,this,&WaveWidget::handleSelectionHighlight);
87 
88  connect(mController, &NetlistSimulatorController::stateChanged, this, &WaveWidget::handleStateChanged);
89  mTreeView->verticalScrollBar()->setValue(0);
90  setSizes({320,880});
91  mTreeModel->restore();
92  log_info(mControllerName, "Simulation controller id={} name='{}' instantiated", mControllerId, mControllerName);
93  }
94 
96  {
97  log_info(mControllerName, "Simulation controller id={} name='{}' disposed", mControllerId, mControllerName);
98  }
99 
101  {
102  int nWaves = mWaveDataList->size();
103  for (int i=0; i<nWaves; i++)
104  {
105  const WaveData* wd = mWaveDataList->at(i);
106  if (!wd->id()) continue;
107  Net* n = gNetlist->get_net_by_id(wd->id());
108  if (!n) continue;
109  QString netName = QString::fromStdString(n->get_name());
110  if (netName == wd->name()) continue;
111  mWaveDataList->updateWaveName(i,netName);
112  }
113  }
114 
116  {
117  if (!mController) return 0;
118  return mControllerId;
119  }
120 
122  {
123  if (!mController) return NetlistSimulatorController::NoGatesSelected;
124  return mController->get_state();
125  }
126 
128  {
129  return mControllerOwner != nullptr;
130  }
131 
132  void WaveWidget::takeOwnership(std::unique_ptr<NetlistSimulatorController>& ctrl)
133  {
134  mControllerOwner = std::move(ctrl);
135  }
136 
137  bool WaveWidget::isEmpty() const
138  {
139  return mWaveItemHash->isEmpty();
140  }
141 
143  {
144  if (mWaveDataList->size() > mWaveItemHash->importedWires()) return true;
145  if (mController)
146  {
147  SaleaeDirectory sd(mController->get_saleae_directory_filename());
148  if (sd.get_next_available_index() > mWaveItemHash->importedWires()) return true;
149  }
150  return false;
151  }
152 
154  {
155  if (!mControllerOwner) return false;
156  deleteLater();
157  return true;
158  }
159 
160  void WaveWidget::handleStateChanged(NetlistSimulatorController::SimulationState state)
161  {
163  qApp->processEvents();
164  }
165 
166  void WaveWidget::handleSelectionHighlight(const QVector<const ModuleItem*>& highlight)
167  {
168  QSet<u32> hlIds;
169  for (const ModuleItem* sti : highlight)
170  if (sti->getType() == ModuleItem::TreeItemType::Net)
171  hlIds.insert(sti->id());
172 
173  mTreeView->setWaveSelection(hlIds);
174  }
175 
176  void WaveWidget::createEngine(const QString &engineFactoryName)
177  {
178  if (mController)
179  mController->create_simulation_engine(engineFactoryName.toStdString());
180  }
181 
182  void WaveWidget::setVisualizeNetState(bool state, bool activeTab)
183  {
185  static const char* grpNames[3] = {"x state", "0 state", "1 state"};
186  mVisualizeNetState = state;
187  if (!activeTab) return;
188  if (mVisualizeNetState)
189  {
190  for (int i=0; i<3; i++)
191  {
192  Grouping* grp = gtm->groupingByName(grpNames[i]);
193  if (!grp)
194  {
195  grp = gNetlist->create_grouping(grpNames[i]);
197  }
198  mGroupIds[i] = grp->get_id();
199  }
200  visualizeCurrentNetState(mTreeModel->cursorTime(),mTreeModel->cursorXpos());
201  connect(mGraphicsCanvas,&WaveGraphicsCanvas::cursorMoved,this,&WaveWidget::visualizeCurrentNetState);
202  }
203  else
204  {
205  disconnect(mGraphicsCanvas,&WaveGraphicsCanvas::cursorMoved,this,&WaveWidget::visualizeCurrentNetState);
206  for (int i=0; i<3; i++)
207  {
208  Grouping* grp = gtm->groupingByName(grpNames[i]);
209  if (grp) gNetlist->delete_grouping(grp);
210  mGroupIds[i] = 0;
211  }
212  }
213  }
214 
216  {
217  QSet<int> alreadyShownInx = mTreeModel->waveDataIndexSet();
218  QSet<QString> alreadyShownNames;
219 
220  // Which wavedata container entries are not shown yet
221  int n = mWaveDataList->size();
223  for (int i=0; i<n; i++)
224  {
225  if (alreadyShownInx.contains(i))
226  alreadyShownNames.insert(mWaveDataList->at(i)->name());
227  else
228  {
229  WaveData* wd = mWaveDataList->at(i);
230  retval.insert(WaveSelectionEntry(wd->id(),wd->name(),wd->fileSize()),i);
231  }
232  }
233 
234  // Which salea directory entries are not shown yet
235  SaleaeDirectory* sd = mController ? new SaleaeDirectory(mController->get_saleae_directory_filename()) : nullptr;
236  if (sd)
237  {
238  for (const SaleaeDirectory::ListEntry& sdle : sd->get_net_list())
239  {
240  QString netName = QString::fromStdString(sdle.name);
241  if (alreadyShownNames.contains(netName)) continue; // already shown
242  if (mWaveDataList->waveIndexByNetId(sdle.id)>=0) continue; // already added to selection list by previous loop
243  retval.insert(WaveSelectionEntry(sdle.id,netName,sdle.size),-1);
244  }
245  }
246  delete sd;
247 // qDebug() << "Addable entries :" << retval.size();
248  return retval;
249  }
250 
252  {
253  SaleaeDirectory* sd = mController ? new SaleaeDirectory(mController->get_saleae_directory_filename()) : nullptr;
254 
255  QVector<WaveData*> wavesToAdd;
256  wavesToAdd.reserve(sel.size());
257 
258  for (auto it = sel.constBegin(); it!=sel.constEnd(); ++it)
259  {
260  int iwave = it.value();
261  if (iwave<0 && sd)
262  {
263  iwave = mWaveDataList->size();
264  WaveData* wd = new WaveData(it.key().id(),it.key().name());
265  if (wd->loadSaleae(mWaveDataList->timeFrame()))
266  {
267  mWaveDataList->add(wd,false);
268  wavesToAdd.append(wd);
269  }
270  }
271  else if (iwave >= 0)
272  wavesToAdd.append(mWaveDataList->at(iwave));
273  }
274  mTreeModel->addWaves(wavesToAdd);
275 
276  if (sd) delete sd;
277  }
278 
280  {
281  if (!canImportWires()) return;
282 
284 
285  WaveSelectionDialog wsd(wseMap,this);
286  if (wsd.exec() == QDialog::Accepted)
287  {
288  wseMap = wsd.selectedWaves();
289  if (!wseMap.isEmpty())
290  addSelectedResults(wseMap);
291  }
292  mGraphicsCanvas->handleTimeframeChanged(&mWaveDataList->timeFrame());
293  }
294 
295  void WaveWidget::setGates(const std::vector<Gate*>& gats)
296  {
297  if (!mController || mController->get_state() != NetlistSimulatorController::NoGatesSelected) return;
298  mController->reset();
299  mController->add_gates(gats);
300  for (const Net* inpNet : mController->get_input_nets())
301  mController->get_waveform_by_net(inpNet);
302  }
303 
304  void WaveWidget::handleNumberWaveformChanged(int count)
305  {
306  if (mTreeModel)
307  {
308  int expectMoreEvents = mTreeModel->decreaseNumberEntriesChangedEvents();
309  if (expectMoreEvents) return;
310  }
311  Q_UNUSED(count);
312  Q_EMIT stateChanged(mController->get_state());
313  }
314 
316  {
318  int w = event->size().width() - 320;
319  if (w < 100) return;
320  setSizes({320,w});
321  }
322 
323  void WaveWidget::visualizeCurrentNetState(double tCursor, int xpos)
324  {
325  QSet<Net*> netState[3]; // x, 0, 1
326 
327  for (auto it = mWaveItemHash->begin(); it != mWaveItemHash->end(); ++it)
328  {
329  WaveItem* wi = it.value();
330  if (!wi) continue;
331  const WaveData* wd = wi->wavedata();
332  if (!wd) continue;
333  Net* n = gNetlist->get_net_by_id(wd->id());
334  if (!n) continue;
335  int val = wi->cursorValue(tCursor, xpos);
336  if (val < -1 || val > 1) continue;
337  netState[val+1].insert(n);
338  }
339 
340  for (int i=0; i<3; i++)
341  {
342  Grouping* grp = gNetlist->get_grouping_by_id(mGroupIds[i]);
343  if (!grp) continue;
344  for (Net* n : grp->get_nets())
345  {
346  auto it = netState[i].find(n);
347  if (it == netState[i].end())
348  grp->remove_net(n);
349  else
350  netState[i].erase(it);
351  }
352  for (Net* n : netState[i])
353  grp->assign_net(n, true);
354  }
355  }
356 
358  {
359  if (mOngoingYscroll) return;
360  mOngoingYscroll = true;
361  if (mTreeView->verticalScrollBar()->value() != ypos)
362  mTreeView->verticalScrollBar()->setValue(ypos);
363 
364 
365  if (mGraphicsCanvas->verticalScrollBar()->value() != ypos)
366  {
367  mGraphicsCanvas->verticalScrollBar()->setMaximum(
368  mTreeView->verticalScrollBar()->maximum());
369  mGraphicsCanvas->verticalScrollBar()->setValue(ypos);
370  }
371  mOngoingYscroll = false;
372  }
373 
375  {
376  if (!grpId) return;
377  mWaveDataList->removeGroup(grpId);
378  }
379 }
SelectionDetailsWidget * getSelectionDetailsWidget()
GroupingManagerWidget * getGroupingManagerWidget()
u32 get_id() const
Definition: grouping.cpp:22
GroupingTableModel * getModel() const
Table that holds information about all groupings.
Grouping * groupingByName(const QString &name) const
QColor recolorGrouping(u32 id, const QColor &groupingColor)
Definition: net.h:58
const std::string & get_name() const
Definition: net.cpp:98
Grouping * create_grouping(const u32 grouping_id, const std::string &name="")
Definition: netlist.cpp:671
bool delete_grouping(Grouping *grouping)
Definition: netlist.cpp:681
Net * get_net_by_id(u32 net_id) const
Definition: netlist.cpp:353
Grouping * get_grouping_by_id(u32 grouping_id) const
Definition: netlist.cpp:691
void stateChanged(hal::NetlistSimulatorController::SimulationState state)
void loadProgress(int percent)
The SaleaeDirectory class provides the API for the SALEAE directory file. The SALEAE directory file w...
int get_next_available_index() const
Getter for next available file index ('digital_XXX.bin' with lowest number XXX not in use)
std::vector< ListEntry > get_net_list() const
Getter for all net entries.
void triggerHighlight(QVector< const ModuleItem * > highlight)
bool loadSaleae(const WaveDataTimeframe &tframe=WaveDataTimeframe())
Definition: wave_data.cpp:270
u64 fileSize() const
Definition: wave_data.h:110
QString name() const
Definition: wave_data.h:104
u32 id() const
Definition: wave_data.h:103
void updateWaveName(int iwave, const QString &nam)
Definition: wave_data.cpp:1347
void waveUpdated(int inx, int grpId)
void booleanAdded(int boolId)
void waveRemovedFromGroup(int iwave, int grpId)
void add(WaveData *wd, bool updateSaleae)
Definition: wave_data.cpp:1444
void triggerEndResetModel()
int waveIndexByNetId(u32 id) const
Definition: wave_data.h:227
void groupAdded(int grpId)
void waveRenamed(int iwave)
void timeframeChanged(const hal::WaveDataTimeframe *tframe)
void waveAdded(int inx)
const WaveDataTimeframe & timeFrame() const
Definition: wave_data.h:233
void triggerAdded(int trigId)
void groupRenamed(int grpId)
void removeGroup(u32 grpId)
Definition: wave_data.cpp:1553
void groupAboutToBeRemoved(hal::WaveDataGroup *grp)
void triggerBeginResetModel()
void groupUpdated(int grpId)
void waveAddedToGroup(const QVector< u32 > &netIds, int grpId)
void handleWaveUpdated(int iwave, int groupId)
void handleTimeframeChanged(const hal::WaveDataTimeframe *tframe)
void cursorMoved(double tCursor, int xpos)
int importedWires() const
Definition: wave_item.cpp:295
const WaveData * wavedata() const
Definition: wave_item.h:129
int cursorValue(double tCursor, int xpos)
Definition: wave_item.cpp:166
QMap< WaveSelectionEntry, int > selectedWaves() const
void addWaves(const QVector< WaveData * > &wds)
void handleWaveAddedToGroup(const QVector< u32 > &netIds, int grpId)
void handleWaveRemovedFromGroup(int iwave, int grpId)
void handleWaveAdded(int iwave)
u64 cursorTime() const
void numberEntriesChanged(int count)
void handleGroupRenamed(int grpId)
void inserted(QModelIndex index)
int decreaseNumberEntriesChangedEvents()
void handleTriggerAdded(int trigId)
int cursorXpos() const
void handleGroupAboutToBeRemoved(WaveDataGroup *grp)
void handleCursorMoved(u64 tCursor, int xpos)
void handleWaveRenamed(int iwave)
void handleGroupAdded(int grpId)
QSet< int > waveDataIndexSet() const
void handleGroupUpdated(int grpId)
void handleBooleanAdded(int boolId)
void handleInserted(const QModelIndex &index)
void setWaveSelection(const QSet< u32 > &netIds)
void triggerUpdateWaveItems()
QMap< WaveSelectionEntry, int > addableEntries() const
void setVisualizeNetState(bool state, bool activeTab)
void setGates(const std::vector< Gate * > &gats)
bool isEmpty() const
u32 controllerId() const
void resizeEvent(QResizeEvent *event) override
void addSelectedResults(const QMap< WaveSelectionEntry, int > &sel)
void takeOwnership(std::unique_ptr< NetlistSimulatorController > &ctrl)
void stateChanged(hal::NetlistSimulatorController::SimulationState state)
NetlistSimulatorController::SimulationState state() const
void createEngine(const QString &engineFactoryName)
void refreshNetNames()
bool hasOwnership() const
bool canImportWires() const
void removeGroup(u32 grpId)
WaveWidget(NetlistSimulatorController *ctrl, QWidget *parent=nullptr)
Definition: wave_widget.cpp:34
void scrollToYpos(int ypos)
void showProgress(int percent)
uint32_t u32
Definition: defines.h:41
#define log_info(channel,...)
Definition: log.h:70
Definition: defines.h:45
ContentManager * gContentManager
Definition: plugin_gui.cpp:78
Netlist * gNetlist
Definition: gui_globals.h:69
QScrollBar * verticalScrollBar() const const
void setMaximum(int)
void setValue(int)
virtual int exec()
QHash::iterator begin()
QHash::iterator end()
bool isEmpty() const const
void setStretchLastSection(bool stretch)
const T & at(int i) const const
int size() const const
QMap::const_iterator constBegin() const const
QMap::const_iterator constEnd() const const
QMap::iterator insert(const Key &key, const T &value)
bool isEmpty() const const
int size() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void deleteLater()
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QObject * parent() const const
bool contains(const T &value) const const
QSet::iterator erase(QSet::iterator pos)
QSet::iterator find(const T &value)
QSet::iterator insert(const T &value)
void addWidget(QWidget *widget)
int count() const const
virtual bool event(QEvent *e) override
virtual void resizeEvent(QResizeEvent *) override
void setSizes(const QList< int > &list)
QString fromStdString(const std::string &str)
int size() const const
std::string toStdString() const const
QueuedConnection
void expandAll()
QHeaderView * header() const const
void setColumnWidth(int column, int width)
virtual void setModel(QAbstractItemModel *model) override
void append(const T &value)
void reserve(int size)