HAL  v4.5.0-133-g64838ea8d
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"
29 #include "gui/gui_globals.h"
30 
31 namespace hal {
32 
34  : QSplitter(parent), mController(ctrl), mControllerOwner(nullptr),
35  mControllerId(ctrl->get_id()), mControllerName(ctrl->get_name()),
36  mOngoingYscroll(false), mVisualizeNetState(false), mAutoAddWaves(true)
37  {
38  mWaveItemHash = new WaveItemHash;
39  mWaveDataList = ctrl->get_waves();
40  mTreeView = new WaveTreeView(mWaveDataList, mWaveItemHash, this);
41  mGraphicsCanvas = new WaveGraphicsCanvas(mWaveDataList, mWaveItemHash, this);
42  mTreeModel = new WaveTreeModel(mWaveDataList, mWaveItemHash, mGraphicsCanvas, this);
43  mTreeView->setModel(mTreeModel);
44  mTreeView->expandAll();
45  mTreeView->setColumnWidth(0,200);
46  mTreeView->setColumnWidth(1,40);
47  mTreeView->setColumnWidth(2,60);
48  mTreeView->header()->setStretchLastSection(true);
49  addWidget(mTreeView);
50 
51  addWidget(mGraphicsCanvas);
52 
66  connect(mTreeModel,&WaveTreeModel::numberEntriesChanged,this,&WaveWidget::handleNumberWaveformChanged,Qt::QueuedConnection);
72 
73 
74  if (parent && parent->parent()) // WaveformViewer -> QTabWidget -> WaveWidget
75  {
76  WaveformViewer* vv = static_cast<WaveformViewer*>(parent->parent());
77  if (vv)
78  {
82  }
83  }
84 
85  connect(gContentManager->getSelectionDetailsWidget(),&SelectionDetailsWidget::triggerHighlight,this,&WaveWidget::handleSelectionHighlight);
86 
87  connect(mController, &NetlistSimulatorController::stateChanged, this, &WaveWidget::handleStateChanged);
88  mTreeView->verticalScrollBar()->setValue(0);
89  setSizes({320,880});
90  mTreeModel->restore();
91  log_info(mControllerName, "Simulation controller id={} name='{}' instantiated", mControllerId, mControllerName);
92  }
93 
95  {
96  log_info(mControllerName, "Simulation controller id={} name='{}' disposed", mControllerId, mControllerName);
97  }
98 
100  {
101  int nWaves = mWaveDataList->size();
102  for (int i=0; i<nWaves; i++)
103  {
104  const WaveData* wd = mWaveDataList->at(i);
105  if (!wd->id()) continue;
106  Net* n = gNetlist->get_net_by_id(wd->id());
107  if (!n) continue;
108  QString netName = QString::fromStdString(n->get_name());
109  if (netName == wd->name()) continue;
110  mWaveDataList->updateWaveName(i,netName);
111  }
112  }
113 
115  {
116  if (!mController) return 0;
117  return mControllerId;
118  }
119 
121  {
122  if (!mController) return NetlistSimulatorController::NoGatesSelected;
123  return mController->get_state();
124  }
125 
127  {
128  return mControllerOwner != nullptr;
129  }
130 
131  void WaveWidget::takeOwnership(std::unique_ptr<NetlistSimulatorController>& ctrl)
132  {
133  mControllerOwner = std::move(ctrl);
134  }
135 
136  bool WaveWidget::isEmpty() const
137  {
138  return mWaveItemHash->isEmpty();
139  }
140 
142  {
143  if (mWaveDataList->size() > mWaveItemHash->importedWires()) return true;
144  if (mController)
145  {
146  SaleaeDirectory sd(mController->get_saleae_directory_filename());
147  if (sd.get_next_available_index() > mWaveItemHash->importedWires()) return true;
148  }
149  return false;
150  }
151 
153  {
154  if (!mControllerOwner) return false;
155  deleteLater();
156  return true;
157  }
158 
159  void WaveWidget::handleStateChanged(NetlistSimulatorController::SimulationState state)
160  {
162  qApp->processEvents();
163  }
164 
165  void WaveWidget::handleSelectionHighlight(const QVector<const ModuleItem*>& highlight)
166  {
167  QSet<u32> hlIds;
168  for (const ModuleItem* sti : highlight)
169  if (sti->getType() == ModuleItem::TreeItemType::Net)
170  hlIds.insert(sti->id());
171 
172  mTreeView->setWaveSelection(hlIds);
173  }
174 
175  void WaveWidget::createEngine(const QString &engineFactoryName)
176  {
177  if (mController)
178  mController->create_simulation_engine(engineFactoryName.toStdString());
179  }
180 
181  void WaveWidget::setVisualizeNetState(bool state, bool activeTab)
182  {
184  static const char* grpNames[3] = {"x state", "0 state", "1 state"};
185  mVisualizeNetState = state;
186  if (!activeTab) return;
187  if (mVisualizeNetState)
188  {
189  for (int i=0; i<3; i++)
190  {
191  Grouping* grp = gtm->groupingByName(grpNames[i]);
192  if (!grp)
193  {
194  grp = gNetlist->create_grouping(grpNames[i]);
196  }
197  mGroupIds[i] = grp->get_id();
198  }
199  visualizeCurrentNetState(mTreeModel->cursorTime(),mTreeModel->cursorXpos());
200  connect(mGraphicsCanvas,&WaveGraphicsCanvas::cursorMoved,this,&WaveWidget::visualizeCurrentNetState);
201  }
202  else
203  {
204  disconnect(mGraphicsCanvas,&WaveGraphicsCanvas::cursorMoved,this,&WaveWidget::visualizeCurrentNetState);
205  for (int i=0; i<3; i++)
206  {
207  Grouping* grp = gtm->groupingByName(grpNames[i]);
208  if (grp) gNetlist->delete_grouping(grp);
209  mGroupIds[i] = 0;
210  }
211  }
212  }
213 
215  {
216  QSet<int> alreadyShownInx = mTreeModel->waveDataIndexSet();
217  QSet<QString> alreadyShownNames;
218 
219  // Which wavedata container entries are not shown yet
220  int n = mWaveDataList->size();
222  for (int i=0; i<n; i++)
223  {
224  if (alreadyShownInx.contains(i))
225  alreadyShownNames.insert(mWaveDataList->at(i)->name());
226  else
227  {
228  WaveData* wd = mWaveDataList->at(i);
229  retval.insert(WaveSelectionEntry(wd->id(),wd->name(),wd->fileSize()),i);
230  }
231  }
232 
233  // Which salea directory entries are not shown yet
234  SaleaeDirectory* sd = mController ? new SaleaeDirectory(mController->get_saleae_directory_filename()) : nullptr;
235  if (sd)
236  {
237  for (const SaleaeDirectory::ListEntry& sdle : sd->get_net_list())
238  {
239  QString netName = QString::fromStdString(sdle.name);
240  if (alreadyShownNames.contains(netName)) continue; // already shown
241  if (mWaveDataList->waveIndexByNetId(sdle.id)>=0) continue; // already added to selection list by previous loop
242  retval.insert(WaveSelectionEntry(sdle.id,netName,sdle.size),-1);
243  }
244  }
245  delete sd;
246 // qDebug() << "Addable entries :" << retval.size();
247  return retval;
248  }
249 
251  {
252  SaleaeDirectory* sd = mController ? new SaleaeDirectory(mController->get_saleae_directory_filename()) : nullptr;
253 
254  QVector<WaveData*> wavesToAdd;
255  wavesToAdd.reserve(sel.size());
256 
257  for (auto it = sel.constBegin(); it!=sel.constEnd(); ++it)
258  {
259  int iwave = it.value();
260  if (iwave<0 && sd)
261  {
262  iwave = mWaveDataList->size();
263  WaveData* wd = new WaveData(it.key().id(),it.key().name());
264  if (wd->loadSaleae(mWaveDataList->timeFrame()))
265  {
266  mWaveDataList->add(wd,false);
267  wavesToAdd.append(wd);
268  }
269  }
270  else if (iwave >= 0)
271  wavesToAdd.append(mWaveDataList->at(iwave));
272  }
273  mTreeModel->addWaves(wavesToAdd);
274 
275  if (sd) delete sd;
276  }
277 
279  {
280  if (!canImportWires()) return;
281 
283 
284  WaveSelectionDialog wsd(wseMap,this);
285  if (wsd.exec() == QDialog::Accepted)
286  {
287  wseMap = wsd.selectedWaves();
288  if (!wseMap.isEmpty())
289  addSelectedResults(wseMap);
290  }
291  mGraphicsCanvas->handleTimeframeChanged(&mWaveDataList->timeFrame());
292  }
293 
294  void WaveWidget::setGates(const std::vector<Gate*>& gats)
295  {
296  if (!mController || mController->get_state() != NetlistSimulatorController::NoGatesSelected) return;
297  mController->reset();
298  mController->add_gates(gats);
299  for (const Net* inpNet : mController->get_input_nets())
300  mController->get_waveform_by_net(inpNet);
301  }
302 
303  void WaveWidget::handleNumberWaveformChanged(int count)
304  {
305  if (mTreeModel)
306  {
307  int expectMoreEvents = mTreeModel->decreaseNumberEntriesChangedEvents();
308  if (expectMoreEvents) return;
309  }
310  Q_UNUSED(count);
311  Q_EMIT stateChanged(mController->get_state());
312  }
313 
315  {
317  int w = event->size().width() - 320;
318  if (w < 100) return;
319  setSizes({320,w});
320  }
321 
322  void WaveWidget::visualizeCurrentNetState(double tCursor, int xpos)
323  {
324  QSet<Net*> netState[3]; // x, 0, 1
325 
326  for (auto it = mWaveItemHash->begin(); it != mWaveItemHash->end(); ++it)
327  {
328  WaveItem* wi = it.value();
329  if (!wi) continue;
330  const WaveData* wd = wi->wavedata();
331  if (!wd) continue;
332  Net* n = gNetlist->get_net_by_id(wd->id());
333  if (!n) continue;
334  int val = wi->cursorValue(tCursor, xpos);
335  if (val < -1 || val > 1) continue;
336  netState[val+1].insert(n);
337  }
338 
339  for (int i=0; i<3; i++)
340  {
341  Grouping* grp = gNetlist->get_grouping_by_id(mGroupIds[i]);
342  if (!grp) continue;
343  for (Net* n : grp->get_nets())
344  {
345  auto it = netState[i].find(n);
346  if (it == netState[i].end())
347  grp->remove_net(n);
348  else
349  netState[i].erase(it);
350  }
351  for (Net* n : netState[i])
352  grp->assign_net(n, true);
353  }
354  }
355 
357  {
358  if (mOngoingYscroll) return;
359  mOngoingYscroll = true;
360  if (mTreeView->verticalScrollBar()->value() != ypos)
361  mTreeView->verticalScrollBar()->setValue(ypos);
362 
363 
364  if (mGraphicsCanvas->verticalScrollBar()->value() != ypos)
365  {
366  mGraphicsCanvas->verticalScrollBar()->setMaximum(
367  mTreeView->verticalScrollBar()->maximum());
368  mGraphicsCanvas->verticalScrollBar()->setValue(ypos);
369  }
370  mOngoingYscroll = false;
371  }
372 
374  {
375  if (!grpId) return;
376  mWaveDataList->removeGroup(grpId);
377  }
378 }
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:673
bool delete_grouping(Grouping *grouping)
Definition: netlist.cpp:683
Net * get_net_by_id(u32 net_id) const
Definition: netlist.cpp:355
Grouping * get_grouping_by_id(u32 grouping_id) const
Definition: netlist.cpp:693
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()
Definition: wave_widget.cpp:99
bool hasOwnership() const
bool canImportWires() const
void removeGroup(u32 grpId)
WaveWidget(NetlistSimulatorController *ctrl, QWidget *parent=nullptr)
Definition: wave_widget.cpp:33
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:79
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)